:- lib(ic_global). :- use_module(library(ic_global)). |
Consider another example where three of the variables have domain 1..3. Clearly, if all the variables are to be different, then no other variable can take a value in the range 1..3, since each of those values must be assigned to one of the original three variables. Again, the standard alldifferent/1 constraint cannot determine this:?- L = [X1, X2, X3, X4, X5], L :: 1 .. 4, ic:alldifferent(L). X1 = X1{1 .. 4} X2 = X2{1 .. 4} X3 = X3{1 .. 4} X4 = X4{1 .. 4} X5 = X5{1 .. 4} L = [X1{1 .. 4}, X2{1 .. 4}, X3{1 .. 4}, X4{1 .. 4}, X5{1 .. 4}] There are 5 delayed goals. Yes
On the other hand, ic_global's alldifferent/1 constraint performs some stronger, more global reasoning, and for both of the above examples makes the appropriate inference:?- [X1, X2, X3] :: 1 .. 3, [X4, X5] :: 1 .. 5, ic:alldifferent([X1, X2, X3, X4, X5]). X1 = X1{1 .. 3} X2 = X2{1 .. 3} X3 = X3{1 .. 3} X4 = X4{1 .. 5} X5 = X5{1 .. 5} There are 5 delayed goals. Yes
Of course, there is a trade-off here: the stronger version of the constraint takes longer to perform its propagation. Which version is best depends on the nature of the problem being solved.?- L = [X1, X2, X3, X4, X5], L :: 1 .. 4, ic_global:alldifferent(L). No ?- [X1, X2, X3] :: 1 .. 3, [X4, X5] :: 1 .. 5, ic_global:alldifferent([X1, X2, X3, X4, X5]). X1 = X1{1 .. 3} X2 = X2{1 .. 3} X3 = X3{1 .. 3} X4 = X4{[4, 5]} X5 = X5{[4, 5]} There are 2 delayed goals. Yes