如何解决为什么我的序言规则陷入无限递归
我的代码可以达到预期的目的,但总是在最后陷入循环,给我一个错误,提示“超出堆栈限制”。我的代码如下:
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).
byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).
byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).
travel(X,Y):- byCar(X,Y).
travel(X,Y):- byTrain(X,Y):- byPlane(X,Y):- travel(X,Z),travel(Z,Y).
解决方法
当您调用类似travel(metz,To)
之类的内容时,travel/2
的最后一个子句将使用新变量travel(metz,Z)
调用Z
,然后可以使用以下变量调用travel(metz,Z2)
一个新变量Z2
,依此类推。
此问题称为“左递归”:您有一个递归调用,该调用等效于子句从头到尾(即从头开始)的原始目标。解决方案是在递归调用之前“取得一些进展”。在这种情况下,您可以在递归之前跳一跳:
step(X,Y) :-
byCar(X,Y).
step(X,Y) :-
byTrain(X,Y) :-
byPlane(X,Y).
travel(X,Y) :-
step(X,Y).
travel(X,Z) :-
step(X,Y),travel(Y,Z).
此操作现在终止:
?- travel(metz,To).
To = frankfurt ;
To = paris ;
To = bangkok ;
To = singapore ;
To = auckland ;
To = hamilton ;
To = raglan ;
To = auckland ;
To = hamilton ;
To = raglan ;
To = losAngeles ;
To = auckland ;
To = hamilton ;
To = raglan ;
false.
正如false的注释中指出的那样,您可以使用通用谓词来捕获这种闭合:Definition of Reflexive Transitive Closure。另外,某些Prolog系统提供了一个称为“ tabling”的功能,您可以使用它来避免这种问题:https://www.swi-prolog.org/pldoc/man?section=tabling-non-termination
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。