Prolog Constraint Programing finding even and odd numbers

拟墨画扇 提交于 2020-01-02 15:24:06

问题


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.


回答1:


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




回答2:


% 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



回答3:


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


来源:https://stackoverflow.com/questions/21584521/prolog-constraint-programing-finding-even-and-odd-numbers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!