You are on page 1of 54

# Choco solver

http://choco.mines-nantes.fr/

Tutorials

^

^

O..

^

June 29, 2011

Copyright (C) 1999, 2011 F. Laburthe, N. Jussien.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled ”GNU

CHOCO Tutorials
GNU Free Documentation License 2011

-2/50-

29/6/2011

CONTENTS

Contents
Preface

1

I

3

Tutorials

1 Getting started: welcome to Choco
1.1 Before starting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Download Choco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2 First Example: Magic square
2.1 First, the model . . . . . . .
2.2 Then, the solver . . . . . .
2.3 The entire code . . . . . . .
2.4 Conclusion . . . . . . . . .

7
7
7

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

9
. 9
. 11
. 11
. 13

3 Exercises
3.1 I’m new to CP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.1 Exercise 1.1 (A soft start) . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1.2 Exercise 1.2 (DONALD + GERALD = ROBERT) . . . . . . . . . . . .
3.1.3 Exercise 1.3 (A famous example. . . a sudoku grid) . . . . . . . . . . .
3.1.4 Exercise 1.4 (The knapsack problem) . . . . . . . . . . . . . . . . . . . .
3.1.5 Exercise 1.5 (The n-queens problem) . . . . . . . . . . . . . . . . . . . .
3.2 I know CP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.1 Exercise 2.1 (Bin packing, cumulative and search strategies) . . . . . . .
3.2.2 Exercise 2.2 (Social golfer) . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2.3 Exercise 2.3 (Golomb rule) . . . . . . . . . . . . . . . . . . . . . . . . .
3.3 I know CP and Choco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.3.1 Exercise 3.1 (Hamiltonian Cycle Problem Traveling Salesman Problem)
3.3.2 Exercise 3.2 (Shop scheduling) . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.

15
15
15
16
16
17
17
18
18
19
21
21
21
22

4 Solutions
4.1 I’m new to CP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.1 Solution of Exercise 1.1 (A soft start) . . . . . . . . . . . . . . . . . . . . . . . . .
4.1.2 Solution of Exercise 1.2 (DONALD + GERALD = ROBERT) . . . . . . . . . . .
4.1.3 Solution of Exercise 1.3 (A famous example. . . a sudoku grid) . . . . . . . . . . .
4.1.4 Solution of Exercise 1.4 (The knapsack problem) . . . . . . . . . . . . . . . . . . .
4.1.5 Solution of Exercise 1.5 (The n-queens problem) . . . . . . . . . . . . . . . . . . .
4.2 I know CP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1 Solution of Exercise 2.1 (Bin packing, cumulative and search strategies) . . . . . .
4.2.2 Solution of Exercise 2.2 (Social golfer) . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.3 Solution of Exercise 2.3 (Golomb rule) . . . . . . . . . . . . . . . . . . . . . . . . .
4.3 I know CP and Choco2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3.1 Solution of Exercise 3.1 (Hamiltonian Cycle Problem Traveling Salesman Problem)
4.3.2 Solution of Exercise 3.2 (Shop scheduling) . . . . . . . . . . . . . . . . . . . . . . .

25
25
25
25
26
28
28
31
31
31
31
31
31
32

CHOCO Tutorials
GNU Free Documentation License 2011

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

-3/50-

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

29/6/2011

CONTENTS
5 Applications with global constraints
5.1 Placement and use of the Geost constraint . . . . . . . . . . . .
5.1.1 Example and way to implement it . . . . . . . . . . . .
5.1.2 Support for Greedy Assignment within the geost Kernel
5.2 Scheduling and use of the cumulative constraint . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

Bibliography

43

GNU Free Documentation License
1. APPLICABILITY AND DEFINITIONS . . . . . . . . .
2. VERBATIM COPYING . . . . . . . . . . . . . . . . . .
3. COPYING IN QUANTITY . . . . . . . . . . . . . . . .
4. MODIFICATIONS . . . . . . . . . . . . . . . . . . . . .
5. COMBINING DOCUMENTS . . . . . . . . . . . . . . .
6. COLLECTIONS OF DOCUMENTS . . . . . . . . . . .
7. AGGREGATION WITH INDEPENDENT WORKS . .
8. TRANSLATION . . . . . . . . . . . . . . . . . . . . . .
9. TERMINATION . . . . . . . . . . . . . . . . . . . . . .
10. FUTURE REVISIONS OF THIS LICENSE . . . . . .
11. RELICENSING . . . . . . . . . . . . . . . . . . . . . .

CHOCO Tutorials
GNU Free Documentation License 2011

33
33
33
36
38

-4/50-

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.

45
45
46
46
47
48
48
48
49
49
49
50
50

29/6/2011

CONTENTS

Preface
Choco is a java library for constraint satisfaction problems (CSP) and constraint programming (CP).
Choco is propagation-based constraint solver with a variable-centered propagation loop and backtrackable structures. Choco is an open-source software, distributed under a BSD licence and hosted by
sourceforge.net.
For any informations visit http://choco.mines-nantes.fr and read the documentation.
This document is organized as follows:
• Tutorials provides a fast how-to write a Choco program, a detailed example of a simple program,
and several exercises with their solutions, several guided examples and some examples of Applications.

CHOCO Tutorials
GNU Free Documentation License 2011

-1/50-

29/6/2011

.

Part I Tutorials CHOCO Tutorials GNU Free Documentation License 2011 -3/50- 29/6/2011 .

.

. Solver.). getting started is for you! It introduces to basic concepts of a CHOCO program (Model..If you look for an easy step-by-step program in CHOCO. variables and constraints. CHOCO Tutorials GNU Free Documentation License 2011 -5/50- 29/6/2011 . It covers simple to advanced uses of CHOCO. This part also presents a collection of exercises with their solutions and guided examples.

.

.

diagonals and rows are equal to the same constant M (which is equal to n ∗ (n2 + 1)/2). we need to create a Model object. } } CHOCO Tutorials GNU Free Documentation License 2011 -9/50- 29/6/2011 . n*n). We have the definition. for (int i = 0. all columns. is different from the others and columns. we do).model.CPModel. and both diagonals sum to the same constant. in a square. As we want to solve our problem with constraint programming (of course. j < n. At the begining. 1. we need to create a CPModel. such that the n numbers in all rows. which means that aCell is an integer variable. and its domain is defined from 1 to n*n.makeIntVar("cell" + j. So we are going to solve a problem where unknows are cells value. • Variables A variable is an object defined by a name. our model is empty.1 First. A model is composed of variables and constraints. usually distinct integers. and constraints link variables to each others. int M = n * (n * n + 1) / 2. import choco. no problem has been defined explicitly. i++) { for (int j = 0. But we need n2 variables. let see how to add some Choco in it. i < n. // Our model Model m = new CPModel(). a type and a domain.makeIntVar("aCell". We know that our unknowns are cells of the magic square. Wikipedia tells us that : A magic square of order n is an arrangement of n2 numbers. n * n). So: IntegerVariable cell = Choco.kernel. 1. //constants of the problem: int n = 3. we need to agree on the definition of a magic square of order 3.Model.cp. A normal magic square contains the integers from 1 to n2 . These objects require to import the following classes: import choco. 2. so the easiest way to define them is: IntegerVariable[][] cells = new IntegerVariable[n][n]. knowing that each cell can take its value between 1 and n2 .Chapter 2 First Example: Magic square A simple magic square of order 3 can be seen as the “Hello world!” program in Choco.model. First of all. j++) { cells[i][j] = Choco. the model To define our problem.

CHOCO Tutorials GNU Free Documentation License 2011 -10/50- 29/6/2011 .kernel.model.eq(Choco. //Constraints // . j < n. over diagonals IntegerVariable[][] diags = new IntegerVariable[2][n]. i++) { diags[0][i] = cells[i][i]. diags[1][i] = cells[i][(n . we have to define the constraints between variables. We do not introduce new variables. we get the two diagonals array diags.. we need to add them to the model: m. i++) { for (int j = 0. for (int i = 0.Choco. After the creation of the constraints.. We just reorder the matrix to see the column point of view. So we create the transposed matrix (a 90o rotation of the matrix) of cells. we can declare the constraints as before. Now that our variables are defined.addConstraints(cols). i < n.Constraint.i]. i < n. • Constraints over the rows The sum of ach rows is equal to a constant M .constraints. we need to declare the equality between the sum of each column and M .eq(Choco.CHAPTER 2. import choco. with a temporary array IntegerVariable[][] cellsDual = new IntegerVariable[n][n].sum(cells[i]). and add them to the model: Constraint[] cols = new Constraint[n]. for (int i = 0. M).kernel. i < n. } This part of code requires the following import: import choco. like in the previous step.IntegerVariable..addConstraints(rows). get the columns. But. //.1) . //. • Constraints over the diagonals Now. } m. for (int i = 0.java class.. } } Now. over columns // first. M). i < n. • Constraints over the columns Now. reordering the required cells variables. So we need a sum operator and and equality constraint.variables.. for (int i = 0. i++) { cols[i] = Choco.integer.sum(cellsDual[i]). i++) { rows[i] = Choco.. the way we have declare our variables matrix does not allow us to deal easily with it in the column case.model. j++) { cellsDual[i][j] = cells[j][i]. FIRST EXAMPLE: MAGIC SQUARE This code requires to import the following classes: import choco. The both are provides by the Choco. over rows Constraint[] rows = new Constraint[n].

2. m. One more time. i++) { for (int j = 0.Solver. for (int i = 0. i < n. import choco. stating that each cells variables takes a unique value.addConstraint(Choco.out. we can focus on the way to solve it. we just need to solve it: //solve the problem s. And print the information //Print the values for (int i = 0.eq(Choco.sum(diags[0]). to extract informations: //read the model s. introducing temporary array. we have to reorder the variables. j < n.print(s.3 The entire code The entire code looks like: CHOCO Tutorials GNU Free Documentation License 2011 -11/50- 29/6/2011 .allDifferent(allVars)). } } m. //All cells are different from each other IntegerVariable[] allVars = new IntegerVariable[n * n].CPSolver.getVar(cells[i][j]). The first step is to create a Solver. //Our solver Solver s = new CPSolver().addConstraint(Choco. i < n.2. THE SOLVER } And we add the constraints to the model (in one step this time). thus the solver read the model.solver. it does not require any other information.out. M)).eq(Choco.sum(diags[1]).addConstraint(Choco. After that. m. the solver Our model is established. M)). • Constraints of variables AllDifferent Finally.getVal() + " "). Once it is done. 2. we add the AllDifferent constraints. j++) { System. the model and the solver have to be linked.println(). i++) { for (int j = 0.read(m).cp. THEN. j++) { allVars[i * n + j] = cells[i][j]. This part requires the following imports: import choco. j < n. } System.solver.kernel.2 Then.solve(). } 2.

over rows Constraint[] rows = new Constraint[n].makeIntVar("cell" + j...println(). for (int i = 0.CHAPTER 2. 1. int M = n * (n * n + 1) / 2. i++) { for (int j = 0. // Our model Model m = new CPModel().read(m). with a temporary array IntegerVariable[][] cellsDual = new IntegerVariable[n][n]. diags[1][i] = cells[i][(n . } } m.addConstraint(Choco.sum(cellsDual[i]).eq(Choco.out.i]. i < n.. for (int i = 0. j++) { cells[i][j] = Choco.. IntegerVariable[][] cells = new IntegerVariable[n][n].out. m.1) . i < n. j < n.print(s. M). //Print the values for (int i = 0. } m.addConstraints(cols). get the columns. i < n. over diagonals IntegerVariable[][] diags = new IntegerVariable[2][n]. n * n). } } //Constraints // . FIRST EXAMPLE: MAGIC SQUARE //constants of the problem: int n = 3.sum(cells[i]). j < n. i++) { rows[i] = Choco. //.. M)). i < n. for (int i = 0. } m. } } Constraint[] cols = new Constraint[n]. M)). i++) { diags[0][i] = cells[i][i]. over columns // first.sum(diags[0]).solve().addConstraints(rows). //Our solver Solver s = new CPSolver(). } CHOCO Tutorials GNU Free Documentation License 2011 -12/50- 29/6/2011 . for (int i = 0. i < n. i++) { cols[i] = Choco. i++) { for (int j = 0. for (int i = 0.eq(Choco. //solve the problem s. i < n.. j++) { allVars[i * n + j] = cells[i][j]. j < n. //. i++) { for (int j = 0.addConstraint(Choco. } System. //All cells are different from each other IntegerVariable[] allVars = new IntegerVariable[n * n].getVar(cells[i][j]). } m.eq(Choco.addConstraint(Choco. j < n.sum(diags[1]).getVal() + " ").eq(Choco. i++) { for (int j = 0. //read the model s. i < n. j++) { cellsDual[i][j] = cells[j][i]. j++) { System.allDifferent(allVars)). for (int i = 0. M).

CONCLUSION 2.4.2. We think a main clue to efficiency is to strongly distinguish the modeling part from the resolution part. we will first introduce the modeling elements and then focus on the solving tools. how to modelize and to solve a basic problem using constraint programming and Choco.4 Conclusion We saw. That’s why. in a few steps. from now on. CHOCO Tutorials GNU Free Documentation License 2011 -13/50- 29/6/2011 .

.

1 (A soft start) Algorithm 1 (below) describes a problem which fits the minimum choco syntax requirements.addConstraint(C1). m. // Build enumerated domain variables IntegerVariable x1 = Choco. x3).neq(x1. x2).Chapter 3 Exercises 3. CHOCO Tutorials GNU Free Documentation License 2011 -15/50- 29/6/2011 . • mastering the syntax of Choco in order to tackle basic problems. That is why you are strongly advised to write down your model before starting its implementation within Choco.addConstraint(C2).1. Constraint C2 = Choco.1 I’m new to CP The goal of this practical work is twofold : • problem modelling with the help of variables and constraints . Algorithm 1: Mysterious model. x3).addConstraint(C3). // Build a solver Solver s = new CPSolver().1 Exercise 1. Question 2 give the variable domains after constraint propagation. Warning. 5). 3.makeIntVar("var2". m. // Build a model Model m = new CPModel().makeIntVar("var1". // Build the constraints Constraint C1 = Choco. 5). Constraint C3 = Choco. 0.gt(x2. 0.gt(x1. // Add the constraints to the Choco model m. 5). 0. Question 1 describe the constraint network modelled in Algorithm 1. constraint modelling should not be solver specific. IntegerVariable x2 = Choco.makeIntVar("var3". IntegerVariable x3 = Choco.

The purpose of the game is to fill the grid so that each block. System. . . the initial propagation step (use Choco propagate() method).println("var1 =" + s.getVal()). for both models. a sudoku grid) A sudoku grid is a square composed of nine squares called blocks. Question 3 Test.out. (Solution) 3.3 Exercise 1.1.1: An exemple of a Sudoku grid (Solution) CHOCO Tutorials GNU Free Documentation License 2011 -16/50- 29/6/2011 . // Print the variable domains System. // Solve the problem s. column and row contains all the numbers from 1 to 9 once and only once Question 1 propose a way to model the sudoku problem with difference constraints.getVar(x3). System. What can be noticed ? What is the point in using global constraints ? Figure 3.solve(). Each block is itself composed of 3x3 cells (see figure 1).getVal()).CHAPTER 3.2 (DONALD + GERALD = ROBERT) Associate a different digit to every letter so that the equation DONALD + GERALD = ROBERT is verified. (Solution) 3.2 Exercise 1.getVar(x1).getVar(x2).println("var3 =" + s.out.3 (A famous example.println("var2 =" + s. Question 2 which global constraint can be used to model such a problem ? Modify your code accordingly.read(m).out.getVal()). EXERCISES // Read the model s.1. Implement your model with Choco.

4 Exercise 1.2: A solution of the n-queens problem for n = 8 (Solution) CHOCO Tutorials GNU Free Documentation License 2011 -17/50- 29/6/2011 .5.3). Question 3 Compare the number of nodes created to find the solutions with both models. Question 2 Find and use the choco method to maximise the energetic value of the knapsack.1.2) for a consumed capacity of (7. 95. Question 5 what changes are caused by the use of the global constraint alldifferent ? Figure 3.4 (The knapsack problem) Let us organise a trek. 105. (Solution) 3. Question 1 propose and implement a model based on one Li variable for every row.4. Again. Question 3 Propose a Value selector heuristic to improve the efficiency of the model.1. Try to find a satisfying solution by modelling and implementing the problem within choco. • Select the value j ∈ Li so that the associated column variable Cj has the smallest domain. 90. How can you explain such a difference ? Question 4 Add to the previously implemented model the following heuristics: • Select first the line variable LI which has the smallest domain .1. Use simple difference constraints and confirm that 92 solutions are obtained for n = 8. we will not consider the idea of maximizing the energetic value. compare both approaches in term of number of nodes and solving time to find ONE solution for n = 75. The problem is to find which food is to be put in the knapsack so that the energetic value is maximal.3. The value of Li indicates the column where a queen is to be put. Each hiker carries a knapsack of capacity 34 and can store 3 kinds of food which respectively supply energetic values (6. Continue to use simple difference constraints. Question 1 In the first place. I’M NEW TO CP 3.5 (The n-queens problem) The n-queens problem aims to place n queens on a chessboard of size n so that no queen can attack one another. Question 2 Add a redundant model by considering variables on the columns (Ci ).5 Exercise 1.

for (int i = 0. i++) { pb.makeEnumIntVar("fin " + i.isFeasible() == Boolean.setVarSelector(new StaticVarOrder(branchvars)). n). IntDomainVar[] fin = new IntDomainVar[n].sort(). 1). 1. fin. j++) { System." + (obj. Solver. } IntDomainVar[] branchvars = new IntDomainVar[n + 1]. duree[i] = pb. pb. CHOCO Tutorials GNU Free Documentation License 2011 -18/50- 29/6/2011 . Bonus question Compare different search strategies (variables/values selector) on this model for n between 10 and 15.print(i + " "). i < n. for (int i = 0. instance. i < n.TRUE) { for (int j = 0.1 I know CP Exercise 2. // print solution System. Your model and heuristics will be checked by generating random instances for given n and C. false). if (pb. //Sort objects in increasing order sort. This can be done by considering the occupied size globally.CHAPTER 3.setVerbosity(Solver. int[] instance = getRandomPackingPb(n. j <= obj. branchvars[n] = obj. pb.out. IntDomainVar[] duree = new IntDomainVar[n]. seed). capaBin. Solver.2 3. System. i++) { debut[i] = pb.println("-----------------------. Use your previously stated model but increase regularly the number of containers until a feasible solution is found. 0. } IntDomainVar obj = pb. int nbBinMin = computeLB(instance.makeEnumIntVar("debut " + i. Question 1 Propose a boolean model (0/1 variables). Define an objective function to minimize the number of used bins.SOLUTION). for (int i = 0. capaBin)).currentTimeMillis(). fin[i] = pb. Question 4 Propose a model with integer variables based on the cumulative constraint (see choco user guide/API for details). i < n.print("Bin " + j + ": "). n). IntDomainVar[] debut = new IntDomainVar[n]. duree. Question 2 Let us turn this satisfaction problem into an optimization one.minimize(obj. branchvars. nbBinMin.getVal().out. debut[i])).makeEnumIntVar("nbBin ".getSolver().geq(obj.makeEnumIntVar("duree " + i. 0.cumulative(debut. //long tps = System.post(pb.1 (Bin packing. n). cumulative and search strategies) Can n objects of a given size fit in m bins of capacity C ? The problem is here stated has a satisfaction problem for the sake of simplicity. i++) { if (debut[i]. EXERCISES 3.post(pb. Problem pb = new Problem(). int load = 0. The random generation must be reproducible. Question 3 Implement a naive lower bound. Take a look at the following exercise in the old version of Choco and try to transpose it on new version of Choco. pb. capaBin).flushLogs().2. 0. QuickSort sort = new QuickSort(instance). 0.out. n).isInstantiatedTo(j)) { System.getVal() + 1) + " bins").arraycopy(debut.

get(1)). a golfer can be put in the first available group of each week before considering the next golfer. 6.2. 8). (4. The objective is to build a game scheduling on w weeks so that no golfer play in the same group than another one more than once (hence the name of the problem: social golfers). } (Solution) 3. i++) { for (int j = 0.out. j < numplayers.getNbTot()). 3). k++) golfmat[i][j][k] = pb. 1). 8. // golfmat[i][j][k] : is golfer k playing week j in group i ? IntDomainVar[][][] golfmat = new IntDomainVar[g][w][numplayers]. 4)}. (13.post(pb. s. 4). 2). (9. } } System.println(" . (9. j < w. However. k < numplayers. } //every week.load " + load). The point is only that once they have played together.println("tps " + tps + " node " // + ((NodeLimit) pb.makeEnumIntVar("("+i+"_"+j+"_"+k+")". 0.eq(pb. it may happen that two golfers will never play together. for (int k = 0. } CHOCO Tutorials GNU Free Documentation License 2011 -19/50- 29/6/2011 . j++) for (int k = 0. 1)). getOneMatrix(g)).1: A valid configuration with 4 groups of 3 golfers on 3 weeks. (3. i < g.3. I KNOW CP load += instance[i]. every golfer plays in one group for (int i = 0. i < w.2 (Social golfer) A group of golfers play once a week and are splitted into k groups of size s (there are therefore ks golfers in the club). Problem pb = new Problem(). they cannot play together anymore.out.getSolver(). You can test your model with the parameters (w.2. k < g.2 Exercise 2. 2). j++) { IntDomainVar[] vars = new IntDomainVar[g]. 7. Use an heuristic that consists in scheduling a golfer on every week before scheduling a new one.getSearchSolver(). 8. 6. } pb. i++) { for (int j = 0.limits. int numplayers = g * s. week 1 week 1 week 1 group 1 123 147 159 group 2 456 10 2 5 10 2 6 group 3 789 8 11 3 7 11 3 group 4 10 11 12 6 9 12 4 8 12 Table 3. Question 2 Identify some symmetries of the problem by using every similar elements of the problem. Question 1 Propose a boolean model for this problem. More precisely. for (int i = 0. k++) { vars[k] = golfmat[k][i][j].scalar(vars. 7. g) set to: {(11. Try to improve your model by breaking those symmetries. } //System.

k < w. int cpt = 0. j < numplayers. IntDomainVar[] vars2 = new IntDomainVar[numplayers * g]. EXERCISES } //every group is of size s for (int i = 0. j < g. } CHOCO Tutorials GNU Free Documentation License 2011 -20/50- 29/6/2011 . k++) { for (int l = 0.post(pb. j++) { IntDomainVar[] vars = new IntDomainVar[numplayers]. } } pb. 1)). 0. cpt++. l++) { vars1[cpt] = golfmat[l][k][i]. vars2[cpt] = golfmat[l][k][j]. j < numplayers. } } pb.arraycopy(golfmat[j][i]. for (int k = 0. i < w. l++) { vars1[cpt] = golfmat[l][i][k]. getOneMatrix(numplayers)). i++) { for (int j = i + 1. i++) { for (int j = i + 1. int cpt = 0. l++) { vars[cpt] = golfmat[l][k][i].eq(pb. vars2)).scalar(vars. vars. l < g. 0. } } //break symetries among groups for (int i = 0. i++) { for (int j = i + 1. k++) { for (int l = 0. j < w. } } pb. cpt++. j++) { IntDomainVar[] vars = new IntDomainVar[w * g * 2].post(pb. vars2[cpt] = golfmat[l][j][k]. i++) { for (int j = 0. k < w. } } //break symetries among weeks //enforce a lexicographic ordering between every pairs of week for (int i = 0. s)).post(pb.CHAPTER 3. IntDomainVar[] vars2 = new IntDomainVar[w * g]. l < g. numplayers). k < numplayers. i < numplayers. vars2)). j++) { IntDomainVar[] vars1 = new IntDomainVar[w * g]. i < w.post(new ScalarAtMostv1(vars. j++) { IntDomainVar[] vars1 = new IntDomainVar[numplayers * g]. pb. int cpt = 0. System.lex(vars1. w * g. } } //every pair of players only meets once // Efficient way : use of a ScalarAtMost for (int i = 0.lex(vars1. cpt++. for (int k = 0. k++) { for (int l = 0. vars[cpt + w * g] = golfmat[l][k][j]. l < g. for (int k = 0. i < numplayers.

vars2)). Notice the duplication distinguishes the source from the sink while there is only one warehouse..solve(). i++) { for (int j = 0.lex(vars1.setVarSelector(new StaticVarOrder(staticvars)).3. pb. E).post(pb. Finally. k < g. for (int i = 0. let us denote by Vd = V ∪ {1. CHOCO Tutorials GNU Free Documentation License 2011 -21/50- 29/6/2011 . k++) { staticvars[cpt] = golfmat[k][j][i]. Solver. vars2[cpt] = golfmat[p][i][k]..3 3. i < w. (Solution) 3. IntDomainVar[] vars2 = new IntDomainVar[numplayers]. k < numplayers.3. p++) { IntDomainVar[] vars1 = new IntDomainVar[numplayers].3 (Golomb rule) under development (Solution) 3. j < w. j++) { for (int p = j + 1.flushLogs().setTimeLimit(120000). n} be a set of cities index to cover.setVerbosity(Solver. This exercise first intorduces a naive model to solve the Hamiltonian Cycle Problem. I KNOW CP AND CHOCO } //break symetries among players for (int i = 0. } pb. k++) { vars1[cpt] = golfmat[j][i][k]. Let V = {2. Solver. Thus.SOLUTION).3.2. n + 1} the set of nodes to cover by a tour. pb. int cpt = 0. p < g.3 Exercise 2. A second part tackles with the well known Traveling Salesman Problem.1 (Hamiltonian Cycle Problem Traveling Salesman Problem) Given a graph G = (V. j < g. i++) { for (int j = 0.getSolver(). int cpt = 0.getSolver(). cpt++. cpt++. j++) { for (int k = 0. and let d be a single warehouse duplicated into two indices 1 and n + 1. for (int k = 0. } } } //gather branching variables IntDomainVar[] staticvars = new IntDomainVar[g * w * numplayers].. i < numplayers. .1 I know CP and Choco Exercise 3. an Hamiltonian cycle is a cycle that goes through every nodes of G once and only once. the two following problems are defined: • find an Hamiltonian path covering all the cities of V • find an Hamiltonian cycle of minimum cost that covers all the cities of V . } } } pb.

.

Options. 4.makeIntVar("g". Options. 9. 0. 0. IntegerVariable g = Choco. 9. • From x1 = [0. 29/6/2011 . • Then. we can deduce that : the domain of x2 can be reduce to [1. // Declare every letter as a variable IntegerVariable d = Choco.makeIntVar("r". 3].V_ENUM). 9. 5] and x2 > x3 . 5] and x2 = [0. Options. Options.V_ENUM).1.Chapter 4 Solutions 4. 4] and x1 > x2 . Options. 9. -25/50- 9. 5] and the domain of x2 can be reduce to [0. x1 6= x3 . Options. x3 }: the set of variables. x2 : [1. 4] and the domain of x3 can be reduce to [0.1. we can deduce tha : the domain of x1 can be reduce to [1. 9. 9. 5]. and here is the domain of each variables: x1 : [2.1 I’m new to CP Solution of Exercise 1. x2 .makeIntVar("o". 5]. x2 > x3 }: the set of constraints.makeIntVar("d". We cannot deduce anything else. IntegerVariable e = Choco. from x2 = [0.makeIntVar("a". IntegerVariable l = Choco. 5]. 5] and x2 = [1. we can deduce that : the domain of x1 can be reduce to [2. 5]}: the set of domain • C = {x1 > x2 . CHOCO Tutorials GNU Free Documentation License 2011 0. 4]. 0. Options. IntegerVariable a = Choco. • Then. IntegerVariable r = Choco.makeIntVar("e".makeIntVar("l". Options. 0.2 Solution of Exercise 1. IntegerVariable n = Choco.V_ENUM). 4]. • D = {[0. 0. 0. Question 2: give the variable domains after constraint propagation. 9.V_ENUM).2 (DONALD + GERALD = ROBERT) (Problem) // Build model Model model = new CPModel(). so we have reached a fix point.V_ENUM).V_ENUM). IntegerVariable o = Choco.V_ENUM).V_ENUM).makeIntVar("n". [0. 5]. from x1 = [1.1 4. 3]. 0. x3 : [0. 5] and x1 > x2 . 4] and x3 = [0.1 (A soft start) (Problem) Question 1: describe the constraint network related to code The model is defined as : • V = {x1 . [0.

i++) { CHOCO Tutorials GNU Free Documentation License 2011 -27/50- 29/6/2011 . // Declare variables IntegerVariable[][] rows = Choco. k < n. j < cj + 3.solve().allDifferent(rows[i])). Options. ci += 3) { for (int cj = 0. int n = 9. i++) { for (int j = 0.neq(rows[i][j].V_ENUM). i++) for (int j = cj. n. // Channeling between rows and columns for (int i = 0. The allDifferent constraint can be used to remplace every disequality constraint on the first Sudoku model. cj < n. l++) if (k != i || l != j) m. i < n.1. i < ci + 3. carres[j + k * 3][i + 3] = rows[1 + k * 3][i + j * 3]. k++) { carres[j + k * 3][i] = rows[0 + k * 3][i + j * 3]. It improves the efficient of the model and make it more “readable”. i < n. } // Add alldifferent constraint for (int i = 0. } // Not equal constraint between each case of a sub region for (int ci = 0. s. k < ci + 3. i < n. j < 3. 1.addConstraint(Choco.allDifferent(cols[i])). k++) if (k != i) m. // Build model Model m = new CPModel(). ChocoLogging. carres[j + k * 3][i + 6] = rows[2 + k * 3][i + j * 3]. ci < n.addConstraint(Choco. n. for (int i = 0. i++) for (int k = 0. s. } } } // Add alldifferent on sub regions for (int i = 0. j++) { for (int k = 0.addConstraint(Choco.makeIntVarArray("rows". i++) { for (int j = 0. IntegerVariable[][] cols = new IntegerVariable[n][n]. rows[k][j])). j < n. rows[k ][l])). i < n.4. } // Define sub regions IntegerVariable[][] carres = new IntegerVariable[n][n]. k < 3.addConstraint(Choco.read(m). l < cj + 3. k++) for (int l = cj. i++) { m. // print the grid Question 2: which global constraint can be used to model such a problem ? Modify your code to use this constraint. } // Call solver Solver s = new CPSolver(). I’M NEW TO CP for (int i = 0. n. j++) for (int k = ci. i < 3. j++) cols[i][j] = rows[j][i].toSolution(). cj += 3) // Extraction of disequality of a sub region for (int i = ci. m.neq(rows[i][j].

1. 4. s.makeIntVar("obj1".addConstraint(Choco. Options. int[] volumes = new int[]{7. CHOCO Tutorials GNU Free Documentation License 2011 -28/50- 29/6/2011 . Model m = new CPModel(). 4. It iterates over decreasing values of every domain variables: s.leq(Choco. c = Choco. the second indicates if the search must restart from the root node after finding each solution.solve() with: s. c)). } // Call solver Solver s = new CPSolver(). due to more complex deduction. 3}.getVar(c). Question 2 : Find and use the choco method to maximize the energetic value of the knapsack. What can be noticed ? What is the point in using global constraints ? The sudoku problem can be solved just with the propagation.V_BOUND). 5. 10.addConstraint(c). Options.maximize(s. one can bypass this restriction. 1. obj2.5 (The n-queens problem) (Problem) Question 1 : propose and implement a model based on one Li variable for every row. Replace the common s. new IntegerVariable[]{obj1.V_ENUM). Options. 4.solve(). int capacity = 34. obj2 = Choco.addConstraint(Choco. It can be improved using the following value selector strategy. 0. s. Question 3 : Propose a Value selector heuristic to improve the efficiency of the model. FIXME explanation.scalar(volumes.read(m).V_ENUM).scalar(energy.4 (The knapsack problem) (Problem) Question 1 : In the first place.4 Solution of Exercise 1. // print grid Question 3: Test for both model the initial propagation step (use choco propagate() method). obj3 = Choco. obj2. ChocoLogging. Options. m. 1000000.V_ENUM).CHAPTER 4. capacity)). IntegerVariable IntegerVariable IntegerVariable IntegerVariable obj1 = Choco. we will not consider the idea of maximizing the energetic value.1. false). 0. Try to find a satisfying solution by modelling and implementing the problem within choco.. obj3}). By adding an equality constraint between the expression and a integer variable.makeIntVar("cost".setValIntIterator(new DecreasingDomain()).toSolution(). obj3}) . 5.5 Solution of Exercise 1. new IntegerVariable[]{obj1. 0. 7. s. SOLUTIONS Constraint c = Choco.eq(Choco.read(m). 2}.. The global constraint provides a more efficient filter algorithm. m. int[] energy = new int[]{6. Choco doesn’t allow the optimization of integer expression. Solver s = new CPSolver().allDifferent(carres[i]). m.makeIntVar("obj3". The first argument defines the objective variable to optimize.makeIntVar("obj2".

getVar(queensdual)))).getVar(queens)). } // Returns the "best val" that is the smallest column domain size OR -1 // (-1 is not in the domain of the variables) public int getBestVal(IntDomainVar intDomainVar) { int minValue = Integer. s.solve(). It iterates over variables given and returns the variable ordering by creasing domain size.. with s. } } Question 5 : what changes are caused by the use of the global constraint alldifferent ? int n = 12. 90.dualVar = cols.1]. 105. i <= UB.getVar(queens)). } } return v0. FIXME Question 4 : Add to the previous implemented model the following heuristics.. • Select the value j ∈ Li so that the associated column variable Cj has the smallest domain. if (val < minValue) { minValue = val. How can you explain such a difference ? The channeling permit to reduce more nodes from the tree search. s. Question 3 : Compare the number of nodes created to find the solutions with both models.getDomainSize(). compare both approaches in term of nodes number and solving time to find ONE solution for n = 75. CHOCO Tutorials GNU Free Documentation License 2011 -30/50- 29/6/2011 . new NQueenValueSelector(s. IntegerVariable[] queensdual = new IntegerVariable[n]. Again.getInf(). The value selector strategy has to be created as follow: class NQueenValueSelector implements ValSelector<IntDomainVar> { // Column variable protected IntDomainVar[] dualVar.addGoal(new AssignOrForbidIntVarVal(new MinDomain(s. Model m = new CPModel(). int UB = intDomainVar. public NQueenValueSelector(IntDomainVar[] cols) { this. s. 95.MAX_VALUE. Replace the following lines in your program : s. // Constructor of the value selector.getNextDomainValue(i)) { int val = dualVar[i .CHAPTER 4. v0 = i. SOLUTIONS ChocoLogging. for (int i = intDomainVar. int v0 = -1. • Select first the line variable (Li ) which has the smallest domain . i = intDomainVar.toSolution(). The variable selector strategy (MinDomain) already exists in Choco.addGoal(new AssignOrForbidIntVarVal(new MinDomain(s. new MinVal())).getSup(). IntegerVariable[] queens = new IntegerVariable[n].

SOLUTIONS 4.CHAPTER 4.2 Solution of Exercise 3.3.2 (Shop scheduling) (Problem) under development CHOCO Tutorials GNU Free Documentation License 2011 -32/50- 29/6/2011 .

Each object o= object( id. an origin o. o2 to place them inside a box B (3x4) such that they don’t overlap (see Figure bellow). start. y in 0. each of which taking a shape among a set of shapes S during a given time interval and at a given position in space. • A list of identifiers of the objects to which the constraint applies. Consider we have 3 objects o0 . 0 ≤ d < k. • o1 : x in 0.3.x[k-1]. 0 ≤ d < k.1. a duration o... x[0]. 5.1. Then. a shape id o.1.1. start.. duration. More precisely a shifted box s= shape(sid.1.Chapter 5 Applications with global constraints 5. All attributes sid. and a finishingxs time o.1 Placement and use of the Geost constraint The global constraint geost(k.x[1]. This sometimes allows a drastic reduction in the number of shifted boxes needed to describe a shape. o1 .end) from O is an entity defined by a unique object id o. y in 0. or attributes of the objects of O the constraint considers. All attributes of a shifted box are integer values.1.id (an integer). We describe now how to solve this problem by using Choco.x[]. • o2 : x in 0.. Constraints of the list of constraints C have always two first arguments Ai and Oi (followed by possibly some additional arguments) which respectively specify: • A list of dimensions (integers between 0 and k-1).l[d] > 0. S. C) handles in a generic way a variety of geometrical constraints C in space and time between polymorphic k ∈ N dimensional objects O.1 Example and way to implement it We will explain how to use geost although a 2D example..start. a shape from S is a collection of shifted boxes sharing all the same shape id.t[d]..l[]) is an entity defined by a shape id sid. where each shifted box is described by a box in a k-dimensional space at the given offset with the given sizes.duration> 0. Given that the placement of the objects should be totally inside B this means that the domain of the origins of objects are as follows (we start from 0 this means that the placement space is from 0 to 2 on x and from 0 to 3 on y: • o0 : x in 0. O. y in 0.end. To begin the implementation we build a CP model: CHOCO Tutorials GNU Free Documentation License 2011 -33/50- 29/6/2011 . and a size s. The first object o0 has two potential shapes while o1 and o2 have one shape. duration.. Each shape from S is defined as a finite set of shifted boxes. a starting time o. 0 ≤ d < k. end correspond to domain variables.x[d].. an shift offset s. sid.sid... Typical constraints from the list of constraints C are for instance the fact that a given subset of objects from O do not pairwise overlap. Note that the shifted boxes associated with a given shape may or may not overlap.t[]. Build a CP model.

0. Then we first need to specify the dimension k we are working in. 1. Set the Dimension. coords. however we need to give them dummy values. 1). Finally we are ready to add the object 0 to our objects list: objects. This is done by assigning the dimension to a local variable that we will use later: int dim = 2. 1). int objectId = 0. // object id IntegerVariable shapeId = Choco. which for the current implementation of geost are not working. duration and end). Create the Shifted Boxes. coords[1] = Choco. Now we create the first object o0 by creating all its attributes.makeIntVar("sid". 0. 1). start. 0. We need to specify 3 more Integer Domain Variables representing the temporal attributes (start. IntegerVariable start = Choco. To create the shifted boxes for the shape 0 (that corresponds to o0 ).1: Geost objects and shapes Model m = new CPModel(). // coordinates of the origin coords[0] = Choco. 1). // shape id (2 possible values) IntegerVariable coords[] = new IntegerVariable[dim].makeIntVar("x". Then we start by creating the objects and store them in a list as such: List<GeostObject> objects = new ArrayList<GeostObject>().add(new GeostObject(dim.CHAPTER 5. end)). we start by the first shifted box by creating the sid and 2 arrays one to specify the offset of the box in each dimension and one for the size CHOCO Tutorials GNU Free Documentation License 2011 -34/50- 29/6/2011 .makeIntVar("start". duration. 1). 1. objectId.makeIntVar("duration". shapeId. 0. Create the Objects.makeIntVar("end". To create the shapes and their shifted boxes we create the shifted boxes and associate them with the corresponding shapeId. first we create a list called sb for example List<ShiftedBox> sb = new ArrayList<ShiftedBox> (). 0). APPLICATIONS WITH GLOBAL CONSTRAINTS Figure 5. IntegerVariable end = Choco. IntegerVariable duration = Choco. Now we do the same for the other object o1 and o2 and add them to our objects .makeIntVar("y". This is done as follows.

sid should be set to its minimum possible value if v [0]< 0. o5 .solve().x[min(2).e.e.e.. Solve the problem. This is achieved by: • Fixing the objects according to the order they were passed to the geost kernel.read(m). We can in fact give a list of lists v1 . also specified by the user. . sb.. by using min(2)). o3 .. o(p+pa) . max(I)). min(I) (respectively. ectr).CHAPTER 5. ..e. by using max(3)). for performance reasons.1. APPLICATIONS WITH GLOBAL CONSTRAINTS Create the geost constraint and add it to the model. . This is illustrated by Figure bellow: for instance. The only difference consists of the fact that a variable is replaced by an expression (The character denotes the fact that the corresponding attribute is irrelevant..min(3)]) and (2) object(_. fix the y-coordinate of an object to its its maximum value (i. fix the x-coordinate of an object to its its minimum value (i. . by using max(1)).max(1). fix the y-coordinate of an object to its its minimum value (i. – A value to assign that can either be the smallest or the largest value. Since. m. by using min(3)) and • fix the shape variable of an object to its maximum value (i.2 Support for Greedy Assignment within the geost Kernel Motivation and functionality description. o6 by alternatively using strategies (1) object(_. o(2+pa) . fix the x-coordinate of an object to its its maximum value (i. Part(I ) specifies that we alternatively: • fix the shape variable of an object to its maximum value (i. o4 . where I is a strictly positive integer. by using max(1) ). objects. o2 . we provide a way to specify a preferred order on how to fix all the objects in one single propagation step. s.. we know that it is always fixed ). CHOCO Tutorials GNU Free Documentation License 2011 -36/50- 29/6/2011 . since for instance.e. 5.x[max(2). fixing its shape variable as well as its coordinates: – According to an order on these variables that can be explicitly specified. Constraint geost = Choco.max(3)).max(1). In the example associated with Part (I) we successively fix objects o1 . • When considering one object. Solver s = new CPSolver(). s..addConstraint(geost).e. The meaning is that the corresponding variable should be fixed to its minimum (respectively maximum value) in the order I. the geost kernel offers a mode where he tries to fix all objects during one single propagation step. This is encoded by a term that has exactly the same structure as the term associated to an object of geost. The greedy algorithm for fixing an object o is controlled by a list v of length k+1 such that: • The shape variable o. vp in order to specify how to fix objects o(1+pa) . Note that the use of the greedy mode assumes that no other constraint is present in the problem. Implementation. by using max(2)).. and to its maximum possible value otherwise.geost(dim.. v2 . .

5.2: Greedy placement CHOCO Tutorials GNU Free Documentation License 2011 -37/50- 29/6/2011 . PLACEMENT AND USE OF THE GEOST CONSTRAINT Figure 5.1.

o11 . o9 . sb.min(1). These strategies are encoded respectively as [−1. o11 having 4 potential shapes and we want to place them in a box B (7x6) (see Figure bellow).3: A second Geost instance. suppose that we want use two strategies when greedy algorithm is called: the term object(_. 4. o3 . 3}. APPLICATIONS WITH GLOBAL CONSTRAINTS • abs(v [1])-2 is the most significant dimension (the one that varies the slowest) during the sweep. and in descending order otherwise. Figure 5. o6 . In fact we just need to create the list of controlling lists before creating the geost constraint. 2.addConstraint(geost). by adding the list of controlling vectots as an another argument.min(3)]) for objects o0 .add(v1).[max(3). . objects.r. int[] v0 = {-1. Second example. We will explain although a 2D example how to take into account of greedy mode.max(1). o5 . The values are tried in ascending order if v [1]< 0. -3}.geost(dim.t.min(4). • abs(v [2])-2 is the next most significant dimension. . Moreover. 3]. 2. and the term object(_. Given that the placement of the objects should be totally inside B this means that the domain of the origins of objects are as follows x ∈ [0. For example. 2. 4]. ectr. CHOCO Tutorials GNU Free Documentation License 2011 -38/50- 29/6/2011 . The placement obtained using the preceding strategies is displayed in the following figure (right side). y ∈ [0. . ctrlVs.add(v0). Consider we have 12 identical objects o0 .CHAPTER 5. a term object(_.[max(2). −3] and [1.[min(2) . . o2 . −3]. and then create the geost constraint. We comment only the additional step w.max(3)]) for objects o1 . o1 . and so on. 5]. -2. o8 . the preceding example. ctrlVs. Each controlling list is an array: List <int[]> ctrlVs = new ArrayList<int[]>(). o7 . and its sign indicates the value order.max(2)]) is encoded as the list [−1. o10 . −2.min(1).ctrlVs). int[] v1 = {1. as follows: Constraint geost = Choco. m. o4 .

5: A cumulative scheduling problem instance This tutorial might help you to deal with : • The profile of the resource that varies in time whereas the API of the cumulative only accepts a constant capacity CHOCO Tutorials GNU Free Documentation License 2011 -39/50- 29/6/2011 . It shows the resource profile on the left and on the right. Figure 5.4: A solution placement 5. the set of tasks to be scheduled. Notice that the profile is not a straight line but varies in time. Each task is represented here as a rectangle whose height is the resource consumption of the task and whose length is the duration of the task. The following picture summarizes the instance that we will use as example.2 Scheduling and use of the cumulative constraint We present a simple example of a scheduling problem solved using the cumulative global constraint. SCHEDULING AND USE OF THE CUMULATIVE CONSTRAINT Figure 5. The problem is to maximize the number of tasks that can be scheduled on a single resource within a given time horizon.2.5.

CHOCO Tutorials GNU Free Documentation License 2011 -42/50- 29/6/2011 .CHAPTER 5. APPLICATIONS WITH GLOBAL CONSTRAINTS Figure 5.6: Cumulative profile of a solution.

BIBLIOGRAPHY Bibliography CHOCO Tutorials GNU Free Documentation License 2011 -43/50- 29/6/2011 .

.