Prolog predicate - infinite loop

喜你入骨 提交于 2019-11-28 13:47:18

This happends because the of evaluation order of pow2. If you switch the order of pow2, you'll have the first example stuck in infinite loop.. So you can check first if Y is a var or nonvar.

Like so:

times2(X,Y) :-
  add(X,X,Y).

pow2(0,s(0)).
pow2(s(N),Y) :-
  var(Y),
  pow2(N,Z),
  times2(Z,Y).
pow2(s(N),Y) :-
  nonvar(Y),
  times2(Z,Y),
  pow2(N,Z).

Here is a version that terminates for the first or second argument being bound:

pow2(E,X) :-
  pow2(E,X,X).

pow2(0,s(0),s(_)).
pow2(s(N),Y,s(B)) :-
   pow2(N,Z,B),
   add(Z,Z,Y).

You can determine its termination conditions with cTI.

So, how did I come up with that solution? The idea was to find a way how the second argument might determine the size of the first argument. The key idea being that for all iN: 2i > i.

So I added a further argument to express this relation. Maybe you can strengthen it a bit further?


And here is the reason why the original program does not terminate. I give the reason as a . See tag for more details and other examples.

?- pow2(P,s(s(0))), false.

pow2(0,s(0)) :- false.
pow2(s(N),Y) :-
  pow2(N,Z), false,
  times2(Z,Y).

It is this tiny fragment which is the source for non-termination! Look at Z which is a fresh new variable! To fix the problem, this fragment has to be modified somehow.


And here is the reason why @Keeper's solution does not terminate for pow2(s(0),s(N)).

?- pow2(s(0),s(N)), false.

add(0,Z,Z) :- false.
add(s(X),Y,s(Z)) :-
  add(X,Y,Z), false.

times2(X,Y) :-
  add(X,X,Y), false.

pow2(0,s(0)) :- false.
pow2(s(N),Y) :- false,
  var(Y),
  pow2(N,Z),
  times2(Z,Y).
pow2(s(N),Y) :-
  nonvar(Y),
  times2(Z,Y), false,
  pow2(N,Z).
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!