Numberjack - Modelling, reformulation, and solving

advertisement
Numberjack
Modelling, reformulation, and solving
Barry Hurley
barry.hurley@insight-centre.org
ModRef 2014
Outline
Introduction to Numberjack
Modelling Constructs
solve() and friends
Example Application and Demos
Summary
Insight Centre for Data Analytics
September 8, 2014
Slide 2
Numberjack Overview
What is Numberjack?
• A platform for combinatorial optimization
• Open source project (Github, LGPL)
• Python
• Common platform for diverse paradigms (CP, SAT, MIP)
• Fast backend solvers
Insight Centre for Data Analytics
September 8, 2014
Slide 3
CP, SAT, MIP: choice is good!
Numberjack
• Write a single model in Python
• Numberjack constructs: union of SAT, MIP, and CP
• Encoded depending on the choice of solver
Operationally different
• Algorithms are different
• CP: Constraint propagation + Search
• SAT: Unit propagation + Clause Learning + Search
• MIP: Linear relaxation + Cutting planes + Branch & Bound
• Encodings matter
Insight Centre for Data Analytics
September 8, 2014
Slide 4
Backend Solvers Available
CP Solvers
MIP Solvers
• Mistral v1 & v2
• IBM ILOG CPLEX
• Toulbar2
• Gurobi
SAT Solvers
• MiniSat
• Walksat
• Lingeling
• CryptoMiniSat
• Glucose
• SCIP
• Through COIN-OR Open
Solver Interface:
•
•
•
•
•
•
•
COIN-OR CBC
COIN-OR CLP
COIN-OR DyLP
COIN-OR SYMPHONY
COIN-OR Volume Algorithm
GNU LP Toolkit
Soplex
• . . . any CNF solver
Insight Centre for Data Analytics
September 8, 2014
Slide 5
Installation
Python Package Index (PyPI)
pip install Numberjack
Insight Centre for Data Analytics
September 8, 2014
Slide 6
Section 2
Modelling Constructs
Insight Centre for Data Analytics
September 8, 2014
Slide 7
Variables in Numberjack
Different Variable constructors
Constructor
Variable()
Variable(’x’)
Variable(N)
Variable(N, ’x’)
Variable(l,u)
Variable(l,u, ’x’)
Variable(list)
Variable(list, ’x’)
Insight Centre for Data Analytics
Description
Boolean variable
Boolean variable called ’x’
Variable in the domain of [0 . . . N − 1]
Variable in the domain of [0 . . . N − 1] called ’x’
Variable in the domain of [l . . . u]
Variable in the domain of [l . . . u] called ’x’
Variable with domain specified as a list
Variable with domain as a list called ’x’
September 8, 2014
Slide 8
More Variables in Numberjack
Similarily for arrays and matrices
Constructor
VarArray(N)
VarArray(N, u)
VarArray(N, l, u)
..
.
Description
Array of N Boolean variables
Array of N variables with domains [0 . . . u − 1]
Array of N variables with domains [l . . . u]
Matrix(N, M)
Matrix(N, M, u)
Matrix(N, M, l, u)
N × M matrix of Boolean variables
N × M matrix of variables with domains [0 . . . u − 1]
N × M matrix of variables with domains [l . . . u]
Insight Centre for Data Analytics
September 8, 2014
Slide 9
Concise Models
VarArray and Matrix allow for concise modelling.
Slices
Given a 9 × 9 Sudoku matrix, we
could get a 3 × 3 cell:
AllDiff( matrix[x:x+3, y:y+3] )
Rows and Columns
for row in matrix.row:
m += AllDiff(row)
for col in matrix.col:
m += AllDiff(col)
Insight Centre for Data Analytics
September 8, 2014
Slide 10
Constraints in Numberjack
Constraints can be specified in a number of ways
Simply by arithmetic operators on variables:
x
y
x
x
> y
<= z
!= z
+ y == z
Insight Centre for Data Analytics
x + 4 > z * 3
z == (x < y)
z <= (x < y)
(x == y) != (a == b)
September 8, 2014
Slide 11
Global Constraints
v == Max([x,y,z])
Disjunction([x < y, y > z, a != b])
AllDiff([x,y,z])
Sum([a,b,c,d]) >= e
Sum([a,b,c,d], [2, 1, 0.5, 3]) == e # Weighted Sum
Sum([2∗a, b, 0.5∗c, 3∗d]) == e # Weighted Sum
LessLex(VarArray(5, 5), VarArray(5, 5))
LeqLex(VarArray(5, 5), VarArray(5, 5))
Gcc(VarArray(4, 1, 5), {1: [1, 3], 2: [1, 2]})
Element(VarArray(10, 1, 10), Variable(10))
myarray[myvariable] # Element
Minimize(2∗x + 3∗y)
Maximize(objective)
PostUnary, PostBinary, PostNary, ... # Cost functions
Insight Centre for Data Analytics
September 8, 2014
Slide 12
Custom Constraints
Easy to define your own custom constraints for modelling purposes
and add custom decompositions for solvers which don’t support it.
Example
class MyAllDiff(Expression):
def decompose(self):
return [var1 != var2 for var1, var2 in pair_of(self.children)]
class NoOverlap(Predicate):
def decompose(self):
task_i, task_j = self.children
return [((task_i + task_i.duration) <= task_j) |
((task_j + task_j.duration) <= task_i)]
Insight Centre for Data Analytics
September 8, 2014
Slide 13
Custom Decompositions
Override the default decomposition
simply by defining your own method:
Example
def decompose_AllDiff(self):
return [var1 != var2 for var1, var2 in pair_of(self.children)]
Insight Centre for Data Analytics
September 8, 2014
Slide 14
Section 3
solve() and friends
Insight Centre for Data Analytics
September 8, 2014
Slide 15
One Model, Many Solvers
Constraint Solvers
mistral = model.load("Mistral")
toulbar = model.load("Toulbar2")
MIP Solvers
gurobi = model.load("Gurobi")
cplex = model.load("CPLEX")
SAT Solvers
minisat = model.load("MiniSat")
walksat = model.load("Walksat")
lingeling = model.load("Lingeling")
Insight Centre for Data Analytics
September 8, 2014
Slide 16
Customizable SAT Encoding
Change the default encoding globally
model.load(solver, encoding=...)
direct
support
p cnf
1 2 3
-1 -2
-1 -3
-2 -3
4 5 6
-4 -5
-4 -6
-5 -6
7 8 9
-7 -8
-7 -9
-8 -9
-1 -4
-2 -5
-3 -6
-1 -7
-2 -8
-3 -9
-4 -7
-5 -8
-6 -9
p cnf 9 30
1 2 3 0
-1 -2 0
-1 -3 0
-2 -3 0
4 5 6 0
-4 -5 0
-4 -6 0
-5 -6 0
7 8 9 0
-7 -8 0
-7 -9 0
-8 -9 0
5 6 -1 0
4 6 -2 0
4 5 -3 0
2 3 -4 0
1 3 -5 0
1 2 -6 0
8 9 -1 0
7 9 -2 0
...
9 21
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Insight Centre for Data Analytics
order
regular
p cnf 6 12
-1 2 0
-3 4 0
-5 6 0
-1 -3 0
1 3 -2 -4 0
2 4 0
-1 -5 0
1 5 -2 -6 0
2 6 0
-3 -5 0
3 5 -4 -6 0
4 6 0
p cnf 15 27
1 2 3 0
-4 5 0
-1 4 0
-2 -4 0
-2 5 0
-3 -5 0
6 7 8 0
-9 10 0
-6 9 0
-7 -9 0
-7 10 0
-8 -10 0
11 12 13 0
-14 15 0
-11 14 0
-12 -14 0
-12 15 0
-13 -15 0
-1 -6 0
-2 -7 0
...
September 8, 2014
Slide 17
Customizable SAT Encoding
Pure direct/sparse domain encoding
x = Variable(3)
x.encoding = EncodingConfiguration(direct=True, order=False)
x0 ∨ x1 ∨ x2
¬x0 ∨ ¬x1
¬x0 ∨ ¬x2
¬x1 ∨ ¬x2
Regular domain encoding
y0 ∨ y1 ∨ y 2
¬y≤0 ∨ y≤1
y = Variable(3)
y.encoding = EncodingConfiguration(direct=True, order=True)
¬y0 ∨ y≤0
¬y1 ∨ ¬y≤0
¬y1 ∨ y≤1
¬y2 ∨ ¬y≤1
Full regular domain encoding
z = Variable(3)
z.encoding = EncodingConfiguration(direct=False, order=True)
Insight Centre for Data Analytics
¬z≤0 ∨ z≤1
September 8, 2014
Slide 18
Customizable SAT Encoding
Per constraint
neq.encoding = EncodingConfiguration(
conflict=False, support=True, order=False)
¬x0 ∨ y1 ∨ y2
¬x1 ∨ y0 ∨ y2
¬x2 ∨ y0 ∨ y1
...
Multiple encodings
con = AllDiff(variables)
con.encoding = EncodingConfiguration(alldiff_encoding=
AllDiffEncoding.PairwiseDecomp |
AllDiffEncoding.LadderAMO |
AllDiffEncoding.PigeonHole)
Named presets
con.encoding = NJEncodings[’pairwise_ladder_pigeon’]
Insight Centre for Data Analytics
September 8, 2014
Slide 19
Configuring the Solver
# Search strategies (solver specific)
mistral.setHeuristic("DomainOverWDegree", "Lex")
mistral.setHeuristic("Impact")
# Set Limits
solver.setTimeLimit(60) # Seconds
solver.setNodeLimit(1000000)
# Solve
solver.solve()
# Solve using custom restart parameters
mistral.solveAndRestart(GEOMETRIC, 64, 1.3)
mistral.solveAndRestart(LUBY, 1000)
# Find all solutions
solver.getNextSolution()
# Feasibility?
solver.is_sat()
solver.is_opt()
solver.is_unsat()
Insight Centre for Data Analytics
September 8, 2014
Slide 20
Custom Search: Full binary DFS
solver.startNewSearch()
while not proven_infeasibility:
if solver.propagate(): # left branch
x = variableselection(variables)
if x is None:
# Complete, no more variables to assign
return solver.get_solution()
v = x.get_min()
solver.save()
solver.post(x == v)
else: # right branch
proven_infeasibility = not solver.undo()
if not proven_infeasibility:
# Invert the previous decision, i.e. x != v
solver.deduce()
Insight Centre for Data Analytics
September 8, 2014
Slide 21
Model Output
Output LP model
cplex = model.load("CPLEX")
cplex.output_lp("mymodel.lp")
Output MPS model
gurobi = model.load("Gurobi")
gurobi.output_mps("mymodel.mps")
Output CNF model
minisat = model.load("MiniSat")
minisat.output_cnf("mymodel.cnf")
Insight Centre for Data Analytics
September 8, 2014
Slide 22
External Input Formats
XCSP
from Numberjack.XCSP import XCSPParser
parser = XCSPParser(filename)
model, variables = parser.model, parser.variables
mzn/fzn
# Just run Numberjack solvers directly
mzn_numberjack model.mzn data.dzn
fzn_numberjack flattened.fzn
# Translate to a Numberjack/Python file
mzn2py model.mzn data.dzn > model.py
Other custom parsers are easy in Python
cnf, pls, uai, . . .
Insight Centre for Data Analytics
‘import antigravity’
September 8, 2014
Slide 23
Section 4
Example Application and Demos
Insight Centre for Data Analytics
September 8, 2014
Slide 24
Optical Network Design
Insight Centre for Data Analytics
September 8, 2014
Slide 25
Demo: Map Colouring
Insight Centre for Data Analytics
September 8, 2014
Slide 26
Demo: Controlling Search
Demo: controlling search
Insight Centre for Data Analytics
September 8, 2014
Slide 27
Summary
What is Numberjack?
•
•
•
•
•
•
A Python platform for combinatorial optimization
Common platform for diverse paradigms (CP, SAT, MIP)
Practical, easy to use, and intuitive
Highly customizable encodings
Fast backend solvers
Open source (Github, LGPL)
http://numberjack.ucc.ie
Insight Centre for Data Analytics
September 8, 2014
Slide 28
Acknowledgements
This work is supported by Science Foundation Ireland (SFI) Grant
10/IN.1/I3032 and FP7 FET-Open Grant 284715.
The Insight Centre for Data Analytics is supported by SFI Grant
SFI/12/RC/2289.
Insight Centre for Data Analytics
September 8, 2014
Slide 29
Download