如何在PROLOG中正确定义否定事实?解决not(person(table))无效问题
嘿,刚接触Prolog的朋友确实容易在否定事实这里绕晕,我来给你掰扯清楚~
首先得明白Prolog的核心逻辑:它是基于闭世界假设的——简单说就是「Prolog不知道的事实,默认就是假的」。所以如果你的知识库只写了:
person(anna).
那你查询person(table).的时候,Prolog会返回false,这其实已经隐含了「桌子不是人」的结论,根本不用额外写否定事实。
那为什么你直接写not(person(table))没用呢?因为Prolog里的not/1(或者标准写法\+/1)是否定失败(Negation as Failure),它不是用来声明事实的,而是用来在查询时判断「某个目标无法被证明」。你把它当成事实写进去,Prolog会把not(person(table))当成一个独立的原子事实,完全不是你想要的“否定person(table)”的意思。
接下来给你两种正确的处理方式:
1. 利用闭世界假设(最常用)
这是Prolog的常规用法:只声明所有肯定的事实,否定的事实靠“无法证明即为假”来推导。
比如你的知识库:
person(anna). person(bob).
当你需要判断“桌子是不是人”时,直接用否定失败查询:
% 查询:桌子不是人吗? \+ person(table). % 返回 true
(注:很多Prolog方言里not是\+的别名,所以not(person(table))在查询时是有效的,但不能把它作为事实写进知识库)
2. 显式定义否定谓词(特殊场景用)
如果你的业务逻辑需要一个明确的“不是人”的谓词,可以自己定义:
person(anna). person(bob). % 定义not_person谓词:当X不是person时成立 not_person(X) :- \+ person(X).
之后查询not_person(table).就会返回true,完全符合你的需求。
如果是某些特定对象需要特别声明“不是人”(比如闭世界假设不适用的场景),也可以直接写事实:
not_person(table). not_person(chair).
但这种情况很少见,因为闭世界假设已经能覆盖绝大多数场景了。
最后再强调一下:Prolog里的否定不是逻辑上的“绝对否定”,而是“当前知识库无法证明这个事实为真,所以暂时认为它是假的”——这一点一定要和传统逻辑区分开哦~
内容的提问来源于stack exchange,提问作者Matthias Neubert

