Prolog超出本地堆栈空间/无限递归

时间:2014-08-26 14:05:15

标签: recursion prolog infinite-loop transitive-closure failure-slice

我在本网站上已经阅读了其他类似的问题和答案,但似乎无法找到我特定问题的答案。我正在尝试编码Prolog中的迷宫。 从区域0,您可以自由移动到区域1或区域3.从区域3,您可以自由移动到区域0,区域4或区域5等。我想找到长度为7的所有路径从开始到结束(从0到14)。我在SWI-Prolog中以下列方式编码了问题:

    region(0).
    region(1).
    region(2).
    region(3).
    region(4).
    region(5).
    region(6).
    region(7).
    region(8).
    region(9).
    region(10).
    region(11).
    region(12).
    region(13).
    region(14).
    region(15).

    connection(0,1).                %connection exists between these two regions
    connection(0,3).        
    connection(1,2).
    connection(1,8).
    connection(1,7).
    connection(3,4).
    connection(3,5).
    connection(7,9).
    connection(7,5).
    connection(7,8).
    connection(5,6).
    connection(8,10).
    connection(8,11).
    connection(11,12).
    connection(11,13).
    connection(13,15).
    connection(13,14).

    double_link(X,Y) :-
       region(X),
       region(Y),
       ( connection(X,Y) | connection(Y,X) ). %can go from region X to region Y, and vice versa

    path(X,Y) :-
       double_link(X,Y).
    path(X,Y) :-
       double_link(X,Z),
       path(Z,Y).

当我执行path(14,0).时,我得到true。但是,当我执行path(0,14)。时,我的本地堆栈空间不足。我不知道那是怎么回事。谢谢你的帮助!

2 个答案:

答案 0 :(得分:4)

你说:

  

当我执行path(14,0).时,我得到true

这是事实的一半!哦,甚至还不到那个!事实上,你得到true不是一次,而是多次!

?- path(14,0).
true ;
true ;
true ;
true ;
true ;
true ...

有一种简单的方法可以避免一直输入; SPACE 。只需使用目标 false

    ?- path(14,0), false
    **LOOPS**

现在,您还可以在程序中添加 false -goals。通过这种方式,你排除了部分计划;如果剩下的部分仍然循环,你知道那里肯定存在问题。这就是我得到的:

region(0) :- false.
% ...
region(12) :- false.
region(13).
region(14).
region(15) :- false.

connection(0,1) :- false.
% ...
connection(13,15) :- false.
connection(13,14).

double_link(X,Y) :-
   region(X),
   region(Y),
   ( connection(X,Y) ; connection(Y,X) ).

path(X,Y) :- false,
   double_link(X,Y).
path(X,Y) :-
   double_link(X,Z),
   path(Z,Y), false.

所以在剩下的部分中,必须解决循环问题。它现在应该是不言自明的,不是吗?

答案 1 :(得分:2)

问题出现了,因为你可以在迷宫中进入圈子。例如。在你的迷宫中你有联系0 - 1 - 7 - 5 - 3 - 0。您尚未采取任何措施来确保搜索不会盲目跟随这些圈子。

通常的做法是在路径谓词中添加一个参数,该参数包含已访问过的区域(最初为空)。然后,您必须确保何时转到XX不在该列表中的新位置(例如nonmember(X,Visited))。