Can between/3 not be recursive? - prolog

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.

Related

Why does prolog use =< and not <=?

The numerical comparison operators in prolog are pretty much the same as every other language.
operator
meaning
X > Y
X greater than Y
X < Y
X less than Y
X >= Y
X greater than or equal to Y
X =< Y ( not <= )
X less than or equal to Y
Question: Why did prolog diverge from most other languages and use =< and not <=?
Is the reason to due with how such symbol were written by hand, the explanation often cited for the :- meaning <- implication from right to left.
updated - edited to correct typos
In imperative programming languages, smaller equal is literally written as <=. But in Prolog, <= looks more like an arrow to the left since Prolog is often used to implement various theorem provers. Thus =< was the more natural choice1 for the arithmetical comparison operator.
For arithmetical evaluation and comparison, this is just a little nuisance as a misuse will show up as a harmless syntax error. But it becomes more cumbersome in the context of constraints. The implementation of clpfd by SICStus has both #<= and #=< as infix operators meaning implication and smaller equal respectively which leads to many unnecessary beginners' errors. Note that such errors are very difficult to detect, since many uses like X #<= 1 are valid for both meanings.
Because of this confusion, newer implementations like clpfd for SWI and its successor clpz (for both SICStus and Scryer) use rather #<== and #==> for implication and thus do not define #<= at all.
Note that also other programming languages have to work around this problem. Most notably Haskell uses => for class constraints thus writing the arrow in the other direction since <= is already taken to mean comparison.
1 At least since DEC 10 Prolog of 1978.
The earliest use is probably in the benchmark qsort
on page 54 of Report 40, D.H.D. Warren, Implementing Prolog—Compiling Predicate Logic Programs. May 1977.
partition([X,..L],Y,[X,..L1],L2) :- X =< Y, !,
partition(L,Y,L1,L2).
This ,.. is a | in ISO. The ..-notation is still present in =.. univ.

Prolog why the following term doesn't unify?

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.

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.

PROLOG predicate order

I've got a very large number of equations which I am trying to use PROLOG to solve. However, I've come a minor cropper in that they are not specified in any sort of useful order- that is, some, if not many variables, are used before they are defined. These are all specified within the same predicate. Can PROLOG cope with the predicates being specified in a random order?
Absolutely... ni (in Italian, Yes and Not)
That is, ideally Prolog requires that you specify what must be computed, not how, writing down the equations controlling the solution in a fairly general logical form, Horn clauses.
But this ideal is far from reach, and this is the point where we, as programmers, play a role. You should try to topologically sort formulae, if you want Prolog just apply arithmetic/algorithms.
But at this point, Prolog is not more useful than any other procedural language. It just make easier to do such topological sort, in sense that formulas can be read (this builtin it's a full Prolog parser!), variables identified and quantified easily, terms transformed, evaluated, and the like (metalanguages features, a strong point of Prolog).
Situation changes if you can use CLP(FD). Just an example, a bidirectional factorial (cool, isn't it?), from the documentation of the shining implementation that Markus Triska developed for SWI-Prolog:
You can also use CLP(FD) constraints as a more declarative alternative for ordinary integer arithmetic with is/2, >/2 etc. For example:
:- use_module(library(clpfd)).
n_factorial(0, 1).
n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
This predicate can be used in all directions. For example:
?- n_factorial(47, F).
F = 258623241511168180642964355153611979969197632389120000000000 ;
false.
?- n_factorial(N, 1).
N = 0 ;
N = 1 ;
false.
?- n_factorial(N, 3).
false.
To make the predicate terminate if any argument is instantiated, add the (implied) constraint F #\= 0 before the recursive call. Otherwise, the query n_factorial(N, 0) is the only non-terminating case of this kind.
Thus if you write your equations in CLP(FD) you get much more chances to have your 'equation system' solved as is. SWI-Prolog has dedicated debugging for the low level details used to solve CLP(FD).
HTH

Resources