Prolog Constraint编程查找偶数和奇数

时间:2014-02-05 17:42:40

标签: prolog clpfd constraint-programming

我需要创建一个谓词:

applyConstraints(L)

这对L中的变量应用约束,使得L中没有两个连续元素都是奇数,甚至我怎么能这样做?固定尺寸L很简单,但可变尺寸L呢? 我需要使用sicstus-prolog clpfd库来完成。

3 个答案:

答案 0 :(得分:5)

% 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

答案 1 :(得分:2)

受@ MatsCarlsson版本的启发,我试图尽量减少所涉及的约束变量的数量:

applyConstraints(Xs) :-
   S #\= R,
   applyConstraints(Xs, S, R).

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

编辑:这个版本有一个目标applyConstraints([])的缺陷,不容易看到。实际上,需要在SICStus中切换到full_answer模式,如下所示:

| ?- applyConstraints([]).
yes
| ?- assertz(clpfd:full_answer).
yes
| ?- applyConstraints([]).
clpfd:(_A#\=_B),
_A in inf..sup,
_B in inf..sup ? ;
no

所以我们有这种无用的约束,可能会占用资源。 为克服这一缺陷,需要一些特殊的外壳:

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

注1 - 在 SWI或 YAP中,无法直接切换完整应答模式。解决问题的唯一方法是将查询包装在call_residue_vars/2中,如下所示:

?- applyConstraints([]).
true.

?- call_residue_vars(applyConstraints([]),RVs).
RVs = [_G794, _G797],
_G794#\=_G797.

注2 - 感谢@mat,自SWI 7.3以来有类似的功能(请记住,SWI 7需要--traditional才能兼容):

?- set_prolog_flag(toplevel_residue_vars, true).
true.

?- applyConstraints([]).
% with detached residual goals
_G430#\=_G433.

(目前尚不清楚“分离”在这种背景下应该是什么意思,毕竟残余目标 是真的,以使答案成立。所以没有涉及分离。 )

答案 2 :(得分:1)

只考虑一对元素

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

测试(使用SWI-Prolog库(clpfd),也许你需要用来自Sicstus的对应物替换ins / 2)

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