为什么这个prolog查询既真实又错误?

del*_*del 30 prolog swi-prolog prolog-toplevel

我的SWI-Prolog知识库包含以下两个事实:

f(a,b).
f(a,c).
Run Code Online (Sandbox Code Playgroud)

现在,如果我提出查询

?- f(a,c).
true.
Run Code Online (Sandbox Code Playgroud)

?- f(a,b).
true ;
false.
Run Code Online (Sandbox Code Playgroud)

为什么f(a,b)既真又假?当KB中有三个事实时,也会发生这种情况.如果我追加f(a,d).到KB,然后f(a,d)为真(仅),但f(a,b)和f(a,c)都是真和假.发生了什么,我能做些什么让Prolog回答(仅)回答这些问题?

Mic*_*son 27

(注意:这个答案有点猜)

考虑Prolog如何判断是否f(a,c)真实.它会检查第一个规则,f(a,b)但找不到匹配项,但第二个规则f(a,c)匹配.因此,f(a,c)是真的.此外,由于没有更多的规则f,没有必要允许回溯发生 - 没有其他可能的解决方案.

现在考虑f(a,b).Prolog将检查第一条规则,并找到匹配项.因此,f(a,b)是真的.但是,并非所有规则都已用尽.因此,Prolog将允许搜索继续(如果你点击;).当您继续搜索并回溯时,它会发现其余规则,特别f(a,c)是不匹配f(a,b).因此,结果是错误的.

  • 这个答案是对的.在Prolog中,编写规则的事实的顺序决定了查询将找到它们的顺序.更具体地说,'回溯'选项";" 本质上告诉强制查询引擎丢弃返回的结果并回答"是否有*其他*答案?"的问题.所以,并不是f(a,b)既是真的又是假的; 但它确实如此,如果您选择忽略该结果,引擎将告诉您没有其他f(a,b)事实条目.为了证明这一点,请观察如果添加第二个f(a,b)事实会发生什么. (12认同)
  • 这也说明了如果您关注性能,应该注意参数的顺序.如果谓词`f`中的参数的顺序被翻转,那么这不会发生,因为初始参数不再相同,所以不要留下选择点.这是因为大多数prolog执行参数索引,这允许预先从搜索空间中删除具有不兼容参数的谓词.SWI Prolog默认只对第一个参数编制索引,但可以更改. (4认同)

Kaa*_*rel 13

除了迈克尔威廉姆森的回答.如果你想告诉Prolog在第一次成功点击后停止寻找答案,那么使用cut(!):

?- f(a, b), !.
true.

?- f(a, c), !.
true.
Run Code Online (Sandbox Code Playgroud)