【问题标题】:Finding all possible paths in a graph without cycle在没有循环的图中查找所有可能的路径
【发布时间】:2016-11-25 14:28:59
【问题描述】:

我正在尝试编写一个 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()) 排除循环并避免无限循环,但它并不能产生所有可能的解决方案。如何更改程序以获取带循环的图中两点之间的所有可能路径?

【问题讨论】:

  • 你能举一个给定输入的预期输出示例吗?
  • 另见here

标签: prolog graph-theory


【解决方案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.

【讨论】:

  • 清除解决方案但不适用于此图表:gist.github.com/afshinm/27f1c8a6f84821dc0b73db3d5fa04949
  • @AfshinMehrabani 我刚刚更新了我的答案,请确保您尝试了最新版本。我无法检查自己,因为您链接的图表不是edge(X,Y) 格式,而且您没有说明您希望得到什么。
  • 抱歉,您能解释一下为什么使用reversedif 吗?我无法理解这两个的意义..
  • @AfshinMehrabani 你说得对,我们不需要dif,因为not(member…) 已经检查过了。至于reverse,我们需要它,因为累加器会按照你想要的P中相反的顺序累加路径,因此我们在最后将它反转。
【解决方案2】:

您可以很容易地看到 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.

您也可以通过以下方式获得@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.

【讨论】:

  • 这是一个很好的解决方案,但它不适用于我拥有的另一个图表:gist.github.com/afshinm/27f1c8a6f84821dc0b73db3d5fa04949
  • 不错,这是一个很棒的解决方案。但很抱歉,我只能接受一个。赞成。
  • 是的,我只是发布它以供将来参考和完整性,谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
  • 2020-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多