ILOG CPLEX 11.0 User's Manual > Languages and APIs > ILOG Concert Technology for C++ Users > Example: Optimizing the Diet Problem in C++ > Problem Representation

The problem contains a set of foods, which are the modeling variables; a set of nutritional requirements to be satisfied, which are the constraints; and an objective of minimizing the total cost of the food. There are two ways of looking at this problem:

Concert Technology is equally suited for both kinds of modeling; in fact, you can even mix both approaches in the same program. If a new food product is created, you can create a new variable for it regardless of how the model was originally built. Similarly, if a new nutrient is discovered, you can add a new constraint for it.

Creating a Model Row by Row

You walk into the store and compile a list of foods that are offered. For each food, you store the price per unit and the amount in stock. For some foods that you particularly like, you also set a minimum amount you would like to use in your diet. Then, for each of the foods, you create a modeling variable to represent the quantity to be purchased for your diet.

Now you get a nutrition book and look up which nutrients are known and relevant for you. For each nutrient, you note the minimum and maximum amounts that should be found in your diet. Also, you go through the list of foods and decide how much a food item will contribute for each nutrient. This gives you one constraint per nutrient, which can naturally be represented as a range constraint in pseudo-code like this:

nutrMin[i] <= sum_j (nutrPer[i][j] * Buy[j]) <= nutrMax[i] 

where i represents the number of the nutrient under consideration, nutrMin[i] and nutrMax[i] the minimum and maximum amount of nutrient i and nutrPer[i][j] the amount of nutrient i in food j.

Finally, you specify your objective function in pseudo-code like this:

minimize sum_j (cost[j] * Buy[j])

The loop in the example combines those two ideas and looks like this:

   mod.add(IloMinimize(env, IloScalProd(Buy,foodCost)));
   for (i = 0; i < m; i++) {
      IloExpr expr(env);
      for (j = 0; j < n; j++) {
         expr += Buy[j] * nutrPer[i][j];
      }
      mod.add(nutrMin[i] <= expr <= nutrMax[i]);
      expr.end();

This way of creating the model appears in the function buildModelByRow, in the example ilodiet.cpp.

Creating a Model Column by Column

You start with the nutrition book where you compile the list of nutrients that you want to make sure are properly represented in your diet. For each of the nutrients, you create an empty constraint:

nutrMin[i] ... nutrMax[i]

where ... is left to be filled once you walk into the store. Also, you set up the objective function to minimize the cost. Constraint i is referred to as range[i] and to the objective as cost.

Now you walk into the store and, for each food, you check the price and nutritional content. With this data you create a variable representing the amount you want to buy of the food type and install the variable in the objective function and constraints. That is, you create the following column in pseudo code, like this:

cost(foodCost[j]) "+" "sum_i" (range[i](nutrPer[i][j])) 

where the notation + and sum indicate in pseudo code that you add the new variable j to the objective cost and constraints range[i]. The value in parentheses is the linear coefficient that is used for the new variable. This notation is similar to the syntax actually used in Concert Technology, as demonstrated in the function buildModelByColumn, in the example ilodiet.cpp.

   for (j = 0; j < n; j++) {
      IloNumColumn col = cost(foodCost[j]);
      for (i = 0; i < m; i++) {
         col += range[i](nutrPer[i][j]);
      }
      Buy.add(IloNumVar(col, foodMin[j], foodMax[j], type));
      col.end();
   }