遍历图形(带有可能的循环)并在Prolog中返回路径

时间:2010-10-10 17:04:37

标签: list prolog transitive-closure

我给出了一个弧列表:

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

我写了一组子句,告诉我是否有从节点X到节点Y的路径。循环可能会发生,我已经解释了。

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

path(X,Y,P) :-
    arc(X,Y).
path(X,Y,P) :-
    \+ member(X,P),
    arc(X,Z),
    append([X],P,L),
    path(Z,Y,L).

我需要将其修改为成功时返回遍历的节点列表。我不清楚我将如何做到这一点。

我认为我的基本情况类似于path2(X,Y,[X,Y]) :- arc(X,Y).,但这不适用于我的程序。我前一部分的解决方案是否有问题,或者我只是错过了一个小修改?任何帮助,将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:2)

关闭......但请考虑:

path(Start, End, Path) :-
    path(Start, End, [], Path).

使用起始和结束节点调用path/3将构建它们之间的路径(如果存在),并回溯以为您提供备用路由。没有两次访问节点。 []是一个节点累加器列表,因此我们可以检查我们是否在构建路径时不在圈内。

path(Now, End, Acc, Path) :-
    arc(Now, Mid),
    Mid == End, !,
    append(Acc, [Now, End], Path).

path(Now, End, Acc, Path) :-
    arc(Now, Mid),
    \+ member(Mid, Acc),
    path(Mid, End, [Now|Acc], Path).

这些谓词可以完成实际工作。第一个是基本情况,通过另一个arc/2调用到达终端节点;在这种情况下,已经建立了一条路径。第二个遍历(有向)图,但仅遍历尚未访问过的节点。

可以使用findall/3通过以下方式立即找到所有路径:

findall(Path, path(Start,End,Path), Paths).

对于节点原子的StartEnd的绑定值。

答案 1 :(得分:1)

转到higher level并使用 1 作为基本习语!

%        your binary predicate arc/2 gets used here
%         |
%         v
?- 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 = a, To = e, Path = [a,b,c,d,e]
;  From = a, To = f, Path = [a,b,c,d,e,f]
;  From = b, To = c, Path = [b,c]
;  From = b, To = d, Path = [b,c,d]
;  From = b, To = e, Path = [b,c,d,e]
;  From = b, To = f, Path = [b,c,d,e,f]
;  From = c, To = d, Path = [c,d]
;  From = c, To = b, Path = [c,d,b]
;  From = c, To = e, Path = [c,d,e]
;  From = c, To = f, Path = [c,d,e,f]
;  From = d, To = b, Path = [d,b]
;  From = d, To = c, Path = [d,b,c]
;  From = d, To = e, Path = [d,e]
;  From = d, To = f, Path = [d,e,f]
;  From = e, To = f, Path = [e,f]
;  false.

脚注1:由多才多艺的 path/4实施。

答案 2 :(得分:0)

sharky给出的答案对我来说似乎没有用,但是下面的mod确实对我来说更直接。 :

path(Now, End, Acc, [Now,End]) :-
    arc(Now, End),
    \+ member(Now, Acc),
    \+ member(End, Acc).

path(Now, End, Acc, Path) :-
    arc(Now, Mid),
    \+ member(Mid, Acc),
    path(Mid, End, [Now|Acc], Path).

请告诉我,我是否遗漏了某些东西。