如何在Prolog中的图形路径中存储受访节点的列表

时间:2013-05-01 16:26:08

标签: prolog

我正在学习Prolog,我发现在解释我教授提出的幻灯片时遇到了一些困难。

从经典程序开始,表示如果存在图形的两个节点之间的路径,则为:

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

path(X,Y) :- edge(X,Y).

path(X,Y) :- path(X,Z),
             edge(Z,Y).

他介绍了一个使用谓词的新版本:路径(X,Y,路径)如果图中存在X和Y之间的路径且路径是访问节点列表

所以他给了我以前程序的以下新版本:

/* BASE CASE: exist an edge between X and Y, so the Path is
              the couple [X,Y]
*/
path(X,Y,[X,Y]) :- edge(X,Y).

path(X,Y,P) :- path(X,Z,P1),
               edge(Z,Y),
               lastelem(P,Y,P1).

基本情况非​​常简单:如果存在连接X和Y的边,则存在从X到Y的路径,并且被访问节点的列表是[X,Y]

我对第二条规则有一些问题:如果X和Y不是仅由一条边连接,那么在X和Y之间有一条路径,必须存在X和另一个节点Z之间的路径(和P1是此路径中访问节点的列表)将Z连接到最终节点Y的边缘。

这很简单......问题在于最后一个谓词 lastelem / 3 ,幻灯片中没有提供它(所以我不确切知道它是做什么的):

lastelem(P,Y,P1).

我认为它会在P1中产生P插入Y或类似的东西......

您是否对此有更准确的想法以及此谓词的可能实现?

3 个答案:

答案 0 :(得分:3)

没有必要通过自己编写递归代码来重新发明轮子。

只需定义二元关系edge/2 ...

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

...并使用 path/4

?- path(edge,Path,From,To).
  Path = [To]       , From = To
; Path = [a,b]      , From = a, To = b 
; Path = [a,b,c]    , From = a, To = c
; Path = [a,b,c,d]  , From = a, To = d
; Path = [a,b,c,d,e], From = a, To = e
; Path = [b,c]      , From = b, To = c
; Path = [b,c,d]    , From = b, To = d
; Path = [b,c,d,e]  , From = b, To = e
; Path = [a,e]      , From = a, To = e
; Path = [c,d]      , From = c, To = d
; Path = [c,d,e]    , From = c, To = e
; Path = [d,e]      , From = d, To = e
; Path = [f,e]      , From = f, To = e 
; false.

答案 1 :(得分:0)

教授可能想将Y追加到P

lastelem(Lst0, X, Lst) :-
    append(Lst0, [X], Lst).

[这是一个非常愚蠢的想法,因为附加到列表需要线性时间。一个恒定时间的解决方案是在元素前面添加:

% I wouldn't actually write a predicate for this, but nevertheless:
lastelem(Lst, X, [X|Lst]).

这会以相反的顺序给出路径,但是单个reverse/2解决了这个问题。]

答案 2 :(得分:0)

我可能会做类似的事情:

path(X,Y,Path) :-
  path(X,Y,T) ,
  reverse(T,Path)
  .

path( X , Y , [] ) :- % a path exists between X and Y:
  connected(X,Y)      % - if they are directly connected
  .                   %
path( X , Y , P  ) :- % a path exists between X and Y:
  connected(X,T) ,    % - if X is connected to another node (T)
  T \= Y ,            % - and T is not the destination (Y)
  not visited(T,P) ,  % - and T has not yet been visited
  path(T,Y, [X|P])    % - and a path exists between T and Y
  .                   %

connected(X,Y) :- edge(X,Y) . % two nodes are connected if they are
connected(X,Y) :- edge(Y,X) . % if they are adjacent adjacent.

visited(X,[X|Xs]) :- ! .             % a node is visited
visited(X,[_|Xs]) :- visited(X,Xs) . % if it exists in the list of already-visited nodes