列举图表中的所有游历

时间:2019-05-31 15:55:39

标签: prolog

给出图形边缘的项表示,即:

edge(a, b).
edge(b, c).

我想构造一个谓词path/1,因为它的唯一参数是该图中的有效路径(即,对于每两个相邻项XY,{ {1}}成立)。给定一个变量,它应该枚举所有步行(可能有重复的节点)。我的第一次尝试:

edge(X, Y)

除了提供非循环图的情况外,它按预期方式工作-path([X, Y]) :- edge(X, Y). path([X, Y, Z | T]) :- path([Y, Z | T]), edge(X, Y). 找到所有解决方案,然后停止,无法构造任何其他路径。另一方面,由于Prolog解析的DFS性质,交换第一和第二项将导致跳过许多步骤。

第二次尝试:

path

它可以按预期工作,但是使用柔和的剪裁感觉有些强迫。我想知道是否有更简单的方法可以完成此操作,在这种特定情况下,是否可能对软切进行更简单的模拟?

2 个答案:

答案 0 :(得分:0)

测试第一个解决方案后,找到三个路径([a,b][a,c][a,b,c]),然后循环。避免这种情况的一种超级快捷方法是使用XSB,SWI和YAP中的制表符。对于SWI,只需添加:- table path/1.作为第一个指令即可避免循环。否则,您需要记住所有路径,并且可以找到很多答案(例如this)。

答案 1 :(得分:0)

给出您的图形定义:

edge(a, b).
edge(b, c).

应该做的事

path(P) :-
  node(X),
  walk(X,_,P)
  .

walk(A,B,P) :-
  walk(A,B,[],V),
  reverse(V,R),
  P = [A|R]
  .               

walk( A, B, T, V ) :-
  edge(A,X),              
  not( member(X,T) ),
  (
    ( B = X , V = [B|T] )
  ;
    walk( X, B, [A|T], V )
  )
  . 

%
% enumerate the distinct nodes in edge/2 via backtracking
%
node(N) :-
  setof( X , edge(X,_);edge(_,X) , Ns ),
  node( Ns , N )
  .

node( [N|_] , N ).
node( [_|Ns] , N ) :- ( Ns , N ).