I am trying to implement exponentiation with the code below, but a simple query like 2^1 (ex(s(s(0)), s(0), Z).
) hangs forever.
nat(0).
nat(s(X)) :- nat(X).
su(0, X, X) :- nat(X).
su(s(X), Y, s(Z)) :- su(X, Y, Z).
mu(0, _, 0).
mu(s(X), Y, Z) :- su(Y, A, Z), mu(X, Y, A).
ex(_, 0, s(0)).
ex(X, s(Y), Z) :- mu(X, A, Z), ex(X, Y, A).
As far as I can see, it is not efficient, because the
mu/3
is called with two free variables. Indeed:Both
A
andZ
are unknown at that moment (I have put them in boldface).Now your
mu/2
is not capable of handling this properly. If we querymu/3
withmu(s(0), A, Z)
, we get:So it got stuck in infinite recursion as well.
This is due to the fact that it will tak the second clause of
mu/3
, and:So
su/3
is called with three unknown variables. The effect of this is thatsu/3
can keep proposing values "until the end of times":even if the recursive
mu(X, Y, A)
rejects all these proposals,su/3
will never stop proposing new solutions.Therefore it might be better to keep that in mind when we design the predicates for
mu/3
, andex/3
.We can for example use an accumulator here that accumulates the values, and returns the end product. The advantage of this, is that we work with real values when we make the
su/3
call, like:Now if we enter
mu/3
with only the first parameter fixed, we see:So that means that we now at least do not get stuck in a loop for
mu/3
with only the first parameter fixed.We can use the same strategy to define an
ex/3
predicate:We then manage to calculate exponents like 21 and 22:
Note that the above has still some flaws, for example calculating for which powers the value is
4
will still loop:By rewriting the predicates, we can avoid that as well. But I leave that as an exercise.