The most important part of this program is related to the strategy for choosing the values to give to the different variables. The strategy can be described informally as trying the most used frequency first. Consequently, you have to keep track of which frequencies are used. You manage this record-keeping in an array of IlcRevInt*
. (You used an array of IlcRevInt*
, instead of an array of IlcRevInt
because some C++ compilers are unable to initialize an array of objects.)
A demon is activated each time a variable is bound. In that case, you increment the number of times that the corresponding frequency is used.
IlcRevInt** freqUsage;
class IlcFreqConstraintI : public IlcConstraintI {
protected:
IlcIntVarArray _x;
public:
IlcFreqConstraintI(IloSolver s, IlcIntVarArray x)
: IlcConstraintI(s), _x(x) {}
~IlcFreqConstraintI() {}
virtual void post();
virtual void propagate() {}
void varDemon(IlcIntVar var);
};
ILCCTDEMON1(FreqDemon, IlcFreqConstraintI, varDemon, IlcIntVar, var);
void IlcFreqConstraintI::post () {
IlcInt i;
for (i = 0; i < _x.getSize(); i++)
_x[i].whenValue(FreqDemon(getSolver(), this, _x[i]));
}
void IlcFreqConstraintI::varDemon (IlcIntVar var) {
IlcRevInt& freq = *freqUsage[var.getValue()];
freq.setValue(getSolver(), freq.getValue() + 1);
}
IlcConstraint IlcFreqConstraint(IloSolver s, IlcIntVarArray x) {
return new (s.getHeap()) IlcFreqConstraintI(s, x);
}