给出图形边缘的项表示,即:
edge(a, b).
edge(b, c).
我想构造一个谓词path/1
,因为它的唯一参数是该图中的有效路径(即,对于每两个相邻项X
,Y
,{ {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
它可以按预期工作,但是使用柔和的剪裁感觉有些强迫。我想知道是否有更简单的方法可以完成此操作,在这种特定情况下,是否可能对软切进行更简单的模拟?
答案 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 ).