Mas*_*rah 35 prolog prolog-dif
我面临的问题有点微不足道.我想在Prolog中使用逻辑,但似乎not/1不是我想要的东西:
course(ai).
course(pl).
course(os).
have(X,Y) :- course(X),course(Y),not(X = Y).
Run Code Online (Sandbox Code Playgroud)
我查询:
have(X,Y), write(X-Y), nl , fail.
Run Code Online (Sandbox Code Playgroud)
我没有得到我想要的结果:(
fal*_*lse 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.
Run Code Online (Sandbox Code Playgroud)
所以到目前为止一切似乎都很好.但是,如果我们只是简单地交换两个目标的顺序呢?
?- \+ a = X, X = b.
false.
?- dif(a, X), X = b.
X = b.
Run Code Online (Sandbox Code Playgroud)
(\+)/1现在给我们一个不同的结果,因为有答案a = X,目标\+ a = X将失败.
(\+)/1因此,这不是否定,而是指在此时无法证明.
dif/2ISO Prolog 中也可以安全地进行近似.
Fre*_*Foo 14
在SWI-Prolog和GNU Prolog中,以下内容应该有效:
have(X, Y) :- course(X), course(Y), X \= Y.
Run Code Online (Sandbox Code Playgroud)
在SWI-Prolog中,您也可以使用dif/2,这可以更方便,因为您可以在谓词中使用它:
have(X, Y) :- dif(X, Y), course(X), course(Y).
Run Code Online (Sandbox Code Playgroud)
作为上述用户“假”答案的补充,即
“代替not(X = Y),您需要编写\ + X = Y,”
这可能给人的印象是:
一种。“ not”和“ \ +”是不同的东西
b。\ +将起作用,而不是,则不会。
我的理解是“ not”和“ \ +”是等效的,但是\ +在现代Prolog程序中是首选,因为它传达了一种更直观的感觉。具体而言,尽管“不”可能暗示粗心的编码器“不正确”,但“ \ +”却暗示“不可证明”,这与该操作实际上在说什么很接近。在Prolog中,“不是”是“否定即失败”的一个示例,但是可以感觉到\ +将使程序员更清楚在任何给定规则中确切地断言了什么。因此,您可以使用“ not”(大多数PL实现将其保留为向后兼容),但要成为惯用的现代PL程序员,您可能应该更喜欢使用\ +。
阅读 Samuel Kamin 的书第 8 章序言,我发现这个解决方案也适合这里,并解释了如何使用cut:
剪切是一种让程序员对计算进行额外控制的方法,允许他指出不允许回溯的地方。具体来说,剪切被写为感叹号 (!),作为子句右侧的目标出现,例如:
G :- H, !, R.
Run Code Online (Sandbox Code Playgroud)
假设选择该子句是为了满足与 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).
Run Code Online (Sandbox Code Playgroud)
not-equals(X, Y)如果 X 不等于 Y,则应成功;如果 X 不等于 Y,则失败;当尝试满足此目标时, X 和 Y 应绑定到基本表达式(即没有自由变量)。