Building the model

Uses the diet example to demonstrate building a model for CPLEX in Java.

All the building blocks are now in place to implement a method that creates a model. The diet problem consists of finding the least expensive diet using a set of foods such that all nutritional requirements are satisfied. The example in this chapter builds the specific diet model, chooses an optimizing algorithm, and shows how to access more detailed information about the solution.

The example includes a set of foods, where food j has a unit cost of foodCost[j]. The minimum and maximum amount of food j which can be used in the diet is designated foodMin[j] and foodMax[j], respectively. Each food j also has a nutritional value nutrPerFood[i][j] for all possible nutrients i. The nutritional requirement states that in the diet the amount of every nutrient i consumed must be within the bounds nutrMin[i] and nutrMax[i].

Mathematically, this problem can be modeled using a variable Buy[j] for each food j indicating the amount of food j to buy for the diet. Then the objective is:


minimize ∑j (Buy[j] * foodCost[j])

The nutritional requirements mean that the following conditions must be observed; that is, for all i :


nutriMin[i] ≤ ∑i nutrPerFood[i][j] * Buy[j] ≤ nutriMax[i]

Finally, every food must be within its bounds; that is, for all j :


foodMin[j] ≤ Buy[j] ≤ foodMax[j]

With what you have learned so far, you can implement a method that creates such a model.


 static void buildModelByRow(IloModeler     model,
                              Data          data,
                              IloNumVar[]   Buy,
                              IloNumVarType type) 
    throws IloException {
    int nFoods = data.nFoods;
    int nNutrs = data.nNutrs;

    for (int j = 0; j < nFoods; j++) {
      Buy[j] = model.numVar(data.foodMin[j], data.foodMax[j], type);
    }
    model.addMinimize(model.scalProd(data.foodCost, Buy));

    for (int i = 0; i < nNutrs; i++) {
      model.addRange(data.nutrMin[i],
                     model.scalProd(data.nutrPerFood[i], Buy),
                     data.nutrMax[i]);
    }
  }

The function accepts several arguments. The argument model is used for two purposes:

  • creating other modeling objects, and

  • representing the model being created.

The argument data contains the data for the model to be built. The argument Buy is an array, initialized to length data.nFoods, containing the model's variables. Finally, the argument type is used to specify the type of the variables being created.

The function starts by creating the modeling variables, one by one, and storing them in the array Buy. Each variable j is initialized to have bounds data.foodMin[j] and data.foodMax[j] and to be of type type.

The variables are first used to construct the objective function expression with the method model.scalProd(foodCost, Buy). This expression is immediately used to create the minimization objective which is directly added to the active model by addMinimize.

In the loop that follows, the nutritional constraints are added. For each nutrient i the expression representing the amount of nutrient in a diet with food levels Buy is computed using model.scalProd(nutrPerFood[i], Buy). This amount of nutrient must be within the ranged constraint bounds nutrMin[i] and nutrMax[i]. This constraint is created and added to the active model with addRange.

Note that function buildModelByRow uses the interface IloModeler rather than IloCplex. This convention allows the function to be called without change in another implementation of IloModeler, such as IloCP.