Example of a propagator
An example of a propagator is provided for illustrative purposes.
While the example in the previous section illustrates the mechanics of writing a propagator, the example is not realistic. As a more realistic example of a propagator, consider the case in which the model contains an array of decision variables and a decision variable that needs to be constrained to take the value of the index of any element that has been assigned a value that is the minimal value of the elements in the array. First, the propagator must be informed of the array of decision variables and the decision variable that is constrained to be an appropriate index of the array. Thus the constructor is:
ArgMinI::ArgMinI(IloIntVar y, IloIntVarArray x) :
IloPropagatorI(y.getEnv()), _y(y), _x(x) {
addVar(y);
for (IloInt i=0; i< x.getSize(); i++)
addVar(x[i]);
}
The execute
method of the
propagator first ensures that the domain of the decision variable
representing the index is within the range of indices of the array.
The method then examines the decision variables in the array and determines
the minimal upper bound of the domains of all the elements of the
array. It also determines, for those elements whose indices are in
the domain of _y
, the minimal value of
the currently possible values, called the minimal active lower bound.
If there is any decision variable in the array whose
domain is strictly greater than the calculated minimal upper bound,
then it cannot be an element that takes the minimal value in the array.
In this case, the value of the index is removed from the domain of
the decision variable _y
.
Then, if there is an index that is not in the domain
of the decision variable _y
, the decision
variable at that index cannot take values smaller than the minimal
active lower bound, and the minimum of the domain of that variable
is set to the minimal active lower bound.
Putting together the pieces, the execute
method
is:
void ArgMinI::execute() {
IloInt i;
setRange(_y, 0, _x.getSize()-1);
IloInt minUpperBound = IloIntMax;
IloInt minActiveLowerBound = IloIntMax;
for (i = 0; i < _x.getSize(); i++) {
if (minUpperBound > getMax(_x[i]))
minUpperBound = getMax(_x[i]);
if (isInDomain(_y, i) && minActiveLowerBound > getMin(_x[i]))
minActiveLowerBound = getMin(_x[i]);
}
for (i = 0; i < _x.getSize(); i++)
if (minUpperBound < getMin(_x[i]))
removeValue(_y,i);
for (i=0; i < _x.getSize(); i++)
if (!isInDomain(_y, i))
setMin(_x[i],minActiveLowerBound);
}