Prolog why the following term doesn't unify? - prolog

In prolog = is used for unification, as far as I understand if the two terms can be matched maybe with the help if variable instantiation, they are unified.
So why the following query fails
?- 2+2 = 4.
Although 2+2 yields into 4 which is the same number as the other term.

Complementing the other posts, I would like to suggest (#=)/2 as a more declarative alternative to (is)/2 when reasoning about integers.
(#=)/2 denotes arithmetic equality of integer expressions. This involves an evaluation step and is therefore different from just syntactic equality. In your case, you expected the former, but got the latter.
Usage example, with GNU Prolog:
| ?- 4 #= 2+2.
yes
The primary advantage of (#=)/2 is that it works in all directions:
| ?- 4 #= 2+X.
X = 2
In contrast, we get with (is)/2:
| ?- 4 is 2+X.
uncaught exception: error(instantiation_error,(is)/2)
Such problems are very common (see instantiation-error) when beginners first learn about arithmetic, and so I recommend you start using more declarative predicates at least in the beginning.

What others have answered is correct, but here's a little more detail.
In Prolog, the term 2+2 is just a syntactical alternative to the term, '+'(2, 2). This is a term with functor + and with two arguments (2 and 2). The term 2 is just an interger and has no arguments. The =/2 operator attempts to unify terms. It does not perform arithmetic expression evaluation. These terms are clearly different and cannot be unified (they don't even have the same number of arguments).
There are operators in Prolog which will perform the expression evaluation. For expression equality, you can use =:=/2 or better, as #mat points out for reasoning over integers, you can use #=/2. So the following will work:
| ?- 2+2 =:= 4.
yes
| ?- 2+2 #= 4.
yes
| ?-
There is also is/2 which will evaluate the second argument only and determine if it's value is the same as the value of the first argument. Thus the following will happen:
| ?- 2+2 is 4.
no
| ?- 4 is 2+2.
yes
| ?-
The above examples are in GNU prolog. Note that in SWI Prolog you must include the CLP(FD) library to use operators that reason over integers:
:- use_module(library(clpfd)).

The expression on the left-hand side is not evaluated by itself. You are instead comparing the unification of strings. To compare the unification of the expression's evaluation with the right-hand side, you need to use the is/2 operator.
?- 4 is 2+2.
Compare with:
?- 2+2 = 2+2.
and
?- X is 2+2.

When you write
2 + 2 = 4
the answer is no, because prolog will compare a number (4) to a formula (2+2), which are not the same. To make it right, you need prolog to evaluate the formula 2 + 2 before comparing it to 4. For that, use the is operator:
The is operator is meant specifically for mathematical functions. The left argument has to be a variable and the right argument has to be a mathematical function with all variables instantiated.
The = operator is used for unification of variables and can be used with any two arguments (although it will fail if the two arguments aren't the same and can't be made the same by instantiating variables a certain way) [source].
So in your example:
4 is 2+2
Will evaluate to yes.

Related

How can I write a rule that finds a number using integer/1?

I am writing a rule that is looking for a particular integer. I assumed I can write something like this
find_number(X):-
integer(X),
X > 1, X < 5.
Then expect the result of a query to integer(X) to result in X=2, X=3, X=4, false. Instead, I just get a false result. The only way I found to write this rule is to use numlist/3 like so
find_number(X):-
numlist(2, 4, NumList),
member(X, NumList).
Can anyone explain why this is?
Your reasoning would be perfectly valid iff integer/1 were an actual relation that satisfies basic logical properties.
For example, in classical logic, a unary predicate P satisfies the following property:
If P(σ(T)) is satisfiable for any substitution σ and term T, then P(T) is also satisfiable.
This seems completely obvious and of course holds also for all pure predicates in Prolog.
The problem is that integer/1 is not a pure relation.
In particular, we have for example:
?- integer(3).
true.
Yet the following more general query fails:
?- integer(X).
false.
Is there any integer? No.
Believe it or not, that's how integer/1 actually works.
Clearly, something seems not quite right for such predicates, and so there are better alternatives in all widely used modern Prolog systems. I strongly recommend you use such alternatives instead, to get the most out of Prolog.
For the case of integers, I recommend you check out CLP(FD) constraints (clpfd).
For example, in GNU Prolog, your code could look like this:
good_number(X) :-
X #> 1,
X #< 5.
With the following queries and answers:
| ?- good_number(X).
X = _#2(2..4)
| ?- good_number(X), fd_labeling([X]).
X = 2 ? ;
X = 3 ? ;
X = 4
This works exactly as we expect a relation to work! I have taken the liberty to change the name such that it makes sense also in more specific cases, where there is nothing left to "find":
| ?- good_number(3).
yes
Depending on your Prolog system, you may have to import a library to use such more declarative features. See also logical-purity for more information.
You get only false because integer/1 tests if the input is an integer and if it is it succeeds else if it is not an integer or if it is a variable that is not instantiated as in your case, then it fails.
You could use between/2 built in predicate:
find_number(X):-between(2,4,X).
This will return:
?- find_number(X).
X = 2 ;
X = 3 ;
X = 4.

Sums of the elements in list

I have to say that there is a similar quetion Sum of elements in list in Prolog needs little explanation, but still makes me confused.
Here is the following solution which needs some explanation.
sum([H],H).
sum([H|T],R):-sum(T,P),R is H + P.
Lets say we do sum([1,2,3],R).
sum([1,2,3],R)
sum([2,3],<unknown-1>)
sum([3],<unknown-2>)
so where it will fulfill the fact sum([H],H) ?
I do write the variable in sum([H],H), the only output for this case is 3,
which means that in the unknown-2 here is 3, why?
Just a beginner in prolog and any answers will be great appreciate.
The short answer: unification.
When, within the scope of a predicate clause, a variable name occurs more than once, all occurrences will be unified with each other. The predicate for unification is =/2, and is declared as operator, so =(A, A) and A = A mean the same. More importantly, this:
=(Term, Term).
is the definition of =/2 (see the documentation!)
In your example, you have a clause that says:
sum([H], H).
This means:
When the first argument of sum/2 is a list with exactly one element, the second argument of sum/2 is that element.
Because term unification is such a fundamental operation in Prolog, usually, it is not spelled out explicitly, as for example:
When the first argument of sum/2 is a list with exactly one element, that element and the second argument of sum/2 are unified with each other.
At least in the SWI-Prolog documentation, if unification is involved, it is usually described with "X is Y" instead of "X and Y are unified". See, for example, the documentation of min_member/2:
min_member(Min, List).
True when Min is the smallest member in the standard order of terms. Fails if List is empty.
It doesn't explicitly tell you that unification is used, and from that, the following behavior follows:
?- min_member(3, [1,2,X]).
X = 3.
I once asked a question about this because I found it too confusing.
By the way, with your current definition of sum/2, you can also get surprises because of the way that unification works. Look:
?- sum([1.5, 2.5], Sum).
Sum = 4.0 ; % unnecessary choice point but at least correct
false.
?- sum([1.5, 2.5], 4).
false. % Oops!
The SWI-Prolog library implementation suffers from the same problem:
?- sum_list([1.5, 2.5], Sum).
Sum = 4.0. % no choice point, at least
?- sum_list([1.5, 2.5], 4).
false. % Oops!
The work-around is to leave the second argument a free variable at first, and then use =:=/2, which does arithmetic comparison of numbers:
?- sum_list([1.5, 2.5], Sum), Sum =:= 4.
Sum = 4.0.
You can do this with your definition of sum/2 as well.
sumList([],0).
sumList([X|Tail],Sum):-
sumList(Tail,Sum1),
Sum is Sum1+X.

Can between/3 not be recursive?

I've seen the Prolog Prologue definition of between/3:
between(Lower, Upper, Lower) :-
Lower =< Upper.
between(Lower1, Upper, X) :-
Lower1 < Upper,
Lower2 is Lower1 + 1,
between(Lower2, Upper, X).
I don't understand why it requires recursion. A logical definition of between could be:
between(Lower, Upper, Something):-
Lower =< Upper,
Lower =< Something,
Something =< Upper.
I tried that on gprolog and it works, but only for simple queries:
| ?- between(0,5,1).
yes
For queries with variables I get:
| ?- between(0,5,X).
uncaught exception: error(instantiation_error, (=<)/2)
I don't really understand why.
I kind of figure Prolog needs some sort of reference number to unify variables against, but why the cryptic error on (=<)/2?
The error is not that cryptic, once you know what general purpose arithmetic in Prolog does. In short, it is simply there to do non-logical, "calculate this and give me the answer" kind of arithmetic. Comparisons (so all the </2, =</2, =:=/2, etc) require that you have arithmetic expressions on both sides; is/2 assumes that it has an arithmetic expression on the left side and a free variable on the right. So, you can do stuff like:
?- X is 3^1.3.
X = 4.171167510947728.
?- 1 =:= sin(pi/2).
true.
If you actually read the GNU-Prolog manual carefully enough, you should find, at the beginning of the relevant section, the following two sentences:
An arithmetic expression is a Prolog term built from numbers, variables, and functors (or operators) that represent arithmetic functions. When an expression is evaluated each variable must be bound to a non-variable expression.
(Emphasis mine)
Predicates like between/3, plus/3, or succ/2 are examples of special purpose integer arithmetic. They have their uses. However, most of the uses for doing actual integer math have been superseded by CLPFD. For GNU-Prolog, you should consult the documentation, but for a short example, to emulate between/3, you could say:
?- fd_domain(X, 0, 2), fd_labeling(X).
X = 0 ? ;
X = 1 ? ;
X = 2
yes
You should notice that this is definitely not recursive (to answer the question in the title). Of course, we are all aware that at some level, there is recursion or iteration involved, in order to get these answers.

How to write number classifiers in prolog?

Playing with Prolog for the first time and while I thought I knew what it basically is good for, I find it hard to get anything done in it. So, I tried to find the easiest possible task and even fail to accomplish that.
I think it is due to me not knowing how prolog data types (numbers) are supposed to work or they have special syntax.
So, my first attempt to classify even numbers was:
even(0).
even(X) :- even(X-2).
Result: stack overflow for the query: even(2).
So I thought well if this is not it, then maybe it is:
even(0).
even(X+2) :- even(X).
Result of even(2): false.
So my simple question is: How to write such simple things in prolog? Is it all not working because i use numbers?
Why not do it the normal way:
is_even(X) :-
X /\ 0x1 =:= 0.
If you want to enumerate non-negative even numbers upon backtracking when the argument is not bound, this is a different thing altogether. It is probably easy to just say:
even(X) :-
between(0, infinite, X),
is_even(X).
You can use the second definition like this:
?- even(X).
X = 0 ;
X = 2 ;
X = 4 ;
X = 6 . % and so on
There are some differences between is_even/1 and even/1:
is_even/1 will work for any integer, positive or negative
is_even/1 will, surprisingly enough, work for expressions that evaluate to integers, too, for example, X = 3, ..., is_even(X + 1). This is because =:= accepts an arithmetic expression on either side.
even/1 uses between/3, so the domain of X and error conditions are the same as for the third argument of between/3.
As a consequence, even/1 does not work with negative integers or arithmetic expressions.
But wait, there's more!
Apparently, between(0, infinite, X) is not something you can do in almost any Prolog apart from SWI. So, instead, you can use another predicate that will enumerate positive integers (list lengths):
even_f(X) :-
length(_, X),
is_even(X).
(Thank you to #false for this)
Use is/2 to force the arithmetic evaluation. On their own, Prolog terms are just structural symbolic entities, X-2 is a compound term of arity 2, -(X,2):
3 ?- write_canonical( X-2 ).
-(_,2)
true.
But is is for arithmetic expressions:
4 ?- Z is 5-2.
Z = 3.
Your definition should thus be
even(X):- X=:=0 -> true
; X > 0 -> Y is X-2, even(Y).
The drawback of such definition is that it can't be called in a generative fashion, like even(X) to get all the evens generated one after the other.
It is only good for checking a given number. For simplicity, it ignores the negative numbers and always fails for them.

Minor inconsistency due to different operator precedence of ** and ^

Why is argument precendence of **/2 (xfx) and (^)/2 (xfy) not the same in Prolog?
This causes minor inconsistencies, such as the following:
?- X = 1, Y is 1 ^ -X.
X = Y, Y = 1.
and:
?- Y is 1 ** -1.
Y = 1.
but:
?- X = 1, Y is 1 ** -X.
ERROR: Syntax error: Operator priority clash
ERROR: X = 1, Y is 1 *
ERROR: ** here **
ERROR: * -X .
Minor point: It's (^)/2 and not ^/2 to indicate that ^ is used as an operator and to make it valid Prolog syntax and a predicate indicator (7.1.6.6).
(**)/2 and (^)/2 are both evaluable functors (9), so they can be used for Arithmetic evaluation (8.7) with (is)/2 and Arithmetic comparison (8.7) with (=:=)/2, (<)/2 and the like. Their definitions differ slightly.
(**)/2 always gives back a float in the same way as (/)/2 always gives a float. (SWI does not follow the standard here, it has its own conventions).
?- X is 2**2.
X = 4.0.
?- X is 2/2.
X = 1.0.
(^)/2 is here to permit integer exponentiation which has become much more important with many systems now supporting arbitrarily large integers. Think of 2^2^X. That is, if both arguments are integers, the result is an integer as well, in the same way that (*)/2 handles this case.
?- X is 2^2, Y is 2*2.
X = 4, Y = 4.
?- X is 2.0^2, Y is 2.0*2.
X = 4.0, Y = 4.0.
In those cases where (^)/2 would give a real value with two integer arguments (like 2^ -1), a type error is produced, and then there are more errors for otherwise complex or undefined results.
(^)/2 was used for exponentiation for quite some time.
An early use of the exponentiation operator is in D.H.D. Warren's Thesis of 1977 in the example for symbolic differentiation. (It is at least not mentioned in Philippe Roussel's 1975 manual). Throughout the thesis and the 1978 User's guide, the ~ character is used consistently where one would expect a ^ like in integers are restricted to the range -2~17 to 2~17-1 , ie. -131072 to 131071. The declaration was the following and is unchanged since 1982.
:- op(300, xfy, ~). % 1977
:- op(200, xfy, ^). % 1982 - today
From 1982 on, it was used in quantification of setof/3 and bagof/3 but also as lambdas in natural language parsers. For all these uses it already had the right associativity and priority. As an evaluable functor it was present in several systems.
The first system to use (^)/2 as an evaluable functor meaning power is probably C-Prolog.
Compared to this heritage, the (**)/2 appeared in Prolog relatively late, most probably inspired by Fortran. It was proposed for inclusion (N80 1991-07, Paris papers) shortly before the first Committee Draft (CD 1992). Systems provided it also as exp/2.
(**)/2 has the same priority as (^)/2 but does not have any associativity, which at first might strike as odd, since there are quite some cases, where it is common to have exponentiation twice. Most prominently, the Gaussian function in its simplest form
e-x2
Instead of using the constant e and exponentiation, a special evaluable functor exp/1 is provided. Above is thus written as exp(- X**2). In fact, also Wikipedia uses this notation. Given this functor, there are no needs for associativity in this common case.
Should there actually be one, I would be very interested to see it.
Compared to other systems it seems quite common to offer two kinds of exponentiation. Think of Haskell which has ^ and **.
To conclude: There does not seem to be a frequent case where nested float exponentiation is needed. So minimal support seems to be preferable.
#false answered your first question.
The example you give is due to the following difference:
?- integer(-1).
true.
?- X = 1, integer(-X).
false.
and the following precedences:
?- current_op(X, xfx, **).
X = 200.
?- current_op(X, fy, -).
X = 200.
The reason (not justification) for the inconsistency is that in the original standard from 1995 only **/2 was an arithmetic exponentiation operator, while ^/2 was only used for quantifying variables in bagof/3 and setof/3. For the latter use, it made sense to have right-associativity, so you could write X^Y^foo(X,Y,Z). Why **/2 was not given xfy associativity I don't know (it would have been consistent with Fortran, for instance).
The ^/2 as an exponentiation operator was added in a 2012 "corrigendum", without revising the syntax, leading to the current inconsistency.
But note that you can simply fix this yourself by adding a directive
:- op(200, xfy, **).
This is unlikely to cause any problems. Moreover, in many modern Prologs operator declarations are effective only locally in a module.

Resources