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