Overview | Group | Tree | Graph | Index | Concepts |
The mechanism used by IBM ILOG Solver to handle soft constraints |
Example |
A soft constraint is a constraint which can be violated. IBM® ILOG Solver provides the user with a mechanism which is able to deal with such constraints.
Suppose you would like the constraint ct
to be a soft constraint.
In other words, the constraint ct
could be violated without triggering a general failure.
IBM ILOG Solver defines a mechanism that gives you all the modifications that could happen in ct
if it was defined as a hard constraint.
Soft constraints are implemented by a copy mechanism.
Thus, if the soft constraint is violated, no general failure is triggered, and if some variables of the soft constraint are modified then the consequences of these modifications are not studied because it is acceptable to violate the constraint ct
.
Here is a more precise description of this copy mechanism:
ct
is defined are copied. These variables are called the copied variables of ct
. The variables from which the copies are made are called the original variables.ct
is defined on the copied variables of ct
. This constraint is called the soft constraint of ct
, and ct
is called the original constraintct
is modified the corresponding copied variable of ct
is accordingly modified.It is also possible to link demons to the soft constraint. There are two types of demons:
In addition a soft constraint is linked to a specific variable called the status
variable. This variable is a 0-1 integer variable, which takes the value 1 if the soft constraint must be satisfied and the value 0 if the soft constraint must be violated.
Soft constraints are managed using the class IlcSoftConstraint
This section presents a simple example of use of the soft constraints new functionality.
This example solve a problem of minimization of the number of violated constraints A set of constraint is considered and a new constraint is defined. This new constraint (IlcManageSoftCtI in the code) creates as many soft constraint as the array of constraint contains elements and use a variable which counts the number of violated constraints (variable _obj in the code). This variable is linked to the violated constraints thanks to a demon. Each time a constraint is violated this demon is called, and it increments the counter of violation.
/* Here is a simple example using soft constraints */ #include <ilsolver/ilosolverint.h> #include <ilsolver/disjunct.h> ILOSTLBEGIN class IlcManageSoftCtI : public IlcConstraintI { IlcConstraintArray _cons; IlcRevInt _numFails; IlcIntVar _obj; IlcSoftCtHandler _sh; public: IlcManageSoftCtI(IlcConstraintArray cons, IlcIntVar obj): IlcConstraintI(cons.getManager()), _cons(cons), _obj(obj), _sh(cons.getManager(),100){} void post(); void propagate(); void softCtFailDemon(const IlcInt softCtIndex); void softCtVarDemon(const IlcInt softCtIndex); }; ILCCTDEMON1(mySoftCtVarDemon,IlcManageSoftCtI,softCtVarDemon, IlcInt,i); ILCCTDEMON1(mySoftCtFailDemon,IlcManageSoftCtI,softCtFailDemon, IlcInt, i); void IlcManageSoftCtI::softCtFailDemon(const IlcInt softCtIndex){ // this demon is called when the soft constraint of index softCtIndex is violated // the number of fails is incremented, that is // the variable _obj, counting the number of violations, is incremented // any other action could be done here getManager().out() << "constraint: " << _cons[softCtIndex]; getManager().out() << "is violated" << endl; _numFails.setValue(getManager(),_numFails.getValue() +1); _obj.setMin(_numFails.getValue()); } void IlcManageSoftCtI::softCtVarDemon(const IlcInt softCtIndex){ // this function is called each time a variable involved in the soft constraint is modified IlcSoftConstraint softCt=_sh.getSoftConstraint(softCtIndex); const IlcInt cvar=softCt.getCopiedVarInProcess(); getManager().out() << "the copied variable of the variable: "; getManager().out() << _sh.getVar(_sh.getVarOfCopiedVar(cvar)); getManager().out() << " of the constraint: " << _cons[softCtIndex]; getManager().out() << " has been modified" << endl; getManager().out() << "the copied variable is: "; getManager().out() << _sh.getCopiedVar(cvar) << endl; } void IlcManageSoftCtI::post(){ } void IlcManageSoftCtI::propagate(){ // for each constraint in array _cons, a corresponding soft constraint is defined // and the demons are linked to the possible modifications const IlcInt numCt=_cons.getSize(); for(IlcInt i=0;i<numCt;i++){ // creation of the soft constraint IlcSoftConstraint softCt=_sh.createSoftConstraint(_cons[i]); // addition of demons softCt.whenFail(mySoftCtFailDemon(getManager(),this,i)); softCt.whenDomainReduction(mySoftCtVarDemon(getManager(),this,i)); // addition of the soft constraint add(softCt); } _sh.getImpl()->printCvars(); _sh.getImpl()->printSoftCts(); _sh.getImpl()->printVars(); } IlcConstraint IlcManageSoftCt(IlcConstraintArray cons,IlcIntVar obj){ return new (cons.getManager().getHeap()) IlcManageSoftCtI(cons,obj); } ILOCPCONSTRAINTWRAPPER2(IloManageSoftCt, solver, IloConstraintArray, _cons, IloIntVar, _obj){ use(solver, _cons); use(solver, _obj); return IlcManageSoftCt(solver.getConstraintArray(_cons), solver.getIntVar(_obj)); } int main(int argc, char** argv) { IloEnv env; try { IloModel model(env); // 3 variables are defined IloIntVarArray vars(env,3,0,1); vars[0].setName("x0"); vars[1].setName("x1"); vars[2].setName("x2"); // 3 constraints are defined IloConstraintArray cons(env,3); cons[0] = (vars[0]!=vars[1]); cons[1] = (vars[0]!=vars[2]); cons[2] = (vars[1]!=vars[2]); // an objective is defined IloIntVar obj(env,0,3); // in order to define these constraints as soft constraints a new constraint is defined // this constraint creates a soft constraint for each constraint of cons array // on the other hand, this constraint ensures that the objective corresponds to the number of // constraints that are violated model.add(IloManageSoftCt(env, cons, obj)); // we search for a solution minimizing the number of violations model.add(IloMinimize(env, obj)); IloSolver solver(model); solver.startNewSearch(IloGenerate(env,vars)); while(solver.next()){ solver.out() << "obj = " << solver.getIntVar(obj) << endl << solver.getIntVarArray(vars) << endl << endl; } solver.endSearch(); } catch (IloException& ex) { cout << "Error: " << ex << endl; } env.end(); return 0; }