IBM ILOG Solver User's Manual > Extending the Library > Writing a Goal: Car Sequencing > Writing a goal: Car sequencing > Complete car sequencing program

The complete program follows. You can also view the entire program online in the file YourSolverHome/examples/src/carseq.cpp.

#include <ilsolver/ilosolverint.h>
 
ILOSTLBEGIN
 
//
// First Model
//
 
 
IloModel IloCarSequencing( IloEnv env,
                           IloInt maxCar,
                           IloIntArray maxConfs,
                           IloIntArray confs,
                           IloIntVarArray sequence){
 
 
  const IloInt abstractValue=-1; // we assume that confs[i] != -1
  const IloInt confs_size=confs.getSize();
  const IloInt sequence_size = sequence.getSize();
  IloIntArray nval(env, confs_size+1);
  IloIntVarArray ncard(env, confs_size+1);
 
  nval[OL]=abstractValue;
  ncard[OL]=IloIntVar(env, sequence_size - maxCar, sequence_size);
 
  IloInt i;
  for(i=0;i<confs_size;i++){
    nval[i+1]=confs[i];
    if (maxConfs[i] > maxCar)
      ncard[i+1]=IloIntVar(env, 0, maxCar);
    else
      ncard[i+1]=IloIntVar(env, 0, maxConfs[i]);
  }
 
  IloIntVarArray nvars(env,sequence_size);
  for (i = 0; i < sequence_size ; i++)
    nvars[i] = IloIntVar(env, nval);
 
 
  IloModel carseq_model(env);
  carseq_model.add(IloAbstraction(env, nvars, sequence, confs,abstractValue));
  carseq_model.add(IloDistribute(env, ncard, nval, nvars));
  return carseq_model;
}
 
 
void firstModel(){
  IloEnv env;
  try {
    IloModel model(env);
 
    const IloInt nbOptions = 5;
    const IloInt nbConfs   = 6;
    const IloInt nbCars    = 10;
 
    IloIntVarArray cars(env, nbCars,0,nbConfs-1);
 
    IloIntArray confs(env, 6, 0, 1, 2, 3, 4, 5);
    IloIntArray nbRequired(env, 6, 1, 1, 2, 2, 2, 2);
 
    IloIntVarArray cards(env, 6);
    for(IloInt conf=0;conf<nbConfs;conf++) {
      cards[conf]=IloIntVar(env, nbRequired[conf],nbRequired[conf]);
    }
 
    model.add (IloDistribute(env, cards, confs, cars));
 
    IloArray<IloIntArray> optConf(env, nbOptions);
 
    optConf[0] = IloIntArray(env, 3, 0, 4, 5);
    optConf[1] = IloIntArray(env, 3, 2, 3, 5);
    optConf[2] = IloIntArray(env, 2, 0, 4);
    optConf[3] = IloIntArray(env, 3, 0, 1, 3);
    optConf[4] = IloIntArray(env, 1, 2);
 
    IloIntArray maxSeq(env, 5, 1, 2, 1, 2, 1);
    IloIntArray overSeq(env, 5, 2, 3, 3, 5, 5);
 
    IloArray<IloIntArray> optCard(env, nbOptions);
    optCard[0] = IloIntArray(env, 3, 1, 2, 2);
    optCard[1] = IloIntArray(env, 3, 2, 2, 2);
    optCard[2] = IloIntArray(env, 2, 1, 2);
    optCard[3] = IloIntArray(env, 3, 1, 1, 2);
    optCard[4] = IloIntArray(env, 1, 2);
 
    for (IloInt opt=0; opt < nbOptions; opt++) {
      for (IloInt i=0; i < nbCars-overSeq[opt]+1; i++) {
        IloIntVarArray sequence(env,(IloInt)overSeq[opt]);
        for (IloInt j=0; j < overSeq[opt]; j++)
          sequence[j] = cars[i+j];
        model.add(IloCarSequencing(env,
                                   (IloInt)maxSeq[opt],
                                   optCard[opt],
                                   optConf[opt],
                                   sequence));
      }
    }
 
 
    IloSolver solver(model);
 
    solver.solve(IloGenerate(env,cars,IlcChooseMinSizeInt));
    solver.out() << "cars = " << solver.getIntVarArray(cars) << endl;
 
    solver.printInformation();
  }
  catch (IloException& ex) {
    cout << "Error: " << ex << endl;
  }
  env.end();
}
 
// Second Model
//
 
 
IloArray<IloIntArray> readData(IloEnv env,
                               IloInt example,
                               IloInt& nbCars,
                               IloInt& nbOpt,
                               IloIntArray& nbMax,
                               IloIntArray& seqWidth,
                               IloIntArray& confs,
                               IloIntArray& nbCarsByConf){
  char globalName[200];
  switch(example){
  case 1:{
    strcpy(globalName,"../../../examples/data/carseq1.dat");
  } break;
  case 2:{
    strcpy(globalName,"../../../examples/data/carseq2.dat");
  } break;
  }
  IloInt nbConfs;
  ifstream fin(globalName,ios::in);
  if (!fin) env.out() << "problem with file:" << globalName << endl;
  fin >> nbCars >> nbOpt >> nbConfs;
 
  IloInt i;
  confs = IloIntArray(env, nbConfs); // required configurations
  for(i=0;i<nbConfs;i++){
    confs[i]=i;
  }
  IloArray<IloIntArray> confsByOption(env, nbConfs);
  for (i=0;i<nbConfs;i++){
    confsByOption[i] = IloIntArray(env, nbOpt);
  }
  IloIntArray nbConfsByOption(env, nbOpt);
  for (i=0;i<nbOpt;i++){
    nbConfsByOption[i]=0;
  }
 
  // read the maximum number of cars of each sequence that can take the
  // invoked option
  nbMax=IloIntArray(env, nbOpt);
  for(i=0;i<nbOpt;i++){
    fin >> nbMax[i];
  }
 
  // read the size of a sequence for each option
  seqWidth=IloIntArray(env, nbOpt);
  for(i=0;i<nbOpt;i++){
    fin >> seqWidth[i];
  }
 
  // read the options required by each configuration
  nbCarsByConf=IloIntArray(env, nbConfs);
  IloInt dummy;
  IloInt j;
  for(i=0;i<nbConfs;i++){
    fin >> dummy;
    fin >> nbCarsByConf[i];
    for (j=0;j<nbOpt;j++){
      fin >> confsByOption[i][j];
      if (confsByOption[i][j] == 1){
        nbConfsByOption[j]++;
      }
    }
  }
  // compute the configurations required by each option
  IloArray<IloIntArray> optConf(env, nbOpt);
  for(i=0;i<nbOpt;i++){
    optConf[i]=IloIntArray(env, (IloInt)nbConfsByOption[i]);
  }
  IloIntArray ind(env, nbOpt);
  for(i=0;i<nbOpt;i++){
    ind[i]=0;
  }
  for(i=0;i<nbConfs;i++){
    for (j=0;j<nbOpt;j++){
      if (confsByOption[i][j] == 1){
        optConf[j][(IloInt)ind[j]]=i;
        ind[j]++;
      }
    }
  }
  // print the configuration required by each option
  env.out() << "number of times each configuration is required:" << endl;
  for(i=0;i<nbConfs;i++){
    env.out() << nbCarsByConf[i] << " ";
  }
  env.out() << endl;
  env.out() << "configuration required by each option:" << endl;
  for(i=0;i<nbOpt;i++){
    env.out() << "option:" << i << " ";
    for (j=0;j<optConf[i].getSize();j++){
      env.out() << optConf[i][j] << " ";
    }
    env.out() << endl;
  }
  env.out() << "number of times each option is required" << endl;
  for(i=0;i<nbOpt;i++){
    IloInt cpt=0;
    for(j=0;j<optConf[i].getSize();j++){
      cpt += nbCarsByConf[(IloInt)optConf[i][j]];
    }
    env.out() << "option:" << i << " " << cpt << " x ";
    env.out() << nbMax[i] << "/" << seqWidth[i] << endl;
  }
 
  return optConf;
}
 
ILCGOAL1(IlcGenerateAbstractVars, IlcIntVarArray, vars) {
  IlcInt index = IlcChooseFirstUnboundInt(vars);
  if (index == -1) return 0;
  return IlcAnd(IlcDichotomize(vars[index]), this); // first tries vars[index] == 1
}
 
ILOCPGOALWRAPPER1(IloGenerateAbstractVars, solver, IloIntVarArray, vars) {
  return IlcGenerateAbstractVars(solver, solver.getIntVarArray(vars));
}
 
void secondModel(IloInt mode, IloInt example)
{
  IloEnv env;
  try {
    IloModel model(env);
 
    IloInt nbOptions;
    IloInt nbCars;
    IloIntArray confs(env); // array of required configurations
    IloIntArray nbCarsByConf(env); // number of cars to assign
                                    // to each configuration
    IloIntArray nbMax(env);
    IloIntArray seqWidth(env);
 
    IloArray<IloIntArray> optConf = readData(env,
                                             example,
                                             nbCars,
                                             nbOptions,
                                             nbMax,
                                             seqWidth,
                                             confs,
                                             nbCarsByConf);
 
 
    cout << "Pass 1 " << endl;
    const IlcInt nbConfs   = confs.getSize();
 
    IloInt i,j;
    IloIntVarArray cars(env,nbCars,0,nbConfs-1);
    IloIntVarArray cards(env,nbConfs);
    for (i = 0; i < nbConfs; i++){
      cards[i] = IloIntVar(env,nbCarsByConf[i],nbCarsByConf[i]);
    }
    cout << "Pass 2 " << endl;
 
    model.add(IloDistribute(env, cards, confs, cars));
 
    IloInt opt;
    for (opt = 0; opt < nbOptions; opt++) {
      IloIntVarArray ncard(env,optConf[opt].getSize());
      for(i = 0; i < optConf[opt].getSize(); i++){
        ncard[i] = cards[(IloInt)optConf[opt][i]];
      }
      model.add(IloSequence(env,
                            0,
                            (IloInt)nbMax[opt],
                            (IloInt)seqWidth[opt],
                            cars,
                            optConf[opt],
                            ncard));
    }
    cout << "Pass 3 " << endl;
    IloIntArray order(env, nbOptions);
    switch(example){
    case 1:{
      order[OL]=0;
      order[1]=1;
      order[2]=4;
      order[3]=2;
      order[4]=3;
    } break;
    case 2:{
      order[OL]=0;
      order[1]=4;
      order[2]=1;
      order[3]=2;
      order[4]=3;
    }break;
    }
 
    IloBoolVarArray bvars(env,nbOptions*nbCars);
    for(i=0;i < nbOptions;i++){
      opt=(IloInt)order[i];
      IloBoolVarArray bv(env,nbCars);
      for (j = 0; j < nbCars; j++)
        bv[j] = IloBoolVar(env);
      model.add(IloBoolAbstraction(env, bv, cars, optConf[opt]));
      for(j=0;j<nbCars;j++){
        bvars[i*nbCars + j] = bv[j];
      }
    }
    cout << "Pass 4 " << endl;
 
    IloBoolVarArray tbvars(env,nbOptions*nbCars);
    for(j=0;j<nbOptions*nbCars;j+=nbCars){
      IlcInt mid=nbCars/2 - 1;
      for(i=0;i<mid+1;i++){
        tbvars[2*i+j]=bvars[mid-i+j];
        tbvars[2*i+1+j]=bvars[mid+i+1+j];
      }
    }
 
    IloSolver solver(model);
    if (mode) {
      solver.setDefaultFilterLevel(IlcSequenceCt,IlcExtended);
      solver.setDefaultFilterLevel(IlcDistributeCt,IlcExtended);
    }
    if (solver.solve(IloGenerateAbstractVars(env,tbvars)))
      solver.out() << "cars = " << solver.getIntVarArray(cars) << endl;
    else
    solver.out() << "No solution" << endl;
    solver.printInformation();
  }
  catch (IloException& ex) {
    cout << "Error: " << ex << endl;
  }
  env.end();
}
 
 
int main(int argc, char** argv){
  IloInt pb=(argc>1)?atoi(argv[1]):1;
  if (pb != 1 && pb != 2)
    pb=1;
 
  switch(pb){
  case 1 :{
    firstModel();
  } break;
  case 2 :{
    IlcInt mode = (argc>2)?atoi(argv[2]):1;
    if (mode != 0 && mode != 1)
      mode=1;
    IlcInt example = (argc>3)?atoi(argv[3]):1;
    secondModel(mode,example);
  } break;
 
  }
 
  return 0;
}