Summary sheet

More extensive user documentation in Modeling and solving with CPMpy.

import cpmpy as cp

Model class

Solvers

Solvers have the same API as Model. Solvers are instantiated throught the static cp.SolverLookup class:

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.

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.

Minimum

Computes the minimum value of the arguments

Maximum

Computes the maximum value of the arguments

Abs

Computes the absolute value of the argument

Element

The Element(Arr, Idx) global function allows indexing into an array with a decision variable.

Count

The Count global function represents the number of occurrences of a value in an array

Among

The Among global function counts how many variables in an array take values that are in a given set of values.

NValue

The NValue global function counts the number of distinct values in an array.

NValueExcept

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.

AllDifferent

Enforces that all arguments have a different (distinct) value

AllDifferentExcept0

Enforces that all arguments, except those equal to 0, have a different (distinct) value.

AllDifferentExceptN

Enforces that all arguments, except those equal to a value in n, have a different (distinct) value.

AllEqual

Enforces that all arguments have the same value

AllEqualExceptN

Enforces that all arguments, except those equal to a value in n, have the same value.

Circuit

Enforces that the sequence of variables form a circuit, where x[i] = j means that node j is the successor of node i.

Inverse

Enforces that the forward and reverse arrays represent the inverse function of one another.

Table

Enforces that the values of the variables in 'array' correspond to a row in 'table'

ShortTable

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.

NegativeTable

The values of the variables in 'array' do not correspond to any row in 'table'

IfThenElse

Enforces a conditional expression of the form: if condition then if_true else if_false.

InDomain

Enforces the expression is assigned to a value in the given domain.

Xor

Enforces the exclusive-or relation of the arguments.

Cumulative

Enforces that a set of tasks is scheduled such that the capacity of the resource is never exceeded and enforces:

Precedence

Enforces a precedence relationship between a set of variables.

NoOverlap

Enforces that a set of tasks are scheduled without overlapping, and enforces:

GlobalCardinalityCount

Enforces that the number of occurrences of each value vals[i] in the list of variables vars is equal to occ[i].

Increasing

Enforces that the expressions are assigned to (non-strictly) increasing values.

Decreasing

Enforces that the expressions are assigned to (non-strictly) decreasing values.

IncreasingStrict

Enforces that the expressions are assigned to strictly increasing values.

DecreasingStrict

Enforces that the expressions are assigned to strictly decreasing values.

LexLess

Enforces that the first list is lexicographically smaller than the second list.

LexLessEq

Enforces that the first list is lexicographically smaller than or equal to the second list.

LexChainLess

Enforces that all rows of the matrix are lexicographically ordered.

LexChainLessEq

Enforces that all rows of the matrix are lexicographically ordered (less or equal)

DirectConstraint

A DirectConstraint will directly call a function of the underlying solver when added to a CPMpy solver

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.")