在有向图中打印最短路径

时间:2016-09-29 13:48:18

标签: prolog graph-algorithm shortest-path

我有一个没有权重的定向循环图。我想找到A和B之间的最短路线(即跳数最少的路线)。

这是我到目前为止的代码:

path(A,B) :- walk(A,B,[]).

walk(A,B,V) :- edge(A,X), not(member(X,V)), (B=X); walk(X,B,[A|V]).

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

此代码打印为true,一次为其找到的每个路径。我该如何打印路径?我需要做些什么才能找到跳数最少的路径?

2 个答案:

答案 0 :(得分:4)

一旦达到终止条件,您需要将额外参数与V中积累的内容统一起来:

path(A,B,P) :- walk(A,B,[],P).

walk(B,B,V,P) :- reverse(V,P).
walk(A,B,V,P) :- dif(A,B), edge(A,X), maplist(dif(X),V), walk(X,B,[A|V],P).

一旦AB相同,就意味着我们不必再走图了。在这种情况下,我们将V中累积的路径反转为P,该路径从path/3“返回”。

注意:将检查递归终止的代码作为单独的规则,而不是使用;几乎总是更清楚。

要查找跳数最少的路径,您可以找到所需两个点的所有路径,然后选择最小的路径:

shortest_path(A,B,S) :-
    findall(P, path(A,B,P), Ps),
    maplist(prepend_length, Ps, Ls),
    sort(Ls, [[_,S]|_]).

prepend_length(P, [L,P]) :-
    length(P,L).

答案 1 :(得分:1)

要产生路径,您需要添加一个参数来跟踪它;例如:

path(A,B,P) :- walk(A,B,[],P).
walk(A,B,V,[A,B]) :- edge(A,X), not(member(X,V)), (B=X).

(我会将递归案例作为练习。)

要查找最短路径,您可以找到所有路径(findall)&选出最短的。