Prolog 无圈图中所有可能路径的求法

Prolog 无圈图中所有可能路径的求法,prolog,graph-theory,Prolog,Graph Theory,我正试图编写一个Prolog程序,为我提供图形中两点之间的所有可能路径(带循环) 我试图使用not(member())来排除循环并避免无限循环,但它不会产生所有可能的解决方案。如何更改程序以获得循环图中两点之间的所有可能路径?您可以很容易地看到not(member(Y,T))在T未实例化时失败。例如,请尝试: ?- not(member(X,L)). false. 你看到它失败了。要解决此问题,您需要保留一个额外的列表,该列表将在从空列表开始的每个步骤中实例化: show_path(X,Y,R

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


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

您可以很容易地看到
not(member(Y,T))
在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.
?- 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.
您还可以通过以下方式获得@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, 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.
?- 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.

您的程序无法运行,因为
not(成员(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.

你能给出一个给定输入的预期输出的例子吗?这也是一个很好的解决方案,但它不适用于我的另一个图表:很好的一个,这是一个很棒的解决方案。但是对不起,我只能接受一个。投了赞成票。是的,当然我只是为了将来的参考和完整性,谢谢!!清晰的解决方案,但不适用于此图:@AfshinMehrabani我刚刚更新了我的答案,请确保您尝试了最新版本。我无法检查自己,因为您链接的图形的格式不是
edge(X,Y)
,并且您没有指出您希望得到什么。对不起,您能解释一下为什么使用
reverse
dif
?我不明白这两个的意思。@AfshinMehrabani你是对的,我们不需要
dif
,因为
not(member…
已经检查过了。至于
reverse
,我们需要它,因为累加器将以
P
中所需的相反顺序累积路径,因此我们在最后将其反转。