说我有以下理论:
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
定义父项但是,我想知道为什么没有主动的方法来检测哪些人(michael
,david
,...)属于noOrphan/1
关系?
这可能是Prolog的回溯机制的结果,但是Prolog可以维持一个状态,该状态验证一个人是否以积极方式(0,2,4,...)否定深度或负面方式( 1,3,5,...)否定深刻。
答案 0 :(得分:5)
让我们从更简单的事情开始吧。说\+ X = Y
。这里,否定的目标是预定义的内置谓词。所以事情更清楚:X
和Y
应该是不同的。但是,\+ X = Y
失败,因为X = Y
成功。因此,目标失败的精确条件下不会留下痕迹。
因此,\+ \+ X = Y
确实产生一个空答案,而不是预期的X = Y
。 See 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知道michael
和david
以及所有其他人都是人。您还需要明确声明orphan
或not_orphan
是仅适用于人员的关系。您正在建模的世界也可以:
furniture(red_sofa).
furniture(kitchen_table).
abstract_concept(love).
emotion(disbelief).
你需要一种方法让那些不在家庭事务中。
我希望有所帮助。