1

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?

9
  • The call to number(Z) will fail if Z is currently uninstantiated. Commented Jul 30, 2021 at 16:52
  • @gusbro I thought that number(Z) did actually instantiate Z. Because removing that literal yields an error: Arguments are not sufficiently instantiated. Commented Jul 30, 2021 at 16:54
  • number(Z) checks whether Z is a number. The error you are getting when you remove that call is from succ(V, Z) because both V and Z are uninstantiated in your sample call. You have to change your algorithm or use CLP(fd) Commented Jul 30, 2021 at 17:04
  • @gusbro And how would you change the algorithm (I don’t want to use CLP)? Commented Jul 30, 2021 at 17:07
  • 1
    you have to remove the number(Z) as stated in my first comment Commented Jul 30, 2021 at 17:32

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks! Is there a way to make it work for any modes (without CLP)?
You can easily make it work with queries that have 2 ground arguments. You just have to use the proper equation for the unbound argument. I get you want to do this as an exercise so you may try it yourself.
Also the usual recursive solution for this problem uses peano representation of successors and not actual integers. You may look for peano and addition on this site for similar questions.
So add(X, Y, Z) :- succ(V, Z), add(U, Y, V), succ(U, X). works for a single variable in the first position (e.g. add(X, 2, 2)), add(X, Y, Z) :- succ(U, X), succ(V, Z), add(U, Y, V). works for a single variable in the second position (e.g. add(2, Y, 2).), and add(X, Y, Z) :- succ(U, X), add(U, Y, V), succ(V, Z). works for a single variable in the third position (e.g. add(2, 2, Z).). How can I combine these clauses into a single rule to handle these three kinds of query?
@Maggyero: Edited the answer to show how you may combine those clauses onto a single rule that handles any case with at most 1 free variable
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.