3

晚上好,我有一个简单的问题,我警告你我对 prolog 很陌生。假设有三个相同大小的列表,每个列表只包含 1、0 或 -1。我想验证对于所有 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=maximum 值来调用它。但是 compat2 不起作用:在 ";" 之后给出 true,然后 无限期地运行。

谢谢!

4

2 回答 2

3

一些评论:混合library(clpfd)(is)/2大多不是一个好主意。您可以以几乎相同的效率(在 SWI 中)X #= Y + 1进行代替编写,但可以享受其增加的通用性。X is Y + 1

您感兴趣的关系涉及三个列表的第 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).
于 2011-08-22T18:12:29.550 回答
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.
于 2011-08-22T20:40:31.133 回答