使用序言编写一个适用于循环图的谓词,以检查两个节点之间是否存在路径

问题描述

我正在尝试编写一个谓词isway(A,B),该谓词应用于循环图。我试图获得的预期结果是,是否在2个节点之间存在路径。例如:如果我问isway(a,f),则期望它回答是或否。下面是我的代码,但是它永远无法正常工作,并且总是给我false作为输出

%given facts

edge(a,b).
edge(a,c).
edge(b,c).
edge(c,d).
edge(c,e).
edge(d,e).
edge(f,g).
edge(g,h).

edge2(d,a).
edge2(h,f).
edge2(X,Y) :- edge(X,Y).

%my implementation
isway(A,B) :- edge2(A,B,[]).

edge2(A,V) :- edge(A,X),not(member(X,V)),(B = X ; edge2(X,[A|V])).

%my output
?- isway(b,a). %I expect true for this one
false

?- isway(a,f). %False for this is ok but I am not confident about my logic
false.


解决方法

您可以使用tabling计算边缘关系的传递闭合:

edge(a,b).
edge(a,c).
edge(b,c).
edge(c,d).
edge(c,e).
edge(d,e).
edge(f,g).
edge(g,h).

edge(d,a). % acyclic
edge(h,f). % acyclic

:- table path/2.
path(X,Y) :- edge(X,Y).
path(X,Y) :- path(X,Z),path(Z,Y).

然后,查询按预期工作:

?- path(a,f).
false.

?- path(b,a).
true.