Variables and expressions

Engine decision variables and expressions are used in the search.

Creation of engine variables

When the model is extracted to an instance of IloCP, generally an instance of IlcIntVar is automatically created for each IloIntVar in the model. If no IloExtractable uses the decision variable, it will not be extracted unless you explicitly add it to the model.

The second way of introducing search decision variables in CP Optimizer is to create them directly. Here is one constructor to do so:

   IlcIntVar(IlcCPEngine cp, IlcInt min, IlcInt max, char* name=0);

The constructor declares an engine variable that can take a value between min and max (its lower and upper boundaries). In other words, the lower and upper boundaries define the domain of the search decision variable that is being constructed. The character string name is displayed whenever the variable is printed. It is an optional argument. This constructor is intended to be used for creation of search decision variables inside instances of other computation objects. It should not be used to declare variables that are part of the problem statement in the modeling layer. That should be done with the constructor for IloIntVar.

Accessing engine variables

Once an IloIntVar is extracted, you can access the IlcIntVar from the modeling object IloIntVar via the IloCPEngine.

The IloCPEngine of the worker under consideration is available in different contexts. A constraint, a demon, and a goal provide the function getCPEngine() to get an instance of IloCPEngine. A macro for goal or constraint extraction has an IloCPEngine available as parameter.

The following code returns the IlcIntVar from an IloIntVar x:


    IloIntVar x;
    ...
    IloCPEngine cp = getCPEngine();
    IlcIntVar cpx = cp.getIntVar(x);

And now, let us see a complete example for accessing the engine variable during the search process:


   ILCGOAL1(MyInst, IlcIntVar, var) {
      if (var.isFixed()) return 0;
      IlcInt v = var.getMin();
      return IlcOr(var == v, IlcAnd(var != v, this));
   }

   ILCGOAL1(MyGen, IlcIntVarArray, x) {
      IloCPEngine cp = getCPEngine();
      IlcInt choice = IlcChooseMinSizeInt(x);
      if (choice < 0) return 0;
      return IlcAnd(MyInst(cp, x[choice]), this);
   }

   ILOCPGOALWRAPPER1(MyGoal, cp, IloIntVarArray, x) {
      return MyGen(cp, cp.getIntVarArray(x)); // cp is of type IloCPEngine here
   }

   IloEnv env;
   IloIntVarArray x(env, 10, 0, 1);
   IloModel mdl(env);
   mdl.add(x);
   IloCP cp(mdl);
   cp.solve(MyGoal(env, x));
   cout << cp.domain(x) << endl;

This example is a code for defining a custom goal, which will be defined later in this document. The point here is to focus on the access to the IlcIntVarArray object corresponding to an IloIntVarArray given a worker. This is done in the goal MyGoal defined by the macro ILOCPGOALWRAPPER1.

When IloCP::solve(MyGoal(env, x)) is called, it creates different workers, each one having its own IloCPEngine. Each worker executes the code corresponding to MyGoal, which consists only of mapping the model variables to the engine variables and creating the IlcGoal (engine goals) on the engine variables. The cp parameter of the macro ILOCPGOALWRAPPER1 is automatically set by the solver to the IloCPEngine of the worker under consideration (Warning: it is not the master IloCP object defined in the main function). The mapping from IloIntVarArray to IlcIntVarArray is done simply by calling cp.getIntVarArray(x).