我正在学习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之间的路径且路径< strong>是访问节点列表
所以他给了我以前程序的以下新版本:
/* 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或类似的东西......
您是否对此有更准确的想法以及此谓词的可能实现?
答案 0 :(得分:3)
没有必要通过自己编写递归代码来重新发明轮子。
只需定义二元关系edge/2
...
edge(a,b).
edge(b,c).
edge(a,e).
edge(c,d).
edge(d,e).
edge(f,e).
...并使用meta-predicate 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