Prolog:在图中查找路径的子句顺序

时间:2018-11-26 08:29:17

标签: prolog

我有一个带有入口和出口节点的循环图,我想为其找出所有从入口到出口节点的所有路径。

entry(a).
exit(e).
exit(f).

next(a, b).
next(b, c).
next(b, d).
next(c, e).
next(d, f).

/* Cycle */
next(c, d).
next(d, b). 

/* path(entrynode, exitnode, pathtrace) */
path(X, Y, P)       :- entry(X), path2(X, Y, P).
path2(X, Y, [Y])    :- next(X, Y), exit(Y).
path2(X, Y, [P|PS]) :- next(X, P), path2(P, Y, PS).

我的path2谓词在非循环图上很好用。现在我想将其扩展到循环的。我要做的就是检查访问的节点列表中是否已经有新的可能节点。为此,我将not(member(X, PS))添加到我的最后一条规则中。

如果我在递归之前添加它,则它总是返回false。如果在递归之后添加它,那么Prolog会尝试首先查找路径并耗尽堆栈。它会返回正确的答案,但会尝试找到更多答案并陷入困境。

因此:我应该在哪里添加支票,或者我做错了什么/我可以做得更好?

1 个答案:

答案 0 :(得分:1)

您的path2/3谓词需要一个附加参数,因为您的第三个参数是正在构建的路径,而不是已访问节点的列表。即您不能简单地将\+ member(X,Ps)目标添加到谓词的最后一条规则,因为Ps受递归调用的约束。请尝试:

path(X, Y, P) :-
    entry(X),
    path2(X, Y, [], P).

path2(X, Y, _Visited, [Y]) :-
    next(X, Y),
    exit(Y).
path2(X, Y, Visited, [P|PS]) :-
    next(X, P),
    \+ member(P, Visited),
    path2(P, Y, [P| Visited], PS).

通话示例:

| ?- path(X, Y, P).                        

P = [b,c,e]
X = a
Y = e ? ;

P = [b,c,d,f]
X = a
Y = f ? ;

P = [b,d,f]
X = a
Y = f ? ;

no