我正在尝试在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.
答案 0 :(得分:3)
发生无限递归是因为程序不检查周期。以下是可能发生的事情:
A
和B
。B
,它会寻找接触到的轮子。它找到A
。你可以阻止这个在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]).
(为读者练习:缩短它。)