The complete program, ilodiet.cpp
, shown here is also provided online, in the standard distribution.
|
#include <ilcplex/ilocplex.h> ILOSTLBEGIN void usage(const char* name) { cerr << endl; cerr << "usage: " << name << " [options] <file>" << endl; cerr << "options: -c build model by column" << endl; cerr << " -i use integer variables" << endl; cerr << endl; } typedef IloArray<IloNumArray> IloNumArray2; IloNumVarArray buildModelByRow(IloModel mod, const IloNumArray foodMin, const IloNumArray foodMax, const IloNumArray foodCost, const IloNumArray nutrMin, const IloNumArray nutrMax, const IloNumArray2& nutrPer, IloNumVar::Type type) { IloEnv env = mod.getEnv(); IloNumVarArray Buy (env, foodMin, foodMax, type); IloInt i, j; IloInt n = foodCost.getSize(); IloInt m = nutrMin.getSize(); 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]); } return (Buy); } IloNumVarArray buildModelByColumn(IloModel mod, const IloNumArray foodMin, const IloNumArray foodMax, const IloNumArray foodCost, const IloNumArray nutrMin, const IloNumArray nutrMax, const IloNumArray2& nutrPer, IloNumVar::Type type) { IloEnv env = mod.getEnv(); IloNumVarArray Buy(env); IloInt i, j; IloInt n = foodCost.getSize(); IloInt m = nutrMin.getSize(); IloObjective cost = IloAdd(mod, IloMinimize(env)); IloRangeArray range = IloAdd(mod, IloRangeArray(env, nutrMin, nutrMax)); 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)); } return (Buy); } int main(int argc, char **argv) { IloEnv env; try { const char* filename = "../../../examples/data/diet.dat"; IloBool byColumn = IloFalse; IloNumVar::Type varType = ILOFLOAT; IloInt i; for (i = 1; i < argc; ++i) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'c': byColumn = IloTrue; break; case 'i': varType = ILOINT; break; default: usage(argv[0]); throw (-1); } } else { filename = argv[i]; break; } } ifstream file(filename); if ( !file ) { cerr << "ERROR: could not open file '" << filename << "' for reading" << endl; usage(argv[0]); throw (-1); } // model data IloNumArray foodCost(env), foodMin(env), foodMax(env); IloNumArray nutrMin(env), nutrMax(env); IloNumArray2 nutrPer(env); file >> foodCost >> foodMin >> foodMax; file >> nutrMin >> nutrMax; file >> nutrPer; IloInt nFoods = foodCost.getSize(); IloInt nNutr = nutrMin.getSize(); if ( foodMin.getSize() != nFoods || foodMax.getSize() != nFoods || nutrPer.getSize() != nNutr || nutrMax.getSize() != nNutr ) { cerr << "ERROR: Data file '" << filename << "' contains inconsistent data" << endl; throw (-1); } for (i = 0; i < nNutr; ++i) { if (nutrPer[i].getSize() != nFoods) { cerr << "ERROR: Data file '" << argv[0] << "' contains inconsistent data" << endl; throw (-1); } } // Build model IloModel mod(env); IloNumVarArray Buy; if ( byColumn ) { Buy = buildModelByColumn(mod, foodMin, foodMax, foodCost, nutrMin, nutrMax, nutrPer, varType); } else { Buy = buildModelByRow(mod, foodMin, foodMax, foodCost, nutrMin, nutrMax, nutrPer, varType); } // Solve model IloCplex cplex(mod); cplex.exportModel("diet.lp"); cplex.solve(); cplex.out() << "solution status = " << cplex.getStatus() << endl; cplex.out() << endl; cplex.out() << "cost = " << cplex.getObjValue() << endl; for (i = 0; i < foodCost.getSize(); i++) cplex.out() << " Buy" << i << " = " << cplex.getValue(Buy[i]) << endl; } catch (IloException& ex) { cerr << "Error: " << ex << endl; } catch (...) { cerr << "Error" << endl; } env.end(); return 0; } |