- Documentation
- Reference manual
- The SWI-Prolog library
- library(clpfd): CLP(FD): Constraint Logic Programming over Finite Domains
- Introduction
- Arithmetic constraints
- Declarative integer arithmetic
- Example: Factorial relation
- Combinatorial constraints
- Domains
- Example: Sudoku
- Residual goals
- Core relations and search
- Example: Eight queens puzzle
- Optimisation
- Reification
- Enabling monotonic CLP(FD)
- Custom constraints
- Applications
- Acknowledgments
- CLP(FD) predicate index
- Closing and opening words about CLP(FD)
- library(clpfd): CLP(FD): Constraint Logic Programming over Finite Domains
- The SWI-Prolog library
- Packages
- Reference manual
A.8.3 Declarative integer arithmetic
The arithmetic constraints (section
A.8.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 ~/.swiplrc
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.8.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 clpfd_goal_expansion
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't. 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.