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).
产生 false。
但是,如果我用计算替换触摸谓词(两个半径的总和大致等于两个中心之间的距离),那么当答案应该为 false 时,此搜索将进入看起来像无限递归(堆栈溢出)的情况。
鉴于我的“接触”计算本身并不调用“连接”函子,为什么会这样呢?是因为接触函子会尝试匹配比显式谓词更多的原子吗?
粗略地说,这是我计算出的接触点(A 和 B 是轮子,ARAD 和 BRAD 是它们的半径,D 是距离,approx 是“大约等于”函数。
touches(A,B) :-
wheel(A,_,_,ARAD),
wheel(B,_,_,BRAD),
distance(A,B,D),
approx(D,(ARAD+BRAD),2),
A \== B.
I'm trying to model a set of cog wheels in Prolog. And to query to find if two wheels are connected by a chain of others.
I have a simple recursion :
connected(X,Y) :-
engages(X,Y).
connected(X,Y) :-
engages(X,Z),
connected(Z,Y).
If I define engages in terms of a hard-wired predicate :
engages(X,Y) :- touches(X,Y).
and
touches(z1,z2).
touches(z2,z3).
touches(z3,z4).
Then this works.
A test of
connected(z1,z4).
produces true and
connected(z1,z5).
produces false.
However, if I replace my touches predicate with a calculation (that the sum of the two radii is roughly the distance between the two centres), then this search goes into what looks like an infinite recursion (stack overflow) when the answer should be false.
Why should this be, given that my "touches" calculation doesn't itself call the "connected" functor? Is it because a touches functor is going to try to match more atoms than the explicit predicates?
This, roughly, is my calculated touches (A and B are the wheels, ARAD and BRAD are their radii, D is distance and approx is an "approximately equals" function.
touches(A,B) :-
wheel(A,_,_,ARAD),
wheel(B,_,_,BRAD),
distance(A,B,D),
approx(D,(ARAD+BRAD),2),
A \== B.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
发生无限递归是因为程序不检查循环。可能会发生以下情况:
A
和B
,它们相互接触。B
,它会寻找一个接触的轮子。它找到A
。您可以阻止它维护已在
connected
的额外参数中考虑的“封闭组”轮子:(给读者的练习:缩短它。)
The infinite recursion occurs because the program doesn't check for cycles. Here's what might happen:
A
andB
, that touch.B
, it looks for a wheel that touches. It findsA
.You can prevent this from maintaining a "closed set" of wheels already considered in an extra argument to
connected
:(Exercise for the reader: shorten this.)