Reversible data
Reversible data objects can be used to return data to its previous state upon backtracking.
Consider an object, such as a goal, that has a data member with a value that is modified during the search for a solution. The value assigned to this data member depends on the choices and the hypotheses made before this assignment.
If those choices fail to find a solution further on, the
optimizer backtracks, and the computed value for this data member
is no longer valid. For that reason, this data member must be a reversible
data member. That is, the modifier of this data member must save the
initial value of the data member before any modification, so the optimizer
is able to restore the value of the data member to its value before
modification if any failure occurs later. CP Optimizer provides you
with the predefined class IlcRevInt, the
class of reversible integers, for just such a purpose.
In this example is a custom goal that works to assign values to the variables in an array, starting at the smallest index. Each time the goal is executed, the index is incremented. However, when the optimizer backtracks, this integer is not decremented, leading to a situation in which some decision variables are not fixed. For example, the following goal will not ensure that all decision variables in the array are fixed when the search terminates:
ILCGOAL2(MycBadGenerate, IlcIntVarArray, x,int,index){
IloCPEngine cp = getCPEngine();
index++;
if (index > x.getSize())
return 0;
return IlcAnd(IlcInstantiate(x[index-1]),this);
}
ILOCPGOALWRAPPER1(MyoBadGenerate,cp,IloIntVarArray,x) {
IlcInt index=0;
return MycBadGenerate(cp,cp.getIntVarArray(x),index);
}
In order for the state of the index to be restored when
the optimizer backtracks, you can use an instance of an IlcRevInt,
as in the following code segment:
ILCGOAL2(MycGoodGenerate, IlcIntVarArray, x, IlcRevInt *, revIndex){
IloCPEngine cp = getCPEngine();
revIndex->setValue(cp,revIndex->getValue()+1);
if (revIndex->getValue() > x.getSize())
return 0;
return IlcAnd(IlcInstantiate(x[revIndex->getValue()-1]),this);
}
ILOCPGOALWRAPPER1(MyoGoodGenerate,cp,IloIntVarArray,x) {
IlcRevInt* revIndex = new (cp.getHeap()) IlcRevInt(cp);
revIndex->setValue(cp,0);
return MycGoodGenerate(cp,cp.getIntVarArray(x),revIndex);
}