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

时间:2013-10-14 21:57:28

标签: prolog

说我有以下理论:

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

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

c(a).

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

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

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

parent(david,michael).

当然,如果我查询noOrphan(michael),这会在true中产生noOrphan(david)false(因为我没有为david定义父项但是,我想知道为什么没有主动的方法来检测哪些人(michaeldavid,...)属于noOrphan/1关系?

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

2 个答案:

答案 0 :(得分:5)

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

因此,\+ \+ X = Y确实产生一个空答案,而不是预期的X = YSee this answer for more

鉴于此类简单查询已经显示出问题,您不能指望用户定义的目标过多,例如您的目标。

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

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

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

答案 1 :(得分:3)

我可能误解了这个问题,我不明白最后一段。

无论如何,有一种完全有效的方法可以检测哪些不是孤儿。在您的示例中,您忘记告诉计算机您知道的事情,即:

person(michael).
person(david).
% and a few more
person(anna).
person(emilia).

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

parent(david, michael).
parent(anna, david).

?- orphan(X).
X = anna ;
X = emilia.

?- not_orphan(X).
X = michael ;
X = david ;
false.

我不知道你究竟想要如何定义一个“孤儿”,因为这个定义肯定有点奇怪,但这不是重点。

总之:除非您明确说明,否则您不能指望Prolog知道michaeldavid以及所有其他人都是人。您还需要明确声明orphannot_orphan是仅适用于人员的关系。您正在建模的世界也可以:

furniture(red_sofa).
furniture(kitchen_table).
abstract_concept(love).
emotion(disbelief).

你需要一种方法让那些不在家庭事务中。

我希望有所帮助。