The search configuration API of or-tools expects a list.
decision_builder = slv.Phase(all_vars, ...)
But sometimes it's easier to store variables in a dictionary. E.g.
x = {(i,j): slv.IntVar(1, n) for i in range(n)
for j in range(n)}
You can "flatten" a dictionary using the values()
method:
decision_builder = slv.Phase(x.values(), ...)
values()
returns the list of values in the dictionaryMany functions that operate over collections (e.g. list comprehensions):
sum([2*i for i in range(n)])
min([2*i for i in range(n)])
...
...can work also with generator objects:
sum(2*i for i in range(n)) # no brackets, or just ()
print [i for i in range(3)] # [0, 1, 2]
print (i for i in range(3)) # <generator object...
A useful method for printing collections:
<string>.join(<string collection or generator object>)
', '.join(['two', 'strings']) # "two, strings"
'/'.join('%d' % i for i in range(4)) # 0/1/2/3
A useful (and important) distinction:
In the last lecture:
In this lecture:
We will store instance data using JSON
JSON is a format for data serialization
[item1, item2, ...]
{"key1":v1, "key2":v2, ...}
The root element in a JSON document is always a dictionary
Why JSON for our data?
Example:
{
"lectures": [
{ "num": 25, "long": false },
{ "num": 22, "long": false },
{ "num": 15, "long": true }
],
"rooms": [
{ "cap": 66 },
{ "cap": 58 }
]
}
How to read JSON data in python:
import json # import the "json" module
with open(fname) as f: # "f" = file object
data = json.load(f) # read and parse JSON data
open(fname)
returns a file objectwith
takes care of closing the file once the block is overSyntax:
with <func. call> as <name of returned obj>:
<block>
In or-tools, we can attach monitors to the search process:
slv.NewSearch(decision_builder, [m1, m2, ...])
A search monitor is an object that "does something" during search
E.g. search limits are essential, since we often solve NP-hard problems
In or-tools, we can attach monitors to the search process:
slv.NewSearch(decision_builder, [m1, m2, ...])
A search monitor is an object that "does something" during search
Two practical examples:
m1 = slv.SearchLog(num_branches)
m2 = slv.TimeLimit(time_limit)
Two important metrics for the performance of a CP approach:
Solution time:
In or-tools:
slv.WallTime()
Two important metrics for the performance of a CP approach:
Number of branches:
slv.Branches()
slv.Failures()
A number of lectures should be held in a number of rooms.
A number of lectures should be held in a number of rooms.
Build a (CP based) solution approach for the problem
lab02-timetabling.py
contains a template scriptpython lab02-timetabling.py <instance file>
tt-data
data-tt-debug.json
Use the following constraint library as reference:
+, -, *, /, abs...
==, !=, <, <=, >=, >
Try to:
Build a CP based solver for the popular Sudoku puzzle.
Build a CP based solver for the popular Sudoku puzzle.
lab02-sudoku.py
contains a template scriptpython lab02-sudoku.py <instance file>
sudoku-data
sudoku-easy-0.json
Use the following constraint library as reference:
+, -, *, /, abs...
==, !=, <, <=, >=, >
Then try to tackle the medium, hard, and "evil" instances
A number of chemicals must be stored in an array of tanks.
A number of chemicals must be stored in an array of tanks.
tmaxi<tminj
or tmaxj<tmini
i
and j
cannot stay in adjacent tanksBuild a (CP based) solution approach for the problem
lab02-tanks.py
contains a template scriptpython lab02-tanks.py <instance file>
tank-data
data-tanks-debug.json
Use the following constraint library as reference:
+, -, *, /, abs...
==, !=, <, <=, >=, >
Try to build the model incrementally