Prolog传递闭包:迷宫探路者

Prolog传递闭包:迷宫探路者,prolog,transitive-closure,Prolog,Transitive Closure,我对实现一个简单的Prolog程序感兴趣,该程序可以在迷宫结构上执行路径查找查询 /* i_ -> intersections */ i_(c,b). /* horizontal adjacencies */ i_(g,h). i_(h,i). i_(i,g). i_(a,d). /* vertical adjacencies */ i_(d,g). i_(c,f). i_(f,i). /* symmetric interface */ i(X,Y) :- i_(X,Y);i_(Y,X

我对实现一个简单的Prolog程序感兴趣,该程序可以在迷宫结构上执行路径查找查询

/* i_ -> intersections  */
i_(c,b). /* horizontal adjacencies */
i_(g,h).
i_(h,i).
i_(i,g).
i_(a,d). /* vertical adjacencies */
i_(d,g).
i_(c,f).
i_(f,i).

/* symmetric interface */
i(X,Y) :- i_(X,Y);i_(Y,X).

/* path, the rule in question*/
path(X,Y) :- i(X,Y) ; i(X,Z), path(Z,Y).
错误:当path与输入节点>=5步远时,我的Prolog解释器(SWI)会陷入无限递归状态。 但是,当路径中的步进节点少于5个时,该规则可以正常工作。奇怪的是,省略对称规则(简单地声明每个邻接,向后和向前),将路径的调用限制减少到少于3个节点。再次覆盖默认堆栈分配会增加堆栈溢出之前的路径范围

显然,蓄能器是正常的。我怀疑我的程序在运行时崩溃,因为解释器继续重新访问路径中已经遍历的节点

我修改了
路径
,以包含
法律
的附加要求,该要求用作累加器:

/* path --> recursive path check */
legal(Z,[]).
legal(Z,[H|T]):- Z\==H, legal(Z,T). 
path(X,Y,T) :- i(X,Y) ; i(X,Z), legal(Z,T), path(Z,Y,[Z|T]).
然而,我现在面临一个问题,var
Z
是一个“单例”


关于如何正确实现累加器以避免过度堆栈调用的任何建议?

path(X,Y):-closure0(I,X,Y)。
请参阅的定义。使用SWI Prolog时,出现以下错误:?-path(a,b)。错误:路径/2:未定义的过程:closure0/3异常:(7)closure0(i,a,b)?未知选项(h表示帮助)异常:(7)closure0(i,a,b)?creep@DavidShakedfalse显示的链接中给出了
closure0/3
的定义。它不在SWI图书馆。嗨,大卫!我相信我们在前几天的N语言会议上简要地讨论了这一点。
Singleton variables
警告只是提醒您,在
legal(Z,[])子句中,变量
Z
只出现一次。此警告有助于捕获由输入错误(其中一个变量的名称稍有错误)引起的许多错误。通常,当您不需要在同一子句中再次使用变量时,请将其匿名:
legal(,[])。
,这样您就不会收到(无害的)警告。@ShonFeder并不是真正无害的,或者更确切地说,在本例中是无害的,但您可以解释为什么绝对不应该忽略它。
path(X,Y):-closure0(i,X,Y).
请参阅的定义。使用SWI Prolog时,出现以下错误:?-path(a,b)。错误:路径/2:未定义的过程:closure0/3异常:(7)closure0(i,a,b)?未知选项(h表示帮助)异常:(7)closure0(i,a,b)?creep@DavidShakedfalse显示的链接中给出了
closure0/3
的定义。它不在SWI图书馆。嗨,大卫!我相信我们在前几天的N语言会议上简要地讨论了这一点。
Singleton variables
警告只是提醒您,在
legal(Z,[])子句中,变量
Z
只出现一次。此警告有助于捕获由输入错误(其中一个变量的名称稍有错误)引起的许多错误。通常,当您不需要在同一子句中再次使用变量时,请将其匿名:
legal([])。
,这样您就不会收到(无害的)警告。@ShonFeder实际上并不是无害的,或者说,在这种情况下是无害的,但您解释了为什么绝对不应该忽略它。