I need to create a predicate:
applyConstraints(L)
That applies constraints to the variables in L such that no two contiguous elements in L are both odd or even how can I do that? With a fixed size L it's simple but what about a variable size L? I need that to be done using sicstus-prolog clpfd library.
Inspired by @MatsCarlsson's version, I tried to minimize the number of constrained variables involved:
applyConstraints(Xs) :-
S #\= R,
applyConstraints(Xs, S, R).
applyConstraints([], _, _).
applyConstraints([X|Xs], S, R) :-
X mod 2 #= S,
applyConstraints(Xs, R, S).
Edit: This version has one flaw for the goal applyConstraints([])
which is not readily visible. In fact, one needs to switch to full_answer
mode in SICStus like so:
| ?- applyConstraints([]).
yes
| ?- assertz(clpfd:full_answer).
yes
| ?- applyConstraints([]).
clpfd:(_A#\=_B),
_A in inf..sup,
_B in inf..sup ? ;
no
So we have this useless constraint hanging around which might eat up resources. To overcome this deficiency, some special casing is needed:
applyConstraints([]).
applyConstraints([X|Xs]) :-
X mod 2 #= S,
S #\= R,
applyConstraints(Xs, R, S).
Note 1 — in SWI or YAP there is no direct way to switch full answer mode on. The only way to get hold of the problem is to wrap the query around call_residue_vars/2
like so:
?- applyConstraints([]).
true.
?- call_residue_vars(applyConstraints([]),RVs).
RVs = [_G794, _G797],
_G794#\=_G797.
Note 2 — Thanks to @mat, there is similar functionality since SWI 7.3 (remember that SWI 7 needs --traditional
for compatibility):
?- set_prolog_flag(toplevel_residue_vars, true).
true.
?- applyConstraints([]).
% with detached residual goals
_G430#\=_G433.
(It is not quite clear what "detached" should mean in this context, after all, the residual goals have to be true, to make the answer true. So there is no detachement involved.)