Why is Prolog's sum function struggling with non-zero first variables?

  • Thread starter Thread starter gnome
  • Start date Start date
Click For Summary

Discussion Overview

The discussion revolves around the implementation and behavior of a recursive sum function in Prolog, specifically addressing issues encountered when using non-zero first variables. Participants explore the function's definition, its limitations, and potential modifications to improve its performance with various inputs.

Discussion Character

  • Technical explanation
  • Exploratory
  • Debate/contested

Main Points Raised

  • One participant presents a recursive definition of the sum function, noting its effectiveness with zero but struggles with non-zero inputs.
  • Another participant suggests that the issue may stem from how Prolog unifies queries and the use of compound terms like s(X) in the function's clauses.
  • Alternatives to the original clause are proposed, including using arithmetic evaluation with the "is" operator, though some participants express concerns about this approach defeating the purpose of understanding the successor function.
  • One participant shares a working example of a function that converts integers to a symbolic representation using the successor function, indicating that it works correctly for certain queries.
  • There are discussions about the symbolic nature of the successor function and its implications for numerical results in queries.
  • Participants experiment with reordering clauses and combining predicates to see if they can resolve issues with variable inputs and arithmetic expressions.
  • Errors encountered during queries are noted, particularly when supplying variables or incorrect literals, leading to confusion and further exploration of the function's behavior.

Areas of Agreement / Disagreement

Participants do not reach a consensus on the best approach to resolve the issues with the sum function. Multiple competing views and suggestions remain, with ongoing experimentation and refinement of ideas.

Contextual Notes

Some limitations are noted, such as the dependence on the implementation of the successor function in the Prolog interpreter and the challenges with unbound variables in arithmetic expressions. The discussion also highlights the need for careful query formation to avoid errors.

Who May Find This Useful

This discussion may be of interest to those learning Prolog, particularly in understanding recursive functions, unification, and the use of symbolic representations in programming.

gnome
Messages
1,031
Reaction score
1
This is supposed to recursively define a function sum(X,Y,Z) meaning X + Y = Z. how could anything be simpler, right?

Code:
sum(0,Y,Y).
sum(s(X),Y,s(Z)) :- sum(X,Y,Z).
It's very good at telling that 0+1=1 or 0+2=2, etc. But give it anything other than 0 for the first variable and it's lost. What's wrong? :mad:
 
Computer science news on Phys.org
I don't have a Prolog interpreter at hand to check this, but I can make a few suggestions that you can try yourself; at least they will give some clues.

0) I hope a successor predicate is implemented in your interpreter!

1) Prolog works by unifying your query to the head (left-side) of clauses; and unifying is NOT evaluating. So the most probable reason is that compound terms like s(X) or s(Z) in the head of the second clause won't unify with atomic entities such as numbers, in a query like sum(1,2,3).

Try this alternate to your second clause:

sum(X1,Y,Z1) :- X1 is s(X), Z1 is s(Z), sum(X,Y,Z).

(Syntax might vary for the evaluation operator "is"; it might be implemented as "=".)

Hope this helps.

---
Edit:
I fail to recall if s(X) will be at all evaluable. But something that will work in most interpreters is

sum(X1,Y,Z1) :- X1 is X+1, Z1 is Z+1, sum(X,Y,Z).

As for the behavior of the s() predicate, I'm not sure. You can try... and tell us.

---
Edit 2:
Of course, having the ability to evaluate expression you can write a single-clause sum() as

sum(X,Y,Z) :- X is Y+Z.

But I suppose the former has an exercising value. Sorry for the multiple edits, to me it's "long time no see" for Prolog.
 
Last edited:
Thanks for the suggestions, but I still don't have the answer.

0) yes, there is a successor function. For example this program:
Code:
int2s(0,0).
int2s(N,s(S)) :- N>0, N1 is N-1, int2s(N1,S).
works this way:
| ?- int2s(5,T)
T = s(s(s(s(s(0)))))?
yes

1) sum(X1,Y,Z1) :- X1 is s(X), Z1 is s(Z), sum(X,Y,Z).
doesn't compile; gives
error: wrong arithmetic expression : s(_570b34)
error: wrong arithmetic expression : s(_570ba8)

2) sum(X1,Y,Z1) :- X1 is X+1, Z1 is Z+1, sum(X,Y,Z).
sort of defeats the purpose, which was to understand how the successor function works, but I tried it anyway in the interest of science. :smile:
It compiles, and responds reasonably to queries involving addition of 0 to a number, but other queries result in errors I don't understand. For example, this series of queries and responses:
Code:
| ?- compile(math)
Compiling...math.pl
compiled in 0 milliseconds

yes
| ?- load(math)
loading...math.out

yes
| ?- sum(0,1,1)

yes
| ?- sum(X,1,1)
X = 0?
yes
| ?- sum(X,1,2)
** Error ** number_expected:_570828+1
| ?- sum(1,1,2)
** Error ** number_expected:_570828+1
| ?-
 
Hmmm...

It turns out that the original program
Code:
sum(0,Y,Y).
sum(s(X),Y,s(Z)) :- sum(X,Y,Z).
does work. I just wasn't forming the queries correctly. Here's an example of what it gives:
Code:
| ?- sum(s(s(0)),s(s(s(s(s(0))))),T)
T = s(s(s(s(s(s(s(0)))))))?
yes
Guess it'll take a while to figure out how to do something useful with that.
 
Hmmm... and note that this DOESN'T mean that s() is something built-in into your Prolog interpreter. The s() is interpreted symbolically; the whole thing would've equally worked if representing 2 as after(after(0)), where of course after() is nothing special. (And substituting after() for s() accordingly in your clauses, of course.)

As for the failure in " sum(X1,Y,Z1) :- X1 is X+1, Z1 is Z+1, sum(X,Y,Z). ",
1) I assume you did include the initial clause too, "sum(0,Y,Y)."
2) _<number> is the construct the interpreter is using to refer to an unbound variable; the error is saying, "I can't add 1, in X+1 (or Z+1), if X (or Z) has no value". A possible test is to change the order of the second clause (again, experimenting) as
sum(X1,Y,Z1) :- sum(X,Y,Z), X1 is X+1, Z1 is Z+1.
so it'll recurse before the evaluation. (Strange, though.)

Another interesting test is to combine your original problem with the given predicates for int2s() (which "translate" an integer into a symbolic form made of s's). Something like

... int2s as above...

sum(0,Y,Y).
sum(X,Y,Z) :- int2s(X,Xs), int2s(Z,Zs), Xs is s(X0), Zs is s(Z0), sum(X0,Y,Z0).

or, alternatively,

sum(0,Y,Y).
sum(X,Y,Z) :- int2s(X,s(X0)), int2s(Z,s(Z0)), sum(X0,Y,Z0).

and check if it accepts integers now.
 
Last edited:
>>.. and note that this DOESN'T mean that s() is something built-in into your Prolog interpreter.
Thanks for pointing that out. Now it makes more sense that it doesn't produce a numerical result.


>>1) I assume you did include the initial clause too, "sum(0,Y,Y)."
Of course.

>>A possible test is to change the order of the second clause (again, experimenting) as
>>sum(X1,Y,Z1) :- sum(X,Y,Z), X1 is X+1, Z1 is Z+1.
Interestingly, that almost works. It seems to be a case of yes/maybe. Here are some sample queries to that:
Code:
| ?- sum(0,1,T)
T = 1?
yes
| ?- sum(1,1,T)...(
T = 2?
yes
| ?- sum(4,6,T)
T = 10?
yes
| ?- sum(5,2,7)...(here I supplied all 3 literals & it responded correctly)

yes
| ?- sum(1,2,3)...(same here)

yes
| ?- sum(T,2,5)...(here I supply a variable for the first term; response is appropriate)
T = 3?
yes
| ?- sum(2,T,5)...(but it can't deal with the variable as the 2nd term)
** Error ** number_expected:_570828+1
| ?- sum(4,2,7)...(and if I supply 3 literals that don't add correctly, instead of saying "no" it hangs
| ?-......(I had to use ctrl-c to get out of that loop)
Your last two suggestions are interesting, but they didn't work. The first one
Code:
sum(0,Y,Y).
sum(X,Y,Z) :- int2s(X,Xs), int2s(Z,Zs), Xs is s(X0), Zs is s(Z0), sum(X0,Y,Z0).
doesn't compile, giving two "wrong arithmetic expression" errors on the s(X0) and s(Z0) expressions.
The last one
Code:
sum(0,Y,Y).
sum(X,Y,Z) :- int2s(X,s(X0)), int2s(Z,s(Z0)), sum(X0,Y,Z0).
compiles but doesn't do what we wanted. It gives good responses to queries in the form (T,4,4) or (0,4,4) for example, but any other format gives "error : number expected".

Still, there should be some way to combine the predicates. I'll work on it some more as time permits.

PS: If you want to play around with small prolog programs, here's a link to a cute online prolog implementation. It's not what I've been using (I'm using B-prolog) but it seems to work the same for these little programs.
http://kti.ms.mff.cuni.cz/~bartak/prolog/testing.html
 
"Don't give a man a fish, but a fishing rod." Thanks for the link!

Edit: After some sleep :), I can see I forgot, in the second variant of the last example, to convert the s's back to numbers, before recursing...
 
Last edited:

Similar threads

  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 3 ·
Replies
3
Views
806
  • · Replies 1 ·
Replies
1
Views
2K
Replies
1
Views
2K
  • · Replies 8 ·
Replies
8
Views
3K
  • · Replies 11 ·
Replies
11
Views
2K
Replies
26
Views
3K
Replies
2
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K