假设我们有以下计划:
a(tom).
v(pat).
和查询(返回false):
\+ a(X), v(X).
在跟踪时,我可以看到X被实例化为tom,谓词a(tom)成功,因此+ a(tom)失败。
我在一些教程中已经读过Prolog中的not(+)只是一个测试,并没有导致实例化。
有人可以请我澄清以上几点吗?我可以看到实例化。
我知道not(否定为失败)和逻辑否定之间存在差异。你能否提一篇好文章来解释他们在哪些情况下表现相同以及他们什么时候表现不同?
答案 0 :(得分:3)
好问题。
简短的回答:你偶然发现了“挣扎”。
问题是运算符\ +的实现只能起作用 当应用于不包含变量的文字时,即地面 文字。它无法为变量生成绑定,只能生成绑定 测试子目标是成功还是失败。所以要保证合理 对包含否定,否定的程序的查询的答案 必须允许运算符仅应用于地面文字。如果是 应用于非文字,该程序据说比目鱼。 link
如果您反转查询
v(X), \+ a(X).
你会得到正确的答案。一些实现或元解释器检测挣扎的目标并将它们延迟,直到所有变量都被接地为止。
关于您的观点1),您可以看到NAF树中的实例化。那里发生的事情不应该影响外部的变量(在这种情况下是在v(X)中)。 Prolog经常以天真的方式行事,以避免效率低下。理论上它应该只返回错误而不是实例化变量。
2)这是我最喜欢的关于这个主题的文章:Nonmonotonic Logic Programming。
答案 1 :(得分:2)
WRT第2点,Wikipedia article似乎是一个很好的起点。
您已经体验过对NAF的理解可能很困难。部分原因可能是因为(逻辑)否定,即使在简单的谓词演算中也很难定义(例如参见Russel's paradox),部分原因在于Prolog的强大变量是为了保持实际的反例<如果否定证明,则em>失败。看看你是否能理解forall / 2的实际库定义(请阅读文档,它是合成的和有趣的),这是运行故障驱动循环的首选方法:
%% forall(+Condition, +Action)
%
% True if Action if true for all variable bindings for which Condition
% if true.
forall(Cond, Action) :-
\+ (Cond, \+ Action).
我记得第一次看到它时,它看起来像魔术......
我找到了编辑有关教程的内容,同时'偷看'我的链接集合,是J.R.Fisher的一个好site。它充满了有趣的东西,可惜它在解释中有点简洁,要求学生用频繁的执行来回答自己。参见paragraph 2.5,致力于失败的否定。我想你也可以享受第3节Prolog如何工作