Search code examples
recursionprologadditionsuccessor-arithmetics

How to fix this recursive addition?


I am new to logic programming and Prolog. The following Prolog program defines a predicate add/3 for multiplying the first argument to the second argument, which results in the third argument, based on the equation x + y = z which is equivalent to (x − 1) + y = (z − 1):

add(0, Y, Y) :-
  number(Y).
add(X, Y, Z) :-
  number(X),
  number(Z),
  succ(U, X),
  succ(V, Z),
  add(U, Y, V).

But it this query, supposed to solve the equation 1 + 0 = z, does not return the expected result (1):

?- add(1, 0, Z).
   false.

How to fix this recursive addition?


Solution

  • The reason you get false is because the second clause of add/3 calls number(Z) which only succeeds for ground number variables, but you are calling it with Z uninstantiated. number/1 cannot be used as a generator.

    Removing that goal will in turn give you another error, now in succ(V, Z) as you end up calling it with both variables uninstantiated and that predicate requires that at least one of its arguments be instantiated.

    You can swap the goal with the recursive call to add/3 so that V gets instantiated prior to calling succ/2. As succ/2 already checks its arguments I will just remove the check for X being a number.

    add(0, Y, Y) :-
      number(Y).
    add(X, Y, Z) :- 
      succ(U, X),
      add(U, Y, V),
      succ(V, Z).
    

    This procedure now should work for mode +,+,?. It will not work right for other modes. You may want to check CLP(fd).


    To make it work with at most 1 unbound variable within the three parameters you may split the recursive step on two different paths so as to ensure the first call to succ/2 has 1 bound variable and the second call to succ/2 has at least 1 bound variable.

    add(0, Y, Y) :-
      number(Y).
    add(X, Y, Z) :-
      (var(Z) -> L1-R1/L2-R2 = U-X/V-Z; L2-R2/L1-R1 = U-X/V-Z),
      succ(L1, R1),
      add(U, Y, V),
      succ(L2, R2).
    

    which essentially selects an equation which can be evaluated with Prolog arithmetics.