我面临的问题有点微不足道。我想在 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.
而且我没有得到我想要的结果:(
我面临的问题有点微不足道。我想在 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.
而且我没有得到我想要的结果:(
代替not(X = Y)
你需要写\+ X = Y
or 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
因此不是否定的,而是意味着在这个时间点上不可证明。
在 ISO Prolog中dif/2
也可以安全地近似。
在 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).
作为上述用户“false”的答案的补充,即
"代替 not(X = Y) 你需要写 \+ X = Y,"
这可能给人的印象是:
一个。"not" 和 "\+" 是不同的东西
湾。\+ 会起作用,而 not 会,错误,不会。
我的理解是“not”和“\+”是等价的,但是在现代Prolog程序中首选\+,因为它传达了一种更直观的感觉。具体来说,虽然“不”可能对粗心的编码人员表示“不正确”,但“\+”表示“不可证明”,这更接近于该操作的真实含义。在 Prolog 中,“not”是“negation as failure”的一个例子,但感觉 \+ 将使程序员更清楚地知道在任何给定规则中断言的确切内容。因此,您可以使用“不”(大多数 PL 实现保留它是为了向后兼容),但要成为惯用的现代 PL 程序员,您可能应该更喜欢使用 \+。
阅读 Samuel Kamin 关于第 8 章序言的书,我发现这个解决方案也适合这里,并解释了如何使用cut
:
剪切是一种让程序员额外控制计算的方法,允许他指出不允许回溯的地方。具体来说,cut 被写成一个感叹号 (!),作为一个目标出现在一个子句的右侧,例如:
G :- H, !, R.
假设选择这个子句是为了满足与 G统一的目标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).
not-equals(X, Y)
如果 X 不等于 Y 则应该成功,如果是则失败;当试图满足这个目标时, X 和 Y 应该绑定到基本表达式(即没有自由变量)。
就像你说的,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).
这将防止重复的反向结果。
@<
意味着原子地小于。<
是整数,@<
是原子。