Prolog出本地堆栈错误

Prolog出本地堆栈错误,prolog,transitive-closure,Prolog,Transitive Closure,我尝试了一本书中的一些基本示例,它会出现“本地堆栈外”错误(代码之后我会告诉更多)。 代码如下: edge(a,b). edge(a,e). edge(b,d). edge(b,c). edge(c,a). edge(e,b). tedge(Node1,Node2) :- edge(Node1,SomeNode), edge(SomeNode,Node2). edge(X,Y) :- tedge(X,Y). 例如,我尝试编写查询边缘(a,b),结果返回true,然后输入“;”它

我尝试了一本书中的一些基本示例,它会出现“本地堆栈外”错误(代码之后我会告诉更多)。 代码如下:

edge(a,b).
edge(a,e).
edge(b,d).
edge(b,c).
edge(c,a).
edge(e,b).
tedge(Node1,Node2) :-
    edge(Node1,SomeNode),
    edge(SomeNode,Node2).
edge(X,Y) :- tedge(X,Y).
例如,我尝试编写查询边缘(a,b),结果返回true,然后输入“;”它犯了错误。
这里的问题是什么?

问题是您已经以循环的方式定义了什么是边。在寻找从
a
b
的第二条路径时,Prolog正在
tedge(a,VAR)
edge(a,VAR)
tedge(a,VAR)
等之间循环

请注意,即使没有将边定义为对称,Prolog也会循环,这是由于循环
a->b->c->a

解决方案是跟踪以前访问过的顶点和/或边。可以使用(我从SO user false中学到的谓词)直接实现对非重复顶点的检查。如果使用该谓词,则只需要
edge/2
事实和以下查询:

?- closure0(edge, a, b).

简而言之,它进入了无限递归。如果您执行
跟踪
,您将看到发生了什么。为什么要定义边(X,Y):-tedge(X,Y)。?它必然会创建一个循环场景,因为
edge/2
还定义了
tedge/2
所指的事实。把它放在
tedge/2
上,然后查询
tedge(a,b)。
。真是奢侈,我不需要再输入答案了!