FRAMES NO FRAMES

Addition of a soft constraint to the solver
PREVIOUS NEXT
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.

The mechanism used by IBM ILOG Solver to handle soft 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:

  • The variables on which the constraint 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.
  • A new constraint corresponding to the constraint ct is defined on the copied variables of ct. This constraint is called the soft constraint of ct, and ct is called the original constraint
  • Each time an original variable of ct is modified the corresponding copied variable of ct is accordingly modified.
  • If the soft constraint is violated no global fail is triggered.

It is also possible to link demons to the soft constraint. There are two types of demons:

  • Demons that are called when the soft constraint is violated
  • Demons that are called when a copied variable is modified

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.

Note
A soft constraint can be defined only for constraints that involve only IlcIntVar variables.

Soft constraints are managed using the class IlcSoftConstraint

Example

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