Prolog 从顶点到所有其他可到达节点的所有简单路径

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应该是(假设;被垃圾处

我对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应该是(假设;被垃圾处理,直到所有选项都用尽)

我写了这样的东西作为开场白:

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(节点),已访问),所有路径(节点,节点,[节点|已访问])。
非常有用。我需要训练我的眼睛以防犯这样的错误。你可能帮我省了几个小时的检查时间。谢谢,投票表决,我接受答案。