英文:
Find all paths in undirected acyclic graph using Prolog
问题
以下是翻译好的代码部分:
我想要打印出从节点a到节点e在一个带权重的无向无环图中的所有路径,但我的程序错过了一些长路径。
这是我的程序:
%声明所有边
edge(a,b,1).
edge(a,c,6).
edge(b,c,4).
edge(b,d,3).
edge(b,e,1).
edge(c,d,1).
edge(d,e,1).
%如果存在一条边连接X和Y,则它们是相邻的
adj(X, Y, W) :- edge(X, Y, W).
adj(Y, X, W) :- edge(Y, X, W).
%当路径为空时,从节点X到节点X的权重为0,路径为空
findpath(X, X, 0, []).
%如果X和Y相邻,将Y附加到X到路径变量Path中
findpath(X,Y,Weight,Path) :- adj(X,Y,Weight),
append([X],[Y],Path).
%如果X和Y不相邻,考虑那些与Y相邻的节点,带有权重W2,
%使用递归调用路径谓词,将Y替换为A和W1替换为W2,将它们的权重-W作为W1 + W2并附加到路径中
findpath(X,Y,Weight,Path) :- not(adj(X,Y,Weight)),
edge(A,Y,Weight1),
findpath(X,A,Weight2,P1),
Weight is Weight1+Weight2,
append(P1,[Y],Path).
希望这能帮助你理解你的程序以及问题。
英文:
`I want to print all the ways to reach Node e from Node a in a weighted unidrected acyclic graph. but my program misses a few long routes.
This is my program.
%Declare all the edges
edge(a,b,1).
edge(a,c,6).
edge(b,c,4).
edge(b,d,3).
edge(b,e,1).
edge(c,d,1).
edge(d,e,1).
% Two nodes are adjacent if there exists a edge between them
adj(X, Y, W) :- edge(X, Y, W).
adj(Y, X, W) :- edge(Y, X, W).
% return 0 weight and empty path because path is empty to reach the same node
% from the node itself and therefor no wirght as well.
findpath(X, X, 0, []).
% if X and Y are adjacent then append Y to X into the Path Variable
findpath(X,Y,Weight,Path) :- adj(X,Y,Weight),
append([X],[Y],Path).
% if X and Y are not adjacent, then consider nodes who are adjacent to Y with
% weight W2 , recursively call path predicate replacing Y with A and W1 with W2
% add their weight - W as W1 + W2 and append to Path.
findpath(X,Y,Weight,Path) :- not(adj(X,Y,Weight)),
edge(A,Y,Weight1),
findpath(X,A,Weight2,P1),
Weight is Weight1+Weight2,
append(P1,[Y],Path).
Output
`2 ?- findpath(a, e, W, P).
W = 2,
P = [a, b, e] ;
W = 2,
P = [a, b, e] ;
W = 5,
P = [a, b, d, e] ;
W = 5,
P = [a, b, d, e] ;
W = 8,
P = [a, c, d, e] ;
W = 8,
P = [a, c, d, e] ;
false.
My program missed a, b, c, e and a, b, c, d ,e. I dont understand why ?
Also , it repeats the output as well.`
答案1
得分: 2
(There is no path "abce" since there is no connection between c
and e
)
adj/3
描述了与edge/3
完全相同的解决方案。您在头部和目标中交换了参数。只需要交换一次。使用path/4
会给您所有无环路径。然后您需要添加权重。
:- set_prolog_flag(double_quotes, chars).
adj(X, Y, W) :- edge(X, Y, W).
adj(X, Y, W) :- edge(Y, X, W).
adj(X,Y) :-
adj(X,Y,_).
?- path(adj, Path, a,e).
Path = "abcde"
; Path = "abde"
; Path = "abe"
; Path = "acde"
; Path = "acdbe"
; Path = "acbde"
; Path = "acbe"
; false.
?- setof(t,path(adj, Path, a,e),_).
Path = "abcde"
; Path = "abde"
; Path = "abe"
; Path = "acbde"
; Path = "acbe"
; Path = "acdbe"
; Path = "acde".
?- path(adj, Path, a,Y).
Path = "a", Y = a
; Path = "ab", Y = b
; Path = "abc", Y = c
; Path = "abcd", Y = d
; Path = "abcde", Y = e
; Path = "abd", Y = d
; Path = "abde", Y = e
; Path = "abdc", Y = c
; Path = "abe", Y = e
; Path = "abed", Y = d
; Path = "abedc", Y = c
; Path = "ac", Y = c
; Path = "acd", Y = d
; Path = "acde", Y = e
; Path = "acdeb", Y = b
; Path = "acdb", Y = b
; Path = "acdbe", Y = e
; Path = "acb", Y = b
; Path = "acbd", Y = d
; Path = "acbde", Y = e
; Path = "acbe", Y = e
; Path = "acbed", Y = d
; false.
英文:
(There is no path "abce" since there is no connection between c
and e
)
adj/3
describes the very same solutions that edge/3
does. You exchanged arguments both in the head and the goal. Exchange them only once. Using path/4
gives you all acyclic paths. Then you need to add a weight.
:- set_prolog_flag(double_quotes, chars).
adj(X, Y, W) :- edge(X, Y, W).
adj(X, Y, W) :- edge(Y, X, W).
adj(X,Y) :-
adj(X,Y,_).
?- path(adj, Path, a,e).
Path = "abcde"
; Path = "abde"
; Path = "abe"
; Path = "acde"
; Path = "acdbe"
; Path = "acbde"
; Path = "acbe"
; false.
?- setof(t,path(adj, Path, a,e),_).
Path = "abcde"
; Path = "abde"
; Path = "abe"
; Path = "acbde"
; Path = "acbe"
; Path = "acdbe"
; Path = "acde".
?- path(adj, Path, a,Y).
Path = "a", Y = a
; Path = "ab", Y = b
; Path = "abc", Y = c
; Path = "abcd", Y = d
; Path = "abcde", Y = e
; Path = "abd", Y = d
; Path = "abde", Y = e
; Path = "abdc", Y = c
; Path = "abe", Y = e
; Path = "abed", Y = d
; Path = "abedc", Y = c
; Path = "ac", Y = c
; Path = "acd", Y = d
; Path = "acde", Y = e
; Path = "acdeb", Y = b
; Path = "acdb", Y = b
; Path = "acdbe", Y = e
; Path = "acb", Y = b
; Path = "acbd", Y = d
; Path = "acbde", Y = e
; Path = "acbe", Y = e
; Path = "acbed", Y = d
; false.
答案2
得分: 0
你需要维护一个“已访问”边的列表,以防止进入循环。同时,你需要修复你的adj/3
谓词(这是导致你得到双重答案的原因!)
adj(X,Y,D):-edge(X,Y,D);edge(Y,X,D).
path(X,Y,D,P):-p(X,Y,[],D,P).
p(X,X,_,0,[X]).
p(X,Y,V,D,[X|P]):-adj(X,Z,W),\+memberchk(Z,V),p(Z,Y,[X|V],E,P),D is E+W.
英文:
You need to keep a "visited" list of edges if you don't want to go in circles. And you need to fix your adj/3 (this is what is giving you the double answers!)
adj(X,Y,D):-edge(X,Y,D);edge(Y,X,D).
path(X,Y,D,P):-p(X,Y,[],D,P).
p(X,X,_,0,[X]).
p(X,Y,V,D,[X|P]):-adj(X,Z,W),\+memberchk(Z,V),p(Z,Y,[X|V],E,P),D is E+W.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论