在 Prolog 中查找无环图的路径长度
Finding the path length of an Acyclic Graph in Prolog
好的,我有图表:
并且我希望能够创建一个规则来查找从 X 到 Y 的所有路径及其长度(边数)。为了
例如,从 a 到 e 的另一条路径存在于 d、f 和 g。它的长度是 4.
到目前为止,我的代码如下所示:
edge(a,b).
edge(b,e).
edge(a,c).
edge(c,d).
edge(e,d).
edge(d,f).
edge(d,g).
path(X, Y):-
edge(X, Y).
path(X, Y):-
edge(X, Z),
path(Z, Y).
我有点不确定我应该如何处理这个问题。我输入了很多不起作用的规则,现在我很困惑。所以,我想我会把它带回到基础,看看你们能想出什么。如果可能的话,我也想知道您为什么要这样做。提前谢谢你。
这种情况已经问过好几次了。首先,您的 edge/2 谓词不完整,缺少像 edge(c,d)、edge(f,g) 或 edge(g,e) 这样的边。
其次,您需要存储已访问节点的列表以避免创建循环。
然后,当访问一个新节点时,您必须在 Path 变量中检查这个新节点是否尚未访问。但是,Path 尚未实例化。所以你需要一个延迟谓词来检查循环(all_dif/1)。这是使用 https://whosebug.com/users/4609915/repeat.
的惰性实现的简化版本
go(X, Y) :-
path(X, Y, Path),
length(Path, N),
write(Path), write(' '), write(N), nl.
path(X, Y, [X, Y]):-
edge(X, Y).
path(X, Y, [X | Path]):-
all_dif(Path),
edge(X, Z),
path(Z, Y, Path).
%
%which uses a dynamic predicate for defining path
%Here is the lazy implementation of loop-checking
all_dif(Xs) :- % enforce pairwise term inequality
freeze(Xs, all_dif_aux(Xs,[])). % (may be delayed)
all_dif_aux([], _).
all_dif_aux([E|Es], Vs) :-
maplist(dif(E), Vs), % is never delayed
freeze(Es, all_dif_aux(Es,[E|Vs])). % (may be delayed)
下面是一些带有评论的执行
?- go(a,e).
[a,b,e] 3 %%% three nodes: length=2
true ;
[a,c,d,f,g,e] 6
true ;
[a,c,f,g,e] 5
true ;
[a,d,f,g,e] 5
true ;
false. %%% no more solutions
这是对您问题的回复吗?
好的,我有图表:
并且我希望能够创建一个规则来查找从 X 到 Y 的所有路径及其长度(边数)。为了 例如,从 a 到 e 的另一条路径存在于 d、f 和 g。它的长度是 4.
到目前为止,我的代码如下所示:
edge(a,b).
edge(b,e).
edge(a,c).
edge(c,d).
edge(e,d).
edge(d,f).
edge(d,g).
path(X, Y):-
edge(X, Y).
path(X, Y):-
edge(X, Z),
path(Z, Y).
我有点不确定我应该如何处理这个问题。我输入了很多不起作用的规则,现在我很困惑。所以,我想我会把它带回到基础,看看你们能想出什么。如果可能的话,我也想知道您为什么要这样做。提前谢谢你。
这种情况已经问过好几次了。首先,您的 edge/2 谓词不完整,缺少像 edge(c,d)、edge(f,g) 或 edge(g,e) 这样的边。 其次,您需要存储已访问节点的列表以避免创建循环。 然后,当访问一个新节点时,您必须在 Path 变量中检查这个新节点是否尚未访问。但是,Path 尚未实例化。所以你需要一个延迟谓词来检查循环(all_dif/1)。这是使用 https://whosebug.com/users/4609915/repeat.
的惰性实现的简化版本go(X, Y) :-
path(X, Y, Path),
length(Path, N),
write(Path), write(' '), write(N), nl.
path(X, Y, [X, Y]):-
edge(X, Y).
path(X, Y, [X | Path]):-
all_dif(Path),
edge(X, Z),
path(Z, Y, Path).
%
%which uses a dynamic predicate for defining path
%Here is the lazy implementation of loop-checking
all_dif(Xs) :- % enforce pairwise term inequality
freeze(Xs, all_dif_aux(Xs,[])). % (may be delayed)
all_dif_aux([], _).
all_dif_aux([E|Es], Vs) :-
maplist(dif(E), Vs), % is never delayed
freeze(Es, all_dif_aux(Es,[E|Vs])). % (may be delayed)
下面是一些带有评论的执行
?- go(a,e).
[a,b,e] 3 %%% three nodes: length=2
true ;
[a,c,d,f,g,e] 6
true ;
[a,c,f,g,e] 5
true ;
[a,d,f,g,e] 5
true ;
false. %%% no more solutions
这是对您问题的回复吗?