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