Why does prolog use =< and not <=? - prolog

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.

Related

SWI Prolog vs. GNU Prolog - CLP(FD) issues under SWI

I wrote a quick predicate in Prolog trying out CLP(FD) and its ability to solve systems of equations.
problem(A, B) :-
A-B #= 320,
A #= 21*B.
When I call it in SWI, I get:
?- problem(A,B).
320+B#=A,
21*B#=A.
Whereas in GNU, I get the correct answer of:
| ?- problem(A,B).
A = 336
B = 16
What's going on here? Ideally I'd like to get the correct results in SWI as it's a much more robust environment.
This is a good observation.
At first glance, it will no doubt appear to be a shortcoming of SWI that it fails to propagate as strongly as GNU Prolog.
However, there are also other factors at play here.
The core issue
To start, please try the following query in GNU Prolog:
| ?- X #= X.
Declaratively, the query can be read as: X is an integer. The reasons are:
(#=)/2 only holds for integers
X #= X does not constrain the domain of the integer X in any way.
However, at least on my machine, GNU Prolog answers with:
X = _#0(0..268435455)
So, in fact, the domain of the integer X has become finite even though we have not restricted it in any way!
For comparison, we get for example in SICStus Prolog:
?- X #= X.
X in inf..sup.
This shows that the domain of the integer X has not been restricted in any way.
Replicating the result with CLP(Z)
Let us level the playing field. We can simulate the above situation with SWI-Prolog by artificially restricting the variables' domains to, say, the finite interval 0..264:
?- problem(A, B),
Upper #= 2^64,
[A,B] ins 0..Upper.
In response, we now get with SWI-Prolog:
A = 336,
B = 16,
Upper = 18446744073709551616.
So, restricting the domain to a finite subset of integers has allowed us to replicate the result we know from GNU Prolog also with the CLP(FD) solver of SWI-Prolog or its successor, CLP(Z).
The reason for this
The ambition of CLP(Z) is to completely replace low-level arithmetic predicates in user programs by high-level declarative alternatives that can be used as true relations and of course also as drop-in replacements. For this reason, CLP(Z) supports unbounded integers, which can grow as large as your computer's memory allows. In CLP(Z), the default domain of all integer variables is the set of all integers. This means that certain propagations that are applied for bounded domains are not performed as long as one of the domains is infinite.
For example:
?- X #> Y, Y #> X.
X#=<Y+ -1,
Y#=<X+ -1.
This is a conditional answer: The original query is satisfiable iff the so-called residual constraints are satisfiable.
In contrast, we get with finite domains:
?- X #> Y, Y #> X, [X,Y] ins -5000..2000.
false.
As long as all domains are finite, we expect roughly the same propagation strength from the involved systems.
An inherent limitation
Solving equations over integers is undecidable in general. So, for CLP(Z), we know that there is no decision algorithm that always yields correct results.
For this reason, you sometimes get residual constraints instead of an unconditional answer. Over finite sets of integers, equations are of course decidable: If all domains are finite and you do not get a concrete solution as answer, use one of the enumeration predicates to exhaustively search for solutions.
In systems that can reason over infinite sets of integers, you will sooner or later, and necessarily, encounter such phenomena.

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.

Logical purity of when/2 and ground/1

The question
I have a question related to logical purity.
Is this program pure?
when(ground(X), X > 2).
Some [ir]relevant details about the context
I'm trying to write pure predicates with good termination properties. For instance, I want to write a predicate list_length/2 that describes the relation between a list and its length. I want to achieve the same termination behaviour as the built-in predicate length/2.
My question seeks to find if the following predicate is pure:
list_length([], 0).
list_length([_|Tail], N):-
when(ground(N), (N > 0, N1 is N - 1)),
when(ground(N1), N is N1 + 1),
list_length(Tail, N1).
I can achieve my goal with clpfd ...
:- use_module(library(clpfd)).
:- set_prolog_flag(clpfd_monotonic, true).
list_length([], 0).
list_length([_|Tail], N):-
?(N) #> 0,
?(N1) #= ?(N) - 1,
list_length(Tail, N1).
... or I can use var/1, nonvar/1 and !/0, but then is hard to prove that the predicate is pure.
list_length([],0).
list_length([_|Tail], N):-
nonvar(N), !,
N > 0,
N1 is N - 1,
list_length(Tail, N1).
list_length([_|Tail], N):-
list_length(Tail, N1),
N is N1 + 1.
Logical purity of when/2 and ground/1
Note that there is the ISO built-in ground/1 which is just as impure as nonvar/1.
But it seems you are rather talking about the conditions for when/2. In fact, any accepted condition for when/2 is as pure as it can get. So this is not only true for ground/1.
Is this program pure?
when(ground(X), X > 2).
Yes, in the current sense of purity. That is, in the very same sense that considers library(clpfd) as pure. In the very early days of logic programming and Prolog, say in the 1970s, a pure program would have been only one that succeeds if it is true and fails if it is false. Nothing else.
However, today, we accept that ISO errors, like type errors are issued in place of silent failure. In fact, this makes much more sense from a practical point of view. Think of X = non_number, when(ground(X), X > 2 ). Note that this error system was introduced relatively late into Prolog.
While Prolog I reported errors of built-ins explicitly1 the subsequent DEC10-Prolog (as of, e.g. 1978, 1982) nor C-Prolog did not contain a reliable error reporting system. Instead, a message was printed and the predicate failed thus confusing errors with logical falsity. From this time, there is still the value warning of the Prolog flag unknown (7.11.2.4 in ISO/IEC 13211-1:1995) which causes the attempt to execute an undefined predicate to print a warning and fail.
So where's the catch? Consider
?- when(ground(X), X> 2), when(ground(X), X < 2).
when(ground(X), X>2), when(ground(X), X<2).
These when/2s, while perfectly correct, now contribute a lot to producing inconsistencies as answers. After all, above reads:
Yes, the query is true, provided the very same query is true.
Contrast this to SICStus' or SWI's library(clpfd):
?- X #> 2, X #< 2.
false.
So library(clpfd) is capable of detecting this inconsistency, whereas when/2 has to wait until its argument is ground.
Getting such conditional answers is often very confusing. In fact, many prefer in many situations a more mundane instantiation error to the somewhat cleaner when.
There is no obvious general answer to this. After all, many interesting theories for constraints are undecidable. Yes, the very harmless-looking library(clpfd) permits you to formulate undecidable problems already! So we will have to live with such conditional answers that do not contain solutions.
However, once you get a pure unconditional solution or once you get real failure you do know that this will hold.
list_length/2
Your definition using library(clpfd) is actually slightly better w.r.t. termination than what has been agreed upon for the Prolog prologue. Consider:
?- N in 1..3, list_length(L, N).
Also, the goal length(L,L) produces a type error in a very natural fashion. That is, without any explicit tests.
Your version using when/2 has some "natural" irregularities, like length(L,0+0) fails but length(L,1+0) succeeds. Otherwise it seems to be fine — by construction alone.
The earliest account is on p.9 of G. Battani, H. Meloni. Interpréteur du langage de programmation Prolog. Rapport de D.E.A. d'informatique appliquée, 1973. There, a built-in in error was replaced by a goal that was never resolved. In current terms plus/3 of II-3-6 a, p.13 would be in current systems with freeze/2:
plus(X, Y, Z) :-
( integer(X), integer(Y), ( var(Z) ; integer(Z) )
-> Z is X+Y
; freeze(_,erreur(plus(X,Y,Z)))
).
So plus/3 was not "multi-directional".

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