1

如果图 Graph 的某个节点 B 存在边 AB 或 BA,我遇到了这个 cut,它应该返回 true。

node(A,Graph) :- adjacent(A,_,Graph),!.

问题是我不明白为什么删除这个切口会对返回的解决方案产生任何影响。

据我了解,在 Prolog 语句末尾进行剪切的唯一用途是当有另一个同名的语句 [another node(...)] 如果第一个成功时我们不想被调用. 一个例子是一个函数,它接受 X 和 Y 并返回较大的一个作为第三个参数。

max1(X, Y, X) :- X > Y, !.
max1(_X, Y, Y).

但是,没有其他名为 node(...) 的语句,所以我看不到剪切如何影响解决方案。

这是我的代码。它应该找到一棵生成树。这里有详细解释。编译器是 Linux 上的 SWI-Prolog 7.6.4。

:- op(900, fy, not).

stree1( Graph, Tree)  :-
    subset( Graph, Tree),  tree( Tree),  covers( Tree, Graph).

tree( Tree)  :-
    connected( Tree),  not hasacycle( Tree).

connected( Graph)  :-
    not ( node( A, Graph), node( B, Graph), not path( A, B, Graph, _) ).

hasacycle( Graph)  :-
     adjacent( Node1, Node2, Graph),
     path( Node1, Node2, Graph, [Node1, X, Y | _] ). 

covers( Tree, Graph)  :-
    not ( node( Node, Graph), not node( Node, Tree) ).

subset( [], [] ). 
subset( [X | Set], Subset)  :-  subset( Set, Subset).
subset( [X | Set], [X | Subset])  :-  subset( Set, Subset).

adjacent( Node1, Node2, Graph)  :-
      member( Node1-Node2, Graph)
      ;
      member( Node2-Node1, Graph).

node( Node, Graph)  :-  adjacent( Node, _, Graph). 

path( A, Z, Graph, Path)  :-
      path1( A, [Z], Graph, Path).

path1( A, [A | Path1], _, [A | Path1] ).

path1( A, [Y | Path1], Graph, Path)  :-
      adjacent( X, Y, Graph),
      not member( X, Path1), 
      path1( A, [X, Y | Path1], Graph, Path).

未删减返回的解决方案(正确)

?- stree1([a-b, b-c, b-d, c-d], Tree).
Tree = [a-b, b-d, c-d] ;
Tree = [a-b, b-c, c-d] ;
Tree = [a-b, b-c, b-d] ;
false.

使用 cut 返回的解决方案(不正确)

?- stree1([a-b, b-c, b-d, c-d], Tree).
Tree = [a-b] ;
Tree = [a-b, c-d] ;
Tree = [a-b, b-d] ;
Tree = [a-b, b-d, c-d] ;
Tree = [a-b, b-c] ;
Tree = [a-b, b-c, c-d] ;
Tree = [a-b, b-c, b-d] ;
false.
4

1 回答 1

2

“据我所知,在 Prolog 语句末尾进行剪切的唯一用途是当有另一个具有相同名称的语句 [another node(...)] 时,如果第一个语句我们不想被调用成功了。”

好吧,这不适用于您的情况,因为您使用的member/2谓词将与回溯一起使用。在这种情况下,使用削减将修剪 Prolog 在回溯中使用的解决方案树,并可能导致您获得的结果发生变化。要通过示例进行解释,请参见此处原始帖子的稍作修改的代码:

node( Node, Graph , Target)  :-  adjacent( Node, Target, Graph),!.

adjacent( Node1, Node2, Graph)  :-
  member( Node1-Node2, Graph)
  ;
  member( Node2-Node1, Graph).

在控制台中运行此查询时,您将看到输出:

?- node(l,[l-x,l-y],Target).
Target = x

为什么?因为一开始,你的搜索树有两片叶子。(lx) 或 (ly) 对满足 中的条件adjacent/3。然后,根据深度优先搜索,选择对 (lx),并且由于您!的代码中有一条语句,搜索树的其余部分现在被修剪。因此,您得到的结果为Target = x

但是,如果您!从代码中删除该语句,您将看到:

?- node(l,[l-x,l-y],Target).
Target = x ;
Target = y ;
false.

在这里,您会看到搜索树的两个叶子都按照深度优先顺序依次执行,并且您会看到两个结果。这就是导致您在!存在与否时看到不同结果的原因。

于 2019-01-20T18:38:16.327 回答