Constraint Solvers
Theoretical Computer Science (2009)
Available from
Michal Tuláček's profile on Mendeley.
or
Abstract
Constraint solver is a specialized software used to solve constraint satisfaction problems. The thesis surveys constraint solvers and some of them compares using the criteria of user accessibility and variety of problems which can be modeled.
Available from
Michal Tuláček's profile on Mendeley.
Page 1
Constraint Solvers
Charles University in Prague
Faculty of Mathematics and Physics
BACHELOR THESIS
Michal Tula´cˇek
Constraint solvers
Department of Theoretical Computer Science and
Mathematical Logic
Supervisor: Doc. RNDr. Roman Barta´k, Ph.D.
Study programme: General Computer Science
2009
Faculty of Mathematics and Physics
BACHELOR THESIS
Michal Tula´cˇek
Constraint solvers
Department of Theoretical Computer Science and
Mathematical Logic
Supervisor: Doc. RNDr. Roman Barta´k, Ph.D.
Study programme: General Computer Science
2009
Page 2
I wish to thank my supervisor Dr. R. Barta´k for advices and patience. My
thanks also belongs to my friends V. Kopal, M. Berna´t and J. Helmich who
helped me with correction of the English text. Last but not least my thanks
belong to my coach J. Baxa who clearly stated that failure is not an option
and then enforced this policy.
Prohlasˇuji, zˇe jsem svou bakala´rˇskou pra´ci napsal samostatneˇ a vy´hradneˇ
s pouzˇit´ım citovany´ch pramen˚u. Souhlas´ım se zap˚ujcˇova´n´ım pra´ce a jej´ım
zverˇejnˇova´n´ım.
I declare that I wrote my bachelor thesis independently and exclusively with
the use of the cited sources. I agree with lending this thesis.
In Prague, 6th August 2009 Michal Tula´cˇek
2
thanks also belongs to my friends V. Kopal, M. Berna´t and J. Helmich who
helped me with correction of the English text. Last but not least my thanks
belong to my coach J. Baxa who clearly stated that failure is not an option
and then enforced this policy.
Prohlasˇuji, zˇe jsem svou bakala´rˇskou pra´ci napsal samostatneˇ a vy´hradneˇ
s pouzˇit´ım citovany´ch pramen˚u. Souhlas´ım se zap˚ujcˇova´n´ım pra´ce a jej´ım
zverˇejnˇova´n´ım.
I declare that I wrote my bachelor thesis independently and exclusively with
the use of the cited sources. I agree with lending this thesis.
In Prague, 6th August 2009 Michal Tula´cˇek
2
Page 3
Contents
1 Introduction 7
1.1 Constraint Satisfaction Problems . . . . . . . . . . . . . . . 7
1.2 Constraint programming . . . . . . . . . . . . . . . . . . . . 10
1.3 Constraint solvers . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Related work . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5 Outline of the thesis . . . . . . . . . . . . . . . . . . . . . . 13
2 Methodology 15
3 Benchmarks 17
3.1 Essence programming language . . . . . . . . . . . . . . . . 17
3.2 N-queens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.1 Constraint problem model . . . . . . . . . . . . . . . 18
3.3 Magic sequence . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3.1 Constraint problem model . . . . . . . . . . . . . . . 20
3.4 Self-referential quiz . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.1 Constraint problem model . . . . . . . . . . . . . . . 22
3.5 Quasigroup with holes . . . . . . . . . . . . . . . . . . . . . 24
3.5.1 Constraint problem model . . . . . . . . . . . . . . . 25
3.6 Locating warehouses . . . . . . . . . . . . . . . . . . . . . . 26
3.6.1 Constraint problem model . . . . . . . . . . . . . . . 26
4 Constraint solvers 29
4.1 Mozart/Oz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1.1 Solver description . . . . . . . . . . . . . . . . . . . . 30
4.1.2 Debugging support . . . . . . . . . . . . . . . . . . . 31
4.1.3 Subjective description . . . . . . . . . . . . . . . . . 32
4.2 Choco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.2.1 Solver description . . . . . . . . . . . . . . . . . . . . 33
3
1 Introduction 7
1.1 Constraint Satisfaction Problems . . . . . . . . . . . . . . . 7
1.2 Constraint programming . . . . . . . . . . . . . . . . . . . . 10
1.3 Constraint solvers . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Related work . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.5 Outline of the thesis . . . . . . . . . . . . . . . . . . . . . . 13
2 Methodology 15
3 Benchmarks 17
3.1 Essence programming language . . . . . . . . . . . . . . . . 17
3.2 N-queens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.1 Constraint problem model . . . . . . . . . . . . . . . 18
3.3 Magic sequence . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3.1 Constraint problem model . . . . . . . . . . . . . . . 20
3.4 Self-referential quiz . . . . . . . . . . . . . . . . . . . . . . . 21
3.4.1 Constraint problem model . . . . . . . . . . . . . . . 22
3.5 Quasigroup with holes . . . . . . . . . . . . . . . . . . . . . 24
3.5.1 Constraint problem model . . . . . . . . . . . . . . . 25
3.6 Locating warehouses . . . . . . . . . . . . . . . . . . . . . . 26
3.6.1 Constraint problem model . . . . . . . . . . . . . . . 26
4 Constraint solvers 29
4.1 Mozart/Oz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.1.1 Solver description . . . . . . . . . . . . . . . . . . . . 30
4.1.2 Debugging support . . . . . . . . . . . . . . . . . . . 31
4.1.3 Subjective description . . . . . . . . . . . . . . . . . 32
4.2 Choco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.2.1 Solver description . . . . . . . . . . . . . . . . . . . . 33
3
Page 4
4.2.2 Debugging support . . . . . . . . . . . . . . . . . . . 35
4.2.3 Subjective description . . . . . . . . . . . . . . . . . 35
4.3 Minion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.3.1 Solver description . . . . . . . . . . . . . . . . . . . . 37
4.3.2 Debugging support . . . . . . . . . . . . . . . . . . . 38
4.3.3 Subjective description . . . . . . . . . . . . . . . . . 38
4.4 Gecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.4.1 Solver description . . . . . . . . . . . . . . . . . . . . 39
4.4.2 Debugging support . . . . . . . . . . . . . . . . . . . 41
4.4.3 Subjective description . . . . . . . . . . . . . . . . . 41
4.5 ECLiPSe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.5.1 Solver description . . . . . . . . . . . . . . . . . . . . 42
4.5.2 Debugging support . . . . . . . . . . . . . . . . . . . 44
4.5.3 Subjective description . . . . . . . . . . . . . . . . . 44
4.6 SICStus Prolog . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.6.1 Solver description . . . . . . . . . . . . . . . . . . . . 45
4.6.2 Debugging support . . . . . . . . . . . . . . . . . . . 45
4.6.3 Subjective description . . . . . . . . . . . . . . . . . 46
4.7 Tailor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5 Benchmark results 48
5.1 The robustness test . . . . . . . . . . . . . . . . . . . . . . . 49
5.2 The performance test . . . . . . . . . . . . . . . . . . . . . . 50
6 Conclusions 53
6.1 Which solver to choose? . . . . . . . . . . . . . . . . . . . . 53
6.2 Future work . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Bibliography 55
A Contents of the CD 58
A.1 Files and directories . . . . . . . . . . . . . . . . . . . . . . 58
B List of the constraint solvers 59
C List of the constraints 62
4
4.2.3 Subjective description . . . . . . . . . . . . . . . . . 35
4.3 Minion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.3.1 Solver description . . . . . . . . . . . . . . . . . . . . 37
4.3.2 Debugging support . . . . . . . . . . . . . . . . . . . 38
4.3.3 Subjective description . . . . . . . . . . . . . . . . . 38
4.4 Gecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.4.1 Solver description . . . . . . . . . . . . . . . . . . . . 39
4.4.2 Debugging support . . . . . . . . . . . . . . . . . . . 41
4.4.3 Subjective description . . . . . . . . . . . . . . . . . 41
4.5 ECLiPSe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.5.1 Solver description . . . . . . . . . . . . . . . . . . . . 42
4.5.2 Debugging support . . . . . . . . . . . . . . . . . . . 44
4.5.3 Subjective description . . . . . . . . . . . . . . . . . 44
4.6 SICStus Prolog . . . . . . . . . . . . . . . . . . . . . . . . . 44
4.6.1 Solver description . . . . . . . . . . . . . . . . . . . . 45
4.6.2 Debugging support . . . . . . . . . . . . . . . . . . . 45
4.6.3 Subjective description . . . . . . . . . . . . . . . . . 46
4.7 Tailor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5 Benchmark results 48
5.1 The robustness test . . . . . . . . . . . . . . . . . . . . . . . 49
5.2 The performance test . . . . . . . . . . . . . . . . . . . . . . 50
6 Conclusions 53
6.1 Which solver to choose? . . . . . . . . . . . . . . . . . . . . 53
6.2 Future work . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Bibliography 55
A Contents of the CD 58
A.1 Files and directories . . . . . . . . . . . . . . . . . . . . . . 58
B List of the constraint solvers 59
C List of the constraints 62
4
Page 5
D Implementation of the benchmarks 65
D.1 Mozart/Oz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
D.2 Choco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
D.3 Minion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
D.4 Gecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
D.5 ECLiPSe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
D.6 SICStus Prolog . . . . . . . . . . . . . . . . . . . . . . . . . 72
5
D.1 Mozart/Oz . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
D.2 Choco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
D.3 Minion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
D.4 Gecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
D.5 ECLiPSe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
D.6 SICStus Prolog . . . . . . . . . . . . . . . . . . . . . . . . . 72
5
Page 6
Na´zev pra´ce: Rˇesˇicˇe omezuj´ıc´ıch podmı´nek
Autor: Michal Tula´cˇek
e-mail autora: michal@tulacek.eu
Katedra (u´stav): Katedra teoreticke´ informatiky a matematicke´ logiky
Vedouc´ı bakala´rˇske´ pra´ce: Doc. RNDr. Roman Barta´k, Ph.D.
e-mail vedouc´ıho: bartak@kti.mff.cuni.cz
Abstrakt: Rˇesˇicˇ omezuj´ıc´ıch podmı´nek je specializovany´ software, urcˇeny´ k
rˇesˇen´ı proble´mu˚ popsany´ch omezuj´ıc´ımi podmı´nkami. Pra´ce poda´va´ prˇehled
rˇesˇicˇ˚u a vybrane´ z nich testuje z pohledu uzˇivatelske´ prˇ´ıstupnosti a rozsahu
proble´mu˚, ktere´ lze modelovat.
Kl´ıcˇova´ slova: omezuj´ıc´ı podmı´nky, rˇesˇicˇe, benchmarky
Title: Constraint solvers
Author: Michal Tula´cˇek
Author’s e-mail address: michal@tulacek.eu
Department: Department of Theoretical Computer Science and Mathemat-
ical Logic
Supervisor: Doc. RNDr. Roman Barta´k, Ph.D.
Supervisor’s e-mail address: bartak@kti.mff.cuni.cz
Abstract: Constraint solver is a specialized software used to solve constraint
satisfaction problems. The thesis surveys constraint solvers and some of
them compares using the criteria of user accessibility and variety of prob-
lems which can be modeled.
Keywords: constraint satisfaction problems, constraint solvers, benchmarks
6
Autor: Michal Tula´cˇek
e-mail autora: michal@tulacek.eu
Katedra (u´stav): Katedra teoreticke´ informatiky a matematicke´ logiky
Vedouc´ı bakala´rˇske´ pra´ce: Doc. RNDr. Roman Barta´k, Ph.D.
e-mail vedouc´ıho: bartak@kti.mff.cuni.cz
Abstrakt: Rˇesˇicˇ omezuj´ıc´ıch podmı´nek je specializovany´ software, urcˇeny´ k
rˇesˇen´ı proble´mu˚ popsany´ch omezuj´ıc´ımi podmı´nkami. Pra´ce poda´va´ prˇehled
rˇesˇicˇ˚u a vybrane´ z nich testuje z pohledu uzˇivatelske´ prˇ´ıstupnosti a rozsahu
proble´mu˚, ktere´ lze modelovat.
Kl´ıcˇova´ slova: omezuj´ıc´ı podmı´nky, rˇesˇicˇe, benchmarky
Title: Constraint solvers
Author: Michal Tula´cˇek
Author’s e-mail address: michal@tulacek.eu
Department: Department of Theoretical Computer Science and Mathemat-
ical Logic
Supervisor: Doc. RNDr. Roman Barta´k, Ph.D.
Supervisor’s e-mail address: bartak@kti.mff.cuni.cz
Abstract: Constraint solver is a specialized software used to solve constraint
satisfaction problems. The thesis surveys constraint solvers and some of
them compares using the criteria of user accessibility and variety of prob-
lems which can be modeled.
Keywords: constraint satisfaction problems, constraint solvers, benchmarks
6
Page 7
Chapter 1
Introduction
In this thesis we compare several constraint solvers from the perspective of
a user who is not experienced in the constraint programming. We focus on
easiness of a learning process of each solver and we measure performance by
using benchmarks which compare various aspects of examined systems.
1.1 Constraint Satisfaction Problems
Constraint programming is a programming paradigm which uses constraints
to describe a solution rather than to program a way of achieving such a
solution. The constraint can be any relation which can be asserted as true
or false – X < Y , Billy is older than Johnny, Z = 5, etc. As an example
of a problem which can be solved using constraint programming we use the
Sudoku puzzle. Sudoku is a worldwide known logical problem which is easy
to explain, its difficulty can be scaled and one does not need previous training
to solve Sudoku. It makes the problem easier to understand for many people
and, therefore, it is very popular. Simple rules of Sudoku are: There is a
given table of size nine times nine. Every field of the table contains a number
in the range one to nine. In each column all the numbers are different (this
enforces that every column contains all numbers in range one to nine). In
each row there are also all numbers different. Finally the same rule which
applies for columns and rows also restricts three times three sized squares
which are in the puzzle marked using bolder lines. The Sudoku is prefilled
with a couple of values. These values help at the beginning of solving and
the difficulty can be adjusted by their number and placement.
The way how to describe the Sudoku puzzle in constraint programming
7
Introduction
In this thesis we compare several constraint solvers from the perspective of
a user who is not experienced in the constraint programming. We focus on
easiness of a learning process of each solver and we measure performance by
using benchmarks which compare various aspects of examined systems.
1.1 Constraint Satisfaction Problems
Constraint programming is a programming paradigm which uses constraints
to describe a solution rather than to program a way of achieving such a
solution. The constraint can be any relation which can be asserted as true
or false – X < Y , Billy is older than Johnny, Z = 5, etc. As an example
of a problem which can be solved using constraint programming we use the
Sudoku puzzle. Sudoku is a worldwide known logical problem which is easy
to explain, its difficulty can be scaled and one does not need previous training
to solve Sudoku. It makes the problem easier to understand for many people
and, therefore, it is very popular. Simple rules of Sudoku are: There is a
given table of size nine times nine. Every field of the table contains a number
in the range one to nine. In each column all the numbers are different (this
enforces that every column contains all numbers in range one to nine). In
each row there are also all numbers different. Finally the same rule which
applies for columns and rows also restricts three times three sized squares
which are in the puzzle marked using bolder lines. The Sudoku is prefilled
with a couple of values. These values help at the beginning of solving and
the difficulty can be adjusted by their number and placement.
The way how to describe the Sudoku puzzle in constraint programming
7
Page 8
Figure 1.1: Example of the Sudoku puzzle
2 5 3 9 1
1 4
4 7 2 8
5 2
9 8 1
4 3
3 6 7 2
7 3
9 3 6 4
is very straightforward. We define the following model:
1. There are 81 variables sij, i, j ∈ {1, ..., 9} which can contain values in
range 1 to 9. We arrange them into a two-dimensional array with size
9 × 9. (The Sudoku is a table sized 9 × 9 containing values in range
1, ..., 9)
2. For all i in 1, ..., 9 the following condition is true: All values of si• are
different (values in each row are different)
3. For all j in 1, ..., 9 the following condition is true: All values of s•j are
different (values in each column are different)
4. For each square the following condition is true: For all k, l such that k,
l are indexes defining the square all values of skl are different (values
in each square are different)
5. For all prefilled values: qmn = V if and only if the field in the column
n and row m is prefilled and contains V .
These constraints fully describe the Sudoku puzzle problem and as the
reader can see they do not differ from the commonly known rules. A person
solving the Sudoku puzzle can use many techniques starting with randomly
filling the table and looking if this is a good solution (the algorithm using this
technique is called GAT – Generate and Test) and ending with generating all
8
2 5 3 9 1
1 4
4 7 2 8
5 2
9 8 1
4 3
3 6 7 2
7 3
9 3 6 4
is very straightforward. We define the following model:
1. There are 81 variables sij, i, j ∈ {1, ..., 9} which can contain values in
range 1 to 9. We arrange them into a two-dimensional array with size
9 × 9. (The Sudoku is a table sized 9 × 9 containing values in range
1, ..., 9)
2. For all i in 1, ..., 9 the following condition is true: All values of si• are
different (values in each row are different)
3. For all j in 1, ..., 9 the following condition is true: All values of s•j are
different (values in each column are different)
4. For each square the following condition is true: For all k, l such that k,
l are indexes defining the square all values of skl are different (values
in each square are different)
5. For all prefilled values: qmn = V if and only if the field in the column
n and row m is prefilled and contains V .
These constraints fully describe the Sudoku puzzle problem and as the
reader can see they do not differ from the commonly known rules. A person
solving the Sudoku puzzle can use many techniques starting with randomly
filling the table and looking if this is a good solution (the algorithm using this
technique is called GAT – Generate and Test) and ending with generating all
8
Page 9
possible fillings and correcting the solution if something fails (this algorithm
is called backtracking). The first approach can miss a correct solution. Since
the second approach systematically searches all possible solutions it has to
result in a correct solution; however, it can last enormous time to complete
it (even on a supercomputer). The secret of a successful solution is in the
fact that not all numbers can be filled in a specific field. If there is prefilled
value 8 at position [6,7] it means that in row 6 and in column 7 there cannot
be another number 8. And because of constraint (4) there also cannot be
8 in the right middle square. A person who does these observations usually
writes into the destination field all possible values and as an examination of
the puzzle progresses there are less and less possibilities to fill in. In an easy
Sudoku after this examination there is at least one field which can be filled
with only one number. After filling all such fields the solving continues in
the same way until the entire table is filled. A program which uses constraint
programming solves it in the same way. For each variable it remembers the
range of possible values (we will call it a domain). Before the program starts
searching for a solution it tries to eliminate as many values from the domain
as possible. It can reveal that the problem does not have a solution (if there
is a variable with an empty domain) before a backtracking. It is no surprise
that in a user guide to Choco system, one of the available constraint solvers,
it is stated “if you know Sudoku, then you know constraint programming.”
The formal definitions of the constraint satisfaction problem and the solution
of the constraint satisfaction problem follows (the definitions are cited from
[9]).
Definition 1 The Constraint satisfaction problem or CSP consist of:
• a set of variables X = {x1, ..., xn},
• for each variable xi a finite set Di of possible values (its domain),
• and a set of constraints restricting the values that the variables can
simultaneously take.
Definition 2 A solution to a CSP is an assignment of a value from its
domain to every variable, in such a way that every constraint is satisfied.
We may want to find:
• just one solution, with no preference as to which one,
• all solutions,
9
is called backtracking). The first approach can miss a correct solution. Since
the second approach systematically searches all possible solutions it has to
result in a correct solution; however, it can last enormous time to complete
it (even on a supercomputer). The secret of a successful solution is in the
fact that not all numbers can be filled in a specific field. If there is prefilled
value 8 at position [6,7] it means that in row 6 and in column 7 there cannot
be another number 8. And because of constraint (4) there also cannot be
8 in the right middle square. A person who does these observations usually
writes into the destination field all possible values and as an examination of
the puzzle progresses there are less and less possibilities to fill in. In an easy
Sudoku after this examination there is at least one field which can be filled
with only one number. After filling all such fields the solving continues in
the same way until the entire table is filled. A program which uses constraint
programming solves it in the same way. For each variable it remembers the
range of possible values (we will call it a domain). Before the program starts
searching for a solution it tries to eliminate as many values from the domain
as possible. It can reveal that the problem does not have a solution (if there
is a variable with an empty domain) before a backtracking. It is no surprise
that in a user guide to Choco system, one of the available constraint solvers,
it is stated “if you know Sudoku, then you know constraint programming.”
The formal definitions of the constraint satisfaction problem and the solution
of the constraint satisfaction problem follows (the definitions are cited from
[9]).
Definition 1 The Constraint satisfaction problem or CSP consist of:
• a set of variables X = {x1, ..., xn},
• for each variable xi a finite set Di of possible values (its domain),
• and a set of constraints restricting the values that the variables can
simultaneously take.
Definition 2 A solution to a CSP is an assignment of a value from its
domain to every variable, in such a way that every constraint is satisfied.
We may want to find:
• just one solution, with no preference as to which one,
• all solutions,
9
Page 13
M. Placha´ in 2007 wrote the bachelor thesis [18] focused on the same
topic as this thesis. The thesis compared SICStus Prolog, ILOG Solver
and Gecode/J. She compared the modeling capabilities of these solvers and
showed the ways to debug the models. Finally the speed of solvers was
measured on several benchmarks. In this thesis we study a wider range of
solvers. We used the same criteria as the mentioned thesis by M. Placha´ but
additionally we compare the accessibility of the solvers for user.
Every year there is held the International Constraint Solver Competition
where authors of solvers can compete. The solvers can be submitted in two
categories – complete and incomplete. Complete solvers can prove that the
instance of a problem is satisfiable or not (or find and prove the optimum).
As stated in the rules [21] for each solver there is a Boolean capability vector
which indicates which constraints the solver can handle. Solvers with the
same capability vector can be naturally compared. Solvers with different
capabilities can be compared on instances which belong to the intersection
of their capabilities, provided it is non-empty. During the competition the
solvers are run in the sandbox environment on a Linux cluster. The task is
to find a solution of as many benchmarks as possible in the smallest time
amount.
There exists a library [15] of the constraint satisfaction problems which
can be used in benchmarking and comparing of solver capabilities. The li-
brary contains various problems in several fields – optimization problems,
combinatorial problems and so on. We encourage the reader to try to imple-
ment several problems in the chosen solver as a part of learning of modeling
in the solver.
1.5 Outline of the thesis
We described our motivation for this thesis and listed some constraint solvers.
In the second chapter we define methodology used to examine some of the
mentioned solvers. The examination consists of two parts – performance
tests and usability tests. In the third chapter we will define benchmarks
used to performance tests. The fourth chapter describes in details each
solver, mentions a little from their history but mainly focuses on usability
and easiness of learning and using the solver. In the fifth chapter we discuss
the performance tests results and compare the solvers. Finally, in the sixth
chapter we state a conclusion of the whole examination process.
There are four appendixes to this thesis. The content of the included CD
13
topic as this thesis. The thesis compared SICStus Prolog, ILOG Solver
and Gecode/J. She compared the modeling capabilities of these solvers and
showed the ways to debug the models. Finally the speed of solvers was
measured on several benchmarks. In this thesis we study a wider range of
solvers. We used the same criteria as the mentioned thesis by M. Placha´ but
additionally we compare the accessibility of the solvers for user.
Every year there is held the International Constraint Solver Competition
where authors of solvers can compete. The solvers can be submitted in two
categories – complete and incomplete. Complete solvers can prove that the
instance of a problem is satisfiable or not (or find and prove the optimum).
As stated in the rules [21] for each solver there is a Boolean capability vector
which indicates which constraints the solver can handle. Solvers with the
same capability vector can be naturally compared. Solvers with different
capabilities can be compared on instances which belong to the intersection
of their capabilities, provided it is non-empty. During the competition the
solvers are run in the sandbox environment on a Linux cluster. The task is
to find a solution of as many benchmarks as possible in the smallest time
amount.
There exists a library [15] of the constraint satisfaction problems which
can be used in benchmarking and comparing of solver capabilities. The li-
brary contains various problems in several fields – optimization problems,
combinatorial problems and so on. We encourage the reader to try to imple-
ment several problems in the chosen solver as a part of learning of modeling
in the solver.
1.5 Outline of the thesis
We described our motivation for this thesis and listed some constraint solvers.
In the second chapter we define methodology used to examine some of the
mentioned solvers. The examination consists of two parts – performance
tests and usability tests. In the third chapter we will define benchmarks
used to performance tests. The fourth chapter describes in details each
solver, mentions a little from their history but mainly focuses on usability
and easiness of learning and using the solver. In the fifth chapter we discuss
the performance tests results and compare the solvers. Finally, in the sixth
chapter we state a conclusion of the whole examination process.
There are four appendixes to this thesis. The content of the included CD
13
Page 16
model problems described in the third chapter and look for constraints which
cannot be modelled and we describe possible solutions.
Secondly, a quality of documentation is also an important criterion. A
solver can be the best of all, but it is useless if the user cannot understand the
usage. The quality of documentation is perceived subjectively and cannot
be measured exactly. This means that any evaluation is only informational,
although it should be considered. As a documentation we accept a user guide
as well as all other available guides, documents, web pages or a doxygen
style documentation. An existence of user forums or mailing lists is also an
important part of learning of new systems.
Last but not least, we aim for debugging. There are two areas which
can be debugged - correctness of the program and correctness of the model.
The correctness of the program means that the program does what it should
do, that it handles all inputs as the programmer expects and so on. The
correctness of model stands for an accurate description of a given problem.
The user should be able to inspect variables, visualise a decision tree of
search and other information. We discuss the ways how a solver informs
about mistakes (and how much descriptive the information is), the tools
provided with the solver to debug the program and similarly the tools which
can be used to debug the model correctness.
When the user masters the solver and uses it to solve real problems, the
time and space efficiency of used algorithms matters. We neither examine
source codes, nor analyze time complexity of used algorithms. Instead we
measure the time needed to load and the time to solve the problem. If a
solver cannot provide such information we measure only a total time. We
also measure an amount of consumed memory during the program execu-
tion. All measurements are performed several times and averaged to avoid
randomness. A robustness test is also performed. In the robustness test we
set limit ten minutes and try to determine the length of the longest magic
sequence (readers can find a definition of a magic sequence in the section
3.3) can be computed in the given time. We use the models created in the
process described in the previous paragraph. In [14] authors have sent mod-
els to the solvers’ authors and have given them a chance to modify them to
achieve the best performance of their solvers. We focus on first-time users
of a solver, so we use our own models which are not perfect and, more impo-
rantly, not tuned for any particular solver. All solvers are tested on Debian
4.0 Linux with the kernel 2.6.18 on Pentium 4, 3GHz.
16
cannot be modelled and we describe possible solutions.
Secondly, a quality of documentation is also an important criterion. A
solver can be the best of all, but it is useless if the user cannot understand the
usage. The quality of documentation is perceived subjectively and cannot
be measured exactly. This means that any evaluation is only informational,
although it should be considered. As a documentation we accept a user guide
as well as all other available guides, documents, web pages or a doxygen
style documentation. An existence of user forums or mailing lists is also an
important part of learning of new systems.
Last but not least, we aim for debugging. There are two areas which
can be debugged - correctness of the program and correctness of the model.
The correctness of the program means that the program does what it should
do, that it handles all inputs as the programmer expects and so on. The
correctness of model stands for an accurate description of a given problem.
The user should be able to inspect variables, visualise a decision tree of
search and other information. We discuss the ways how a solver informs
about mistakes (and how much descriptive the information is), the tools
provided with the solver to debug the program and similarly the tools which
can be used to debug the model correctness.
When the user masters the solver and uses it to solve real problems, the
time and space efficiency of used algorithms matters. We neither examine
source codes, nor analyze time complexity of used algorithms. Instead we
measure the time needed to load and the time to solve the problem. If a
solver cannot provide such information we measure only a total time. We
also measure an amount of consumed memory during the program execu-
tion. All measurements are performed several times and averaged to avoid
randomness. A robustness test is also performed. In the robustness test we
set limit ten minutes and try to determine the length of the longest magic
sequence (readers can find a definition of a magic sequence in the section
3.3) can be computed in the given time. We use the models created in the
process described in the previous paragraph. In [14] authors have sent mod-
els to the solvers’ authors and have given them a chance to modify them to
achieve the best performance of their solvers. We focus on first-time users
of a solver, so we use our own models which are not perfect and, more impo-
rantly, not tuned for any particular solver. All solvers are tested on Debian
4.0 Linux with the kernel 2.6.18 on Pentium 4, 3GHz.
16
Page 17
Chapter 3
Benchmarks
In this chapter we shall define benchmarks which will later be used to exam-
ine the properties of each solver. We will be dealing with five different cases
which are well known and documented: n-queens problem, magic sequence
problem, self referential quiz, quasigroup with holes problem and locating
warehouses problem. In this chapter, we will show on these benchmarks the
different ways of modeling the problem with solvers. The last benchmarking
problem – locating warehouses – is an optimization problem. The solver not
only has to find correct solutions but also has to evaluate the best of the
solutions based on the value of an objective function. For each benchmark
a general description is presented as is the formal model of the constraint
problem and an implementation in the Essence programming language. The
basics of the language are described in the following section.
3.1 Essence programming language
Essence is a programming language for modeling of combinatorial problems.
It is easy enough to understand and so simple that even person who has never
seen the language before can correctly guess what the expected output of the
program is. Every program in Essence consists of three parts. The first part
defines the version of the language, the second part the used variables and
finally, the third part presents the constraints used on the given variables.
These constrained variables can be integers, booleans and vectors or matri-
ces. The language supports sums and loops over the variables; however, the
bounds of the sum or loop have to be constant as they are in the process of
compiling translated to a sequence of statements. The program itself can be
17
Benchmarks
In this chapter we shall define benchmarks which will later be used to exam-
ine the properties of each solver. We will be dealing with five different cases
which are well known and documented: n-queens problem, magic sequence
problem, self referential quiz, quasigroup with holes problem and locating
warehouses problem. In this chapter, we will show on these benchmarks the
different ways of modeling the problem with solvers. The last benchmarking
problem – locating warehouses – is an optimization problem. The solver not
only has to find correct solutions but also has to evaluate the best of the
solutions based on the value of an objective function. For each benchmark
a general description is presented as is the formal model of the constraint
problem and an implementation in the Essence programming language. The
basics of the language are described in the following section.
3.1 Essence programming language
Essence is a programming language for modeling of combinatorial problems.
It is easy enough to understand and so simple that even person who has never
seen the language before can correctly guess what the expected output of the
program is. Every program in Essence consists of three parts. The first part
defines the version of the language, the second part the used variables and
finally, the third part presents the constraints used on the given variables.
These constrained variables can be integers, booleans and vectors or matri-
ces. The language supports sums and loops over the variables; however, the
bounds of the sum or loop have to be constant as they are in the process of
compiling translated to a sequence of statements. The program itself can be
17
Page 18
split into the model definition and parameters definition parts. Examples
in this chapters show only the model definition parts. The files containing
the parameter definitions can be found on the included CD. The Tailor tool
is the compiler which translate the code from the Essence language to the
solver specific language. In the current version it can translate the Essence
program to Minion input file, FlatZinc and C++ source code which is using
Gecode library. Further description of the Tailor system is in the section
4.7.
3.2 N-queens
This benchmark is based on a classic chess task. The player has to place
eight queens on the chessboard in a way that none of the queens offends
any other. The task can be scaled to a chessboard of any size. The goal is
then place n queens onto a table of size n × n in such way that no queen
offends any other. A queen offends all pieces which are placed in the same
row, column and diagonal on the chessboard. The problem is a little bit
easier if we realize that in order to place n queens on a chessboard with n
columns, there has to be one queen per column. Therefore we only need to
find out in which rows the queens are in each column. We model a solution
of the problem as a vector qi where i ∈ {1, ..., n}. To avoid placing the
queens in the same row we simply add constraint that all qi are different.
Finally we have to include the diagonals in the model: two pieces are on the
same diagonal, if the difference in the horizontal and vertical coordinates
is equal. Therefore we add the constraint |Q(i)−Q(j)| 6= |i− j|. Since
both the chessboard and the modes of offense the queen can carry out are
symmetric, the solutions are symmetric as well. We can decrease the number
of solutions if we avoid such symmetries (see the next subsection).
3.2.1 Constraint problem model
• Variables and domains:
– Positions of queens: q1, ..., qn ∈ {1, ..., n}, qi.
• Constraints:
– All queens are on different rows: ∀i, j ∈ {1, ..., n} : qi 6= qj ,
18
in this chapters show only the model definition parts. The files containing
the parameter definitions can be found on the included CD. The Tailor tool
is the compiler which translate the code from the Essence language to the
solver specific language. In the current version it can translate the Essence
program to Minion input file, FlatZinc and C++ source code which is using
Gecode library. Further description of the Tailor system is in the section
4.7.
3.2 N-queens
This benchmark is based on a classic chess task. The player has to place
eight queens on the chessboard in a way that none of the queens offends
any other. The task can be scaled to a chessboard of any size. The goal is
then place n queens onto a table of size n × n in such way that no queen
offends any other. A queen offends all pieces which are placed in the same
row, column and diagonal on the chessboard. The problem is a little bit
easier if we realize that in order to place n queens on a chessboard with n
columns, there has to be one queen per column. Therefore we only need to
find out in which rows the queens are in each column. We model a solution
of the problem as a vector qi where i ∈ {1, ..., n}. To avoid placing the
queens in the same row we simply add constraint that all qi are different.
Finally we have to include the diagonals in the model: two pieces are on the
same diagonal, if the difference in the horizontal and vertical coordinates
is equal. Therefore we add the constraint |Q(i)−Q(j)| 6= |i− j|. Since
both the chessboard and the modes of offense the queen can carry out are
symmetric, the solutions are symmetric as well. We can decrease the number
of solutions if we avoid such symmetries (see the next subsection).
3.2.1 Constraint problem model
• Variables and domains:
– Positions of queens: q1, ..., qn ∈ {1, ..., n}, qi.
• Constraints:
– All queens are on different rows: ∀i, j ∈ {1, ..., n} : qi 6= qj ,
18
Page 19
Figure 3.1: Implementation of N-Queens Problem in Essence
1 l anguage ESSENCE’ 1. b . a
2 find q u e e n s : m a t r i x i n d e x e d by [ int (1.. n ) ] of int (1.. n )
3 such that
4
5 a l l d i f f ( q u e e n s ) ,
6 f o r a l l i : int (1.. n ) . f o r a l l j : int ( i +1.. n ) .
7 | q u e e n s [ i ] - q u e e n s [ j ] | != | i - j |
– all queens are on different diagonals: ∀i, j ∈ {1, ..., n} : |qi− qj | 6=
|i− j|
– optional avoiding of the symmetry: q1 < qn
The Essence implementation (without symmetry breaking) is in the figure
3.1.
Figure 3.2: Solutions of 4-queens problem
4 0ZQZ
3 L0Z0
2 0Z0L
1 ZQZ0
a b c d
4 0L0Z
3 Z0ZQ
2 QZ0Z
1 Z0L0
a b c d
3.3 Magic sequence
Magic sequence of length n is a sequence of numbers such as mi, i ∈ {0, ...,
n−1} which satisfies the following condition: The value of mk is equal to the
number of occurrences of value k in the sequence. For example the sequence
(2 1 2 0 0) is magic sequence of length five as the condition above is satisfied.
The number zero is twice in the sequence and m0 is equal to two. Similarly
one is in the sequence only once and therefore m1 is one.
19
1 l anguage ESSENCE’ 1. b . a
2 find q u e e n s : m a t r i x i n d e x e d by [ int (1.. n ) ] of int (1.. n )
3 such that
4
5 a l l d i f f ( q u e e n s ) ,
6 f o r a l l i : int (1.. n ) . f o r a l l j : int ( i +1.. n ) .
7 | q u e e n s [ i ] - q u e e n s [ j ] | != | i - j |
– all queens are on different diagonals: ∀i, j ∈ {1, ..., n} : |qi− qj | 6=
|i− j|
– optional avoiding of the symmetry: q1 < qn
The Essence implementation (without symmetry breaking) is in the figure
3.1.
Figure 3.2: Solutions of 4-queens problem
4 0ZQZ
3 L0Z0
2 0Z0L
1 ZQZ0
a b c d
4 0L0Z
3 Z0ZQ
2 QZ0Z
1 Z0L0
a b c d
3.3 Magic sequence
Magic sequence of length n is a sequence of numbers such as mi, i ∈ {0, ...,
n−1} which satisfies the following condition: The value of mk is equal to the
number of occurrences of value k in the sequence. For example the sequence
(2 1 2 0 0) is magic sequence of length five as the condition above is satisfied.
The number zero is twice in the sequence and m0 is equal to two. Similarly
one is in the sequence only once and therefore m1 is one.
19
Page 20
Figure 3.3: Implementation of Magic Sequence Problem in Essence
1 l anguage ESSENCE’ 1. b . a
2 find s : m a t r i x i n d e x e d by [ int (0.. n -1) ] of int (0.. n )
3 such that
4 f o r a l l i : int (0.. n -1) .
5 ( s [ i ] = ( sum j : int (0.. n -1) . ( s [ j ] = i ) ) )
3.3.1 Constraint problem model
Model for a magic sequence m of length k:
• Variables and domains:
– Magic sequence items: m0, ..., mk−1 ∈ {0, ..., k}.
• Constraints:
– Value of mi is i times in the sequence: ∀i ∈ 0, ..., k − 1 :
mi =
∑
mj=i 1.
In case that solver does not support the constraint mi =
∑
mj=i 1, we
can use an alternative model:
• Values and domains:
– Magic sequence items: m0, ..., mk−1 ∈ {0, ..., k},
– auxiliary variables: ∀i, j ∈ 0, ..., k − 1 : auxij .
• Constraints:
– auxij = 1 if and only if mj = i: ∀i, j ∈ {0, ..., k − 1} :
(auxij = 1) ⇔ (mj = i),
– the value of the items of the magic sequence corresponds to the
sum of some auxiliary variables: ∀i ∈ {0, ..., k − 1} :
mi =
∑k−1
j=0 auxij .
The Essence implementation is in the figure 3.3.
20
1 l anguage ESSENCE’ 1. b . a
2 find s : m a t r i x i n d e x e d by [ int (0.. n -1) ] of int (0.. n )
3 such that
4 f o r a l l i : int (0.. n -1) .
5 ( s [ i ] = ( sum j : int (0.. n -1) . ( s [ j ] = i ) ) )
3.3.1 Constraint problem model
Model for a magic sequence m of length k:
• Variables and domains:
– Magic sequence items: m0, ..., mk−1 ∈ {0, ..., k}.
• Constraints:
– Value of mi is i times in the sequence: ∀i ∈ 0, ..., k − 1 :
mi =
∑
mj=i 1.
In case that solver does not support the constraint mi =
∑
mj=i 1, we
can use an alternative model:
• Values and domains:
– Magic sequence items: m0, ..., mk−1 ∈ {0, ..., k},
– auxiliary variables: ∀i, j ∈ 0, ..., k − 1 : auxij .
• Constraints:
– auxij = 1 if and only if mj = i: ∀i, j ∈ {0, ..., k − 1} :
(auxij = 1) ⇔ (mj = i),
– the value of the items of the magic sequence corresponds to the
sum of some auxiliary variables: ∀i ∈ {0, ..., k − 1} :
mi =
∑k−1
j=0 auxij .
The Essence implementation is in the figure 3.3.
20
Page 23
– question 1, A to D:
∀i ∈ {1, ..., 4} : (s1|i = 1) ⇔ ((s4−i+1|1 = 1) ∧ (∀j ∈ {1, ..., 4− i} :
sj|1 = 0)),
– question 1, E:
(s1|5 = 1) ⇔ (∀j ∈ {1, ..., 4} : sj|1 = 0),
– question 2:
∀i ∈ {1, ..., 5} : (s2|i = 1) ⇔ (∀j ∈ {1, ..., 5} : s3+i−1|j = s3+i|j),
– question 3:
∀i ∈ {1, ..., 5} : (s3|i = 1) ⇔ ((s4+i−1|1 = 1) ∧ (∀j ∈ {4, ..., 2 + i} :
sj|1 = 0)),
– question 4:
∀i ∈ {1, ..., 5} : (s4|i = 1) ⇔ ((s2i|2 = 1)∧ (∀j ∈ {1..i−1} : s2j|2 =
0),
– question 5:
∀i ∈ {1, ..., 5} : (s5|i = 1) ⇔ (s2i−1|3 = 1)
– question 6, A:
∀i ∈ {1, ..., 5} : (s6|1 = 1) ⇔ (∃j ∈ {1, ..., 5} : sj|4 = 1 ∧
∀j ∈ 7, ..., 10 : sj|4 = 0)
– question 6, B:
∀i ∈ {1, ..., 5} : (s6|2 = 1) ⇔ (∃j ∈ {7, ..., 10} : sj|4 = 1 ∧
∀j ∈ 1, ..., 5 : sj|4 = 0)
– question 6, C:
∀i ∈ {1, ..., 5} : (s6|3 = 1) ⇔ (∃j ∈ {1, ..., 5, 7, ..., 10} : sj|4 = 1)
– question 6, D:
∀i ∈ {1, ..., 5} : (s6|4 = 1) ⇔ (∀j ∈ {1, ..., 10} : sj|4 = 0)
– question 6, E:
∀i ∈ {1, ..., 5} : (s6|5 = 1) ⇔ (s6|4 = 1)
– question 7:
∀i ∈ {1, ..., 5} : (s7|i = 1) ⇔ (si+4|5 = 1)∧(∀j ∈ {i+4+1, ..., 10} :
sj,5 = 0))
– question 8:
∀i ∈ {1, ..., 5} : (s8|i = 1) ⇔
(
∑10
j=1
(
sj|2 + sj|3 + sj|4
)
= 7− i + 1
)
– question 9:
∀i ∈ {1, ..., 5} : (s9|i = 1) ⇔
(
∑10
j=1
(
sj|1 + sj|5
)
= i− 1
)
.
23
∀i ∈ {1, ..., 4} : (s1|i = 1) ⇔ ((s4−i+1|1 = 1) ∧ (∀j ∈ {1, ..., 4− i} :
sj|1 = 0)),
– question 1, E:
(s1|5 = 1) ⇔ (∀j ∈ {1, ..., 4} : sj|1 = 0),
– question 2:
∀i ∈ {1, ..., 5} : (s2|i = 1) ⇔ (∀j ∈ {1, ..., 5} : s3+i−1|j = s3+i|j),
– question 3:
∀i ∈ {1, ..., 5} : (s3|i = 1) ⇔ ((s4+i−1|1 = 1) ∧ (∀j ∈ {4, ..., 2 + i} :
sj|1 = 0)),
– question 4:
∀i ∈ {1, ..., 5} : (s4|i = 1) ⇔ ((s2i|2 = 1)∧ (∀j ∈ {1..i−1} : s2j|2 =
0),
– question 5:
∀i ∈ {1, ..., 5} : (s5|i = 1) ⇔ (s2i−1|3 = 1)
– question 6, A:
∀i ∈ {1, ..., 5} : (s6|1 = 1) ⇔ (∃j ∈ {1, ..., 5} : sj|4 = 1 ∧
∀j ∈ 7, ..., 10 : sj|4 = 0)
– question 6, B:
∀i ∈ {1, ..., 5} : (s6|2 = 1) ⇔ (∃j ∈ {7, ..., 10} : sj|4 = 1 ∧
∀j ∈ 1, ..., 5 : sj|4 = 0)
– question 6, C:
∀i ∈ {1, ..., 5} : (s6|3 = 1) ⇔ (∃j ∈ {1, ..., 5, 7, ..., 10} : sj|4 = 1)
– question 6, D:
∀i ∈ {1, ..., 5} : (s6|4 = 1) ⇔ (∀j ∈ {1, ..., 10} : sj|4 = 0)
– question 6, E:
∀i ∈ {1, ..., 5} : (s6|5 = 1) ⇔ (s6|4 = 1)
– question 7:
∀i ∈ {1, ..., 5} : (s7|i = 1) ⇔ (si+4|5 = 1)∧(∀j ∈ {i+4+1, ..., 10} :
sj,5 = 0))
– question 8:
∀i ∈ {1, ..., 5} : (s8|i = 1) ⇔
(
∑10
j=1
(
sj|2 + sj|3 + sj|4
)
= 7− i + 1
)
– question 9:
∀i ∈ {1, ..., 5} : (s9|i = 1) ⇔
(
∑10
j=1
(
sj|1 + sj|5
)
= i− 1
)
.
23
Page 24
Figure 3.4: Implementation of the Self Referential Quiz in Essence
1 l anguage ESSENCE’ 1. b . a
2 find s : m a t r i x i n d e x e d by [ int ( 1 . . 1 0 ) , int ( 1 . . 5 ) ] of bool
3 such that
4 $ t h e r e is only one a n s w e r to each q u e s t i o n and t he r e is not any u n a n s w e r e d q u e s t i o n
5 f o r a l l row : int ( 1 . . 1 0 ) . (( sum col : int ( 1 . . 5 ) . s [ row , col ]) = 1) ,
6 $ Q u e s t i o n 1
7 $ A to D
8 f o r a l l col : int ( 1 . . 4 ) . ( ( s [1 , col ] = 1) <= > ( ( s [(4 - col +1) ,1] = 1) /\ ( f o r a l l row :
int (1..(4 - col ) ) . ( s [ row ,1] = 0) ) ) ) ,
9 $ E
10 ( s [1 ,5] = 1) <= > ( f o r a l l row : int ( 1 . . 4 ) . ( s [ row ,1] = 0) ) ,
11
12 $ Q u e s t i o n 2
13 f o r a l l col : int ( 1 . . 5 ) . ( ( s [2 , col ] = 1) <= > ( f o r a l l col2 : int ( 1 . . 5 ) . ( s [3+ col -1 ,
col2 ] = s [3+ col , col2 ]) ) ) ,
14 $ Q u e s t i o n 3
15 f o r a l l col : int ( 1 . . 5 ) . ( ( s [3 , col ] = 1) <= > ( ( s [(4+ col -1) ,1] = 1) /\ ( f o r a l l row :
int ( 4 . . 2 + col ) . s [ row ,1] = 0 ) ) ) ,
16 $ Q u e s t i o n 4
17 f o r a l l col : int ( 1 . . 5 ) . ( ( s [4 , col ] = 1) <= > ( ( s [ col *2 ,2] = 1) /\ ( f o r a l l row : int
( 1 . . ( col -1) ) . s [ row *2 ,2] = 0 ) ) ) ,
18 $ Q u e s t i o n 5
19 f o r a l l col : int ( 1 . . 5 ) . ( ( s [5 , col ] = 1) <= > ( s [2* col -1 ,3]=1 ) ) ,
20 $ Q u e s t i o n 6
21 ( s [6 ,1] = 1) <= > ( ( e x i s t s row : int ( 1 . . 5 ) . s [ row ,4] = 1 ) /\ ( f o r a l l row : int
( 7 . . 1 0 ) . s [ row ,4] = 0 ) ) ,
22 ( s [6 ,2] = 1) <= > ( ( e x i s t s row : int ( 7 . . 1 0 ) . s [ row ,4] = 1 ) /\ ( f o r a l l row : int
( 1 . . 5 ) . s [ row ,4] = 0 ) ) ,
23 ( s [6 ,3] = 1) <= > ( ( e x i s t s row : int ( 7 . . 1 0 ) . s [ row ,4] = 1 ) /\ ( e x i s t s row : int
( 1 . . 5 ) . s [ row ,4] = 1 ) ) ,
24 ( s [6 ,4] = 1) <= > ( f o r a l l row : int ( 1 . . 1 0 ) . s [ row ,4] = 0 ) ,
25 ( s [6 ,5] = 1) <= > ( s [6 ,4] = 1) ,
26 $ Q u e s t i o n 7
27 f o r a l l col : int ( 1 . . 5 ) . ( ( s [7 , col ] = 1) <= > ( ( s [ col +4 ,5] = 1) /\ ( f o r a l l row : int
( col + 4 + 1 . . 1 0 ) . s [ row ,5] = 0 ) ) ) ,
28 $ Q u e s t i o n 8
29 f o r a l l col : int ( 1 . . 5 ) . ( ( s [8 , col ] = 1) <= > ( ( sum row : int ( 1 . . 1 0 ) . ( s [ row ,2] + s [
row ,3] + s [ row ,4]) ) = (7 - col +1) ) ) ,
30 $ Q u e s t i o n 9
31 f o r a l l col : int ( 1 . . 5 ) . ( ( s [9 , col ] = 1) <= > ( ( sum row : int ( 1 . . 1 0 ) . ( s [ row ,1] + s [
row ,5]) ) = ( col -1) ) )
32 $ C o n s t r a i n t s for q u e s t i o n 10 are u s e l e s s
The Essence implementation is in the figure 3.4.
3.5 Quasigroup with holes
Quasigroup or latin square is a table of size n × n filled with numbers in
the range 1, ..., n such that all values in each row and in each column are
unique. There can be also additional condition on the items of quasigroup,
for example that the items on the main diagonal have to be even. The task is
to fully fill the given partly filled quasigroup. The completed quasigroup has
to satisfy all previously stated constraints. This problem is called a quasi-
group completion problem or QCP. Unfortunately, this benchmark does not
provide a consistent result. Some partial fillings can be solved surprisingly
easily while other can be extremely demanding; some can even be impossible
24
1 l anguage ESSENCE’ 1. b . a
2 find s : m a t r i x i n d e x e d by [ int ( 1 . . 1 0 ) , int ( 1 . . 5 ) ] of bool
3 such that
4 $ t h e r e is only one a n s w e r to each q u e s t i o n and t he r e is not any u n a n s w e r e d q u e s t i o n
5 f o r a l l row : int ( 1 . . 1 0 ) . (( sum col : int ( 1 . . 5 ) . s [ row , col ]) = 1) ,
6 $ Q u e s t i o n 1
7 $ A to D
8 f o r a l l col : int ( 1 . . 4 ) . ( ( s [1 , col ] = 1) <= > ( ( s [(4 - col +1) ,1] = 1) /\ ( f o r a l l row :
int (1..(4 - col ) ) . ( s [ row ,1] = 0) ) ) ) ,
9 $ E
10 ( s [1 ,5] = 1) <= > ( f o r a l l row : int ( 1 . . 4 ) . ( s [ row ,1] = 0) ) ,
11
12 $ Q u e s t i o n 2
13 f o r a l l col : int ( 1 . . 5 ) . ( ( s [2 , col ] = 1) <= > ( f o r a l l col2 : int ( 1 . . 5 ) . ( s [3+ col -1 ,
col2 ] = s [3+ col , col2 ]) ) ) ,
14 $ Q u e s t i o n 3
15 f o r a l l col : int ( 1 . . 5 ) . ( ( s [3 , col ] = 1) <= > ( ( s [(4+ col -1) ,1] = 1) /\ ( f o r a l l row :
int ( 4 . . 2 + col ) . s [ row ,1] = 0 ) ) ) ,
16 $ Q u e s t i o n 4
17 f o r a l l col : int ( 1 . . 5 ) . ( ( s [4 , col ] = 1) <= > ( ( s [ col *2 ,2] = 1) /\ ( f o r a l l row : int
( 1 . . ( col -1) ) . s [ row *2 ,2] = 0 ) ) ) ,
18 $ Q u e s t i o n 5
19 f o r a l l col : int ( 1 . . 5 ) . ( ( s [5 , col ] = 1) <= > ( s [2* col -1 ,3]=1 ) ) ,
20 $ Q u e s t i o n 6
21 ( s [6 ,1] = 1) <= > ( ( e x i s t s row : int ( 1 . . 5 ) . s [ row ,4] = 1 ) /\ ( f o r a l l row : int
( 7 . . 1 0 ) . s [ row ,4] = 0 ) ) ,
22 ( s [6 ,2] = 1) <= > ( ( e x i s t s row : int ( 7 . . 1 0 ) . s [ row ,4] = 1 ) /\ ( f o r a l l row : int
( 1 . . 5 ) . s [ row ,4] = 0 ) ) ,
23 ( s [6 ,3] = 1) <= > ( ( e x i s t s row : int ( 7 . . 1 0 ) . s [ row ,4] = 1 ) /\ ( e x i s t s row : int
( 1 . . 5 ) . s [ row ,4] = 1 ) ) ,
24 ( s [6 ,4] = 1) <= > ( f o r a l l row : int ( 1 . . 1 0 ) . s [ row ,4] = 0 ) ,
25 ( s [6 ,5] = 1) <= > ( s [6 ,4] = 1) ,
26 $ Q u e s t i o n 7
27 f o r a l l col : int ( 1 . . 5 ) . ( ( s [7 , col ] = 1) <= > ( ( s [ col +4 ,5] = 1) /\ ( f o r a l l row : int
( col + 4 + 1 . . 1 0 ) . s [ row ,5] = 0 ) ) ) ,
28 $ Q u e s t i o n 8
29 f o r a l l col : int ( 1 . . 5 ) . ( ( s [8 , col ] = 1) <= > ( ( sum row : int ( 1 . . 1 0 ) . ( s [ row ,2] + s [
row ,3] + s [ row ,4]) ) = (7 - col +1) ) ) ,
30 $ Q u e s t i o n 9
31 f o r a l l col : int ( 1 . . 5 ) . ( ( s [9 , col ] = 1) <= > ( ( sum row : int ( 1 . . 1 0 ) . ( s [ row ,1] + s [
row ,5]) ) = ( col -1) ) )
32 $ C o n s t r a i n t s for q u e s t i o n 10 are u s e l e s s
The Essence implementation is in the figure 3.4.
3.5 Quasigroup with holes
Quasigroup or latin square is a table of size n × n filled with numbers in
the range 1, ..., n such that all values in each row and in each column are
unique. There can be also additional condition on the items of quasigroup,
for example that the items on the main diagonal have to be even. The task is
to fully fill the given partly filled quasigroup. The completed quasigroup has
to satisfy all previously stated constraints. This problem is called a quasi-
group completion problem or QCP. Unfortunately, this benchmark does not
provide a consistent result. Some partial fillings can be solved surprisingly
easily while other can be extremely demanding; some can even be impossible
24
Page 25
to solve. The crucial problem is that determining whether the problem can
be solved or not is a NP-complete task [5]. Therefore we cannot determine
with certainty whether the problem is only too hard for the solver or the
solution does not exist at all and the solver has to search through enormous
state space. To avoid this uncertainty, we use a modification of QCP called
quasigroup with holes or QWH. First we generate a fully filled quasigroup
which satisfies the given conditions and then we exclude some of the values;
this quasigroup with holes is the new assignment for QCP. We have a guar-
antee that the assignment is correct and that it can be solved. Generation of
QWH assignments was studied by D. Achlioptas et al. who found out that
the difficulty of finding a solution of such problem depends on the size of the
so called backbone [5]. The backbone is a set of positions in the quasigroup
which have the same value in all solutions. If the size of the backbone is
close to 0%, there are many different solutions and the solver can find some
“by accident”. On the other, hand if the backbone is close to 100%, there
is only one solution and all constraints lead towards it. The experiments [5]
showed that this interesting behavior is somewhere near the 30%. They also
showed that the hard quasigroups of the order n have 1.6n1.55 holes.
The quasigroups we use have no additional conditions. The used quasi-
groups are produced by the generators lsencode developed by Carla Gomez
and walksat by Henry Kautz.
3.5.1 Constraint problem model
Model for a quasigroup of the order n. The assignment values are in the
vector dataij :
• Variables and domains:
– Quasigroup items: q11, ..., qnn ∈ {1, ..., n}.
• Constraints:
– All items in one row are unique: ∀i ∈ {1, ..., n} : ∀j, k ∈ {1, ..., n} :
qij 6= qik,
– all items in one column are unique: ∀i ∈ {1, ..., n} :
∀j, k ∈ {1, ..., n} : qji 6= qki
– some items of the quasigroup are preassigned: dataij defined ⇔
(qij = dataij)
25
be solved or not is a NP-complete task [5]. Therefore we cannot determine
with certainty whether the problem is only too hard for the solver or the
solution does not exist at all and the solver has to search through enormous
state space. To avoid this uncertainty, we use a modification of QCP called
quasigroup with holes or QWH. First we generate a fully filled quasigroup
which satisfies the given conditions and then we exclude some of the values;
this quasigroup with holes is the new assignment for QCP. We have a guar-
antee that the assignment is correct and that it can be solved. Generation of
QWH assignments was studied by D. Achlioptas et al. who found out that
the difficulty of finding a solution of such problem depends on the size of the
so called backbone [5]. The backbone is a set of positions in the quasigroup
which have the same value in all solutions. If the size of the backbone is
close to 0%, there are many different solutions and the solver can find some
“by accident”. On the other, hand if the backbone is close to 100%, there
is only one solution and all constraints lead towards it. The experiments [5]
showed that this interesting behavior is somewhere near the 30%. They also
showed that the hard quasigroups of the order n have 1.6n1.55 holes.
The quasigroups we use have no additional conditions. The used quasi-
groups are produced by the generators lsencode developed by Carla Gomez
and walksat by Henry Kautz.
3.5.1 Constraint problem model
Model for a quasigroup of the order n. The assignment values are in the
vector dataij :
• Variables and domains:
– Quasigroup items: q11, ..., qnn ∈ {1, ..., n}.
• Constraints:
– All items in one row are unique: ∀i ∈ {1, ..., n} : ∀j, k ∈ {1, ..., n} :
qij 6= qik,
– all items in one column are unique: ∀i ∈ {1, ..., n} :
∀j, k ∈ {1, ..., n} : qji 6= qki
– some items of the quasigroup are preassigned: dataij defined ⇔
(qij = dataij)
25
Page 26
Figure 3.5: Implementation of Quasigroup With Holes Problem in Essence
1 l anguage ESSENCE’ 1. b . a
2 l e t t i n g n D o m a i n be d o m a i n int (1.. n )
3 find qcp : m a t r i x i n d e x e d by [ nDomain , n D o m a i n ] of n D o m a i n
4 such that
5 f o r a l l i : n D o m a i n . a l l d i f f ( qcp [ i , n D o m a i n ]) ,
6 f o r a l l i : n D o m a i n . a l l d i f f ( qcp [ nDomain , i ])
The Essence implementation is in the figure 3.5.
3.6 Locating warehouses
Let us assume that we want to help a hypothetical business company with
the decision which warehouses should be built for their stores and which
warehouses should supply which store. The main criterion is in this case the
cost of the solution. The cost has two components. The first one is payment
of the constant cost for opening a new warehouse. The second component
is the price for the distribution of goods from a warehouse to the store. The
price varies and is different for all pairs (warehouse, store). Each possible
warehouse has a defined maximum capacity which accounts for the number
of stores which can be supplied from this warehouse. As the last condition
of the model, we state that all stores have to be supplied. Our task is to
choose the solution with the minimal total cost.
Both maximum capacities of warehouses and a table with prices for sup-
plying each of the pairs (warehouse, store) are the required input parameters
for the solver which computes the vector si, i ∈ {1, ...,# of stores} where si
indicates which warehouse supplies the store i.
3.6.1 Constraint problem model
We can build W warehouses. The price for opening of a new warehouse
is fixed and stored in the parameter openCost. We also have S shops.
The maximum capacity of warehouses is given by vector w, where wi is
the maximum number of shops which can be supplied by the warehouse
i, i ∈ {1, ...,W}. Finally, we have a matrix of supply costs supplyCost
where supplyCostij translates as the cost of supplying the shop j from the
warehouse i.
26
1 l anguage ESSENCE’ 1. b . a
2 l e t t i n g n D o m a i n be d o m a i n int (1.. n )
3 find qcp : m a t r i x i n d e x e d by [ nDomain , n D o m a i n ] of n D o m a i n
4 such that
5 f o r a l l i : n D o m a i n . a l l d i f f ( qcp [ i , n D o m a i n ]) ,
6 f o r a l l i : n D o m a i n . a l l d i f f ( qcp [ nDomain , i ])
The Essence implementation is in the figure 3.5.
3.6 Locating warehouses
Let us assume that we want to help a hypothetical business company with
the decision which warehouses should be built for their stores and which
warehouses should supply which store. The main criterion is in this case the
cost of the solution. The cost has two components. The first one is payment
of the constant cost for opening a new warehouse. The second component
is the price for the distribution of goods from a warehouse to the store. The
price varies and is different for all pairs (warehouse, store). Each possible
warehouse has a defined maximum capacity which accounts for the number
of stores which can be supplied from this warehouse. As the last condition
of the model, we state that all stores have to be supplied. Our task is to
choose the solution with the minimal total cost.
Both maximum capacities of warehouses and a table with prices for sup-
plying each of the pairs (warehouse, store) are the required input parameters
for the solver which computes the vector si, i ∈ {1, ...,# of stores} where si
indicates which warehouse supplies the store i.
3.6.1 Constraint problem model
We can build W warehouses. The price for opening of a new warehouse
is fixed and stored in the parameter openCost. We also have S shops.
The maximum capacity of warehouses is given by vector w, where wi is
the maximum number of shops which can be supplied by the warehouse
i, i ∈ {1, ...,W}. Finally, we have a matrix of supply costs supplyCost
where supplyCostij translates as the cost of supplying the shop j from the
warehouse i.
26
Page 27
• Variables and domains:
– The total cost – the value of an objective function: totalCost ∈ N,
– the number of opened warehouses: numberOpen ∈ {0,W},
– the indication whether the warehouse is open: open1, ...,
openW ∈ {0, 1},
– the indication which warehouse supplies which store: supplier1, ...,
supplierS ∈ {1, ...,W},
– the supply cost for given store: cost1, ..., costS ∈ N,
– total supply cost: costSum ∈ N.
• Constraints:
– The objective function: totalCost = costSum + numberOpen ·
openCost,
– the total supply cost: costSum = ∑i costi,
– the number of opened warehouses: numberOpen = ∑i openi,
– the maximal capacity of each warehouse: ∀i ∈ {1, ...,W} :
wi ≥
∑
supplierj=i 1,
– the warehouse is open if it supplies at least one shop:
∀i ∈ {1, ...,W} : (openi = 1) ⇔
((
∑
supplierj=i 1
)
> 0
)
,
– the supply cost computation: ∀i ∈ 1, ..., S, ∀j ∈ {1, ...,W} :
(supplieri = j) ⇒
(
costi = supplyCostij
)
.
The Essence implementation is in the figure 3.6.
27
– The total cost – the value of an objective function: totalCost ∈ N,
– the number of opened warehouses: numberOpen ∈ {0,W},
– the indication whether the warehouse is open: open1, ...,
openW ∈ {0, 1},
– the indication which warehouse supplies which store: supplier1, ...,
supplierS ∈ {1, ...,W},
– the supply cost for given store: cost1, ..., costS ∈ N,
– total supply cost: costSum ∈ N.
• Constraints:
– The objective function: totalCost = costSum + numberOpen ·
openCost,
– the total supply cost: costSum = ∑i costi,
– the number of opened warehouses: numberOpen = ∑i openi,
– the maximal capacity of each warehouse: ∀i ∈ {1, ...,W} :
wi ≥
∑
supplierj=i 1,
– the warehouse is open if it supplies at least one shop:
∀i ∈ {1, ...,W} : (openi = 1) ⇔
((
∑
supplierj=i 1
)
> 0
)
,
– the supply cost computation: ∀i ∈ 1, ..., S, ∀j ∈ {1, ...,W} :
(supplieri = j) ⇒
(
costi = supplyCostij
)
.
The Essence implementation is in the figure 3.6.
27
Page 31
6. The second propagator finally changes the constraint store to X = 6,
Y = 3.
Propagation can be either interval or domain. The interval propagation
changes only the bounds of domain. Domain propagation also eliminates the
values of the domain. The domain propagation is on the first sight better
technique but is more complex than the interval propagation. Therefore the
interval propagation is more frequently used.
After propagation if the system is in a stable state and still the solution
was not found the distribution phase begins. Mozart choose a variable x
and value v from the domain Dv and create two new spaces S∪{x = v} and
S ∪ {x 6= v}. The computation then continues with the propagation phase
in the new spaces. If the propagation phase ends with a failure the space
also fails. The problem has no solution if all its spaces have failed.
We can choose from several distribution strategies. Choosing of the
proper strategy noticeable affects the computation time. For most problems
the first-fail strategy is the most suitable. However the user can implement
his own distribution strategies to fully suit his needs.
Two techniques can be used in the solving of the optimization problems.
The na¨ıve technique introduces auxiliary variable o and adds the constraint
o = f(P ) where f is the objective function. Then the variable o is increased
until the solution is found. The second possible technique is the branch-and-
bound algorithm which is described in the section 1.2.
4.1.2 Debugging support
Mozart/Oz offers to the user the interactive tool Explorer. The Explorer
can be used to explore the search tree including the choice nodes. The user
can use the Explorer in the interactive mode and choose the subtrees of the
search tree to be expanded. The Explorer tool screenshot is in the figure
4.1. The circles denote the choice nodes of the tree, the diamonds mean
the solution of the problem and finally the squares are the branches with no
solution. The lighter color denotes the nodes which can be expanded. On
the figure there is one solution, two unsuccessful branches and five choice
nodes. Three of the choice nodes can be still expanded. The Explorer tool
offers also exporting of the tree diagram to PostScript.
31
Y = 3.
Propagation can be either interval or domain. The interval propagation
changes only the bounds of domain. Domain propagation also eliminates the
values of the domain. The domain propagation is on the first sight better
technique but is more complex than the interval propagation. Therefore the
interval propagation is more frequently used.
After propagation if the system is in a stable state and still the solution
was not found the distribution phase begins. Mozart choose a variable x
and value v from the domain Dv and create two new spaces S∪{x = v} and
S ∪ {x 6= v}. The computation then continues with the propagation phase
in the new spaces. If the propagation phase ends with a failure the space
also fails. The problem has no solution if all its spaces have failed.
We can choose from several distribution strategies. Choosing of the
proper strategy noticeable affects the computation time. For most problems
the first-fail strategy is the most suitable. However the user can implement
his own distribution strategies to fully suit his needs.
Two techniques can be used in the solving of the optimization problems.
The na¨ıve technique introduces auxiliary variable o and adds the constraint
o = f(P ) where f is the objective function. Then the variable o is increased
until the solution is found. The second possible technique is the branch-and-
bound algorithm which is described in the section 1.2.
4.1.2 Debugging support
Mozart/Oz offers to the user the interactive tool Explorer. The Explorer
can be used to explore the search tree including the choice nodes. The user
can use the Explorer in the interactive mode and choose the subtrees of the
search tree to be expanded. The Explorer tool screenshot is in the figure
4.1. The circles denote the choice nodes of the tree, the diamonds mean
the solution of the problem and finally the squares are the branches with no
solution. The lighter color denotes the nodes which can be expanded. On
the figure there is one solution, two unsuccessful branches and five choice
nodes. Three of the choice nodes can be still expanded. The Explorer tool
offers also exporting of the tree diagram to PostScript.
31
Page 33
and a solver itself. The model contains variables and constraints given in the
problem. Afterwards, the solver is given the model as an input and it tries
to find a solution. Variables in the model can be integers, real numbers or
sets. Then the solver is able to find a solution for the current model. A user
can get information from the solver whether the problem has a solution or it
contains a conflict. There is an interface for resolving solutions themselves,
whereby one can ask for the first, the following or all existing solutions. If
we define a variable equal to a value of an objective function, the solver can
either minimize or maximize this variable . Furthermore, the solver allows
us to choose a strategy which might perfectly fit the given problem. The
variables of the solver depends on the variables of the model and one can
resolve the values only through the variables of the solver.
4.2.1 Solver description
As it has been already mentioned in the previous section, the problem solving
is divided into two separated tasks – to define a model and to deploy the
model to a well-configured solver. The model as well as the solver are the
independent Java objects. First we describe the model and after that we
look at the solver.
Model
The model is an instance of the class CPModel. In Choco the variables of
the model are represented as objects of the following types: IntegerVariable,
RealVariable and SetVariable. Those variables, generally, are not created
using the keyword new, but in the Choco there are factory methods for
this purpose. One has to register those variables first by calling a function
CPModel::addVariable, or CPModel::addVariables when adding an array
of variables at once. While registering variables into a model, we can set
additional properties to the variables, for example to set whether it is a
decision variable, or a variable containing a result of an objective function.
It is not necessary to set those properties every time; however, they might
rapidly improve the computation time. Alternatively, we can define those
properties in the solver, which way is described later in the following section.
Once we have registered the variables, a definition of constraints fol-
lows. It is possible either to use a large number of build-in constraints,
or to define our own constraints. Some of the constraints which are avail-
able natively in the solver are listed in the appendix C. Each constraint
33
problem. Afterwards, the solver is given the model as an input and it tries
to find a solution. Variables in the model can be integers, real numbers or
sets. Then the solver is able to find a solution for the current model. A user
can get information from the solver whether the problem has a solution or it
contains a conflict. There is an interface for resolving solutions themselves,
whereby one can ask for the first, the following or all existing solutions. If
we define a variable equal to a value of an objective function, the solver can
either minimize or maximize this variable . Furthermore, the solver allows
us to choose a strategy which might perfectly fit the given problem. The
variables of the solver depends on the variables of the model and one can
resolve the values only through the variables of the solver.
4.2.1 Solver description
As it has been already mentioned in the previous section, the problem solving
is divided into two separated tasks – to define a model and to deploy the
model to a well-configured solver. The model as well as the solver are the
independent Java objects. First we describe the model and after that we
look at the solver.
Model
The model is an instance of the class CPModel. In Choco the variables of
the model are represented as objects of the following types: IntegerVariable,
RealVariable and SetVariable. Those variables, generally, are not created
using the keyword new, but in the Choco there are factory methods for
this purpose. One has to register those variables first by calling a function
CPModel::addVariable, or CPModel::addVariables when adding an array
of variables at once. While registering variables into a model, we can set
additional properties to the variables, for example to set whether it is a
decision variable, or a variable containing a result of an objective function.
It is not necessary to set those properties every time; however, they might
rapidly improve the computation time. Alternatively, we can define those
properties in the solver, which way is described later in the following section.
Once we have registered the variables, a definition of constraints fol-
lows. It is possible either to use a large number of build-in constraints,
or to define our own constraints. Some of the constraints which are avail-
able natively in the solver are listed in the appendix C. Each constraint
33
Page 34
fits in one of the following groups: basic constraints (true, false, relation
operators), basic expressions (goniometric functions, powers, sums), other
constraints (abs, div, max, ...), reified constraints (and, or, ifOnlyIf) and
global constraints (allDifferent, occurenceMax, ...). Furthermore, there
are constraints available which might be used for modeling geometric con-
straints, scheduling constraints and constraints for a sequence of variables
which is accepted by a finite automaton.
Apart from the build-in constraints, is it possible to define own con-
straints. The first step is to define a constraint p(x, y) as a set of the com-
patible values (a, b), where p is satisfied if x = a and y = b, or, eventually, as
a set of the incompatible values. In that case the set is defined as a table of
the values. Besides, we can define the constraint as a predicate, which has
to be satisfied, whereby the constraint is an instance of a class derived from
a class BinRelation with a method checkCouple having implemented. This
function takes two values as parameters and returns boolean value whether
the condition was satisfied or not. Similarly, we can define constraints over
tuples. For all such constraints (either binary or tuple) we can specify the
desired algorithm for arc consistence. There are AC3, AC2001, AC3rm
and AC3 algorithms available for the binary constraints and AC32, AC3rm,
AC2001 and AC2008 algorithms for the tuple constraints. These algorithms
are the variants of the original AC algorithm. Further description for some
of them can be found in [9].
As we found out while implementing of the Self Referential Quiz the
ifOnlyIf constraint is implemented as an extensional constraint (the table
of compatible values is computed). If the constrained variable has a large
domain then the table could be larger than the possible memory.
Solver
A solver is an instance of class CPSolver, which tries to find a solution
according to the model from the previous section. The solver starts with
reading the variables of the model and converting them into variables of the
solver (IntegerVariable into IntDomainVar, RealVariable into RealVar and
SetVariable into SetVar). Afterwards, it reads the constraints of the model
and creates constraints of the solver according to them. Then the solver
uses a search strategy and searches for solutions. Since the chosen strategy
is a key factor for the speed of solving, one can configure its various options.
A user can specify a selector and an iterator. The selector specifies which
34
operators), basic expressions (goniometric functions, powers, sums), other
constraints (abs, div, max, ...), reified constraints (and, or, ifOnlyIf) and
global constraints (allDifferent, occurenceMax, ...). Furthermore, there
are constraints available which might be used for modeling geometric con-
straints, scheduling constraints and constraints for a sequence of variables
which is accepted by a finite automaton.
Apart from the build-in constraints, is it possible to define own con-
straints. The first step is to define a constraint p(x, y) as a set of the com-
patible values (a, b), where p is satisfied if x = a and y = b, or, eventually, as
a set of the incompatible values. In that case the set is defined as a table of
the values. Besides, we can define the constraint as a predicate, which has
to be satisfied, whereby the constraint is an instance of a class derived from
a class BinRelation with a method checkCouple having implemented. This
function takes two values as parameters and returns boolean value whether
the condition was satisfied or not. Similarly, we can define constraints over
tuples. For all such constraints (either binary or tuple) we can specify the
desired algorithm for arc consistence. There are AC3, AC2001, AC3rm
and AC3 algorithms available for the binary constraints and AC32, AC3rm,
AC2001 and AC2008 algorithms for the tuple constraints. These algorithms
are the variants of the original AC algorithm. Further description for some
of them can be found in [9].
As we found out while implementing of the Self Referential Quiz the
ifOnlyIf constraint is implemented as an extensional constraint (the table
of compatible values is computed). If the constrained variable has a large
domain then the table could be larger than the possible memory.
Solver
A solver is an instance of class CPSolver, which tries to find a solution
according to the model from the previous section. The solver starts with
reading the variables of the model and converting them into variables of the
solver (IntegerVariable into IntDomainVar, RealVariable into RealVar and
SetVariable into SetVar). Afterwards, it reads the constraints of the model
and creates constraints of the solver according to them. Then the solver
uses a search strategy and searches for solutions. Since the chosen strategy
is a key factor for the speed of solving, one can configure its various options.
A user can specify a selector and an iterator. The selector specifies which
34
Page 35
variable is about to be taken in the next solver’s decision and the iterator
chooses each of available values and iterates over them. In a standard distri-
bution of Choco there are basic selectors such as variable with a minimum
domain, variable with a maximum domain and so on. The iterators can try
values in ascendant or descendant order. An alternative to iterator is a value
selector, which returns next available value when required. As for value se-
lector, we can use, for example, the minimal value in a domain, a random
value in a domain and so on. We can choose different user-defined strate-
gies for various groups of variables so as to follow the specified problem in
the best way. In that case we define the solver’s behavior through so-called
goals. A goal contains a definition of a strategy, that means a selector for
certain variables and an iterator over values.
Solving large-scale problems might be enormously time demanding, take
too much system resources and so on. To avoid this we can define solver
limits. In the solver we can set a time limit, a limit for a number of nodes,
a depth of backtracking, a number of fails or a limit for CPU time. Apart
from that, the users can define their own limits.
Once the solver has read the model and the strategies are defined, it starts
solving the problem. The solver offers an interface for accessing either each
solutions (solve, nextSolution), or to get all the solutions at once. Moreover,
we can specify a variable which the solver tries to minimize or maximize.
Since the result is held in variables of the solver and not in user-defined
variables of the model, it is required to resolve the solver’s variables by
calling a function CPSolver::getVar, which accepts a variable of a model
and returns a variable of a solver.
4.2.2 Debugging support
Choco does not include any tools for the graphic visualization of the search
tree such as the systems Mozart or Gecode do; however, in the Choco it is
possible to print out a log of the solving process. One can configure several
levels how detailed information is logged varying from nothing to a complete
list of what the Choco does internally.
4.2.3 Subjective description
The system has a good documentation [2], although it is a little bit bad
organized. Even though the careful readers find virtually everything they
35
chooses each of available values and iterates over them. In a standard distri-
bution of Choco there are basic selectors such as variable with a minimum
domain, variable with a maximum domain and so on. The iterators can try
values in ascendant or descendant order. An alternative to iterator is a value
selector, which returns next available value when required. As for value se-
lector, we can use, for example, the minimal value in a domain, a random
value in a domain and so on. We can choose different user-defined strate-
gies for various groups of variables so as to follow the specified problem in
the best way. In that case we define the solver’s behavior through so-called
goals. A goal contains a definition of a strategy, that means a selector for
certain variables and an iterator over values.
Solving large-scale problems might be enormously time demanding, take
too much system resources and so on. To avoid this we can define solver
limits. In the solver we can set a time limit, a limit for a number of nodes,
a depth of backtracking, a number of fails or a limit for CPU time. Apart
from that, the users can define their own limits.
Once the solver has read the model and the strategies are defined, it starts
solving the problem. The solver offers an interface for accessing either each
solutions (solve, nextSolution), or to get all the solutions at once. Moreover,
we can specify a variable which the solver tries to minimize or maximize.
Since the result is held in variables of the solver and not in user-defined
variables of the model, it is required to resolve the solver’s variables by
calling a function CPSolver::getVar, which accepts a variable of a model
and returns a variable of a solver.
4.2.2 Debugging support
Choco does not include any tools for the graphic visualization of the search
tree such as the systems Mozart or Gecode do; however, in the Choco it is
possible to print out a log of the solving process. One can configure several
levels how detailed information is logged varying from nothing to a complete
list of what the Choco does internally.
4.2.3 Subjective description
The system has a good documentation [2], although it is a little bit bad
organized. Even though the careful readers find virtually everything they
35
Page 36
look for. A documentation for developers is generated by JavaDoc system.
Due to that fact it is available as a hinting tool for many users of common
Java IDEs, that definitely helps for better understanding of the solver. Since
the development of the solver is maintained at SourceForge server, it is quite
easy to access source codes as well as a history of versions via revision control
system Subversion. One can find there also a technical support forum, where
the authors answer the users’ questions. The reaction time is very low and
the answers are of high quality so most of the problems are quickly fixed.
4.3 Minion
Minion is a constraint solver which works as a standalone application. Min-
ion takes as an input the problem description and returns the solutions if
there are any. Minion is open source and available at SourceForge. The
problem description is contained in a file with a special format. The file
contains definitions of variables, their domains and constraints on them.
The best description of the input format could be “the constraint assembly
language”. The constraints cannot use as their parameters expressions. If
we need to constrain the expression we have to introduce a new variable to
be equal to the expression and then constrain this variable. For example let
us assume we can use constraints X = |Y | and X < Y and we need to use
the constraint X < |Y |. We have to introduce the auxiliary variable a and
post two constraints a = |Y | and X < a. Using of the many expressions in
our problem leads to the enormous number of auxiliary variables. Moreover
the language does not contain loops. Therefore we cannot post a various
number of constraints based on the size parameter of the model. We have
to state all constraints for a given problem instance. As a result the defini-
tion of 4-queens problem cannot be easily transformed to 8-queens problem.
The set of constraints is limited and cannot be extended. Moreover some
basic constraints have to be used in an unusual way. If we want to constrain
a = ∑wixi we have to use a pair of constraints a ≤
∑
wixi and a ≥
∑
wixi
since the variant with equal sign is not in the system. The used variables
can be booleans, bounded integers, discrete integers and sparse bounded
integers. Bool variable is a variable with domain {0, 1}. Bounded integer
variable is an integer variable where the solver stores only its bounds. Dis-
crete integers are generally the same as bounded integers except they can
contain holes in the interval. Finally sparse bounded integers are variables
which have a small number of non consecutive values specified in the file.
36
Due to that fact it is available as a hinting tool for many users of common
Java IDEs, that definitely helps for better understanding of the solver. Since
the development of the solver is maintained at SourceForge server, it is quite
easy to access source codes as well as a history of versions via revision control
system Subversion. One can find there also a technical support forum, where
the authors answer the users’ questions. The reaction time is very low and
the answers are of high quality so most of the problems are quickly fixed.
4.3 Minion
Minion is a constraint solver which works as a standalone application. Min-
ion takes as an input the problem description and returns the solutions if
there are any. Minion is open source and available at SourceForge. The
problem description is contained in a file with a special format. The file
contains definitions of variables, their domains and constraints on them.
The best description of the input format could be “the constraint assembly
language”. The constraints cannot use as their parameters expressions. If
we need to constrain the expression we have to introduce a new variable to
be equal to the expression and then constrain this variable. For example let
us assume we can use constraints X = |Y | and X < Y and we need to use
the constraint X < |Y |. We have to introduce the auxiliary variable a and
post two constraints a = |Y | and X < a. Using of the many expressions in
our problem leads to the enormous number of auxiliary variables. Moreover
the language does not contain loops. Therefore we cannot post a various
number of constraints based on the size parameter of the model. We have
to state all constraints for a given problem instance. As a result the defini-
tion of 4-queens problem cannot be easily transformed to 8-queens problem.
The set of constraints is limited and cannot be extended. Moreover some
basic constraints have to be used in an unusual way. If we want to constrain
a = ∑wixi we have to use a pair of constraints a ≤
∑
wixi and a ≥
∑
wixi
since the variant with equal sign is not in the system. The used variables
can be booleans, bounded integers, discrete integers and sparse bounded
integers. Bool variable is a variable with domain {0, 1}. Bounded integer
variable is an integer variable where the solver stores only its bounds. Dis-
crete integers are generally the same as bounded integers except they can
contain holes in the interval. Finally sparse bounded integers are variables
which have a small number of non consecutive values specified in the file.
36
Page 37
During the computation only bounds of the spare bounded integers are up-
dated.
The input format is not very human-friendly. Even for small problems
the number of auxiliary variables grows over reasonable limits and the input
is not easy to understand. It is a reasonable solution to use a generator to
generate a Minion input file. User can either write his own ad hoc generator
for his problem or use a tool like Tailor which is described in the section 4.7.
4.3.1 Solver description
As stated in the previous section Minion is a standalone executable which
takes as a parameter filename of the input file or through the standard in-
put the contents of input. It automatically starts computation and writes
on the standard output or into the specified file solutions. It can handle
only integers and therefore the problems have to be encoded in a such way.
The format of the input file is not stable but uses an identifier which pre-
vents from misinterpretation of the input. If the user feeds the Minion with
an unsupported format of the file the solver informs about that and ends.
The current version of the input file is 3, and the user can recognize it by
observing the first line of the input, which has to contain only string MINION
3. After identification line there follows the sections of the file. The file can
contain the following sections:
• Definition of the variables
• Definition of the tuples
• Definition of the constraints
• Definition of the search parameter
The list of supported constraints can be found in the appendix C. The
search engine behavior can be adjusted either in the input file or at the
command line by parameters. The user can adjust the order of variables
during the selection phase of search, decide whether to find all solutions or
only one or how to format the output.
In the section D.3 we included the implementation of the Magic Sequence
benchmark of the length five. As the reader can see the input file is divided
into several sections. The specification of the file format comes on the first
line. Then follows the sections of the file denoted by the label *** SECTION
37
dated.
The input format is not very human-friendly. Even for small problems
the number of auxiliary variables grows over reasonable limits and the input
is not easy to understand. It is a reasonable solution to use a generator to
generate a Minion input file. User can either write his own ad hoc generator
for his problem or use a tool like Tailor which is described in the section 4.7.
4.3.1 Solver description
As stated in the previous section Minion is a standalone executable which
takes as a parameter filename of the input file or through the standard in-
put the contents of input. It automatically starts computation and writes
on the standard output or into the specified file solutions. It can handle
only integers and therefore the problems have to be encoded in a such way.
The format of the input file is not stable but uses an identifier which pre-
vents from misinterpretation of the input. If the user feeds the Minion with
an unsupported format of the file the solver informs about that and ends.
The current version of the input file is 3, and the user can recognize it by
observing the first line of the input, which has to contain only string MINION
3. After identification line there follows the sections of the file. The file can
contain the following sections:
• Definition of the variables
• Definition of the tuples
• Definition of the constraints
• Definition of the search parameter
The list of supported constraints can be found in the appendix C. The
search engine behavior can be adjusted either in the input file or at the
command line by parameters. The user can adjust the order of variables
during the selection phase of search, decide whether to find all solutions or
only one or how to format the output.
In the section D.3 we included the implementation of the Magic Sequence
benchmark of the length five. As the reader can see the input file is divided
into several sections. The specification of the file format comes on the first
line. Then follows the sections of the file denoted by the label *** SECTION
37
Page 38
NAME ***. These sections can be in the file in any order and repeated as
many times as needed. The only exception is the EOF section which denotes
the end of the file and should be in the file only once at the end of the
file. We used the alternative model of the problem as described in the
section 3.3. Therefore we need five variables for the sequence and twenty-
five auxiliary variables. We define them in the VARIABLES section on lines
4 – 30. Then the constraints are defined in the CONSTRAINTS section. The
implication is modeled using the reification constraint. Since the Minion
have only the constraints
∑
x ≤ a and
∑
x ≥ a but does not have the
constraint
∑
x = a we have to use the constraints sumleq and sumgeq.
Finally the SEARCH section defines the order of the variables. The variables
will be searched in that order. The SEARCH section defines also the solution
using the PRINT command. All variables marked for printing will be printed
out as a solution. To generate the Minion input files we used the Tailor tool
which compiled the Essence source code into the Minion input file; however,
the large models were problematic for this tool. Therefore we had to write
for some benchmarks the ad-hoc generators of the input file.
4.3.2 Debugging support
Minion offers printing out the search tree where one can observe the solvers
actions. However some other output than this printout is not available.
Since the modeling in Minion is difficult the user will probably use the Tailor
tool. Tailor offers not only the translation to the Minion format but direct
invocation of the Minion, passing the input to it and show the solution.
The user then can directly modify the Essence source code and perform the
invocation again if the results are not what he expected.
4.3.3 Subjective description
The largest problem of the solver is the limited set of constraints. If the
problem needs more sophisticated constraints then we cannot represent it
in the Minion. The second large problem is the input format. The problem
can be resolved by using the Tailor tool; however, for the large problems the
tool is not sufficient. Apart of that as a standalone executable which can be
called from the command line it can bring the capability of the constraint
solving to programs written in the languages like bash. The only thing which
is needed is the capability to assemble the input file in the proper format.
38
many times as needed. The only exception is the EOF section which denotes
the end of the file and should be in the file only once at the end of the
file. We used the alternative model of the problem as described in the
section 3.3. Therefore we need five variables for the sequence and twenty-
five auxiliary variables. We define them in the VARIABLES section on lines
4 – 30. Then the constraints are defined in the CONSTRAINTS section. The
implication is modeled using the reification constraint. Since the Minion
have only the constraints
∑
x ≤ a and
∑
x ≥ a but does not have the
constraint
∑
x = a we have to use the constraints sumleq and sumgeq.
Finally the SEARCH section defines the order of the variables. The variables
will be searched in that order. The SEARCH section defines also the solution
using the PRINT command. All variables marked for printing will be printed
out as a solution. To generate the Minion input files we used the Tailor tool
which compiled the Essence source code into the Minion input file; however,
the large models were problematic for this tool. Therefore we had to write
for some benchmarks the ad-hoc generators of the input file.
4.3.2 Debugging support
Minion offers printing out the search tree where one can observe the solvers
actions. However some other output than this printout is not available.
Since the modeling in Minion is difficult the user will probably use the Tailor
tool. Tailor offers not only the translation to the Minion format but direct
invocation of the Minion, passing the input to it and show the solution.
The user then can directly modify the Essence source code and perform the
invocation again if the results are not what he expected.
4.3.3 Subjective description
The largest problem of the solver is the limited set of constraints. If the
problem needs more sophisticated constraints then we cannot represent it
in the Minion. The second large problem is the input format. The problem
can be resolved by using the Tailor tool; however, for the large problems the
tool is not sufficient. Apart of that as a standalone executable which can be
called from the command line it can bring the capability of the constraint
solving to programs written in the languages like bash. The only thing which
is needed is the capability to assemble the input file in the proper format.
38
Page 39
There is available the reference guide [17] with description of all constraints
available and description of the input format.
4.4 Gecode
Gecode is a C++ library for solving constraint problems. It allows to model
a problem which contains integers, boolean variables and finite integer sets.
Gecode is a free open source software just like most of the mentioned solvers
are. The library is distributed in the source codes and for the Microsoft
Windows there is also an installer with precompiled libraries. Optionally,
an user needs a Qt library, which is used in a visualization graphic tool Gist.
Apart from the basic constraints, Gecode has also constraints for scheduling,
finite automatons, graphs and so on. We describe those constraints further in
the following section. The key person behind the Gecode solver is Christian
Schulte, who also participated in a development of the system Mozart/Oz.
4.4.1 Solver description
A problem is modeled as a class inherited from a class Space. In this partic-
ular class there are defined variables and constraints. The variables are ob-
jects of one of the following types: IntVar for integers, BoolVar for booleans
and SetVar for finite integer sets. Compared to the other solvers the boolean
variables aren’t just integers with a domain {0, 1}. It is not even allowed
to declare a constraint b = i having a boolean variable b and an integer
i. When a relation between the boolean and integer variables is required,
one can use either reified constraints (i = 1) ⇔ (b = true), or channelling
constraints (bj = 1) ⇔ (i = j) (such as b = (0, 0, 0, 1, 0, 0), i = 3). The con-
straints are global functions in a Gecode namespace. To add a constraint
to the model one has to use the post function which takes a constraint as a
parameter. Due to the function overriding, most of the constraints are im-
plemented in a way, where there are more variants each available through the
overriding; and the appropriate one is chosen. If the users uses a so-called
minimodel, they can use short expressions, for instance a constraint a = x ·y
can be written as post(home, a == x*y ) instead of mult(home,x,y,a);
however, the minimodel works only as a “syntactic sugar” and, therefore, it
does not come up with any new constraints and it only ease a way how the
current ones are written.
39
available and description of the input format.
4.4 Gecode
Gecode is a C++ library for solving constraint problems. It allows to model
a problem which contains integers, boolean variables and finite integer sets.
Gecode is a free open source software just like most of the mentioned solvers
are. The library is distributed in the source codes and for the Microsoft
Windows there is also an installer with precompiled libraries. Optionally,
an user needs a Qt library, which is used in a visualization graphic tool Gist.
Apart from the basic constraints, Gecode has also constraints for scheduling,
finite automatons, graphs and so on. We describe those constraints further in
the following section. The key person behind the Gecode solver is Christian
Schulte, who also participated in a development of the system Mozart/Oz.
4.4.1 Solver description
A problem is modeled as a class inherited from a class Space. In this partic-
ular class there are defined variables and constraints. The variables are ob-
jects of one of the following types: IntVar for integers, BoolVar for booleans
and SetVar for finite integer sets. Compared to the other solvers the boolean
variables aren’t just integers with a domain {0, 1}. It is not even allowed
to declare a constraint b = i having a boolean variable b and an integer
i. When a relation between the boolean and integer variables is required,
one can use either reified constraints (i = 1) ⇔ (b = true), or channelling
constraints (bj = 1) ⇔ (i = j) (such as b = (0, 0, 0, 1, 0, 0), i = 3). The con-
straints are global functions in a Gecode namespace. To add a constraint
to the model one has to use the post function which takes a constraint as a
parameter. Due to the function overriding, most of the constraints are im-
plemented in a way, where there are more variants each available through the
overriding; and the appropriate one is chosen. If the users uses a so-called
minimodel, they can use short expressions, for instance a constraint a = x ·y
can be written as post(home, a == x*y ) instead of mult(home,x,y,a);
however, the minimodel works only as a “syntactic sugar” and, therefore, it
does not come up with any new constraints and it only ease a way how the
current ones are written.
39
Page 40
Apart from the standard arithmetic constraints and order constraints,
Gecode offers wide range of specialized constraints. For SAT there is a
constraint clause(space,rel,x,y,z), which is equal to a condition ∨ xi ∨
∨
¬yi = z, respectively,
∧
xi ∧
∧
¬yi = z depending on a parameter rel.
There is another interesting constraint count, which guarantees that #{i|xi =
j} = yj is satisfied. This brings us to the fact that the benchmark Magic
sequence can be modeled and implemented by using only one constraint
count(*this, x, x). Moreover, there are also available the extensional
constraints. Those are constraints defined using of the extension, for ex-
ample, a deterministic finite automaton. In such a case, the constraint has
the following pattern: x is a word, which is accepted by the automaton A.
As for graph constraints, Gecode has a constraint x is a Hamiltonian cycle.
For an area of scheduling, there is available a constraint cumulatives(home,
resource, start, duration, end, height, limit, atmost), which gu-
arantees, that in a set of tasks T (task Ti = 〈machinei, starti, durationi, endi,
heighti〉) will be performed on the available machines. Each machine can
handle at most limitj tasks at one moment.
The following constraints can be used for constraining of the set variables:
standard set operations, constraints for cardinality of set and a constraint
which guarantees, that a weighed sum of set has a given value. That means
if we have a set x, a weight vector w and the total should be y, the constraint
has a pattern
∑
xiwi = y. Furthermore, there are two constraints available,
both of which are related to convexity. A set is convexed, if it contains a
continual interval of numbers. A set {1, 2, 3} is convex, but {1, 3, 4, 5} is
not convex, since it does not contain the number 2. The convex hull is the
least convex superset. A constraint convex(home,x) guarantees, that x is
convex and convex(home,x,y) means, that y is a convex hull for x. If one
needs to model an optimization problem, the problem representing class is
derived from a class MaximizeSpace (or MinimizeSpace) instead of a class
Space. In the class there has to be implemented the cost function which
returns the value of the objective function.
Searching is maintained by a function branch(home,x,var,val), which
sets a search vector x. While distributing, a parameter var defines an al-
gorithm for choosing a variable and a parameter val defines an algorithm
for choosing of a value of variable on which depends the distribution. The
following code shows the call interface for the application to invoke a search
for the solution:
Model* m = new Model;
40
Gecode offers wide range of specialized constraints. For SAT there is a
constraint clause(space,rel,x,y,z), which is equal to a condition ∨ xi ∨
∨
¬yi = z, respectively,
∧
xi ∧
∧
¬yi = z depending on a parameter rel.
There is another interesting constraint count, which guarantees that #{i|xi =
j} = yj is satisfied. This brings us to the fact that the benchmark Magic
sequence can be modeled and implemented by using only one constraint
count(*this, x, x). Moreover, there are also available the extensional
constraints. Those are constraints defined using of the extension, for ex-
ample, a deterministic finite automaton. In such a case, the constraint has
the following pattern: x is a word, which is accepted by the automaton A.
As for graph constraints, Gecode has a constraint x is a Hamiltonian cycle.
For an area of scheduling, there is available a constraint cumulatives(home,
resource, start, duration, end, height, limit, atmost), which gu-
arantees, that in a set of tasks T (task Ti = 〈machinei, starti, durationi, endi,
heighti〉) will be performed on the available machines. Each machine can
handle at most limitj tasks at one moment.
The following constraints can be used for constraining of the set variables:
standard set operations, constraints for cardinality of set and a constraint
which guarantees, that a weighed sum of set has a given value. That means
if we have a set x, a weight vector w and the total should be y, the constraint
has a pattern
∑
xiwi = y. Furthermore, there are two constraints available,
both of which are related to convexity. A set is convexed, if it contains a
continual interval of numbers. A set {1, 2, 3} is convex, but {1, 3, 4, 5} is
not convex, since it does not contain the number 2. The convex hull is the
least convex superset. A constraint convex(home,x) guarantees, that x is
convex and convex(home,x,y) means, that y is a convex hull for x. If one
needs to model an optimization problem, the problem representing class is
derived from a class MaximizeSpace (or MinimizeSpace) instead of a class
Space. In the class there has to be implemented the cost function which
returns the value of the objective function.
Searching is maintained by a function branch(home,x,var,val), which
sets a search vector x. While distributing, a parameter var defines an al-
gorithm for choosing a variable and a parameter val defines an algorithm
for choosing of a value of variable on which depends the distribution. The
following code shows the call interface for the application to invoke a search
for the solution:
Model* m = new Model;
40
Page 41
SEARCH<Model> e(m);
delete m;
while (Model* s = e.next())
{
s->print();
delete s;
}
A model is a class derived from a class Space or, respectively, Maximize-
Script, which represents a model of CSP. In the real application the SEARCH
must be changed to one of the followings: DFS – the depth-first left-most
search, LDS – the limited discrepancy, BAB – the branch-and-bound algo-
rithm and finally Restart – the depth-first left-most restart search. Both
algorithms BAB a Restart can be used when searching an optimal solution.
All of the algorithms can be used for a parallel computation. Having a
computer with more CPUs, one can reach much faster computation.
4.4.2 Debugging support
In Gecode there is a tool Gist, which visualizes a search tree. It is a tool quite
similar to the tool Explorer in Mozart/Oz solver. The interface, graphic
symbols and functions are the same as in Explorer. On the other hand, Gist
gives us an additional function Gist node statistics, which gives us more
information about a specific node of the search tree, such as the depth of
the node (according to a tree root), current height of the node’s subtree and
the number of successful/unsuccessful solutions in the subtree. In Gist there
is also a tool Inspector, which works equally to the Inspector in Mozart/Oz.
4.4.3 Subjective description
Gecode is a typical example of a top software, which can be totally unusable
due to the absence of a documentation. Before the version 3.0.0, which was
released in March 2009, there was only a technical documentation generated
by Doxygen. Furthermore, the example models were sealed into a pattern
class Example to achieve a more simple call of the examples; however, it
lacked any further explanations how to implement the solver inside own
project and it was necessary to deeply examine the source code of the solver.
Since the version 3.0.0 being released, there is available an e-book Modelling
41
delete m;
while (Model* s = e.next())
{
s->print();
delete s;
}
A model is a class derived from a class Space or, respectively, Maximize-
Script, which represents a model of CSP. In the real application the SEARCH
must be changed to one of the followings: DFS – the depth-first left-most
search, LDS – the limited discrepancy, BAB – the branch-and-bound algo-
rithm and finally Restart – the depth-first left-most restart search. Both
algorithms BAB a Restart can be used when searching an optimal solution.
All of the algorithms can be used for a parallel computation. Having a
computer with more CPUs, one can reach much faster computation.
4.4.2 Debugging support
In Gecode there is a tool Gist, which visualizes a search tree. It is a tool quite
similar to the tool Explorer in Mozart/Oz solver. The interface, graphic
symbols and functions are the same as in Explorer. On the other hand, Gist
gives us an additional function Gist node statistics, which gives us more
information about a specific node of the search tree, such as the depth of
the node (according to a tree root), current height of the node’s subtree and
the number of successful/unsuccessful solutions in the subtree. In Gist there
is also a tool Inspector, which works equally to the Inspector in Mozart/Oz.
4.4.3 Subjective description
Gecode is a typical example of a top software, which can be totally unusable
due to the absence of a documentation. Before the version 3.0.0, which was
released in March 2009, there was only a technical documentation generated
by Doxygen. Furthermore, the example models were sealed into a pattern
class Example to achieve a more simple call of the examples; however, it
lacked any further explanations how to implement the solver inside own
project and it was necessary to deeply examine the source code of the solver.
Since the version 3.0.0 being released, there is available an e-book Modelling
41
Page 42
with Gecode [20], which has completely changed the situation. The e-book
is a tutorial, which step by step guides the reader from a basic query – from a
given problem construct a model for the solver – to wide range of possibilities
of setting up the solver. Apart from the classical documentation, there is
also an e-mail conference, which is – while writing this thesis – quite a great
place to ask and where the authors answer after a short period.
4.5 ECLiPSe
The ECLiPSe Constraint Programming System is an open source implemen-
tation of the Prolog programming language. ECLiPSe is provided with li-
braries for constraint solving. It is possible to solve models over integers, real
numbers and finite integer sets. The solver is not just one library but there
is one general solver and several specialized solvers. The basic solver is the
ic library – interval constraints which contains basic arithmetic constraints.
For global constraints there is an ic global library. The global constraints
are constraints which use a couple of more advanced techniques to filter the
variable domain, for example the alldifferent constraint implemented as
a matching in a bipartite graph. The ic library contains the alldifferent
constraint too, but the one introduced in ic global library is stronger. For
scheduling problems there is an ic cumulative library and for finite integer
sets an ic sets library. The users can define their own constraints if the
shipped set of constraints is not satisfactory.
4.5.1 Solver description
As stated in the previous paragraph ECLiPSe is an implementation of the
Prolog programming language. The system contains the solver as an inde-
pendent library. Therefore the users are not limited to use only the shipped
solvers, but they can use their own solvers if any. A standard solver is the
ic solver which is a hybrid finite domain and real number interval constraint
solver. As the name suggests, it offers constraining the variables with both
real and integer domains. It supports arithmetic expressions, arithmetic
constraints, global constraints, reified constraints and search algorithms.
The set of global constraints can be extended by using ic global constraints.
This library provides constraints for lists such as alldifferent, ordered,
occurences and so on. For scheduling the mentioned ic cumulative con-
straint is available as well as their stronger versions ic edge finder or ic ed-
42
is a tutorial, which step by step guides the reader from a basic query – from a
given problem construct a model for the solver – to wide range of possibilities
of setting up the solver. Apart from the classical documentation, there is
also an e-mail conference, which is – while writing this thesis – quite a great
place to ask and where the authors answer after a short period.
4.5 ECLiPSe
The ECLiPSe Constraint Programming System is an open source implemen-
tation of the Prolog programming language. ECLiPSe is provided with li-
braries for constraint solving. It is possible to solve models over integers, real
numbers and finite integer sets. The solver is not just one library but there
is one general solver and several specialized solvers. The basic solver is the
ic library – interval constraints which contains basic arithmetic constraints.
For global constraints there is an ic global library. The global constraints
are constraints which use a couple of more advanced techniques to filter the
variable domain, for example the alldifferent constraint implemented as
a matching in a bipartite graph. The ic library contains the alldifferent
constraint too, but the one introduced in ic global library is stronger. For
scheduling problems there is an ic cumulative library and for finite integer
sets an ic sets library. The users can define their own constraints if the
shipped set of constraints is not satisfactory.
4.5.1 Solver description
As stated in the previous paragraph ECLiPSe is an implementation of the
Prolog programming language. The system contains the solver as an inde-
pendent library. Therefore the users are not limited to use only the shipped
solvers, but they can use their own solvers if any. A standard solver is the
ic solver which is a hybrid finite domain and real number interval constraint
solver. As the name suggests, it offers constraining the variables with both
real and integer domains. It supports arithmetic expressions, arithmetic
constraints, global constraints, reified constraints and search algorithms.
The set of global constraints can be extended by using ic global constraints.
This library provides constraints for lists such as alldifferent, ordered,
occurences and so on. For scheduling the mentioned ic cumulative con-
straint is available as well as their stronger versions ic edge finder or ic ed-
42
Page 45
4.6.1 Solver description
Similarly as in the ECLiPSe system the solvers are independent libraries
shipped with the system. The constraint solver over the finite domain consist
of the clp(fd) library [12]. The language constructs are different compared
to ECLiPSe ; however, the basic properties are preserved. Therefore porting
the ECLiPSe program to SICStus Prolog is not a hard work but also it is
not trivial. The number of available constraints is higher than the ECLiPSe
system provides. The clp(fd)library offers standard arithmetic expressions,
the relation constraints and the global constraints. The library also provides
the scheduling constraints and the extensional constraints.
The clp(b) provides a solver over the boolean variables. The solver con-
tains the relation constraints as well as constraints for the tautology and
satisfiability. Finally the clp(q,r) library [16] provides constraining over the
rational and real numbers. The constraint solver for set variables is not
available.
The standard set of constraints can be expanded by the user defined
constraints. As well as the ECLiPSe system the SICStus Prolog offers to
add constraints using the Constraint Handling Rules language and FlatZinc
language. User can also define his own constraints as the Prolog predicate.
The user created constraint can be either a global constraint or a primitive
constraint. The ways how to create such constraints are described in the
SICStus Prolog manual.
The constraint library clfpd is very similar to the ECLiPSe library ic.
We used the benchmarks already implemented in the ECLiPSe system and
changed a very small amount of library-specific calls to get the SICStus
Prolog source code.
4.6.2 Debugging support
The SICStus Prolog offers the Finite Domain Constraint Debugger or fdbg
library. This library can be used next to the standard Prolog debugging
predicate trace. This predicate allows to debug any Prolog program. The
fdbg library provides the log of the constraint propagation and distribution.
There are logged all changes to the domains and other events which occurred
during the computation. The example of the fdbg output is in the figure
4.2. On the first line there is a Prolog query. We constrain the variable
X to be in the domain {5, ..., 9} and the variable Y to be in the domain
{1, ..., 6}. Then we constrain the variable X to be smaller than variable
45
Similarly as in the ECLiPSe system the solvers are independent libraries
shipped with the system. The constraint solver over the finite domain consist
of the clp(fd) library [12]. The language constructs are different compared
to ECLiPSe ; however, the basic properties are preserved. Therefore porting
the ECLiPSe program to SICStus Prolog is not a hard work but also it is
not trivial. The number of available constraints is higher than the ECLiPSe
system provides. The clp(fd)library offers standard arithmetic expressions,
the relation constraints and the global constraints. The library also provides
the scheduling constraints and the extensional constraints.
The clp(b) provides a solver over the boolean variables. The solver con-
tains the relation constraints as well as constraints for the tautology and
satisfiability. Finally the clp(q,r) library [16] provides constraining over the
rational and real numbers. The constraint solver for set variables is not
available.
The standard set of constraints can be expanded by the user defined
constraints. As well as the ECLiPSe system the SICStus Prolog offers to
add constraints using the Constraint Handling Rules language and FlatZinc
language. User can also define his own constraints as the Prolog predicate.
The user created constraint can be either a global constraint or a primitive
constraint. The ways how to create such constraints are described in the
SICStus Prolog manual.
The constraint library clfpd is very similar to the ECLiPSe library ic.
We used the benchmarks already implemented in the ECLiPSe system and
changed a very small amount of library-specific calls to get the SICStus
Prolog source code.
4.6.2 Debugging support
The SICStus Prolog offers the Finite Domain Constraint Debugger or fdbg
library. This library can be used next to the standard Prolog debugging
predicate trace. This predicate allows to debug any Prolog program. The
fdbg library provides the log of the constraint propagation and distribution.
There are logged all changes to the domains and other events which occurred
during the computation. The example of the fdbg output is in the figure
4.2. On the first line there is a Prolog query. We constrain the variable
X to be in the domain {5, ..., 9} and the variable Y to be in the domain
{1, ..., 6}. Then we constrain the variable X to be smaller than variable
45
Page 47
exhaustive [4]. The system is not available freely for the public use but the
time limited trial version can be acquired.
4.7 Tailor
Tailor is not a constraint solver. It is an open source Essence compiler which
produces an input format of the Minion solver, a C++ source for the Gecode
solver or an input format of Gecode/FlatZinc. Tailor is a Java application,
which can be run either interactively, or as a command line utility. Tailor
accepts as an input both an Essence program and an Essence parameters file.
Then it normalizes the input into one source code. After normalization it
performs the flattening of the code. During the flattening phase it replaces
all the foreach loops and the sums with new auxiliary variables and with
repeated basic constraints. Finally, it transforms this normalized code to a
target language. Moreover, one can tune up the output of the Tailor solver
by setting up several parameters about the language constructs which can
be used. Another feature, which Tailor has, is that one can run the solver
directly from its environment over the translated source code.
47
time limited trial version can be acquired.
4.7 Tailor
Tailor is not a constraint solver. It is an open source Essence compiler which
produces an input format of the Minion solver, a C++ source for the Gecode
solver or an input format of Gecode/FlatZinc. Tailor is a Java application,
which can be run either interactively, or as a command line utility. Tailor
accepts as an input both an Essence program and an Essence parameters file.
Then it normalizes the input into one source code. After normalization it
performs the flattening of the code. During the flattening phase it replaces
all the foreach loops and the sums with new auxiliary variables and with
repeated basic constraints. Finally, it transforms this normalized code to a
target language. Moreover, one can tune up the output of the Tailor solver
by setting up several parameters about the language constructs which can
be used. Another feature, which Tailor has, is that one can run the solver
directly from its environment over the translated source code.
47
Page 48
Chapter 5
Benchmark results
In this chapter we present the results of the performance measuring of each
solver. There are two types of tests. The robustness test and the perfor-
mance test. In the robustness test we compare the solvers according to
the size of the task which the solver was able to compute in a given time
limit. In the performance tests we measure the time which is needed to
find a solution to the problem and the consumed memory. We used for
this purpose designed tool. The tool runs the solver executable with given
parameters. While the solver process is running the benchmarking tool pe-
riodically checks the /proc/(pid)/stat file and saves the current state. If
the elapsed time is larger than the given limit the SIGINT signal is sent to
the process. The process has one second to end and produce some output.
If the process is still running one second after the SIGINT signal the SIGKILL
signal is sent and process is killed. In the robustness test the tool tries to
estimate the size of the task using the binary search.
All of the benchmarks were performed on a single dedicated computer
Pentium IV, 3GHz (single core with hyper threading), 1GB RAM running
the Debian Linux with Linux kernel 2.6.18. Except the Mozart/Oz solver
and SICStus Prolog all solvers were compiled on the target machine. The
precompiled binaries distribution was used for the Mozart/Oz solver be-
cause the source distribution contained in the time of writing of this thesis
error which prevented compiling of the code. The SICStus Prolog is not dis-
tributed as source code but only as a binary. Therefore we used the shipped
executable. Since the SICStus Prolog is not a free open-source software we
used a trial version of the solver. There should be limited only the period
when the solver can be used. The performance of the solver should not be
48
Benchmark results
In this chapter we present the results of the performance measuring of each
solver. There are two types of tests. The robustness test and the perfor-
mance test. In the robustness test we compare the solvers according to
the size of the task which the solver was able to compute in a given time
limit. In the performance tests we measure the time which is needed to
find a solution to the problem and the consumed memory. We used for
this purpose designed tool. The tool runs the solver executable with given
parameters. While the solver process is running the benchmarking tool pe-
riodically checks the /proc/(pid)/stat file and saves the current state. If
the elapsed time is larger than the given limit the SIGINT signal is sent to
the process. The process has one second to end and produce some output.
If the process is still running one second after the SIGINT signal the SIGKILL
signal is sent and process is killed. In the robustness test the tool tries to
estimate the size of the task using the binary search.
All of the benchmarks were performed on a single dedicated computer
Pentium IV, 3GHz (single core with hyper threading), 1GB RAM running
the Debian Linux with Linux kernel 2.6.18. Except the Mozart/Oz solver
and SICStus Prolog all solvers were compiled on the target machine. The
precompiled binaries distribution was used for the Mozart/Oz solver be-
cause the source distribution contained in the time of writing of this thesis
error which prevented compiling of the code. The SICStus Prolog is not dis-
tributed as source code but only as a binary. Therefore we used the shipped
executable. Since the SICStus Prolog is not a free open-source software we
used a trial version of the solver. There should be limited only the period
when the solver can be used. The performance of the solver should not be
48
Page 49
affected.
The following versions of the solvers were used:
• Mozart 1.4.0-20080704
• Choco 2.1.0
• Minion 0.8.1
• Gecode 3.1.0
• ECLiPSe 6.0 96
• SICStus Prolog 4.0.7 – Linux, glibc 2.7
In the performance test as well as in the robustness test we used the fist-
fail search strategy for all of the implemented benchmarks. This strategy is
the default strategy the all solvers.
5.1 The robustness test
In the robustness test we measure how long magic sequence the solver is
able to compute in ten minutes. As stated in the previous paragraph the
benchmarking tool uses for this purpose the binary search. The tool has an
interval [a, b] of values on which the search is performed. It picks a value
v in the middle of the interval and tries to compute the solution of that
length. If it success it changes the interval to [v + 1, b], if it fails it changes
the interval to [a, v − 1]. Then the search continues in the same way until
the lower bound of the interval is larger than upper bound. The results of
the robustness test are in the table 5.1.
The results of the robustness test are in the table 5.1 (the best result is
bolded). As we can see the most robust solver is the Minion solver followed
by the Gecode. At first we tried to implement the benchmark problem in the
Gecode system by using of the constraint count. This constraint meaning is
exactly the Magic Sequence problem; however, the longest magic sequence
which we were able to compute had the length 27. If we compare this value
with the current value 191 it is obvious that the implementation of this
constraint is problematic.
49
The following versions of the solvers were used:
• Mozart 1.4.0-20080704
• Choco 2.1.0
• Minion 0.8.1
• Gecode 3.1.0
• ECLiPSe 6.0 96
• SICStus Prolog 4.0.7 – Linux, glibc 2.7
In the performance test as well as in the robustness test we used the fist-
fail search strategy for all of the implemented benchmarks. This strategy is
the default strategy the all solvers.
5.1 The robustness test
In the robustness test we measure how long magic sequence the solver is
able to compute in ten minutes. As stated in the previous paragraph the
benchmarking tool uses for this purpose the binary search. The tool has an
interval [a, b] of values on which the search is performed. It picks a value
v in the middle of the interval and tries to compute the solution of that
length. If it success it changes the interval to [v + 1, b], if it fails it changes
the interval to [a, v − 1]. Then the search continues in the same way until
the lower bound of the interval is larger than upper bound. The results of
the robustness test are in the table 5.1.
The results of the robustness test are in the table 5.1 (the best result is
bolded). As we can see the most robust solver is the Minion solver followed
by the Gecode. At first we tried to implement the benchmark problem in the
Gecode system by using of the constraint count. This constraint meaning is
exactly the Magic Sequence problem; however, the longest magic sequence
which we were able to compute had the length 27. If we compare this value
with the current value 191 it is obvious that the implementation of this
constraint is problematic.
49
Page 50
Table 5.1: The results of the robustness test.
Mozart/Oz Choco Minion Gecode ECLiPSe SICStus Prolog
94 111 236 191 55 174
5.2 The performance test
This test compares the solvers according to the two criteria. The first cri-
terion is the time needed to solve given problem instances. The second
criterion is the highest peak of used computer memory during the compu-
tation. We divided the instances of the benchmarks into two groups. In the
first group there are the instances of the Quasigroup With Holes problem.
We generated 25 balanced quasigroups of the order n = 16 and removed
approximately 1.6n1.55 values. According to the [5] the quasigroups with this
number of the holes are hard to solve compared to the other quasigroup of
the same order. To generate the quasigroups we used the lsencode combined
with the walksat.
This benchmark gives us a comparison of the allDifferent constraint.
This constraint is a global constraint. That means that the constraint is
not binary but it constrain a set of variables. The allDifferent constraint is
typically implemented using the matching in a bipartite graph [22]. The one
group of nodes consists of the variables and the second group consists of the
possible values of these variables. The variable node and the value node are
connected by the edge if and only if the value is in the variables’ domain.
As we can see in the graph in the figure 5.1 (a version with logarithmic
scale is in the figure 5.2) the best results were achieved with Gecode, Mozart
and Minion. The performance of the SICStus Prolog and ECLiPSe compared
to the others is worse than the order of the magnitude.
In the second group of benchmarks there are the following instances of
the benchmarks:
• queens10 – find all solutions of the 10 queens problem,
• queens100 –find one solution of the 100 queens problem,
• magic20 – find the Magic sequence of the length 20,
• srq – find the solution of the Self Referential Quiz,
50
Mozart/Oz Choco Minion Gecode ECLiPSe SICStus Prolog
94 111 236 191 55 174
5.2 The performance test
This test compares the solvers according to the two criteria. The first cri-
terion is the time needed to solve given problem instances. The second
criterion is the highest peak of used computer memory during the compu-
tation. We divided the instances of the benchmarks into two groups. In the
first group there are the instances of the Quasigroup With Holes problem.
We generated 25 balanced quasigroups of the order n = 16 and removed
approximately 1.6n1.55 values. According to the [5] the quasigroups with this
number of the holes are hard to solve compared to the other quasigroup of
the same order. To generate the quasigroups we used the lsencode combined
with the walksat.
This benchmark gives us a comparison of the allDifferent constraint.
This constraint is a global constraint. That means that the constraint is
not binary but it constrain a set of variables. The allDifferent constraint is
typically implemented using the matching in a bipartite graph [22]. The one
group of nodes consists of the variables and the second group consists of the
possible values of these variables. The variable node and the value node are
connected by the edge if and only if the value is in the variables’ domain.
As we can see in the graph in the figure 5.1 (a version with logarithmic
scale is in the figure 5.2) the best results were achieved with Gecode, Mozart
and Minion. The performance of the SICStus Prolog and ECLiPSe compared
to the others is worse than the order of the magnitude.
In the second group of benchmarks there are the following instances of
the benchmarks:
• queens10 – find all solutions of the 10 queens problem,
• queens100 –find one solution of the 100 queens problem,
• magic20 – find the Magic sequence of the length 20,
• srq – find the solution of the Self Referential Quiz,
50
Page 51
0
2000
4000
6000
8000
10000
12000
14000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
R
un
tim
e
[m
s]
The problem instance id
QWH - order 16
Mozart
Choco
Minion
Gecode
ECLiPSe
SICStus Prolog
Figure 5.1: The QWH benchmark results
• warehouses – find the best solution of the Locating Warehouses prob-
lem.
As we can see in the tables 5.2 and 5.3 (the best result of each benchmark
is bolded) none of the solvers is the ultimate winner; however, the three
solvers – SICStus Prolog, Gecode and Mozart – achieved the best results
in some of the problem instances. ECLiPSe and Minion did not solve the
100 queens problem in the given time limit. Therefore we consider them as
unreliable. The ECLiPSe and Choco were unable to load the big problems
to the memory so we changed the memory limit to one gigabyte. For the
ECLiPSe we changed it for all of the experiments and for the Choco we
used this large memory only for the magic sequence problem. The table 5.3
indicates that the Java Virtual Machine which is running the Choco as well
as the ECLiPSe solver allocated the whole allowed amount of memory. We
observer in the performance test the same problem with the count constraint
in the Gecode system as in the robustness test. For a comparison the original
results for the magic20 benchmark was 2926.86 milliseconds. The memory
peak was nearly the same.
51
2000
4000
6000
8000
10000
12000
14000
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
R
un
tim
e
[m
s]
The problem instance id
QWH - order 16
Mozart
Choco
Minion
Gecode
ECLiPSe
SICStus Prolog
Figure 5.1: The QWH benchmark results
• warehouses – find the best solution of the Locating Warehouses prob-
lem.
As we can see in the tables 5.2 and 5.3 (the best result of each benchmark
is bolded) none of the solvers is the ultimate winner; however, the three
solvers – SICStus Prolog, Gecode and Mozart – achieved the best results
in some of the problem instances. ECLiPSe and Minion did not solve the
100 queens problem in the given time limit. Therefore we consider them as
unreliable. The ECLiPSe and Choco were unable to load the big problems
to the memory so we changed the memory limit to one gigabyte. For the
ECLiPSe we changed it for all of the experiments and for the Choco we
used this large memory only for the magic sequence problem. The table 5.3
indicates that the Java Virtual Machine which is running the Choco as well
as the ECLiPSe solver allocated the whole allowed amount of memory. We
observer in the performance test the same problem with the count constraint
in the Gecode system as in the robustness test. For a comparison the original
results for the magic20 benchmark was 2926.86 milliseconds. The memory
peak was nearly the same.
51
Page 52
0
2
4
6
8
10
12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
R
un
tim
e
[lo
g m
s]
The problem instance id
QWH - order 16
Mozart
Choco
Minion
Gecode
ECLiPSe
SICStus Prolog
Figure 5.2: The QWH benchmark results, logarithmic scale
Table 5.2: The results of the performance test. Runtime (ms)
Benchmark Moz Cho Min Gec ECL SiP
queens10 237.95 850.27 227.69 65.35 809.45 327.53
queens100 184.19 1005.02 × 34.70 × 15.40
magic20 11.48 1092.95 71.24 65.41 4514.14 198.32
srq 6.22 482.81 55.81 25.89 691.13 13.54
warehouses 68.28 1500.83 2338.45 169.71 1808.29 14.41
Table 5.3: The results of the performance test. Memory peak (MB)
Benchmark Moz Cho Min Gec ECL SiP
queens10 8.62 209.42 44.17 8.58 1158.15 38.08
queens100 23.31 209.46 × 6.71 × 1.35
magic20 2.32 1173.19 44.57 7.26 1157.99 39.30
srq 63.36 209.35 44.56 6.68 1158.08 0.94
warehouses 6.79 209.12 44.30 7.00 1157.99 0.89
52
2
4
6
8
10
12
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
R
un
tim
e
[lo
g m
s]
The problem instance id
QWH - order 16
Mozart
Choco
Minion
Gecode
ECLiPSe
SICStus Prolog
Figure 5.2: The QWH benchmark results, logarithmic scale
Table 5.2: The results of the performance test. Runtime (ms)
Benchmark Moz Cho Min Gec ECL SiP
queens10 237.95 850.27 227.69 65.35 809.45 327.53
queens100 184.19 1005.02 × 34.70 × 15.40
magic20 11.48 1092.95 71.24 65.41 4514.14 198.32
srq 6.22 482.81 55.81 25.89 691.13 13.54
warehouses 68.28 1500.83 2338.45 169.71 1808.29 14.41
Table 5.3: The results of the performance test. Memory peak (MB)
Benchmark Moz Cho Min Gec ECL SiP
queens10 8.62 209.42 44.17 8.58 1158.15 38.08
queens100 23.31 209.46 × 6.71 × 1.35
magic20 2.32 1173.19 44.57 7.26 1157.99 39.30
srq 63.36 209.35 44.56 6.68 1158.08 0.94
warehouses 6.79 209.12 44.30 7.00 1157.99 0.89
52
Page 54
as “slow systems”. ECLiPSe has also the limited set of constraint compared
to the other solvers. The set can be extended by the user but the other
system offers wider set of the constraints in the basic release. Minion has a
limited set of constraints which cannot be extended. Moreover it failed to
compute one of the benchmarks. Mozart/Oz is quite fast system; however
the set of available constraints is also limited and the system development
seems stopped.
This leaves us the SICStus Prolog and Gecode which can be recom-
mended as the first choice. The SICStus Prolog was the best in most of the
performance benchmarks and offers many specialized constraints; however,
it is not a free open source system and the price has to be considered. Also
the results of the Quasigroup With Holes benchmark was one the worst com-
pared to the other solvers. Gecode offers nearly as large set of constraints as
SICStus Prolog. Moreover Gecode offers constraining over the set variables
which is not available in the SICStus Prolog.
6.2 Future work
We did not perform a deeper study of the search strategies of the solvers.
In the future it would be useful to compare the other strategies which are
shipped with the solver. In the solvers which offers ways to implement the
own strategy we should try to implement such a strategy and compare it
with the shipped strategies. Also the comparison of the solver based on the
Quasigroup With Holes problem can be performed on the quasigroups of the
higher order (at least 30). Such a comparison should give us a more accurate
data about the performance of each solver. Finally we could examine the
solvers on the real world applications for example as a solver subsystem of
a larger software.
54
to the other solvers. The set can be extended by the user but the other
system offers wider set of the constraints in the basic release. Minion has a
limited set of constraints which cannot be extended. Moreover it failed to
compute one of the benchmarks. Mozart/Oz is quite fast system; however
the set of available constraints is also limited and the system development
seems stopped.
This leaves us the SICStus Prolog and Gecode which can be recom-
mended as the first choice. The SICStus Prolog was the best in most of the
performance benchmarks and offers many specialized constraints; however,
it is not a free open source system and the price has to be considered. Also
the results of the Quasigroup With Holes benchmark was one the worst com-
pared to the other solvers. Gecode offers nearly as large set of constraints as
SICStus Prolog. Moreover Gecode offers constraining over the set variables
which is not available in the SICStus Prolog.
6.2 Future work
We did not perform a deeper study of the search strategies of the solvers.
In the future it would be useful to compare the other strategies which are
shipped with the solver. In the solvers which offers ways to implement the
own strategy we should try to implement such a strategy and compare it
with the shipped strategies. Also the comparison of the solver based on the
Quasigroup With Holes problem can be performed on the quasigroups of the
higher order (at least 30). Such a comparison should give us a more accurate
data about the performance of each solver. Finally we could examine the
solvers on the real world applications for example as a solver subsystem of
a larger software.
54
Page 55
Bibliography
[1] Mozart Documentation, 2008. [online, available at http://www.mozart-
oz.org/documentation/; accessed 06-August-2009].
[2] Choco solver, Documentation, 2009. [online, available at
http://www.emn.fr/x-info/choco-solver/doku.php?id=documentation;
accessed 06-August-2009].
[3] Gecode Reference Documentation 3.1.0, 2009. [online, available at
http://www.gecode.org/doc-latest/reference/index.html; accessed 06-
August-2009].
[4] SICStus Prolog User’s Manual, release 4.0.7, 2009. [online, available at
http://www.sics.se/sicstus/docs/latest4/pdf/sicstus.pdf; accessed 06-
August-2009].
[5] Dimitris Achlioptas, Carla Gomes, Henry Kautz, and Bart Selman.
Generating satisfiable problem instances. In AAAI/IAAI, pages 256–
261. AAAI Press, 2000.
[6] The National Aeronautics and Space Administration. Deep
space 1: Autonomous remote agent. [online, available at
http://nmp.nasa.gov/ds1/tech/autora.html; accessed 02-December-
2008], 2001.
[7] Roman Barta´k. Omezuj´ıc´ı podmı´nky: od sudoku po vesmı´rne´ aplikace.
In Umeˇla´ inteligence (5), pages 146–172. Academia, 2007. In czech
language.
[8] Roman Barta´k. On-line guide to constraint programming – sys-
tems, 2007. [online, available at http://ktiml.mff.cuni.cz/ bartak/con-
straints/systems.html; accessed 21-July-2008].
55
[1] Mozart Documentation, 2008. [online, available at http://www.mozart-
oz.org/documentation/; accessed 06-August-2009].
[2] Choco solver, Documentation, 2009. [online, available at
http://www.emn.fr/x-info/choco-solver/doku.php?id=documentation;
accessed 06-August-2009].
[3] Gecode Reference Documentation 3.1.0, 2009. [online, available at
http://www.gecode.org/doc-latest/reference/index.html; accessed 06-
August-2009].
[4] SICStus Prolog User’s Manual, release 4.0.7, 2009. [online, available at
http://www.sics.se/sicstus/docs/latest4/pdf/sicstus.pdf; accessed 06-
August-2009].
[5] Dimitris Achlioptas, Carla Gomes, Henry Kautz, and Bart Selman.
Generating satisfiable problem instances. In AAAI/IAAI, pages 256–
261. AAAI Press, 2000.
[6] The National Aeronautics and Space Administration. Deep
space 1: Autonomous remote agent. [online, available at
http://nmp.nasa.gov/ds1/tech/autora.html; accessed 02-December-
2008], 2001.
[7] Roman Barta´k. Omezuj´ıc´ı podmı´nky: od sudoku po vesmı´rne´ aplikace.
In Umeˇla´ inteligence (5), pages 146–172. Academia, 2007. In czech
language.
[8] Roman Barta´k. On-line guide to constraint programming – sys-
tems, 2007. [online, available at http://ktiml.mff.cuni.cz/ bartak/con-
straints/systems.html; accessed 21-July-2008].
55
Page 57
[19] Tom Schrijvers. Constraint handling rules (CHR). [online, available
at http://www.cs.kuleuven.be/ dtai/projects/CHR/; accessed 26-July-
2009], 2009.
[20] Christian Schulte, Guido Tack, and Mikael Zayenz Lagerkvist. Modeling
with Gecode, 2009. [online, available at http://www.gecode.org/doc-
latest/modeling.pdf; accessed 06-August-2009].
[21] Marc van Dongen. Call for solvers and benchmarks fourth international
constraint solver competition (csp, max-csp and weighted-csp competi-
tion). [online, available at http://cpai.ucc.ie/09/call2009.pdf; accessed
26-July-2009], 2009.
[22] Willem-Jan van Hoeve. The alldifferent constraint: A survey. Sixth An-
nual Workshop of the ERCIM Working Group on Constraints, Prague,
2001.
57
at http://www.cs.kuleuven.be/ dtai/projects/CHR/; accessed 26-July-
2009], 2009.
[20] Christian Schulte, Guido Tack, and Mikael Zayenz Lagerkvist. Modeling
with Gecode, 2009. [online, available at http://www.gecode.org/doc-
latest/modeling.pdf; accessed 06-August-2009].
[21] Marc van Dongen. Call for solvers and benchmarks fourth international
constraint solver competition (csp, max-csp and weighted-csp competi-
tion). [online, available at http://cpai.ucc.ie/09/call2009.pdf; accessed
26-July-2009], 2009.
[22] Willem-Jan van Hoeve. The alldifferent constraint: A survey. Sixth An-
nual Workshop of the ERCIM Working Group on Constraints, Prague,
2001.
57
Page 59
Appendix B
List of the constraint solvers
We present here a short list of the constraint solvers. The more detailed list
can be found in [8].
CHIP V5
CHIP (constraint handling in Prolog) is the second-generation constraint
programming tool. It supports modeling of the scheduling, logistics and
manpower planning.
URL: http://www.cosytec.com/production scheduling/chip/optimization pro-
duct chip.htm
Choco
Choco is a solver library written in the Java programming language.
URL: http://www.emn.fr/x-info/choco-solver/
Comet
Comet is an Object Oriented Programming Language for Constraint-Based
Local Search.
URL: http://www.comet-online.org/
59
List of the constraint solvers
We present here a short list of the constraint solvers. The more detailed list
can be found in [8].
CHIP V5
CHIP (constraint handling in Prolog) is the second-generation constraint
programming tool. It supports modeling of the scheduling, logistics and
manpower planning.
URL: http://www.cosytec.com/production scheduling/chip/optimization pro-
duct chip.htm
Choco
Choco is a solver library written in the Java programming language.
URL: http://www.emn.fr/x-info/choco-solver/
Comet
Comet is an Object Oriented Programming Language for Constraint-Based
Local Search.
URL: http://www.comet-online.org/
59
Page 63
Table C.1: Relation and arithmetic constraints
Constraint Moz Cho Min Gec ECL SiP
x ∼ y • • ◦ • • •
∑
i xi ∼ y • • ◦ • • •
∑
i (xiwi) ∼ y • • ◦ • × •
∑
i
(
xi
∏
j wij
)
∼ y • × × × × ×
∧
i xi ∧
∧
i ¬yi = b × × × • × ×
∨
i xi ∨
∨
i ¬yi = b × × × • × ×
|x| = y • • • • • •
|x− y| ∼ z • × ◦ × × •
xmod y = z • • • • • •
means SICStus Prolog.
We divide the constraints into four groups – relation and arithmetic,
global, scheduling and other constraints. The most of the relation and arith-
metic constraints (see the table C.1) are supported in the all solvers. As we
can see the Minion system has for some of the constraints only the partial
support. For the sums it means that Minion supports only the ≤ and ≥ op-
erators. The partialy supported constraint x ∼ y on the other hand means
that it supports only the = and 6= operators and finally for the |x− y| ∼ z
constraint only the operator = is supported. The global constraints (see
the table C.2) are the constraints which constrain the vectors of variables.
The basic global constraint is alldifferent which constrains the given vector
x such that each variable contained in the vector has a different value. The
hamming constraints ensures that the hamming distance of the two given
vectors is at least c. The scheduling constraints as the name suggest offers
the support for modelling of the scheduling problems. The cummulative
constraint is used if we need to schedule the tasks on the given machines.
The overlaps and the disjunctive are used to constrain the relative order of
the taks. Finally in the fourth group there are the other constraints. By
using the extensional constraint we can constrain the complex relations of
the variables by specifying the set of compatible values. The constraint then
constrain the variables such that they have only the compatible values. The
DFA stands for the deterministic fiinite automaton. The constraint enforces
that the given vector of variables is the word which is accepted by the solver.
63
Constraint Moz Cho Min Gec ECL SiP
x ∼ y • • ◦ • • •
∑
i xi ∼ y • • ◦ • • •
∑
i (xiwi) ∼ y • • ◦ • × •
∑
i
(
xi
∏
j wij
)
∼ y • × × × × ×
∧
i xi ∧
∧
i ¬yi = b × × × • × ×
∨
i xi ∨
∨
i ¬yi = b × × × • × ×
|x| = y • • • • • •
|x− y| ∼ z • × ◦ × × •
xmod y = z • • • • • •
means SICStus Prolog.
We divide the constraints into four groups – relation and arithmetic,
global, scheduling and other constraints. The most of the relation and arith-
metic constraints (see the table C.1) are supported in the all solvers. As we
can see the Minion system has for some of the constraints only the partial
support. For the sums it means that Minion supports only the ≤ and ≥ op-
erators. The partialy supported constraint x ∼ y on the other hand means
that it supports only the = and 6= operators and finally for the |x− y| ∼ z
constraint only the operator = is supported. The global constraints (see
the table C.2) are the constraints which constrain the vectors of variables.
The basic global constraint is alldifferent which constrains the given vector
x such that each variable contained in the vector has a different value. The
hamming constraints ensures that the hamming distance of the two given
vectors is at least c. The scheduling constraints as the name suggest offers
the support for modelling of the scheduling problems. The cummulative
constraint is used if we need to schedule the tasks on the given machines.
The overlaps and the disjunctive are used to constrain the relative order of
the taks. Finally in the fourth group there are the other constraints. By
using the extensional constraint we can constrain the complex relations of
the variables by specifying the set of compatible values. The constraint then
constrain the variables such that they have only the compatible values. The
DFA stands for the deterministic fiinite automaton. The constraint enforces
that the given vector of variables is the word which is accepted by the solver.
63
Page 65
Appendix D
Implementation of the
benchmarks
D.1 Mozart/Oz
The following code shows the implementation of the Locating Warehouses
problem in the Mozart/Oz solver.
1 fun {Warehouses Data}
2
3 fun {Regret X}
4 M = {FD . r e f l e c t . min X}
5 in
6 {FD . r e f l e c t . nex tLarge r X M} − M
7 end
8
9 NbStores = {Width Data . c o s t s }
10 NbWarehouses = {Width Data . c a p a c i t y }
11 Capaci ty = Data . c a p a c i t y
12 WarehouseCost = Data . warehouseCost
13 CostMatr ix = Data . c o s t s
14
15 in
16 proc { $ So l }
17 Tota lCos t = {FD . d e c l }
18 Open = {FD . t u p l e warehouse 5 0#1}
19 Su pp l i e r = {FD . t u p l e s u p p l i e r NbStores 1#NbWarehouses}
20
21 Cost = {FD . t u p l e s t o r e NbStores 0#FD . sup}
22 SumCost = {FD . d e c l } = {FD . sum Cost ’ =: ’}
23
24 S t or e s = { L i s t . number 1 NbStores 1}
25
26 NbOpen = {FD . d e c l } = {FD . sum Open ’ =: ’}
27 in
28 So l = p lan ( t o t a l C o s t : Tota lCos t open : Open s u p p l i e r : Supp l i e r )
29
30 Tota lCos t =: SumCost + NbOpen ∗ WarehouseCost
31
32 {For 1 NbStores 1
33 proc {$ S tor e }
34 Cost . S tor e : : {Record . t o L i s t CostMatr ix . S tor e }
35 {FD . e lement S upp l i e r . S tor e CostMatr ix . S tor e Cost . S tor e }
36 end}
37
38 {For 1 NbWarehouses 1
39 proc {$ Warehouse}
65
Implementation of the
benchmarks
D.1 Mozart/Oz
The following code shows the implementation of the Locating Warehouses
problem in the Mozart/Oz solver.
1 fun {Warehouses Data}
2
3 fun {Regret X}
4 M = {FD . r e f l e c t . min X}
5 in
6 {FD . r e f l e c t . nex tLarge r X M} − M
7 end
8
9 NbStores = {Width Data . c o s t s }
10 NbWarehouses = {Width Data . c a p a c i t y }
11 Capaci ty = Data . c a p a c i t y
12 WarehouseCost = Data . warehouseCost
13 CostMatr ix = Data . c o s t s
14
15 in
16 proc { $ So l }
17 Tota lCos t = {FD . d e c l }
18 Open = {FD . t u p l e warehouse 5 0#1}
19 Su pp l i e r = {FD . t u p l e s u p p l i e r NbStores 1#NbWarehouses}
20
21 Cost = {FD . t u p l e s t o r e NbStores 0#FD . sup}
22 SumCost = {FD . d e c l } = {FD . sum Cost ’ =: ’}
23
24 S t or e s = { L i s t . number 1 NbStores 1}
25
26 NbOpen = {FD . d e c l } = {FD . sum Open ’ =: ’}
27 in
28 So l = p lan ( t o t a l C o s t : Tota lCos t open : Open s u p p l i e r : Supp l i e r )
29
30 Tota lCos t =: SumCost + NbOpen ∗ WarehouseCost
31
32 {For 1 NbStores 1
33 proc {$ S tor e }
34 Cost . S tor e : : {Record . t o L i s t CostMatr ix . S tor e }
35 {FD . e lement S upp l i e r . S tor e CostMatr ix . S tor e Cost . S tor e }
36 end}
37
38 {For 1 NbWarehouses 1
39 proc {$ Warehouse}
65
Page 66
40 {FD . atMost Capaci ty . Warehouse Su pp l i e r Warehouse}
41 Open . Warehouse = {FD . r e i f i e d . sum {Map St or e s fun { $ S tor e } Su pp l i e r . S tor e =:
Warehouse end} ’ >: ’ 0}
42 end}
43
44 {FD . d i s t r i b u t e f f S up p l i e r }
45 end
46 end
47
48 proc {Order Old New}
49 Old . t o t a l C o s t >: New . t o t a l C o s t
50 end
D.2 Choco
The following code shows the implementation of the self referential quiz in
the Choco solver.
1 Model m = new CPModel ( ) ;
2 So l v e r s = new CPSolver ( ) ;
3
4 I n t e g e rVa r i a b l e [ ] [ ] q u e s t i o n s = new I n t e g e rVa r i a b l e [ 1 0 ] [ ] ;
5
6 for ( int i = 0 ; i < 10 ; i++)
7 {
8 q u e s t i o n s [ i ] = makeBooleanVarArray ( " q u e s t i o n s _ "+i , 5) ;
9
10 m. addCons t ra in t ( eq ( sum( q u e s t i o n s [ i ] ) , 1) ) ;
11
12 m. addVar iab l e s ( q u e s t i o n s [ i ] ) ;
13 }
14
15 // Quest ion 1 A−D
16 for ( int i = 0 ; i < 4 ; i++)
17 {
18 Cons t ra in t c = eq ( q u e s t i o n s [4− i −1 ] [ 0 ] , 1) ;
19
20 for ( int j = 0 ; j < 4− i −1; j++)
21 {
22 c = and ( c , eq ( q u e s t i o n s [ j ] [ 0 ] , 0) ) ;
23 }
24
25 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 0 ] [ i ] , 1) , c ) ) ;
26 }
27
28 // Quest ion 1 E
29 Cons t ra in t c1e = TRUE ;
30 for ( int i = 0 ; i < 4 ; i++)
31 {
32 c1e = and ( c1e , eq ( q u e s t i o n s [ i ] [ 0 ] , 0 ) ) ;
33 }
34 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 0 ] [ 4 ] , 1) , c1e ) ) ;
35
36 // Quest ion 2
37 for ( int i = 0 ; i < 5 ; i++)
38 {
39 Cons t ra in t c = TRUE ;
40
41 for ( int j = 0 ; j < 5 ; j++)
42 {
43 c = and ( c , eq ( q u e s t i o n s [2+ i ] [ j ] , q u e s t i o n s [3+ i ] [ j ] ) ) ;
44 }
45
46 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 1 ] [ i ] , 1) , c ) ) ;
47 }
48
49 // Quest ion 3
50 for ( int i = 0 ; i < 5 ; i++)
51 {
52 Cons t ra in t c = eq ( q u e s t i o n s [ i +3 ] [ 0 ] , 1 ) ;
53
66
41 Open . Warehouse = {FD . r e i f i e d . sum {Map St or e s fun { $ S tor e } Su pp l i e r . S tor e =:
Warehouse end} ’ >: ’ 0}
42 end}
43
44 {FD . d i s t r i b u t e f f S up p l i e r }
45 end
46 end
47
48 proc {Order Old New}
49 Old . t o t a l C o s t >: New . t o t a l C o s t
50 end
D.2 Choco
The following code shows the implementation of the self referential quiz in
the Choco solver.
1 Model m = new CPModel ( ) ;
2 So l v e r s = new CPSolver ( ) ;
3
4 I n t e g e rVa r i a b l e [ ] [ ] q u e s t i o n s = new I n t e g e rVa r i a b l e [ 1 0 ] [ ] ;
5
6 for ( int i = 0 ; i < 10 ; i++)
7 {
8 q u e s t i o n s [ i ] = makeBooleanVarArray ( " q u e s t i o n s _ "+i , 5) ;
9
10 m. addCons t ra in t ( eq ( sum( q u e s t i o n s [ i ] ) , 1) ) ;
11
12 m. addVar iab l e s ( q u e s t i o n s [ i ] ) ;
13 }
14
15 // Quest ion 1 A−D
16 for ( int i = 0 ; i < 4 ; i++)
17 {
18 Cons t ra in t c = eq ( q u e s t i o n s [4− i −1 ] [ 0 ] , 1) ;
19
20 for ( int j = 0 ; j < 4− i −1; j++)
21 {
22 c = and ( c , eq ( q u e s t i o n s [ j ] [ 0 ] , 0) ) ;
23 }
24
25 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 0 ] [ i ] , 1) , c ) ) ;
26 }
27
28 // Quest ion 1 E
29 Cons t ra in t c1e = TRUE ;
30 for ( int i = 0 ; i < 4 ; i++)
31 {
32 c1e = and ( c1e , eq ( q u e s t i o n s [ i ] [ 0 ] , 0 ) ) ;
33 }
34 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 0 ] [ 4 ] , 1) , c1e ) ) ;
35
36 // Quest ion 2
37 for ( int i = 0 ; i < 5 ; i++)
38 {
39 Cons t ra in t c = TRUE ;
40
41 for ( int j = 0 ; j < 5 ; j++)
42 {
43 c = and ( c , eq ( q u e s t i o n s [2+ i ] [ j ] , q u e s t i o n s [3+ i ] [ j ] ) ) ;
44 }
45
46 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 1 ] [ i ] , 1) , c ) ) ;
47 }
48
49 // Quest ion 3
50 for ( int i = 0 ; i < 5 ; i++)
51 {
52 Cons t ra in t c = eq ( q u e s t i o n s [ i +3 ] [ 0 ] , 1 ) ;
53
66
Page 68
128
129
130 // Quest ion 8
131 I n t e g e rVa r i a b l e sumConsonants = makeIntVar ( " q u e s t i o n _ 8 _ s u m C o n s o n a n t s " , 0 , 10) ;
132 I n t e g e rVa r i a b l e [ ] consonants = new I n t e g e rV a r i a b l e [ 3 ∗ 1 0 ] ;
133 for ( int i = 0 ; i < 10 ; i++)
134 {
135 consonants [ 3∗ i ] = q u e s t i o n s [ i ] [ 1 ] ;
136 consonants [ 3∗ i + 1 ] = q u e s t i o n s [ i ] [ 2 ] ;
137 consonants [ 3∗ i + 2 ] = q u e s t i o n s [ i ] [ 3 ] ;
138 }
139 m. addCons t ra in t ( eq ( sum( consonants ) , sumConsonants ) ) ;
140
141 for ( int i = 0 ; i < 5 ; i++)
142 {
143 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 7 ] [ i ] , 1) , eq ( sumConsonants , 7 − i ) ) ) ;
144 }
145
146
147 // Quest ion 9
148 I n t e g e rVa r i a b l e sumVowels = makeIntVar ( " q u e s t i o n _ 9 _ s u m V o w e l s " , 0 , 10) ;
149 I n t e g e rVa r i a b l e [ ] vowe l s = new I n t e g e rV a r i a b l e [ 2 ∗ 1 0 ] ;
150 for ( int i = 0 ; i < 10 ; i++)
151 {
152 vowe l s [ 2∗ i ] = q u e s t i o n s [ i ] [ 0 ] ;
153 vowe l s [ 2∗ i + 1 ] = q u e s t i o n s [ i ] [ 4 ] ;
154 }
155 m. addCons t ra in t ( eq ( sum( vowe l s ) , sumVowels ) ) ;
156
157 for ( int i = 0 ; i < 5 ; i++)
158 {
159 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 8 ] [ i ] , 1) , eq ( sumVowels , i ) ) ) ;
160 }
161
162 s . read (m) ;
163
164 Boolean some = s . s o l v e ( ) ;
165
166 i f ( some )
167 {
168 do {
169 for ( int i = 0 ; i < q u e s t i o n s . l e n g t h ; i++) {
170
171 for ( int j = 0 ; j < q u e s t i o n s [ i ] . l e n g t h ; j++)
172 {
173 int v a l u e = s . getVar ( q u e s t i o n s [ i ] [ j ] ) . ge tVa l ( ) ;
174 System . out . p r i n t ( v a l u e+" " ) ;
175 }
176 System . out . p r i n t l n ( ) ;
177 }
178 } while ( s . n e x t S o l u t i o n ( ) ) ;
179 }
D.3 Minion
The following code shows the Minion input file for the Magic Sequence prob-
lem of the length 5.
1 MINION 3
2
3 ∗∗VARIABLES∗∗
4 DISCRETE s [ 5 ] {0 . . 5}
5
6 BOOL aux0
7 BOOL aux1
8 BOOL aux2
9 BOOL aux3
10 BOOL aux4
11 BOOL aux5
12 BOOL aux6
13 BOOL aux7
68
129
130 // Quest ion 8
131 I n t e g e rVa r i a b l e sumConsonants = makeIntVar ( " q u e s t i o n _ 8 _ s u m C o n s o n a n t s " , 0 , 10) ;
132 I n t e g e rVa r i a b l e [ ] consonants = new I n t e g e rV a r i a b l e [ 3 ∗ 1 0 ] ;
133 for ( int i = 0 ; i < 10 ; i++)
134 {
135 consonants [ 3∗ i ] = q u e s t i o n s [ i ] [ 1 ] ;
136 consonants [ 3∗ i + 1 ] = q u e s t i o n s [ i ] [ 2 ] ;
137 consonants [ 3∗ i + 2 ] = q u e s t i o n s [ i ] [ 3 ] ;
138 }
139 m. addCons t ra in t ( eq ( sum( consonants ) , sumConsonants ) ) ;
140
141 for ( int i = 0 ; i < 5 ; i++)
142 {
143 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 7 ] [ i ] , 1) , eq ( sumConsonants , 7 − i ) ) ) ;
144 }
145
146
147 // Quest ion 9
148 I n t e g e rVa r i a b l e sumVowels = makeIntVar ( " q u e s t i o n _ 9 _ s u m V o w e l s " , 0 , 10) ;
149 I n t e g e rVa r i a b l e [ ] vowe l s = new I n t e g e rV a r i a b l e [ 2 ∗ 1 0 ] ;
150 for ( int i = 0 ; i < 10 ; i++)
151 {
152 vowe l s [ 2∗ i ] = q u e s t i o n s [ i ] [ 0 ] ;
153 vowe l s [ 2∗ i + 1 ] = q u e s t i o n s [ i ] [ 4 ] ;
154 }
155 m. addCons t ra in t ( eq ( sum( vowe l s ) , sumVowels ) ) ;
156
157 for ( int i = 0 ; i < 5 ; i++)
158 {
159 m. addCons t ra in t ( i f O n l y I f ( eq ( q u e s t i o n s [ 8 ] [ i ] , 1) , eq ( sumVowels , i ) ) ) ;
160 }
161
162 s . read (m) ;
163
164 Boolean some = s . s o l v e ( ) ;
165
166 i f ( some )
167 {
168 do {
169 for ( int i = 0 ; i < q u e s t i o n s . l e n g t h ; i++) {
170
171 for ( int j = 0 ; j < q u e s t i o n s [ i ] . l e n g t h ; j++)
172 {
173 int v a l u e = s . getVar ( q u e s t i o n s [ i ] [ j ] ) . ge tVa l ( ) ;
174 System . out . p r i n t ( v a l u e+" " ) ;
175 }
176 System . out . p r i n t l n ( ) ;
177 }
178 } while ( s . n e x t S o l u t i o n ( ) ) ;
179 }
D.3 Minion
The following code shows the Minion input file for the Magic Sequence prob-
lem of the length 5.
1 MINION 3
2
3 ∗∗VARIABLES∗∗
4 DISCRETE s [ 5 ] {0 . . 5}
5
6 BOOL aux0
7 BOOL aux1
8 BOOL aux2
9 BOOL aux3
10 BOOL aux4
11 BOOL aux5
12 BOOL aux6
13 BOOL aux7
68
Page 69
14 BOOL aux8
15 BOOL aux9
16 BOOL aux10
17 BOOL aux11
18 BOOL aux12
19 BOOL aux13
20 BOOL aux14
21 BOOL aux15
22 BOOL aux16
23 BOOL aux17
24 BOOL aux18
25 BOOL aux19
26 BOOL aux20
27 BOOL aux21
28 BOOL aux22
29 BOOL aux23
30 BOOL aux24
31
32 ∗∗SEARCH∗∗
33
34 PRINT [ s ]
35
36 VARORDER [
37 s , aux0 , aux1 , aux2 , aux3 , aux4 , aux5 , aux6 , aux7 , aux8 , aux9 , aux10 , aux11 , aux12 ,
aux13 , aux14 , aux15 , aux16 , aux17 , aux18 , aux19 , aux20 , aux21 , aux22 , aux23 , aux24 ]
38
39
40 ∗∗CONSTRAINTS∗∗
41
42 r e i f y ( eq (0 , s [ 0 ] ) , aux0 )
43 r e i f y ( eq (0 , s [ 1 ] ) , aux1 )
44 r e i f y ( eq (0 , s [ 2 ] ) , aux2 )
45 r e i f y ( eq (0 , s [ 3 ] ) , aux3 )
46 r e i f y ( eq (0 , s [ 4 ] ) , aux4 )
47 sumleq ( [ aux0 , aux1 , aux2 , aux3 , aux4 ] , s [ 0 ] )
48 sumgeq ( [ aux0 , aux1 , aux2 , aux3 , aux4 ] , s [ 0 ] )
49 r e i f y ( eq (1 , s [ 0 ] ) , aux5 )
50 r e i f y ( eq (1 , s [ 1 ] ) , aux6 )
51 r e i f y ( eq (1 , s [ 2 ] ) , aux7 )
52 r e i f y ( eq (1 , s [ 3 ] ) , aux8 )
53 r e i f y ( eq (1 , s [ 4 ] ) , aux9 )
54 sumleq ( [ aux5 , aux6 , aux7 , aux8 , aux9 ] , s [ 1 ] )
55 sumgeq ( [ aux5 , aux6 , aux7 , aux8 , aux9 ] , s [ 1 ] )
56 r e i f y ( eq (2 , s [ 0 ] ) , aux10 )
57 r e i f y ( eq (2 , s [ 1 ] ) , aux11 )
58 r e i f y ( eq (2 , s [ 2 ] ) , aux12 )
59 r e i f y ( eq (2 , s [ 3 ] ) , aux13 )
60 r e i f y ( eq (2 , s [ 4 ] ) , aux14 )
61 sumleq ( [ aux10 , aux11 , aux12 , aux13 , aux14 ] , s [ 2 ] )
62 sumgeq ( [ aux10 , aux11 , aux12 , aux13 , aux14 ] , s [ 2 ] )
63 r e i f y ( eq (3 , s [ 0 ] ) , aux15 )
64 r e i f y ( eq (3 , s [ 1 ] ) , aux16 )
65 r e i f y ( eq (3 , s [ 2 ] ) , aux17 )
66 r e i f y ( eq (3 , s [ 3 ] ) , aux18 )
67 r e i f y ( eq (3 , s [ 4 ] ) , aux19 )
68 sumleq ( [ aux15 , aux16 , aux17 , aux18 , aux19 ] , s [ 3 ] )
69 sumgeq ( [ aux15 , aux16 , aux17 , aux18 , aux19 ] , s [ 3 ] )
70 r e i f y ( eq (4 , s [ 0 ] ) , aux20 )
71 r e i f y ( eq (4 , s [ 1 ] ) , aux21 )
72 r e i f y ( eq (4 , s [ 2 ] ) , aux22 )
73 r e i f y ( eq (4 , s [ 3 ] ) , aux23 )
74 r e i f y ( eq (4 , s [ 4 ] ) , aux24 )
75 sumleq ( [ aux20 , aux21 , aux22 , aux23 , aux24 ] , s [ 4 ] )
76 sumgeq ( [ aux20 , aux21 , aux22 , aux23 , aux24 ] , s [ 4 ] )
77
78 ∗∗EOF∗∗
D.4 Gecode
The following code shows the implementation of the Locating Warehouses
problem in the Gecode solver. The code is complete except the loading of
69
15 BOOL aux9
16 BOOL aux10
17 BOOL aux11
18 BOOL aux12
19 BOOL aux13
20 BOOL aux14
21 BOOL aux15
22 BOOL aux16
23 BOOL aux17
24 BOOL aux18
25 BOOL aux19
26 BOOL aux20
27 BOOL aux21
28 BOOL aux22
29 BOOL aux23
30 BOOL aux24
31
32 ∗∗SEARCH∗∗
33
34 PRINT [ s ]
35
36 VARORDER [
37 s , aux0 , aux1 , aux2 , aux3 , aux4 , aux5 , aux6 , aux7 , aux8 , aux9 , aux10 , aux11 , aux12 ,
aux13 , aux14 , aux15 , aux16 , aux17 , aux18 , aux19 , aux20 , aux21 , aux22 , aux23 , aux24 ]
38
39
40 ∗∗CONSTRAINTS∗∗
41
42 r e i f y ( eq (0 , s [ 0 ] ) , aux0 )
43 r e i f y ( eq (0 , s [ 1 ] ) , aux1 )
44 r e i f y ( eq (0 , s [ 2 ] ) , aux2 )
45 r e i f y ( eq (0 , s [ 3 ] ) , aux3 )
46 r e i f y ( eq (0 , s [ 4 ] ) , aux4 )
47 sumleq ( [ aux0 , aux1 , aux2 , aux3 , aux4 ] , s [ 0 ] )
48 sumgeq ( [ aux0 , aux1 , aux2 , aux3 , aux4 ] , s [ 0 ] )
49 r e i f y ( eq (1 , s [ 0 ] ) , aux5 )
50 r e i f y ( eq (1 , s [ 1 ] ) , aux6 )
51 r e i f y ( eq (1 , s [ 2 ] ) , aux7 )
52 r e i f y ( eq (1 , s [ 3 ] ) , aux8 )
53 r e i f y ( eq (1 , s [ 4 ] ) , aux9 )
54 sumleq ( [ aux5 , aux6 , aux7 , aux8 , aux9 ] , s [ 1 ] )
55 sumgeq ( [ aux5 , aux6 , aux7 , aux8 , aux9 ] , s [ 1 ] )
56 r e i f y ( eq (2 , s [ 0 ] ) , aux10 )
57 r e i f y ( eq (2 , s [ 1 ] ) , aux11 )
58 r e i f y ( eq (2 , s [ 2 ] ) , aux12 )
59 r e i f y ( eq (2 , s [ 3 ] ) , aux13 )
60 r e i f y ( eq (2 , s [ 4 ] ) , aux14 )
61 sumleq ( [ aux10 , aux11 , aux12 , aux13 , aux14 ] , s [ 2 ] )
62 sumgeq ( [ aux10 , aux11 , aux12 , aux13 , aux14 ] , s [ 2 ] )
63 r e i f y ( eq (3 , s [ 0 ] ) , aux15 )
64 r e i f y ( eq (3 , s [ 1 ] ) , aux16 )
65 r e i f y ( eq (3 , s [ 2 ] ) , aux17 )
66 r e i f y ( eq (3 , s [ 3 ] ) , aux18 )
67 r e i f y ( eq (3 , s [ 4 ] ) , aux19 )
68 sumleq ( [ aux15 , aux16 , aux17 , aux18 , aux19 ] , s [ 3 ] )
69 sumgeq ( [ aux15 , aux16 , aux17 , aux18 , aux19 ] , s [ 3 ] )
70 r e i f y ( eq (4 , s [ 0 ] ) , aux20 )
71 r e i f y ( eq (4 , s [ 1 ] ) , aux21 )
72 r e i f y ( eq (4 , s [ 2 ] ) , aux22 )
73 r e i f y ( eq (4 , s [ 3 ] ) , aux23 )
74 r e i f y ( eq (4 , s [ 4 ] ) , aux24 )
75 sumleq ( [ aux20 , aux21 , aux22 , aux23 , aux24 ] , s [ 4 ] )
76 sumgeq ( [ aux20 , aux21 , aux22 , aux23 , aux24 ] , s [ 4 ] )
77
78 ∗∗EOF∗∗
D.4 Gecode
The following code shows the implementation of the Locating Warehouses
problem in the Gecode solver. The code is complete except the loading of
69
Page 70
the data from the external source.
1 #include <gecode / int . hh>
2 #include <gecode / search . hh>
3 #include <gecode /minimodel . hh>
4
5 #include <iostream >
6 #include <fstream >
7 #include <vector>
8 #include <s t r i ng >
9
10 using namespace Gecode ;
11
12 class Warehouses : public MinimizeSpace {
13 protected :
14 IntVar To ta lCos t ;
15 IntVar NumberOpen ;
16
17 IntVarArray Open ;
18 IntVarArray Su pp l i e r ;
19
20
21 IntVarArray Cost ;
22 IntVar SumCost ;
23
24 int numberOfWarehouses ;
25 int numberOfStores ;
26
27 public :
28 Warehouses (
29 int nbWarehouses ,
30 int nbStores ,
31 const s t d : : vec t o r<int>& supp lyCost ,
32 const s t d : : vec t o r<int>& warehouseCapaci ty
33 )
34 :
35 numberOfWarehouses ( nbWarehouses ) ,
36 numberOfStores( nbS to r e s ) ,
37 Su pp l i e r (∗ this , nbStores , 0 , nbWarehouses −1) ,
38 Tota lCos t (∗ this , 0 , Gecode : : I n t : : L im i t s : : max ) ,
39 Open (∗ this , nbWarehouses , 0 , 1) ,
40 NumberOpen(∗ this , 0 , nbWarehouses ) ,
41 Cost (∗ this , nbStores , 0 , Gecode : : In t : : L im i t s : : max) ,
42 SumCost (∗ this , 0 , Gecode : : I n t : : L im i t s : : max )
43 {
44
45 for ( int i = 0 ; i < numberOfWarehouses ; i++)
46 {
47 IntVarArray au x s u p p l i e d (∗ this , numberOfStores , 0 , 1) ;
48
49 for ( int j = 0 ; j < numberOfStores ; j++)
50 {
51 pos t (∗ this , t t ( imp ( Su pp l i e r [ j ] == i , au x s u p p l i e d [ j ] == 1) ) ) ;
52 pos t (∗ this , t t ( imp ( Su pp l i e r [ j ] != i , au x s u p p l i e d [ j ] == 0) ) ) ;
53
54 pos t (∗ this , t t ( imp ( Su pp l i e r [ j ] == i , Cost [ j ] == supp lyCos t [ i + j ∗
numberOfWarehouses ] ) ) ) ;
55 }
56
57 IntVar aux sum (∗ this , 0 , numberOfStores) ;
58
59 l i n e a r (∗ this , aux s up p l i ed , IRT EQ , aux sum ) ;
60
61 pos t (∗ this , t t ( imp ( aux sum > 0 , Open [ i ] == 1 ) ) ) ;
62 pos t (∗ this , t t ( imp ( aux sum == 0 , Open [ i ] == 0 ) ) ) ;
63
64 r e l ( ∗ this , aux sum , IRT LQ , warehouseCapaci ty [ i ] ) ;
65 }
66
67 l i n e a r (∗ this , Open , IRT EQ , NumberOpen) ;
68
69 l i n e a r (∗ this , Cost , IRT EQ , SumCost ) ;
70
71 In tArg s co s tArg s (2) ;
72 co s tArg s [ 0 ] = 1 ;
73 co s tArg s [ 1 ] = 50 ;
74
75 IntVarArgs c o s t Va r i a b l e s (2) ;
76 c o s t Va r i a b l e s [ 0 ] = SumCost ;
70
1 #include <gecode / int . hh>
2 #include <gecode / search . hh>
3 #include <gecode /minimodel . hh>
4
5 #include <iostream >
6 #include <fstream >
7 #include <vector>
8 #include <s t r i ng >
9
10 using namespace Gecode ;
11
12 class Warehouses : public MinimizeSpace {
13 protected :
14 IntVar To ta lCos t ;
15 IntVar NumberOpen ;
16
17 IntVarArray Open ;
18 IntVarArray Su pp l i e r ;
19
20
21 IntVarArray Cost ;
22 IntVar SumCost ;
23
24 int numberOfWarehouses ;
25 int numberOfStores ;
26
27 public :
28 Warehouses (
29 int nbWarehouses ,
30 int nbStores ,
31 const s t d : : vec t o r<int>& supp lyCost ,
32 const s t d : : vec t o r<int>& warehouseCapaci ty
33 )
34 :
35 numberOfWarehouses ( nbWarehouses ) ,
36 numberOfStores( nbS to r e s ) ,
37 Su pp l i e r (∗ this , nbStores , 0 , nbWarehouses −1) ,
38 Tota lCos t (∗ this , 0 , Gecode : : I n t : : L im i t s : : max ) ,
39 Open (∗ this , nbWarehouses , 0 , 1) ,
40 NumberOpen(∗ this , 0 , nbWarehouses ) ,
41 Cost (∗ this , nbStores , 0 , Gecode : : In t : : L im i t s : : max) ,
42 SumCost (∗ this , 0 , Gecode : : I n t : : L im i t s : : max )
43 {
44
45 for ( int i = 0 ; i < numberOfWarehouses ; i++)
46 {
47 IntVarArray au x s u p p l i e d (∗ this , numberOfStores , 0 , 1) ;
48
49 for ( int j = 0 ; j < numberOfStores ; j++)
50 {
51 pos t (∗ this , t t ( imp ( Su pp l i e r [ j ] == i , au x s u p p l i e d [ j ] == 1) ) ) ;
52 pos t (∗ this , t t ( imp ( Su pp l i e r [ j ] != i , au x s u p p l i e d [ j ] == 0) ) ) ;
53
54 pos t (∗ this , t t ( imp ( Su pp l i e r [ j ] == i , Cost [ j ] == supp lyCos t [ i + j ∗
numberOfWarehouses ] ) ) ) ;
55 }
56
57 IntVar aux sum (∗ this , 0 , numberOfStores) ;
58
59 l i n e a r (∗ this , aux s up p l i ed , IRT EQ , aux sum ) ;
60
61 pos t (∗ this , t t ( imp ( aux sum > 0 , Open [ i ] == 1 ) ) ) ;
62 pos t (∗ this , t t ( imp ( aux sum == 0 , Open [ i ] == 0 ) ) ) ;
63
64 r e l ( ∗ this , aux sum , IRT LQ , warehouseCapaci ty [ i ] ) ;
65 }
66
67 l i n e a r (∗ this , Open , IRT EQ , NumberOpen) ;
68
69 l i n e a r (∗ this , Cost , IRT EQ , SumCost ) ;
70
71 In tArg s co s tArg s (2) ;
72 co s tArg s [ 0 ] = 1 ;
73 co s tArg s [ 1 ] = 50 ;
74
75 IntVarArgs c o s t Va r i a b l e s (2) ;
76 c o s t Va r i a b l e s [ 0 ] = SumCost ;
70
Page 71
77 c o s t Va r i a b l e s [ 1 ] = NumberOpen ;
78
79 l i n e a r (∗ this , costArgs , c o s tVa r i a b l e s , IRT EQ , Tota lCos t ) ;
80
81 branch (∗ this , Supp l i e r , INT VAR SIZE MIN , INT VAL MIN) ;
82 }
83
84 virtual IntVar c o s t ( ) const {
85 return Tota lCos t ;
86 }
87
88 Warehouses (bool share , Warehouses& s ) : MinimizeSpace ( share , s ) {
89 Su pp l i e r . update (∗ this , share , s . Su pp l i e r ) ;
90 Tota lCos t . update (∗ this , share , s . Tota lCos t ) ;
91 Open . update (∗ this , share , s . Open ) ;
92 NumberOpen . update (∗ this , share , s . NumberOpen) ;
93 Cost . update (∗ this , share , s . Cost ) ;
94 SumCost . update (∗ this , share , s . SumCost ) ;
95
96 numberOfWarehouses = s . numberOfWarehouses ;
97 numberOfStores = s . numberOfStores ;
98 }
99
100 virtual Space∗ copy (bool share )
101 {
102 return new Warehouses ( share , ∗ this ) ;
103 }
104
105 void p r i n t (void ) const {
106 s t d : : cou t << " Cost : " << Tota lCos t << s t d : : end l ;
107 s t d : : cou t << " S u p p l i e r s : " << S upp l i e r << s t d : : end l ;
108 s t d : : cou t << " Open : " << Open << s t d : : end l ;
109 }
110
111 } ;
112
113 int main ( int argc , char∗∗ argv )
114 {
115 s t d : : vec t o r <int> supp lyCos t ;
116 s t d : : vec t o r <int> warehouseCapaci ty ;
117
118 // There shou ld be t he l o a d i n g o f t h e data i n t o t he v e c t o r s .
119 // We l e f t i t ou t in p r i n t o u t
120
121 Warehouses ∗ w = new Warehouses ( warehouseCapaci ty . s i z e ( ) , supp lyCos t . s i z e ( ) /
warehouseCapaci ty . s i z e ( ) , supp lyCost , warehouseCapaci ty ) ;
122
123 BAB<Warehouses> e (w) ;
124 delete w ;
125
126 Warehouses ∗ l a s t = 0 ;
127 while ( Warehouses ∗ s = e . nex t ( ) )
128 {
129 i f ( l a s t != 0)
130 {
131 delete l a s t ;
132 }
133
134 l a s t = s ;
135 }
136
137 i f ( l a s t )
138 {
139 l a s t −>p r i n t ( ) ;
140 delete l a s t ;
141 }
142
143 return 0 ;
144 }
71
78
79 l i n e a r (∗ this , costArgs , c o s tVa r i a b l e s , IRT EQ , Tota lCos t ) ;
80
81 branch (∗ this , Supp l i e r , INT VAR SIZE MIN , INT VAL MIN) ;
82 }
83
84 virtual IntVar c o s t ( ) const {
85 return Tota lCos t ;
86 }
87
88 Warehouses (bool share , Warehouses& s ) : MinimizeSpace ( share , s ) {
89 Su pp l i e r . update (∗ this , share , s . Su pp l i e r ) ;
90 Tota lCos t . update (∗ this , share , s . Tota lCos t ) ;
91 Open . update (∗ this , share , s . Open ) ;
92 NumberOpen . update (∗ this , share , s . NumberOpen) ;
93 Cost . update (∗ this , share , s . Cost ) ;
94 SumCost . update (∗ this , share , s . SumCost ) ;
95
96 numberOfWarehouses = s . numberOfWarehouses ;
97 numberOfStores = s . numberOfStores ;
98 }
99
100 virtual Space∗ copy (bool share )
101 {
102 return new Warehouses ( share , ∗ this ) ;
103 }
104
105 void p r i n t (void ) const {
106 s t d : : cou t << " Cost : " << Tota lCos t << s t d : : end l ;
107 s t d : : cou t << " S u p p l i e r s : " << S upp l i e r << s t d : : end l ;
108 s t d : : cou t << " Open : " << Open << s t d : : end l ;
109 }
110
111 } ;
112
113 int main ( int argc , char∗∗ argv )
114 {
115 s t d : : vec t o r <int> supp lyCos t ;
116 s t d : : vec t o r <int> warehouseCapaci ty ;
117
118 // There shou ld be t he l o a d i n g o f t h e data i n t o t he v e c t o r s .
119 // We l e f t i t ou t in p r i n t o u t
120
121 Warehouses ∗ w = new Warehouses ( warehouseCapaci ty . s i z e ( ) , supp lyCos t . s i z e ( ) /
warehouseCapaci ty . s i z e ( ) , supp lyCost , warehouseCapaci ty ) ;
122
123 BAB<Warehouses> e (w) ;
124 delete w ;
125
126 Warehouses ∗ l a s t = 0 ;
127 while ( Warehouses ∗ s = e . nex t ( ) )
128 {
129 i f ( l a s t != 0)
130 {
131 delete l a s t ;
132 }
133
134 l a s t = s ;
135 }
136
137 i f ( l a s t )
138 {
139 l a s t −>p r i n t ( ) ;
140 delete l a s t ;
141 }
142
143 return 0 ;
144 }
71
Page 73
33 s e l e c t c o l umn (N, ColId , Matrix , Col , 0) .
34
35 s e l e c t c o l umn ( , , [ ] , [ ] , ) .
36 s e l e c t c o l umn (N, ColId , [H|T ] , [H|CT] , A) :−
37 ColId i s A mod N,
38 AA i s A + 1 ,
39 s e l e c t c o l umn (N, ColId , T , CT, AA) .
40 s e l e c t c o l umn (N, ColId , [ |T ] , CT, A) :−
41 Mod is A mod N,
42 Mod \= ColId ,
43 AA i s A + 1 ,
44 s e l e c t c o l umn (N, ColId , T , CT, AA) .
45
46
47 s e l e c t r o w (N, RowId , Matrix , Row) :−
48 BoundL i s RowId∗N,
49 BoundH i s (RowId+1)∗N−1,
50 s e l e c t r ow (N, Matrix , Row , 0 , BoundL , BoundH ) .
51
52 s e l e c t r o w ( , [ ] , [ ] , , , ) :− ! .
53 s e l e c t r o w ( , , [ ] , A, , BH) :− BH < A , ! .
54
55 s e l e c t r o w (N, [H|T ] , [H |RT ] , A, BL , BH) :−
56 A >= BL ,
57 A =< BH,
58 AA i s A + 1 ,
59 ! ,
60 s e l e c t r ow (N, T, RT, AA, BL , BH) .
61
62 s e l e c t r o w (N, [ |T ] , RT, A, BL , BH) :−
63 A < BL ,
64 AA i s A + 1 ,
65 ! ,
66 s e l e c t r ow (N, T, RT, AA, BL , BH) .
67
68
69 q c o n s t r a i n t (N, Matr ix ) :−
70 q c o n s t r a i n t (N, Matrix , 0) .
71
72 q c o n s t r a i n t (N, , M) :− M >= N, ! .
73 q c o n s t r a i n t (N, Matrix , A) :−
74 A < N,
75 s e l e c t r ow (N, A, Matrix , Row) ,
76 s e l e c t c o l umn (N, A, Matrix , Col ) ,
77 a l l d i f f e r e n t (Row) ,
78 a l l d i f f e r e n t ( Col ) ,
79 AA i s A + 1 ,
80 ! ,
81 q c o n s t r a i n t (N, Matrix , AA) .
73
34
35 s e l e c t c o l umn ( , , [ ] , [ ] , ) .
36 s e l e c t c o l umn (N, ColId , [H|T ] , [H|CT] , A) :−
37 ColId i s A mod N,
38 AA i s A + 1 ,
39 s e l e c t c o l umn (N, ColId , T , CT, AA) .
40 s e l e c t c o l umn (N, ColId , [ |T ] , CT, A) :−
41 Mod is A mod N,
42 Mod \= ColId ,
43 AA i s A + 1 ,
44 s e l e c t c o l umn (N, ColId , T , CT, AA) .
45
46
47 s e l e c t r o w (N, RowId , Matrix , Row) :−
48 BoundL i s RowId∗N,
49 BoundH i s (RowId+1)∗N−1,
50 s e l e c t r ow (N, Matrix , Row , 0 , BoundL , BoundH ) .
51
52 s e l e c t r o w ( , [ ] , [ ] , , , ) :− ! .
53 s e l e c t r o w ( , , [ ] , A, , BH) :− BH < A , ! .
54
55 s e l e c t r o w (N, [H|T ] , [H |RT ] , A, BL , BH) :−
56 A >= BL ,
57 A =< BH,
58 AA i s A + 1 ,
59 ! ,
60 s e l e c t r ow (N, T, RT, AA, BL , BH) .
61
62 s e l e c t r o w (N, [ |T ] , RT, A, BL , BH) :−
63 A < BL ,
64 AA i s A + 1 ,
65 ! ,
66 s e l e c t r ow (N, T, RT, AA, BL , BH) .
67
68
69 q c o n s t r a i n t (N, Matr ix ) :−
70 q c o n s t r a i n t (N, Matrix , 0) .
71
72 q c o n s t r a i n t (N, , M) :− M >= N, ! .
73 q c o n s t r a i n t (N, Matrix , A) :−
74 A < N,
75 s e l e c t r ow (N, A, Matrix , Row) ,
76 s e l e c t c o l umn (N, A, Matrix , Col ) ,
77 a l l d i f f e r e n t (Row) ,
78 a l l d i f f e r e n t ( Col ) ,
79 AA i s A + 1 ,
80 ! ,
81 q c o n s t r a i n t (N, Matrix , AA) .
73
Sign up today - FREE
Mendeley saves you time finding and organizing research. Learn more
- All your research in one place
- Add and import papers easily
- Access it anywhere, anytime
Start using Mendeley in seconds!
Readership Statistics
1 Reader on Mendeley
by Discipline
by Academic Status
100% Student (Bachelor)
by Country
100% Czech Republic


