Did you know ... | Search Documentation: |
Declarative integer arithmetic |
The arithmetic constraints (section
A.9.2) #=/2, #>/2
etc. are meant to be used instead of the primitives (is)/2
,
(=:=)/2
, (>)/2
etc. over integers. Almost
all Prolog programs also reason about integers. Therefore, it is
recommended that you put the following directive in your <config>/init.pl
initialisation file to make CLP(FD) constraints available in all your
programs:
:- use_module(library(clpfd)).
Throughout the following, it is assumed that you have done this.
The most basic use of CLP(FD) constraints is evaluation of arithmetic expressions involving integers. For example:
?- X #= 1+2. X = 3.
This could in principle also be achieved with the lower-level
predicate (is)/2
. However, an important advantage of
arithmetic constraints is their purely relational nature: Constraints
can be used in all directions, also if one or more of their
arguments are only partially instantiated. For example:
?- 3 #= Y+2. Y = 1.
This relational nature makes CLP(FD) constraints easy to explain and use, and well suited for beginners and experienced Prolog programmers alike. In contrast, when using low-level integer arithmetic, we get:
?- 3 is Y+2. ERROR: is/2: Arguments are not sufficiently instantiated ?- 3 =:= Y+2. ERROR: =:=/2: Arguments are not sufficiently instantiated
Due to the necessary operational considerations, the use of these low-level arithmetic predicates is considerably harder to understand and should therefore be deferred to more advanced lectures.
For supported expressions, CLP(FD) constraints are drop-in replacements of these low-level arithmetic predicates, often yielding more general programs. See n_factorial/2 (section A.9.4) for an example.
This library uses goal_expansion/2 to automatically rewrite constraints at compilation time so that low-level arithmetic predicates are automatically used whenever possible. For example, the predicate:
positive_integer(N) :- N #>= 1.
is executed as if it were written as:
positive_integer(N) :- ( integer(N) -> N >= 1 ; N #>= 1 ).
This illustrates why the performance of CLP(FD) constraints is almost
always completely satisfactory when they are used in modes that can be
handled by low-level arithmetic. To disable the automatic rewriting, set
the Prolog flag optimise_clpfd to false
.
If you are used to the complicated operational considerations that low-level arithmetic primitives necessitate, then moving to CLP(FD) constraints may, due to their power and convenience, at first feel to you excessive and almost like cheating. It isn'. Constraints are an integral part of all popular Prolog systems, and they are designed to help you eliminate and avoid the use of low-level and less general primitives by providing declarative alternatives that are meant to be used instead.