在没有循环的情况下查找图形中的所有可能路径

时间:2016-11-25 14:29:00

标签: graph prolog

我正在尝试编写一个Prolog程序,为我提供图形中两点之间的所有可能路径(带循环)。

edge(a,b).
edge(a,c).
edge(a,d).
edge(b,e).
edge(c,e).
edge(c,f).
edge(d,f).
edge(f,g).
edge(g,e).
edge(e,a).

show_path(X,Y,[X,Y]) :- edge(X,Y).
show_path(X,Z,[X|T]) :- edge(X,Y), not(member(Y, T)), show_path(Y,Z,T).

我正在尝试使用not(member())来排除循环并避免无限循环,但它不会产生所有可能的解决方案。如何更改程序以获得带有循环的图形中两点之间的所有可能路径?

2 个答案:

答案 0 :(得分:1)

当T未实例化时,您可以很容易地看到not(member(Y, T))失败。例如,尝试:

?- not(member(X,L)).
false.

你看到它失败了。要解决此问题,您需要保留一个额外的列表,该列表将在以空列表开头的每个步骤中实例化:

show_path(X,Y,R):-show_path(X,Y,[],R).

show_path(X,Y,_,[X,Y]) :- edge(X,Y).
show_path(X,Y,L,[X|R]) :- edge(X,Z),\+member(Z,L),
                          show_path(Z,Y,[Z|L],R).

示例:

?- show_path(a,e,L).
L = [a, b, e] ;
L = [a, b, e, a, c, e] ;
L = [a, b, e, a, c, f, g, e] ;
L = [a, b, e, a, d, f, g, e] ;
L = [a, c, e] ;
L = [a, c, e, a, b, e] ;
L = [a, c, e, a, d, f, g, e] ;
L = [a, c, f, g, e] ;
L = [a, c, f, g, e, a, b, e] ;
L = [a, d, f, g, e] ;
L = [a, d, f, g, e, a, b, e] ;
L = [a, d, f, g, e, a, c, e] ;
false.

你可以通过写一下@Fatalize建议输出:

show_path(X,Y,[X,Y]) :- edge(X,Y).
show_path(X,Y,R) :- edge(X,Z), show_path(Z,Y,RZ),R=[X|RZ],       
                           sort(R,R1),length(R,N),length(R1,N1),
                           (N>N1->!,fail ;true).

示例:

?- show_path(a,e,L).
L = [a, b, e] ;
L = [a, c, e] ;
L = [a, c, f, g, e] ;
L = [a, d, f, g, e] ;
false.

答案 1 :(得分:1)

您的程序无效,因为not(member(Y, T))始终为false:此时T未实例化,因此始终可以找到包含Y的列表

您可以通过添加累加器修复程序:

show_path(X,X,T,P) :- reverse([X|T],P).
show_path(X,Z,T,P) :- edge(X,Y), not(member(X,T)), show_path(Y,Z,[X|T],P).

show_path(X,Y,P) :- show_path(X,Y,[],P).

通过避免循环不清楚你的意思。与@ coder的答案不同,它会避免在同一点上传递两次。例如:

?- show_path(a,e,Z).
Z = [a, b, e] ;
Z = [a, c, e] ;
Z = [a, c, f, g, e] ;
Z = [a, d, f, g, e] ;
false.