Prolog编译器返回错误

Prolog编译器返回错误,prolog,logic,prolog-toplevel,transitive-closure,Prolog,Logic,Prolog Toplevel,Transitive Closure,我有一个假设的程序来检查从a点到B点的路径是否存在 /*city rules*/ edge(phx, tuc). edge(tuc, ccg). edge(ccg, sf). connected(C1, C2) :- edge(C1, C2). connected(C1, C2) :- edge(C1, X), connected(X, C2). 问题是它返回true,然后返回false。错误从何而来?让我们看看您从Prolog得到的确切答复!首先,您得到一个true,

我有一个假设的程序来检查从a点到B点的路径是否存在

/*city rules*/

edge(phx, tuc).
edge(tuc, ccg).
edge(ccg, sf).

connected(C1, C2) :-
   edge(C1, C2).
connected(C1, C2) :- 
   edge(C1, X),
   connected(X, C2).

问题是它返回true,然后返回false。错误从何而来?

让我们看看您从Prolog得到的确切答复!首先,您得到一个
true
,然后按空格或;你最终得到:

?- connected(phx,sf).
true ;
false.
所以你得到了
真的;错误。
作为完整答案。
表示“或”。所以Prolog本质上说:您的查询
已连接(phx,sf)。
true相同;错误。
因此,您需要查看整个答案以了解其含义。当然这有点奇怪,如果
为真。
就足够了

但首先让我们举另一个例子:

?- connected(phx,X).
X = tuc ;
X = ccg ;
X = sf ;
false.
这里Prolog的完整答案是:
connected(phx,X)。
描述了与
X=tuc相同的解决方案集;X=ccg;X=fg;false。
如果省略
false
,则其长度也会更短

那么为什么Prolog会写出这个
false
?Prolog以增量方式计算答案。它首先向您显示
X=tuc
,然后等待您将要执行的操作。从某种意义上说,不立即向您展示所有内容有点懒惰。有时,Prolog确实知道不会有进一步的答案,在这种情况下,它直接写一个点:

?- member(X,[1,2]).
X = 1 ;
X = 2.
这里的序言说:迪西!我已经说过了

但有时,情况并非如此确定:

?- member(1,[1,2]).
true ;
false.
在证明1是成员后,它将停止,否则它将不得不进一步探索列表

所以这个
;false。
意思是:在最后一个答案/解决方案之后,Prolog还不能确定所有的问题都已经研究过了。这可能是一种低效,也可能是一种可以改进的迹象。但是,永远不要将此作为在程序中插入剪切的借口。另一个答案的切入点是完全错误的。这是很多很多错误的根源。在开始使用cuts之前,你真的应该首先学习Prolog的另一个纯粹的部分

顺便说一句:
connected/2
有一个更好的定义,它通过使用避免了无限循环(点击它获得定义)

connected(C0,C) :-
   edge(C0,C1)
   closure0(edge,C1,C).