Prolog:迭代

时间:2011-08-22 17:38:53

标签: lambda prolog constraint-programming clpfd

晚上好, 我有一个简单的问题,我警告你,我对prolog很新。 假设有三个相同大小的列表,每个列表只包含1s,0s或-1s。 我想验证对于所有i,三个列表中的第i个元素,只有一个是非零的。

此代码适用于固定的i:

:- use_module(library(clpfd)).

compat1(V1,V2,V3,I) :-
    length(V1,G),
    nth1(I,V1,X),
    nth1(I,V2,Y),
    nth1(I,V3,Z),
    W is X*X+Y*Y+Z*Z,
    W is 1,
    I in 1..G.

我怎么能告诉“为了所有我,compat1(V1,V2,V3,I)”? 我试着定义

compat2(V1,V2,V3,1) :- compat1(V1,V2,V3,1).
compat2(V1,V2,V3,K) :- compat2(V1,V2,V3,J), compat1(V1,V2,V3,K), K is J+1.

所以我可以用K =我感兴趣的最大值来调用它。 但compat2不起作用:然后,在“;”之后给出true无限期地运行。

谢谢!

2 个答案:

答案 0 :(得分:3)

一些评论:混合library(clpfd)(is)/2大多不是一个好主意。你可以用X #= Y + 1来代替X is Y + 1,效率几乎相同(在SWI中),但享受它的普遍性。

您感兴趣的关系涉及三个列表的第i个元素。也就是说,我们可以写:maplist(r, Xs, Ys, Zs)其中r/3是您感兴趣的关系。所以我们必须定义r(X,Y,Z)

abs(X)+abs(Y)+abs(Z) #= 1怎么样?

使用library(lambda),您可以将其全部放在一行中:

maplist(\X^Y^Z^(abs(X)+abs(Y)+abs(Z) #= 1), Xs, Ys, Zs).

答案 1 :(得分:0)

你可以通过一个简单的递归来做到这一点。该程序仅测试输入,不能用于生成解决方案。如果您需要,您必须说明事实中允许哪些值,例如添加onlyOne(0,0,1). onlyOne(0,0,-1).

onlyOne(0,0,_).
onlyOne(0,_,0).
onlyOne(_,0,0).
onlyOne([],[],[]).
onlyOne([H1|T1],[H2|T2],[H3|T3]) :- onlyOne(H1,H2,H3), onlyOne(T1,T2,T3).

编辑:重新阅读问题我猜你需要一个条目非零,而不是最多一个。在这种情况下,您需要这些规则而不是事实:

onlyOne(0,0,X) :- X \= 0.
onlyOne(0,X,0) :- X \= 0.
onlyOne(X,0,0) :- X \= 0.