Recursion Prolog:具有计算结束条件的递归问题

Recursion Prolog:具有计算结束条件的递归问题,recursion,prolog,Recursion,Prolog,我试图在Prolog中为一组齿轮建模。并查询两个车轮是否由其他车轮链连接 我有一个简单的递归: connected(X,Y) :- engages(X,Y). connected(X,Y) :- engages(X,Z), connected(Z,Y). 如果我用硬连线谓词定义接合: engages(X,Y) :- touches(X,Y). 及 这样就行了 测试 connected(z1,z4). 产生真实的 connected(z1,z5). 产生错误

我试图在Prolog中为一组齿轮建模。并查询两个车轮是否由其他车轮链连接

我有一个简单的递归:

connected(X,Y) :-   
    engages(X,Y).

connected(X,Y) :-
    engages(X,Z),
    connected(Z,Y).
如果我用硬连线谓词定义接合:

engages(X,Y) :- touches(X,Y).

这样就行了

测试

connected(z1,z4).
产生真实的

connected(z1,z5).
产生错误

但是,如果我用一个计算(两个半径之和大致等于两个中心之间的距离)替换我的touch谓词,那么当答案为false时,这个搜索将进入一个看起来像无限递归(堆栈溢出)的过程

既然我的“接触”计算本身并不调用“连接”函子,为什么会这样呢?是因为一个函数试图匹配比显式谓词更多的原子吗

这大致是我计算的接触(A和B是车轮,ARAD和BRAD是半径,D是距离,近似是“近似等于”的函数)

touches(A,B) :- 
    wheel(A,_,_,ARAD),
    wheel(B,_,_,BRAD),
    distance(A,B,D),
    approx(D,(ARAD+BRAD),2),
    A \== B.

发生无限递归是因为程序不检查循环。下面是可能发生的情况:

  • 程序会找到触碰的车轮
    A
    B
  • 给定
    B
    ,它寻找一个接触的轮子。它找到
    a
  • 转到1
  • 您可以防止这种情况发生,使
    已连接的
    的额外参数中已考虑的控制盘保持“闭合集”:

    connected(X,Y) :-
        connected(X,Y,[]).
    connected(X,Y,Closed) :-
        touches(X,Y),
        \+ memberchk(Y,Closed).
    connected(X,Z,Closed) :-
        touches(X,Y),
        \+ memberchk(Y,Closed),
        connected(Y,Z,[Y|Closed]).
    

    (读者练习:缩短时间。)

    无限递归发生是因为程序不检查循环。下面是可能发生的情况:

  • 程序会找到触碰的车轮
    A
    B
  • 给定
    B
    ,它寻找一个接触的轮子。它找到
    a
  • 转到1
  • 您可以防止这种情况发生,使
    已连接的
    的额外参数中已考虑的控制盘保持“闭合集”:

    connected(X,Y) :-
        connected(X,Y,[]).
    connected(X,Y,Closed) :-
        touches(X,Y),
        \+ memberchk(Y,Closed).
    connected(X,Z,Closed) :-
        touches(X,Y),
        \+ memberchk(Y,Closed),
        connected(Y,Z,[Y|Closed]).
    

    (读者练习:缩短此长度。)

    好的。这只发生在第二种情况下,即计算接触,因为这是接触(A,B)和接触(B,A)都为真的情况。让我试试……好的,太好了。谢谢。:-)好的。它只发生在第二种情况下,计算接触,因为接触(A,B)和接触(B,A)都是真的。让我试试……好的,那太好了。谢谢。:-)