In prolog, why is `(1+2) is (2+1)` false? - prolog

I'm trying to learn some prolog using the gprolog tool. I'm trying to see if lists sum up to the same value. I'm trying to understand why this expression is false.
{trace,1}
| ?- (2+1) is (1+2).
2 2 Call: 2+1 is 1+2 ?
2 2 Fail: 2+1 is 1+2 ?
no
Shouldn't 1+2 and 2+1 be equivalent because addition is associative?

It's simple because is evaluates the right-hand side and tries to unify it with the left-hand side.
Thus you get:
(2+1) = 3.
These two don't look the same (in fact, the "term" on the left-hand side is the prettyprinted structure +(2,1) as you can check by calling write_canonical(2+1).) and = (which is "unification", not comparison or assignment) fails.
What you want in his case is
?- 2+1 =:= 2+1.
true.
which performs numeric evaluation on both left-hand and right-hand sides, and then numerically compares the results.
Which is why this fails:
?- X =:= 2+1.
ERROR: Arguments are not sufficiently instantiated
but this succeeds:
?- X = 3, X =:= 2+1.
X = 3.

The two terms 1+2 and 2+1 are not equivalent. If you evaluate them as arithmetic expression, they have equal numeric values:
?- 1+2 =:= 2+1. % arithmetic equality
Alternatively, you could evaluate explicitly both sides and then compare:
?- X is 1 + 2, Y is 2 + 1, X == Y.
But this has its own different semantics. For example:
?- X is sin(pi/2), X == 1. % no!
?- X is sin(pi/2), X =:= 1. % yes
Unification with = and equivalence with == are two different things. This is what unification can do:
?- X + 2 = 1 + Y.
Equivalence checks if the two terms are equivalent. +(1, 2) and +(2, 1) are not equivalent; the functor is the same but the two arguments are swapped.

Related

Prolog power of 2 recursion

Need help creating a recursive clause is a rule: X is a power of 2 only if there is a Y such that when adding Y to Y the result is
X, and Y is a power of 2. in prolog
We are going to define this predicate recursively. The followings are the fact and rule for detecting whether a numeral
is a power of 2 or not:
• The base clause is a fact: 1 is a power of 2 (because 1=20);
• The recursive clause is a rule: X is a power of 2 only if there is a Y such that when adding Y to Y the result is
X, and Y is a power of 2.
For example, the following shows how the queries should be performed:
| ?- powerOf2(succ(succ(succ(succ(0))))).
true ?
yes
| ?- powerOf2(succ(succ(succ(0)))).
no
The first query shows that 4 is a power of 2; while the second shows that 3 is not.
can not use the built-in is/2 predicate to perform arithmetic
To make it easier to represent natural numbers in Peano notation, you can use the following predicate:
nat(0, 0).
nat(N, s(P)) :-
succ(M, N),
nat(M, P).
Examples:
?- nat(3, P).
P = s(s(s(0))) ;
false.
?- nat(5, P).
P = s(s(s(s(s(0))))) ;
false.
To get the double of a Peano number, use the predicate:
double(0, 0).
double(s(A), s(s(B))) :-
double(A, B).
Examples:
?- nat(1, P), double(P, D).
P = s(0),
D = s(s(0)) ;
false.
?- nat(3, P), double(P, D).
P = s(s(s(0))),
D = s(s(s(s(s(s(0)))))) ;
false.
To check whether a Peano number is a power of two, use the predicate:
power_of_two(s(0)).
power_of_two(s(s(N))) :-
double(M, s(s(N))),
power_of_two(M).
Example:
?- between(1,9,N), nat(N,P), power_of_two(P).
N = 1,
P = s(0) ;
N = 2,
P = s(s(0)) ;
N = 4,
P = s(s(s(s(0)))) ;
N = 8,
P = s(s(s(s(s(s(s(s(0)))))))) ;
false.
Need help creating a recursive clause
The recursive clause will be:
power_of_two(1).
power_of_two(X) :-
X > 1,
Y is X / 2,
power_of_two(Y).
A base case which handles 1 being a power of two. And a case which handles when X is greater than one, Y is half X and recursively checks that Y is a power of two.
can not use the built-in is/2 predicate to perform arithmetic
You can't, but I can for the sake of illustrating the recursive clause you asked about. I'm assuming that since it tells you to use "succ(succ(succ(succ(0))))" you already have met that and have some code for adding/subtracting/dividing which you can reuse to replace Y is X / 2.

SWI-Prolog: Call 3=2+1 -> Fail: 3=2+1

I'm working on something in Prolog and I wanted to check, at some point in my proogram, if some variable1 equals variable 2 + 1 (var1=var2+1). It said false. Variable1 is equal to 3 in my case, and var2 is equal to 2. It doesn't register as true and I can't understand why. I tried to 'trace' it, but still can't understand what the problem is, it just fails.
In Prolog 2+1 is just 2+1, or more canonical +(2,1). After all, it is only because some people see + as addition that 2+1 is equivalent to 3.
You can use is/2 [swi-doc] to evaluate an arithmetic expression, for example:
?- X is 2+1.
X = 3.
?- 3 is 2+1.
true.
You can also =:=/2 [swi-doc] to check if the two operands are equivalent if these are evaluated arithmetically:
?- 3 =:= 2+1.
true.
?- 4 =:= 2+1.
false.

Prolog - equal operator wrapping

equal(a, b) :- (a = b).
I defined equal.
1 ?- [index].
true.
2 ?- equal(1, 1).
false.
3 ?- 1 = 1.
true.
When I run
equal(1, 1)
it returns false.
Why does it return false and how can i fix it?
First of all, you should write equal(A, B) :- A = B instead of what you've written. The difference is that a and b are constants and A and B are variables that can be unified with values. I guess then it should work for your example.
But you should note that "=" predicate just tries to unify its arguments. So when you ask "1 = 1" the result is true because 1 unifies with 1. But when you ask "2 + 2 = 4" (or equal(2 + 2, 4)) the result will be false because this operator does not evaluate arithmetic operations. If comparing arithmetic expressions is what you want to do use =:= operator instead:
equal(A, B) :- A =:= B.

Why `X=1,X=1.` prints `X=1` instead of `true`

I'm learning the basics of Prolog and I was wondering why the following line prints X = 1 instead of true?
?- X=1,1=X.
X = 1.
--
The first X=1 in my command is an assignment, and the second one will be a check of equality.
There are no assignments or equality tests in your query, only unification of terms. The query succeeds by unifying the variable X with 1 and that's what the top-level reports: it tells which variable bindings makes the query true.
After the first goal in the conjunction, X = 1, succeeds, the second goal is the unification 1 = 1, which trivially succeeds.
P.S. Also note that Prolog systems differ in the way they report successful queries. Some print true, others print yes (the traditional way that successful queries are reported).
When the answer is true and a value is bound to variable at the top level, the value of the variable is displayed, which implies the result was true.
Here are some examples.
test_01 :-
X = 1,
X = 1.
test_02 :-
X = 1,
X = 2.
test_03(X) :-
X = 1,
X = 1.
test_04(X) :-
X = 1,
X = 2.
and when the examples are run from the top level using SWI-Prolog
?- test_01.
true.
?- test_02.
false.
?- test_03(X).
X = 1.
?- test_04(X).
false.
Here are some examples that are done only in the top level
?- X=1.
X = 1.
?- 1=1.
true.
?- 1=0.
false.
?- 1==0.
false.
The first X=1 in my command is an assignment, and the second one will be a check of equality.
X=1 is not an assignment it is a unification of the integer 1 to the variable X. The second X=1 is not a check of the equality, it is another unification of X to 1, but since X is bound to 1 by this time, it is really a different unification.
To do equality checking in Prolog use ==, e.g.
?- 1 == 1.
true.
?- 1 == 2.
false.
Also , is the logical and, so if
?- X = 1.
X = 1.
then 1 is bound to X and is true and similar for the second line in your question.
However the code has to be also viewed as
?- true,true.
true.
as opposed to
?- true,false.
false.
While ; is logical or
?- true;true.
true ;
true.
?- true;false.
true ;
false.
?- true;false;true.
true ;
true.
?- false;true.
true.
?- false;false.
false.
Notice that the first 3 answers have 2 results, but the last two answers have 1 result.

What is the difference between is and =?

I have entered these statements into the prolog interpreter and am confused by the results. Shouldn't they return the same thing; true?
1 ?- 7 = 5 + 2.
false.
2 ?- 7 is 5 + 2.
true.
No, because =/2 does not mean assign in Prolog, but rather unify. And the unification algorithm does not know anything at all about arithmetic, just structure. So you can do some interesting things with arithmetic expressions in Prolog that are quite difficult to pull off in other languages:
?- X = 5 + 2.
X = 5+2.
It looks like nothing happened there, but what actually happened is X was given the value "5 + 2" as a structure. Put another way:
?- A + B = 5 + 2.
A = 5,
B = 2.
Or even:
?- X = 5 + 2, X =.. [Op|_].
X = 5+2,
Op = (+).
That last one might make more sense with the whole list though:
?- X = 5 + 2, X =.. Y.
X = 5+2,
Y = [+, 5, 2].
This is an effect of the remarkable "univ" operator, =../2, which is able to convert between Lisp-like lists and Prolog syntax, enabling you to do interesting construction and decomposition of structures in a generic fashion.
Now, is/2, on the other hand, does know about arithmetic. It unifies its left argument with the result of arithmetic simplification of its right. Do note that it only works in one direction:
?- 7 is 5 + 2.
true.
?- 5 + 2 is 7.
false.
You could say that =/2 is interested in structure and is/2 is interested in numeric equality. But it does mean that it's unusually easy to teach Prolog algebra:
simplify(X * Y + X * Z, X * (Y + Z)). % distributive property
simplify(X, X).
?- simplify(A * 3 + A * 4, Q).
Q = A* (3+4)
Now, this isn't perfect (note that we got 3+4 and not 7) and it's still a lot of work to make it really smart:
?- simplify(3 * A + 4 * A, Q).
Q = 3*A+4*A.
But that's a problem for another day.
Nutshell:
=/2 triggers unification
is/2 triggers arithmetic evaluation

Resources