【问题标题】:Prolog - why does the following code generate the solution X=root forever?Prolog - 为什么以下代码会永远生成解决方案 X=root?
【发布时间】:2020-06-06 02:05:54
【问题描述】:
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).

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

我真的不知道为什么。由于 foo 的第一部分,我们得到了第一个 root。然后我们应该去第二部分,然后我们继续寻找边缘(root,root)black(root) 返回 true,foo(root) 也是如此,所以我们得到另一个根 solution。那么我们为什么不去边缘(v1,root)?我错过了什么?

【问题讨论】:

  • 你做了一个无限循环,因为对于foo(root),它每次也可以采取递归情况,与edge(root, root)统一,从而找到另一个解决方案。 Prolog 搜索深度优先,而不是广度优先

标签: prolog failure-slice


【解决方案1】:

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

黑色(根)。 黑色(v1):- 黑色(v3):- 黑色(v4):- 。 边缘(根,根)。 edge(v1,root) :- falseedge(v2,v1) :- falseedge(v3,v1) :- falseedge(v4,v3) :- falseedge(v5,v2) :- falseedge(v5,v4) :- falseedge(v6,v5) :- falsefoo(root) :- false。 foo(X) :- edge(X,Y), black(Y), foo(Y), false

解决这个问题的最简单方法是重用closure0/3

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

foo(X) :-
   closure0(edgeb, X, root).

...或者改变你的事实。上面的failure-slice 向我们展示了edge(root,root). 是问题的一部分。什么,如果我们只是删除这个事实?或者把它变成

edge(root,root) :- false

现在foo(X) 终止:

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

为避免多次敲击 ;SPACE,您的腕管建议:

?- foo(X), false.
false.

我们已经证明您的程序将总是终止。不可能有任何特殊情况潜伏。

【讨论】:

    【解决方案2】:

    因为寻找第三种解决方案是从重试foo(Y) 开始,而Y=root,并且您已经确定至少有两种不同的方法来证明foo(root)。 (但是,正如@WillemVanOnsem 指出的那样,情况比这要糟糕得多。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-08
      • 1970-01-01
      • 2018-12-13
      • 1970-01-01
      • 2018-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多