Prolog - equal operator wrapping - prolog

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.

Related

Find two Prolog terms A and B such that: "A is B." is false. "A =:= B." is true

Could some expert in Prolog please give example of such a scenario?
Facts-
fruit('mango')
fruit('apple).
dif(fruit(X), fruit(Y)).
fruit(X) \= fruit(Y).
?- 2+2 is 4.
false
?- 2+2 =:= 4.
true
Because:
+Expr1 =:= +Expr2
True if expression Expr1 evaluates to a number equal to Expr2.
and
-Number is +Expr
True when Number is the value to which Expr evaluates. Typically, is/2 should be used with unbound left operand.
is evaluates only the term on the right, =:= evaluates both.

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

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.

first order logic creating terms for arithmetic expressions using prolog

given a signature (0,Z,{plus(2),minus(2),times(2)}, constants are integers and functions are plus, minus and times with arity 2 for each. I wanted to write a two predicates arth/2 and printarth/1 which takes terms in the above signature and do the necessary arithmetic calculations addition, subtraction and multiplication.arth/2 will print the results and printarth/1 should results out the evaluation expression as shown below.
I wanted to achieve two things
first:
?- arth( plus(minus(8,2), times(4,-3)), N).
N = -6
N is evaluated as ((8−2) + (4∗−3)) = (6 +−12) =−6
second:
?- printarth(plus(minus(8,2), times(4,-3)), N).
((8 - 2) + (4 * -3))
true.
I understand that the use of Terms, Ops and complex terms are used for this and started my code as below
arithmetic_operator('+').
arithmetic_operator('-').
arithmetic_operator('*').
arithmetic_expression(N) :- integer(N).
arithmetic_expression(Term) :-
Term =..[Functor,Component1,Component2],
arithmetic_operator(Functor),
arithmetic_expression(Component1),
arithmetic_expression(Component2).
From here I find it difficult on how to create arth/2 and printarth/1 as I cannot call arithmetic_expression(Term) and throws me an error when I call it.
?- arithmetic_expression(..[+,5,7]).
ERROR: Syntax error: Operator expected
ERROR: arithmetic_expression(.
ERROR: ** here **
ERROR: .[+,5,7]) .
any resources on this task is very useful.
If you want to take a term that looks like this:
minus(2, 3)
and turn it into an arithmetic expression -(2, 3) which is equivalent to 2 - 3 (with the default definition of - as an operator), then evaluate it, you could do it like this:
term_arithmetic_expression(T, E) :-
T =.. [Name, X, Y],
binary_op(Name, Op),
E =.. [Op, X, Y].
eval_arithmetic_expression(T, R) :-
term_arithmetic_expression(T, E),
R is E.
binary_op(minus, -).
% add more binary operations
Now this at least works:
?- eval_arithmetic_expression(minus(2, 3), R).
R = -1.
As you see, both term_arithmetic_expression/2 and eval_arithmetic_expression/2 have two arguments. This is what you need to map minus(2, 4) to 2 - 4.
Your arithmetic_expression/1 is correctly traversing, but not mapping from the one representation to the other. Your arithmetic_operator has the same problem. With minimal changes:
arithmetic_operator(plus, +).
arithmetic_operator(minus, -).
arithmetic_operator(times, *).
arithmetic_expression(N, N) :- integer(N).
arithmetic_expression(Term, Expr) :-
Term =.. [Functor,Component1,Component2],
arithmetic_operator(Functor, Operator),
arithmetic_expression(Component1, Expr1),
arithmetic_expression(Component2, Expr2),
Expr =.. [Operator, Expr1, Expr2].
and then:
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr).
Expr = 8-2+4* -3 ;
false.
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
Result is Expr.
Expr = 8-2+4* -3,
Result = -6 ;
false.
?- arithmetic_expression(plus(minus(8,2), times(4,-3)), Expr),
Result is Expr,
display(Expr).
+(-(8,2),*(4,-3))
Expr = 8-2+4* -3,
Result = -6 ;
false.
The display is what is outputting +(-(8,2),*(4,-3)) in the last query.

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.

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.

Resources