Complete Program

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;
}


Previous Page: Solving the Model with IloCplex  Return to Top Next Page: Using the ILOG CPLEX Callable Library