prolog - 在Prolog中找到图中两个节点之间的最短路径

标签 prolog graph-theory shortest-path

我想在 Prolog 中找到两个节点之间的最短路径。
我想出了如何找到两个节点之间的所有路径,但不幸的是以下代码陷入循环:

arc(a,b).
arc(b,a).
arc(b,c).
arc(c,b).
arc(c,d).
arc(d,c).

path(X,Y,[arc(X,Y)]) :-
   arc(X,Y).
path(X,Y,[arc(X,Z)|P]) :-
   arc(X,Z),
   path(Z,Y,P).

代码运行是:
?- path(a,c,R).
R = [arc(a, b), arc(b, c)] ;
R = [arc(a, b), arc(b, a), arc(a, b), arc(b, c)] ;
R = [arc(a, b), arc(b, a), arc(a, b), arc(b, a), arc(a, b), arc(b, c)] 
....

所以,我的问题是:如何在不无限循环的情况下获得所有路径?

在一天结束时,我会得到列表的长度并找到最小值。

如果可能,请给出 ISO Prolog 的解决方案。

注意:这是更新的代码,我仍然有问题。显然,成员谓词在检查事实而不是原子时不起作用。
xxx([]).

path(X,Y,[arc(X,Y)]) :-
   arc(X,Y).
path(X,Y,[arc(X,Z)|P]) :- 
        arc(X,Z)
        ,xxx(L)
        ,member(arc(X,Z),L)->
            !;
            (member(arc(Z,X),L)->
                !;
                (append(L,[arc(X,Z)],R),retract(xxx(_)),assert(xxx(R)),path(Z,Y,P))).

我的成员谓词是:
member(X,[X|T]).
member(X,[H|T])  :-  member(X,T). 

谢谢你。

最佳答案

我们使用 path/4 结合arc/2的定义你给的:

?- path(arc,Path,From,To).
  From = To        , Path = [To] 
; From = a,  To = b, Path = [a,b]
; From = a,  To = c, Path = [a,b,c]
; From = a,  To = d, Path = [a,b,c,d]
; From = b,  To = a, Path = [b,a]
; From = b,  To = c, Path = [b,c]
; From = b,  To = d, Path = [b,c,d]
; From = c,  To = b, Path = [c,b]
; From = c,  To = a, Path = [c,b,a]
; From = c,  To = d, Path = [c,d]
; From = d,  To = c, Path = [d,c]
; From = d,  To = b, Path = [d,c,b]
; From = d,  To = a, Path = [d,c,b,a]
; false.
path/4的定义排除所有循环。

为了获得最短路径,我们需要查看所有解决方案!

为了证明事实确实如此,让我们扩展您对 arc/2 的定义像这样:
arc(a,b).
arc(b,a).
arc(b,c).
arc(a,c).               % (new)
arc(b,d).               % (new)
arc(c,b).
arc(c,d).
arc(d,c).

假设我们想要“获取从 ad 的所有最短路径”,所以我们查询:
?- path(arc,Path,a,d).
  Path = [a,b,c,d]
; Path = [a,b,d]        % shortest path #1
; Path = [a,c,b,d]
; Path = [a,c,d]        % shortest path #2
; false.

在上面的查询中,有来自 a 的两条不同的最短路径至 d .

要获得两者,我们必须查看所有路径---或使用更智能的 (留作作业)。

关于prolog - 在Prolog中找到图中两个节点之间的最短路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10812108/

相关文章:

algorithm - 查找仅包含度数为 2 和 3 的节点的最大子图

prolog - 将递归转换为尾递归?

algorithm - 坚持 DFS/BFS 任务(USACO 银牌)

Prolog 参数没有充分实例化

graph - 需要图形分区技术

algorithm - 为什么 Bellman-Ford 算法需要 v-1 遍?

c - 打印 dijkstra 算法中的路径

hadoop - Giraph 最短路径示例 ClassNotFoundException

Prolog如何打印列表中的前3个元素

Prolog 和 headless 含义