Prolog 从顶点到所有其他可到达节点的所有简单路径
我对Prolog完全是新手,并且一直在研究图表。我在网上发现一个问题,要求我指定一个节点,然后列出从该节点可以访问的所有简单路径。没有目标节点,只需尝试所有可能性并返回所有路径 我将图形表示为路径(X,Y),表示从X到Y的有向边 我建立了这个简单的知识库,它是循环的:Prolog 从顶点到所有其他可到达节点的所有简单路径,prolog,graph-theory,transitive-closure,meta-predicate,Prolog,Graph Theory,Transitive Closure,Meta Predicate,我对Prolog完全是新手,并且一直在研究图表。我在网上发现一个问题,要求我指定一个节点,然后列出从该节点可以访问的所有简单路径。没有目标节点,只需尝试所有可能性并返回所有路径 我将图形表示为路径(X,Y),表示从X到Y的有向边 我建立了这个简单的知识库,它是循环的: path(a, b). path(b, c). path(c, d). path(d, a). path(d, e). path(d, f). path(f, g). 如果我查询所有_路径(a,p),那么p应该是(假设;被垃圾处
path(a, b).
path(b, c).
path(c, d).
path(d, a).
path(d, e).
path(d, f).
path(f, g).
如果我查询所有_路径(a,p),那么p应该是(假设;被垃圾处理,直到所有选项都用尽)
我写了这样的东西作为开场白:
all_paths(Source, P) :- all_paths(Source, P, []).
all_paths(_, [], _).
all_paths(Source, [Source | P], Visited) :-
path(Source, Node),
\+ memberchk(Node, Visited),
all_paths(Node, P, [Node | Visited]).
好的,稍微改变一下,现在我回来了:
X = [] ? ;
X = [a] ? ;
X = [a,b] ? ;
X = [a,b,c] ? ;
X = [a,b,c,d] ? ; <- Here it does not pick up e
X = [a,b,c,d] ? ;
X = [a,b,c,d] ? ;
X = [a,b,c,d,f] ? ;
X=[];
X=[a];
X=[a,b];
X=[a,b,c];
X=[a,b,c,d] 不需要重新发明轮子
首先,我们将谓词path/2
重命名为edge/2
:
edge(a, b).
edge(b, c).
edge(c, d).
edge(d, a).
edge(d, e).
edge(d, f).
edge(f, g).
?- 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 = [a,b,c,d,f], From = a, To = f
; Path = [a,b,c,d,f,g], From = a, To = g
; Path = [b,c], From = b, To = c
; Path = [b,c,d], From = b, To = d
; Path = [b,c,d,a], From = b, To = a
; Path = [b,c,d,e], From = b, To = e
; Path = [b,c,d,f], From = b, To = f
; Path = [b,c,d,f,g], From = b, To = g
; Path = [c,d], From = c, To = d
; Path = [c,d,a], From = c, To = a
; Path = [c,d,a,b], From = c, To = b
; Path = [c,d,e], From = c, To = e
; Path = [c,d,f], From = c, To = f
; Path = [c,d,f,g], From = c, To = g
; Path = [d,a], From = d, To = a
; Path = [d,a,b], From = d, To = b
; Path = [d,a,b,c], From = d, To = c
; Path = [d,e], From = d, To = e
; Path = [d,f], From = d, To = f
; Path = [d,f,g], From = d, To = g
; Path = [f,g], From = f, To = g
; false.
然后,我们结合使用edge/2
:
edge(a, b).
edge(b, c).
edge(c, d).
edge(d, a).
edge(d, e).
edge(d, f).
edge(f, g).
?- 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 = [a,b,c,d,f], From = a, To = f
; Path = [a,b,c,d,f,g], From = a, To = g
; Path = [b,c], From = b, To = c
; Path = [b,c,d], From = b, To = d
; Path = [b,c,d,a], From = b, To = a
; Path = [b,c,d,e], From = b, To = e
; Path = [b,c,d,f], From = b, To = f
; Path = [b,c,d,f,g], From = b, To = g
; Path = [c,d], From = c, To = d
; Path = [c,d,a], From = c, To = a
; Path = [c,d,a,b], From = c, To = b
; Path = [c,d,e], From = c, To = e
; Path = [c,d,f], From = c, To = f
; Path = [c,d,f,g], From = c, To = g
; Path = [d,a], From = d, To = a
; Path = [d,a,b], From = d, To = b
; Path = [d,a,b,c], From = d, To = c
; Path = [d,e], From = d, To = e
; Path = [d,f], From = d, To = f
; Path = [d,f,g], From = d, To = g
; Path = [f,g], From = f, To = g
; false.
编辑
如果我们只对从a
开始的路径感兴趣,我们只需编写:
?- path(edge,Path,a,To).
Path = [a], To = a
; Path = [a, b], To = b
; Path = [a, b, c], To = c
; Path = [a, b, c, d], To = d
; Path = [a, b, c, d, e], To = e
; Path = [a, b, c, d, f], To = f
; Path = [a, b, c, d, f, g], To = g
; false.
“交换”节点和源
all_paths(_, [], _).
all_paths(Source, [Node | P], Visited) :-
path(Source, Node),
\+ memberchk(Node, Visited),
all_paths(Node, P, [Source | Visited]).
屈服
?- all_paths(a, P).
P = [] ;
P = [b] ;
P = [b, c] ;
P = [b, c, d] ;
P = [b, c, d, e] ;
P = [b, c, d, f] ;
P = [b, c, d, f, g] ;
false.
?- all_paths(a, P).
P = [a] ;
P = [a, b] ;
P = [a, b, c] ;
P = [a, b, c, d] ;
P = [a, b, c, d, e] ;
P = [a, b, c, d, f] ;
P = [a, b, c, d, f, g] ;
false.
它缺少start节点,我只需在“driver”谓词中添加该节点:
all_paths(Source, [Source|P]) :- all_paths(Source, P, []).
屈服
?- all_paths(a, P).
P = [] ;
P = [b] ;
P = [b, c] ;
P = [b, c, d] ;
P = [b, c, d, e] ;
P = [b, c, d, f] ;
P = [b, c, d, f, g] ;
false.
?- all_paths(a, P).
P = [a] ;
P = [a, b] ;
P = [a, b, c] ;
P = [a, b, c, d] ;
P = [a, b, c, d, e] ;
P = [a, b, c, d, f] ;
P = [a, b, c, d, f, g] ;
false.
风格提示:如果我们遵循一些关于IO参数的规则,代码的可读性会更好。输出参数应该在输入参数之后。嗯,这并不总是适用的…对不起,我可能没有说清楚。除了成员函数之外,我不想使用任何库,而且我的路径必须始终从a开始,即,我希望所有简单路径都从a开始到其他一些节点。例如,我不需要从节点b开始的路径。@Pterodactylus。有一个很常见的成语:用它!我很感谢您的输入,但是我如何自己实现这个路径函数呢?我对黑匣子本身很感兴趣,看起来我正在朝着正确的方向前进,但我写的逻辑中缺少了一些东西。@Pterodactylus。重新开始。请看“代码>路径/ 4 /代码>())的摇滚实作。感谢链接,我将调查它。考虑此修复:<代码> ALLYPATH(X,[X-XS]):-ALLYROPATH(X,XS,[X])。所有路径(u,[],u)。所有路径(源,[节点|已访问]):路径(源,节点),映射列表(dif(节点),已访问),所有路径(节点,节点,[节点|已访问])。
非常有用。我需要训练我的眼睛以防犯这样的错误。你可能帮我省了几个小时的检查时间。谢谢,投票表决,我接受答案。