我面临的问题有点微不足道。
我想在Prolog中使用逻辑,但似乎not/1
不是我想要的东西:
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X),course(Y),not(X = Y).
我查询:
have(X,Y), write(X-Y), nl , fail.
我没有得到我想要的结果:(
答案 0 :(得分:36)
代替not(X = Y)
,您需要撰写\+ X = Y
或X \= Y
。但请考虑使用dif(X,Y)
代替。 dif/2
存在于B,SWI,YAP,SICStus中。要看到差异:
?- X = b, dif(a, X).
X = b.
?- X = b, \+ a = X.
X = b.
所以到目前为止一切似乎都很好。但是,如果我们简单的话 交换两个目标的顺序?
?- \+ a = X, X = b.
false.
?- dif(a, X), X = b.
X = b.
(\+)/1
现在给出了不同的结果,因为有答案
对于a = X
,目标\+ a = X
将失败。
(\+)/1
因此不是否定,但意味着此时无法证明
及时。
dif/2
{{1}}。
答案 1 :(得分:14)
在SWI-Prolog和GNU Prolog中,以下内容应该有效:
have(X, Y) :- course(X), course(Y), X \= Y.
在SWI-Prolog中,你也可以使用dif/2
,这可以更方便,因为你可以在谓词的早期使用它:
have(X, Y) :- dif(X, Y), course(X), course(Y).
答案 2 :(得分:5)
作为上述用户“false”的答案的附件,即
“代替不(X = Y)你需要写\ + X = Y,”
这可能会给人以下印象:
一个。 “不”和“\ +”是不同的东西
湾\ +将起作用,而不会,错误,不是。
我的理解是“不”和“\ +”是等价的,但是\ +在现代Prolog程序中是首选,因为它传达的感觉更直观。具体来说,虽然“不”可能暗示对于那些粗心的编码人员来说“不是真的”,但“\ +”表示“不可证明”,这更接近于该行动真正所说的真相。在Prolog中,“not”是“否定为失败”的一个例子,但是感觉\ +会使程序员更清楚地知道在任何给定规则中确切地断言了什么。所以你可以使用“not”(大多数PL实现保持它的向后兼容性)但是作为一个惯用的现代PL程序员,你可能更喜欢使用\ +。
答案 3 :(得分:2)
在第8章prolog上阅读Samuel Kamin的book,我发现这个解决方案也适用于此并解释了如何使用cut
:
剪切是一种通过允许程序员指示回溯不允许的位置来给程序员额外控制计算的方法。具体来说,剪辑被写为感叹号(!),作为条款右侧的目标,例如:
G :- H, !, R.
假设选择此子句是为了满足G unifies的目标 g 。试图满足H.如果成功,R被证明。 如果R证明成功,则证明g ;在这种情况下,剪辑没有任何作用。 然而,如果R的证据失败,而不是回溯并尝试重新证明H,切割的存在会导致目标g立即失败;即使存在可能适用于g的其他条款,也会发生这种情况。一个例子是 not-equals :
的定义
equals(X, X).
not-equals(X, Y) :- equals(X, Y), !, fail.
not-equals(X, Y).
如果X不等于Y,则 not-equals(X, Y)
应该成功,如果不是则失败;在尝试满足此目标时,X和Y应绑定到ground expressions(即没有自由变量)。
答案 4 :(得分:1)
就像你说的,OP,这是微不足道的。
尝试
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X), course(Y), X \== Y).
那应该修复你的谓词。
向前迈出一步,数学上是短语,你可能正在寻找解决方案(n C 2)而不是(n P 2)你的谓词目前提供 - 组合而不是排列,选择的选择,而不是选择的选择安排。这就是我的想法。
如果这是你想要的,我建议你试试
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X), course(Y), X @< Y).
这可以防止重复的反转结果。
@<
意味着原子地小于。 <
用于整数,@<
用于原子。