10

假设我有以下理论:

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

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

c(a).

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

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

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

parent(david,michael).

当然,如果我查询noOrphan(michael),这将导致trueand noOrphan(david)in false(因为我没有为 定义父david级)。但是我想知道为什么没有主动方法来检测哪些人(michaeldavid,...)属于该noOrphan/1关系?

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

4

2 回答 2

8

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

因此,\+ \+ X = Y确实会产生一个空答案,而不是预期的X = Y. 有关更多信息,请参阅此答案

鉴于这种简单的查询已经显示出问题,您不能对像您这样的用户定义目标抱有太多期望。

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

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

如此有效,一般否定与纯 Prolog 程序配合得不是很好。Prolog 的核心确实是该语言的纯粹、单调的子集。不过,在 Prolog(或其各自的扩展)的约束部分内,否定可能会很好地工作。

于 2013-10-15T14:13:01.987 回答
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 知道这一点michael,并且所有其他人都是人。david您还需要明确说明orphannot_orphan仅适用于人的关系。您正在建模的世界也可能有:

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

你需要一种方法让这些人远离你的家庭事务。

我希望这会有所帮助。

于 2013-10-15T04:30:27.167 回答