IBM ILOG Solver User's Manual > Extending the Library > Writing a Constraint: Allocating Frequencies > Writing your own metaconstraint > Programming tips |
Programming tips |
INDEX
![]() |
This section describes some useful tips, collected from users of Solver.
Constraint programming is more efficient when it effectively reduces the variable domains as early as possible.
In order to reduce the domains of constrained variables as quickly as possible, you have to carry out all propagation. You do so by propagating constraints in every direction. While predefined constraints respect this rule, you have to exercise care when writing a new constraint to insure that your user-defined constraints respect this rule as well.
Another way of looking at this issue is to see that constraints are not directed, but must be seen as equations in the widest sense of the term. The final results of the search for a solution must be the same, regardless of the order in which constraints are posted, even user-defined constraints.
Let's consider the constraint x + y = z. The domain of z must be modified when the domain of x or of y is modified. At the same time, you must not forget that the domain of x must be modified when the domain of y or of z is modified. A similar rule applies for y as well. This is what is meant by propagating in all directions.
More generally, when designing a new constraint class, you must not overlook any direction of propagation.
Let's look again at our IlcDiff
example. Each time one of its variables is bound, isBound
is checked against the two variables. You can avoid these redundant tests by using intermediate demons, that is, by posting different demons on the different variables. You might think of demons as goals without subgoals, that is, goals which return the null pointer.
You add two member functions to the class IlcDiffConstraint
, each of them responsible for the propagation of the constraint on one variable when the other is bound. Here is the modification.
Now you need to define intermediate demons on variables that call the new member functions. You do that in this way.
ILCCTDEMONO(IlcDiffCst_xDemon,IlcDiffConstraint,xDemon); ILCCTDEMON0(IlcDiffCst_yDemon,IlcDiffConstraint,yDemon); |
Finally, you change the post
member function to take this modification into account, like this:
void IlcDiffConstraint::post(){ _x.whenValue(IlcDiffCst_xDemon(getSolver(),this)); _y.whenValue(IlcDiffCst_yDemon(getSolver(),this)); } |
This new version of the IlcDiffConstraint
is faster that the previous one since the isBound
tests in propagate
are avoided. The price to pay for this efficiency is the memory used by the two intermediate goals.
© Copyright IBM Corp. 1987, 2009. Legal terms. | PREVIOUS NEXT |