Recursion 如何避免Prolog递归中的这个陷阱?

Recursion 如何避免Prolog递归中的这个陷阱?,recursion,prolog,Recursion,Prolog,我的目标是能够遍历图中的节点,并在Prolog中输出路径的长度。我正在使用递归,我在这个问题上陷入了困境。这是我迄今为止的尝试 edge(a,b). edge(b,c). edge(a,d). edge(d,f). distance(X,Y,1) :- edge(X,Y). distance(X,Y,Dis) :- edge(X,Z), distance(Z, Y, D), Dis is D +1. 问题:我想说Dis=0。如果路径无效。与中一样,没有连接两个节点的边,Dis=0。目前,我的

我的目标是能够遍历图中的节点,并在Prolog中输出路径的长度。我正在使用递归,我在这个问题上陷入了困境。这是我迄今为止的尝试

edge(a,b).
edge(b,c).
edge(a,d).
edge(d,f).

distance(X,Y,1) :- edge(X,Y).
distance(X,Y,Dis) :- edge(X,Z), distance(Z, Y, D), Dis is D +1.

问题:我想说Dis=0。如果路径无效。与中一样,没有连接两个节点的边,Dis=0。目前,我的代码对一个无效的路径说false。我在这方面的尝试导致我打破了递归。谢谢你的帮助。

正如@Hashcut在他的评论中所说,如果
Dis=0
,那么
X=Y
就更有意义了。事实上,如果路径无效,谓词将失败是完全合乎逻辑的

现在,如果你真的想做你所说的,你可以这样做:

distance_(X,Y,1) :- edge(X,Y).
distance_(X,Y,Dis) :- edge(X,Z), distance_(Z, Y, D), Dis is D + 1.

distance(X,Y,D) :- distance_(X,Y,D) -> true ; D = 0.
我们只需将原始谓词重命名为
距离
,然后创建谓词
距离
,如果路径存在,它的操作与之前相同;如果路径失败,则将
D
0
统一<如果路径有效,则代码>->用于放弃选择
D=0

请注意,您有以下行为:

?- distance(a,a,X).
X = 0.

?- distance(b,f,X).
X = 0.

这有点奇怪,但因为你想要的东西而被期待。

你确定距离的语义吗?Dis=0是否意味着这两个节点是相同的?这可以编码为距离(X,X,0)。