为什么双重否定在Prolog中没有约束力

Wil*_*sem 8 prolog

说我有以下理论:

a(X) :- \+ b(X).

b(X) :- \+ c(X).

c(a).
Run Code Online (Sandbox Code Playgroud)

它只是说真的,这当然是正确的,a(X)因为没有b(X)(因为有限的失败否定).因为只有一个b(X)如果没有c(X),我们就有c(a),可以说这是真的.我想知道为什么Prolog没有提供答案X = a?比如说我介绍一些语义:

noOrphan(X) :- \+ orphan(X).

orphan(X) :- \+ parent(_,X).

parent(david,michael).
Run Code Online (Sandbox Code Playgroud)

当然,如果我查询noOrphan(michael),这将导致truenoOrphan(david)false(因为我没有定义父david),但我不知道为什么会有的检测没有积极主动地哪些人(michael,david,...)属于noOrphan/1关系?

这可能是Prolog的回溯机制的结果,但是Prolog可以维持一个状态,该状态验证一个人是否以积极方式(0,2,4,...)否定深度或负面方式(1,3) ,5,...)否定深刻.

fal*_*lse 5

让我们从更简单的事情开始吧.说\+ X = Y.这里,否定的目标是预定义的内置谓词.因此,事情更清楚:XY应有所不同.然而,\+ X = Y失败,因为X = Y成功.因此,没有任何痕迹留在目标失败的精确条件下.

因此,\+ \+ X = Y确实产生一个空的答案,而不是预期的答案X = Y.看到这个答案更多.

鉴于这些简单的查询已经显示出问题,您不能期望过多的用户定义目标,例如您的目标.

在一般情况下,您必须首先重新考虑否定的实际含义.答案比初看起来要复杂得多.想想该计划p :- \+ p.应该p成功还是失败?应该p是真的吗?实际上有两种模型不再符合Prolog关于使用最小模型的观点.这些考虑为逻辑编程开辟了新的分支,如答案集编程(ASP).

但是,让我们坚持Prolog.否定只能在非常有限的上下文中使用,例如当目标被充分实例化并且定义被分层时.不幸的是,没有普遍接受的安全执行否定目标的标准.我们可以等到目标变量自由(地面),但这通常意味着我们必须等待太长时间 - 用行话:否定的目标比目鱼.

如此有效,一般否定与纯Prolog程序并不完美.Prolog的核心确实是该语言的纯粹,单调的子集.然而,在Prolog(或其各自的扩展)的约束部分中,否定可能会很好地起作用.