【问题标题】:Find the shortest path between two nodes in a graph in Prolog在 Prolog 中查找图中两个节点之间的最短路径
【发布时间】:2023-04-10 13:15:01
【问题描述】:

我想在 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). 

谢谢。

【问题讨论】:

    标签: prolog graph-theory shortest-path


    【解决方案1】:

    我们将 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.
    

    在上面的查询中有两条不同的最短路径ad

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

    【讨论】:

    • 没有比枚举所有路径更好的算法吗?
    【解决方案2】:

    当您只需要一种解决方案时,您可以查看剪切运算符“!”。

    为避免陷入无限循环,您可能应该使用存储已访问节点的累加器列表。

    【讨论】:

    • 我更新了我的代码。请看一下。我的成员谓词似乎有问题。
    • 任何实际的编码都会比建议更受欢迎。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2016-03-04
    • 2021-12-18
    • 2019-02-20
    • 2015-02-19
    • 2012-12-18
    相关资源
    最近更新 更多