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' global constraint enforces that the result equals Arr[Idx] with 'Arr' an array of constants or variables (the first argument) and 'Idx' an integer decision variable, representing the index into the array.

Count

The Count (numerical) global constraint represents the number of occurrences of val in arr

Among

The Among (numerical) global constraint represents the number of variable that take values among the values in arr

NValue

The NValue constraint counts the number of distinct values in a given set of variables.

NValueExcept

The NValueExceptN constraint counts the number of distinct values,

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

All arguments have a different (distinct) value

AllDifferentExcept0

All nonzero arguments have a distinct value

AllDifferentExceptN

All arguments except those equal to a value in n have a distinct value.

AllEqual

All arguments have the same value

AllEqualExceptN

All arguments except those equal to a value in n have the same value.

Circuit

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

Inverse

Inverse (aka channeling / assignment) constraint.

Table

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

The IfThenElse constraint, defining a conditional expression of the form: if condition then if_true else if_false where condition, if_true and if_false are all boolean expressions.

InDomain

The "InDomain" constraint, defining non-interval domains for an expression

Xor

The Xor exclusive-or constraint

Cumulative

Global cumulative constraint.

Precedence

Constraint enforcing some values have precedence over others.

NoOverlap

NoOverlap constraint, enforcing that the intervals defined by start, duration and end do not overlap.

GlobalCardinalityCount

The number of occurrences of each value vals[i] in the list of variables vars must be equal to occ[i].

Increasing

The "Increasing" constraint, the expressions will have increasing (not strictly) values

Decreasing

The "Decreasing" constraint, the expressions will have decreasing (not strictly) values

IncreasingStrict

The "IncreasingStrict" constraint, the expressions will have increasing (strictly) values

DecreasingStrict

The "DecreasingStrict" constraint, the expressions will have decreasing (strictly) values

LexLess

Given lists X,Y, enforcing that X is lexicographically less than Y.

LexLessEq

Given lists X,Y, enforcing that X is lexicographically less than Y (or equal).

LexChainLess

Given a matrix X, LexChainLess enforces that all rows are lexicographically ordered.

LexChainLessEq

Given a matrix X, LexChainLessEq enforces that all rows are lexicographically ordered.

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