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.