void test()
{
Int a1, a2, a3;
Int b1, b2, b3;
(a1 == a2) || (a1 == a3) || (a2 == a3);
(b1 == b2) || (b1 == b3) || (b2 == b3);
// ...
}
You can rewrite this using your own constraint, just like you would with usual C++ code :
void at_least_two_equal(IntExpr & x, IntExpr & y, IntExpr & z)
{
(x == y) || (x == z) || (y == z);
}
void test()
{
Int a1, a2, a3;
Int b1, b2, b3;
at_least_two_equal(a1, a2, a3);
at_least_two_equal(b1, b2, b3);
// ...
}
However, the prefered way to design constraint functions is to make them return the whole constraint, so that you can combine them within more complex constraints :
BoolExpr & at_least_two_equal(IntExpr & x, IntExpr & y, IntExpr & z)
{
return (x == y) || (x == z) || (y == z);
}
void test()
{
Int a1, a2, a3;
Int b1, b2, b3;
at_least_two_equal(a1, a2, a3) && at_least_two_equal(b1, b2, b3);
// ...
}
void test() { { // Prints positive integers whose sum is less than or equal to 10. SInt<0, 10> a, b, c; c == a + b; cout << solutions(a, b, c); // using lexicographical order on (a, b, c) } { // Same as above except that the triplets are sorted first by the sum. SInt<0, 10> a, b, c; c == a + b; cout << solutions(c, a, b); // using lexicographical order on (c, a, b) } }
Finally, explicitly declaring a SolSet object lets you use the advanced function ISolSet::Search().use(). This function may be called to use some specific strategy for the choice of the variables to instanciate and their assigned values during the search. Most of these search strategies have an incidence on the order of the iterated solutions. For exemple :
void test() { { // Prints positive integers whose sum is less than or equal to 10. typedef SInt<0, 10> MyInt; SInt<0, 10> a, b, c; c == a + b; typedef SolSet<MyInt, MyInt, MyInt> Sols; Sols S(a, b, c); S.Search().use(choice::variable::static_order, choice::value::descending); cout << S; // using reverse lexicographical order on (a, b, c) } }
void test() { Int a, b, r; int i = 5; r < (a + 1) * i; // ok r < (a + 1) * b; // ko : not yet implemented... // ... }
There is a simple workaround though, that uses the special function easy::cp::verify :
bool is_product(int res, int a, int b) { return res == a * b; } void test() { Int a, b, r, aux; verify(mT(aux, (a + 1), b), is_product); // ok: aux == (a + 1)* b r < aux; // ... }
easy::cp::verify is an advanced feature that works as follows :
You first have to define a predicate function that works on VALUES (here : is_product).
Then, you can pass it to the verify function, together with a tuple of arguments for the predicate function.
Here, the call to verify constrains aux, (a + 1) and b to satisfy the predicat is_product,
whatever values they have.
Looking at is_product's definition, we finally get : aux == (a + 1)* b.