为什么这个Prolog查询既是真的又是假的?

31

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

f(a,b).
f(a,c).

现在,如果我提出以下查询:

?- f(a,c).
true.
但是。
?- f(a,b).
true ;
false.
为什么f(a,b)既为真又为假?当知识库里有三个事实时也会发生这种情况。如果我将f(a,d)添加到知识库中,则只有f(a,d)为真,但f(a,b)和f(a,c)既为真又为假。发生了什么,我该怎么做才能让Prolog对这些查询只回答真呢?
2个回答

31

(注意:本答案可能只是猜测)

考虑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)不匹配。因此,结果为假。


13
这个答案是正确的。在Prolog中,事实和规则的书写顺序决定了查询时它们被找到的顺序。更具体地说,“回溯”选项“;”强制查询引擎放弃返回的结果,并回答“是否有任何其他答案?”的问题。因此,f(a,b)既不是真又不是假;而是真的,如果您选择忽略该结果,引擎会告诉您没有其他的f(a,b)事实条目。要证明这一点,请看看如果添加第二个f(a,b)事实会发生什么。 - Assaf
4
这也说明了为什么如果你关心性能,就应该注意你参数的顺序。如果谓词f中参数的顺序被颠倒,那么这种情况就不会发生,因为初始参数不再相同,所以不会留下选择点。这是因为大多数Prolog都执行参数索引,可以提前从搜索空间中修剪具有不兼容参数的谓词。SWI Prolog默认只对第一个参数进行索引,但这可以改变。 - nedned

14

除了Michael Williamson的回答之外,还有一个补充。如果你想让Prolog在找到第一个成功的匹配项后停止寻找答案,那么可以使用cut()。

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接