Prolog 否定和逻辑否定
Posted
技术标签:
【中文标题】Prolog 否定和逻辑否定【英文标题】:Prolog negation and logical negation 【发布时间】:2013-01-20 19:47:45 【问题描述】:假设我们有以下程序:
a(tom).
v(pat).
和查询(返回 false):
\+ a(X), v(X).
跟踪时,我可以看到X
被实例化为tom
,谓词a(tom)
成功,因此\+ a(tom)
失败。
我在一些教程中读到,Prolog 中的 not (\+
) 只是一个测试,不会导致实例化。
有人可以为我澄清上述观点吗?我可以看到实例化。
我了解非(否定为失败)和逻辑否定之间存在差异。您能否参考一篇好文章来解释它们在哪些情况下表现相同以及它们何时表现不同?
【问题讨论】:
【参考方案1】:很好的问题。
简短的回答:你偶然发现了“挣扎”。
问题是操作符 \+ 的实现只能工作 当应用于不包含变量的文字时,即接地 文字。它不能为变量生成绑定,但只能 测试子目标是成功还是失败。所以要保证合理 对包含否定的程序的查询的答案,否定 必须允许运算符仅适用于地面文字。如果是 应用于非地面文字,该程序被称为挣扎。 link
如果你反转查询
v(X), \+ a(X).
你会得到正确的答案。一些实现或元解释器检测到挣扎的目标并延迟它们,直到所有变量都被接地。
关于您的第 1 点),您会看到 NAF 树内的实例化。那里发生的事情不应该影响外部变量(在本例中为 v(X))。 Prolog 经常以幼稚的方式行事,以避免效率低下。理论上它应该只返回一个错误而不是实例化变量。
2) 这是我最喜欢的关于该主题的文章:Nonmonotonic Logic Programming。
【讨论】:
你是怎么理解的?据我了解,这仅仅意味着像safenot(G) :- when(ground(G), \+ G).
这样的协同目标是答案的一部分。但你似乎有不同的概念。
第二点:不要求接地,只要坚持在否定目标之外发生的变量的接地就足够了。即便如此,要求也太高了。
我不确定我是否理解您的问题。 safenot(G) :- when(ground(G), \+ G).
是为那些有解决方案的情况而苦苦挣扎的解决方案。而对于挣扎,我打算出现一个目标,因为 NAF 的 Prolog 概念导致一个不正确的答案。
§15, Lloyd87: ... flounders 如果在计算中的某个点达到了仅包含非地面否定文字的目标。因此\+a(X), v(X)
不会挣扎,但\+a(X)
会。
不确定正式定义,但您会发现诸如“对于给定的程序和目标,挣扎意味着选择非基本否定规则文字”之类的东西。 (ida.liu.se/~wlodr/DHM.alpsws07.paper.pdf)【参考方案2】:
WRT 第 2 点,Wikipedia article 似乎是一个很好的起点。
您已经体验到理解 NAF 可能很困难。部分原因可能是(逻辑)否定,即使在谓词演算的简单竞赛中也很难定义(例如参见Russel's paradox),部分原因是 Prolog 的强大变量是圆顶的,以保留 的实际反例如果否定证明失败。看看你是否能理解 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 的工作原理
【讨论】:
以上是关于Prolog 否定和逻辑否定的主要内容,如果未能解决你的问题,请参考以下文章
Prolog - 使用否定(声明方法)将member / 2定义为仅对每个数字成功一次