The constraint all_distinct(L) holds if variables in L are pair-wisely different. One naive way of implementing this constraint is to generate binary inequality constraints between all pairs of variables in L. This implementation has two problems: First, the space required to store the constraint is quadratic in the number of variables in L; second, splitting the constraint into small granularity ones may lead to the loss of possible propagation opportunities.
To solve the space problem, we define all_distinct(L) in the following way:
all_distinct(L):-all_distinct(L,[]). all_distinct([],Left). all_distinct([X|Right],Left):- outof(X,Left,Right), all_distinct(Right,[X|Left]). delay outof(X,Left,Right):- dvar(X) : {ins(X)}. outof(X,Left,Right):-true : outof(X,Left),outof(X,Right).For each variable X, let Left be the list of variables to the left of X and Right be the list of variables to the right of X. The predicate call outof(X,Left,Right) holds if X appears in neither Left nor Right. Instead of generating inequality constraints between X and all the variables in Left and Right, the call outof(X,Left,Right) delays until X is instantiated. After X becomes an integer, the calls outof(X,Left) and outof(X,Right) exclude X from the domains of the variables in Left and Right. It is not difficult to understand that this implementation only consumes linear space.
In terms of the propagation ability, the second implementation is the same as the first one. In some systems, consistency checks are done to detect failure as early as possible. It is very easy to introduce consistency checks into the implementation. To do so, we only need to define outof(X,Left,Right) as follows:
delay outof(X,Left,Right):- dvar(X) : {dom(X),min(X),max(X),ins(X)}, consistency_check(X,Left,Right). outof(X,Left,Right):-true : outof(X,Left),outof(X,Right).where consistency_check(X,Left,Right) does the consistency check. There are many possible algorithms. The one implemented in B-Prolog is as follows: Let
n =If![]()
m =![]()