Summary sheet
More extensive user documentation in Modeling and solving with CPMpy.
import cpmpy as cp
Model class
model = cp.Model()– Create aModel.model += constraint– Add a constraint (anExpression) to the model.model.maximize(obj)ormodel.minimize(obj)– Set the objective (anExpression).model.solve()– Solve the model with the default solver, returns True/False.model.solveAll()– Solve and enumerate all solutions, returns number of solutions.model.status()– Get the status of the last solver run.model.objective_value()– Get the objective value obtained during the last solver run.
Solvers
Solvers have the same API as Model. Solvers are instantiated throught the static cp.SolverLookup class:
cp.SolverLookup.solvernames()– List all installed solvers (including subsolvers).cp.SolverLookup.get(solvername, model=None)– Initialize a specific solver.
Decision Variables
Decision variables are NumPy-like objects: shape=None|1 creates one variable, shape=4 creates a vector of 4 variables, shape=(2,3) creates a matrix of 2x3 variables, etc.
Name is optional too, indices are automatically added to the name so each variable has a unique name.
x = cp.boolvar(shape=4, name="x")– Create four Boolean decision variables.x = cp.intvar(lb, ub)– Create one integer decision variable with domain[lb, ub](inclusive).x.value()– Get the value ofxobtained during the last solver run.
Core Expressions
You can apply the following standard Python operators on CPMpy expressions, which creates the corresponding Core Expression object:
Comparison:
==,!=,<,<=,>,>=Arithmetic:
+,-,*,//(integer division),%(modulo),**(power)Logical:
&(and),|(or),~(not),^(xor)Logical implication:
x.implies(y)
Logical operators only work on Boolean variables/constraints, numeric operators work on both integer and Boolean variables/expressions.
CPMpy overwrites the following Python built-ins, they allow vectorized operations:
You can index CPMpy expressions with an integer decision variable: x[y], which will create an Element expression object.
To index non-CPMpy arrays, wrap them with cpm_array(): cpm_array([1,2,3])[y].
Global Functions
Global functions are numeric functions that some solvers support natively (through a solver-specific global constraint). CPMpy automatically rewrites the global function as needed to work with any solver.
Computes the minimum value of the arguments |
|
Computes the maximum value of the arguments |
|
Computes the absolute value of the argument |
|
The Element(Arr, Idx) global function allows indexing into an array with a decision variable. |
|
The Count global function represents the number of occurrences of a value in an array |
|
The Among global function counts how many variables in an array take values that are in a given set of values. |
|
The NValue global function counts the number of distinct values in an array. |
|
The NValueExcept global function counts the number of distinct values in an array, excluding a specified value. |
Global Constraints
Global constraints are constraints (Boolean functions) that some solvers support natively. All global constraints can be reified (implication, equivalence) and used in other expressions, which CPMpy will handle.
Enforces that all arguments have a different (distinct) value |
|
Enforces that all arguments, except those equal to 0, have a different (distinct) value. |
|
Enforces that all arguments, except those equal to a value in n, have a different (distinct) value. |
|
Enforces that all arguments have the same value |
|
Enforces that all arguments, except those equal to a value in n, have the same value. |
|
Enforces that the sequence of variables form a circuit, where x[i] = j means that node j is the successor of node i. |
|
Enforces that the forward and reverse arrays represent the inverse function of one another. |
|
Enforces that the values of the variables in 'array' correspond to a row in 'table' |
|
Extension of the Table constraint where the table matrix may contain wildcards (STAR), meaning there are no restrictions for the corresponding variable in that tuple. |
|
The values of the variables in 'array' do not correspond to any row in 'table' |
|
Enforces a conditional expression of the form: if condition then if_true else if_false. |
|
Enforces the expression is assigned to a value in the given domain. |
|
Enforces the exclusive-or relation of the arguments. |
|
Enforces that a set of tasks is scheduled such that the capacity of the resource is never exceeded and enforces: |
|
Enforces a precedence relationship between a set of variables. |
|
Enforces that a set of tasks are scheduled without overlapping, and enforces: |
|
Enforces that the number of occurrences of each value vals[i] in the list of variables vars is equal to occ[i]. |
|
Enforces that the expressions are assigned to (non-strictly) increasing values. |
|
Enforces that the expressions are assigned to (non-strictly) decreasing values. |
|
Enforces that the expressions are assigned to strictly increasing values. |
|
Enforces that the expressions are assigned to strictly decreasing values. |
|
Enforces that the first list is lexicographically smaller than the second list. |
|
Enforces that the first list is lexicographically smaller than or equal to the second list. |
|
Enforces that all rows of the matrix are lexicographically ordered. |
|
Enforces that all rows of the matrix are lexicographically ordered (less or equal) |
|
A |
Guidelines and tips
Do not
from cpmpy import *, the implicit overloading of any/all and sum may break or slow down other libraries.Explicitly use CPMpy versions of built-in functions (
cp.sum,cp.all, etc.).Use global constraints/global functions where possible, some solvers will be much faster.
Stick to integer constants; floats and fractional numbers are not supported.
For maintainability, use logical code organization and comments to explain your constraints.
Toy example
import cpmpy as cp
# Decision Variables
b = cp.boolvar()
x1, x2, x3 = x = cp.intvar(1, 10, shape=3)
# Constraints
model = cp.Model()
model += (x[0] == 1)
model += cp.AllDifferent(x)
model += cp.Count(x, 9) == 1
model += b.implies(x[1] + x[2] > 5)
# Objective
model.maximize(cp.sum(x) + 100 * b)
# Solving
solved = model.solve()
if solved:
print("Solution found:")
print('b:', b.value(), ' x:', x.value().tolist())
else:
print("No solution found.")