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

时间:2011-04-11 18:40:30

标签: recursion prolog

我正在尝试在Prolog中模拟一组齿轮。并查询以确定两个轮子是否通过其他链连接。

我有一个简单的递归:

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

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

如果我根据硬连线谓词定义参与:

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

touches(z1,z2).
touches(z2,z3).
touches(z3,z4).

然后这可行。

的测试
connected(z1,z4).

生成true和

connected(z1,z5).

产生错误。

但是,如果我用计算替换我的触摸谓词(两个半径的总和大致是两个中心之间的距离),那么这个搜索会在答案时进入无限递归(堆栈溢出)应该是假的。

为什么要这样,因为我的“触摸”计算本身并不称为“连接”仿函数?是因为触摸函数会尝试匹配比显式谓词更多的原子吗?

这大致是我的计算触摸(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.

1 个答案:

答案 0 :(得分:3)

发生无限递归是因为程序不检查周期。以下是可能发生的事情:

  1. 该程序会找到触及的轮子AB
  2. 鉴于B,它会寻找接触到的轮子。它找到A
  3. 转到1。
  4. 你可以阻止这个在connected的额外参数中考虑已经考虑过的“闭合集”轮子:

    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]).
    

    (为读者练习:缩短它。)