문제

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.

도움이 되었습니까?

해결책 2

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.)

다른 팁

% SICStus:

applyConstraints([]).
applyConstraints([X|Xs]) :-
    X mod 2 #= R,
    applyConstraints(Xs, R).

applyConstraints([], _).
applyConstraints([X|Xs], R) :-
    X mod 2 #= S,
    S #\= R,
    applyConstraints(Xs, S).

% Query:

| ?- applyConstraints(L), length(L,2), !, domain(L,-2,2), labeling([],L).
L = [-2,-1] ? ;
L = [-2,1] ? ;
L = [-1,-2] ? ;
L = [-1,0] ? ;
L = [-1,2] ? ;
L = [0,-1] ? ;
L = [0,1] ? ;
L = [1,-2] ? ;
L = [1,0] ? ;
L = [1,2] ? ;
L = [2,-1] ? ;
L = [2,1] ? ;
no

Just consider pair of elements

applyConstraints([A,B|R]) :-
    A mod 2 #\= B mod 2,
    applyConstraints([B|R]).
applyConstraints([_]).

test (using SWI-Prolog library(clpfd), maybe you will need to substitute ins/2 with the counterpart from Sicstus)

?- L=[X,Y,Z], applyConstraints(L), L ins 1..4, label(L).
L = [1, 2, 1],
X = Z, Z = 1,
Y = 2 ;
L = [1, 2, 3],
X = 1,
Y = 2,
Z = 3 ;
...
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top