Prolog-为什么下面的代码永远生成解决方案X=root?

Prolog-为什么下面的代码永远生成解决方案X=root?,prolog,failure-slice,Prolog,Failure Slice,然后我键入foo(X),只得到X=root 我真的不明白为什么。由于foo的第一部分,我们得到了第一个根。然后我们应该转到第二部分,然后继续查找边(根,根)black(root)返回true,foo(root)也返回true,因此我们得到另一个root解决方案。然后我们为什么不转到边缘(v1,root)?我遗漏了什么?因为寻找第三种解决方案首先是在Y=root时重试foo(Y),并且您已经确定至少有两种不同的方法可以证明foo(root)。(但是,正如@WillemVanOnsem所指出的,情况

然后我键入
foo(X)
,只得到
X=root


我真的不明白为什么。由于foo的第一部分,我们得到了第一个
。然后我们应该转到第二部分,然后继续查找边
(根,根)
black(root)
返回true,foo(root)
也返回true,因此我们得到另一个root
解决方案。然后我们为什么不转到边缘
(v1,root)
?我遗漏了什么?

因为寻找第三种解决方案首先是在
Y=root
时重试
foo(Y)
,并且您已经确定至少有两种不同的方法可以证明
foo(root)
。(但是,正如@WillemVanOnsem所指出的,情况远比这糟糕。)

这里有一个片段负责非终止,称为a。您需要以某种方式修改其余部分,以避免该循环

black(root). 
black(v1). 
black(v3). 
black(v4). 

edge(root,root).
edge(v1,root). 
edge(v2,v1). 
edge(v3,v1). 
edge(v4,v3). 
edge(v5,v2). 
edge(v5,v4). 
edge(v6,v5). 

foo(root). 
foo(X) :- edge(X,Y), black(Y), foo(Y).
。。。或者改变你的事实。上面告诉我们,
边(根,根)。
是问题的一部分。如果我们把这个事实去掉呢?或者把它变成

edgeb(X, Y) :-
   edge(X, Y),
   black(Y).

foo(X) :-
   closure0(edgeb, X, root).
避免锤击;或多次间隔,您的腕管建议:

?- foo(X).
   X = root
;  X = v1
;  X = v2
;  X = v3
;  X = v4
;  X = v5
;  false.

通过这一点,我们已证明您的程序将始终终止。不可能有任何特殊情况存在。

您创建了一个infinte循环,因为对于
foo(root)
,它每次也可以采用递归情况,与
edge(root,root)
统一,从而找到另一个解决方案。Prolog搜索深度优先,而不是广度优先。 edge(root,root) :- false.
?- foo(X).
   X = root
;  X = v1
;  X = v2
;  X = v3
;  X = v4
;  X = v5
;  false.
?- foo(X), false.
false.