Global Functions (cpmpy.expressions.globalfunctions)

Global functions conveniently express numerical global constraints in function form.

For example cp.Maximum(iv1, iv2, iv3) == iv4, or cp.Abs(iv1) > iv2 or m.minimize(cp.Count(IVS, 0)), or other nested numeric expressions.

Global functions are implemented as classes that inherit from GlobalFunction.

Solver perspective

  • Native support: some solvers natively support the function form of global functions,

such as other CP languages, SMT solvers, Cplex, Hexaly etc.

  • Predicate form: CP solvers and MINLP solvers only support the predicate form of global functions.

For example, cp.Maximum(iv1, iv2, iv3) == iv4 has to be posted to the solver API as addMaximumEquals([iv1,iv2,iv3], iv4), and expressions like cp.Abs(iv1) > iv2 have to be flattened and posted as addAbsEquals(iv1, aux) and aux > iv2. This is automatically done by the flattening transformation in the flatten_model transformation.

  • Decomposition: if a solver does not support a global function, then it will be automatically

decomposed by the decompose_in_tree() transformation, which will call its decompose() method.

The .decompose() function returns two arguments:
  1. A single CPMpy expression representing the numerical value of the global function,

    this is often an auxiliary variable, a sum of auxiliary variables or a sum over nested expressions.

  2. If the decomposition introduces new auxiliary variables, then the second argument

    has to be a list of constraints that (totally) define those new variables.

To make maximum use of simplification and common subexpression elimination, we recommend that decompositions

use nested expression as much as possible and avoid creating auxiliary variables unless not expressible in a more direct way.

Example:

class MySum(GlobalFunction):
    def __init__(self, args):
        assert len(args) == 2, "MySum takes 2 arguments"
        super().__init__("my_sum", args)

    def decompose(self):
        return (self.args[0] + self.args[1]), []  # the decomposition

List of classes

Minimum

Computes the minimum value of the arguments

Maximum

Computes the maximum value of the arguments

Abs

Computes the absolute value of the argument

Division

Computes the integer division of the arguments, rounding towards zero: int(x/y)

Modulo

Computes the modulo of the arguments, the remainder with integer division (rounding towards zero): x - (y * (x div y))

Power

Computes the power of the arguments, the base raised to the exponent: base ** exponent

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.

class cpmpy.expressions.globalfunctions.Abs(expr: Expression)[source]

Computes the absolute value of the argument

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of Abs global function.

Can only be decomposed by introducing an auxiliary variable and enforcing its value to be positive,

based on the value of the given argument to the global function. I.e., if the argument is negative, the auxiliary variable will take the negated value of the argument, and otherwise it will take the argument itself.

Returns:

A tuple containing the expression representing the absolute value (may be the argument itself, its negation, or an auxiliary variable), and a list of constraints defining it (empty if no auxiliary variable is needed)

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the lowest and highest possible absolute value

Returns:

A tuple of (lower bound, upper bound) for the absolute value

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The absolute value of the argument, or None if the argument is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.Among(arr: list[Expression], vals: list[int])[source]

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

This is similar to Count, but instead of counting occurrences of a single value, it counts occurrences of any value in a set. For example, Among([x1, x2, x3, x4], [1, 2]) returns the number of variables among x1, x2, x3, x4 that take the value 1 or 2.

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of the Among global function.

Among is decomposed into a sum of Count global functions, one for each value in the set. For example, Among(arr, [1, 2, 3]) is decomposed as Count(arr, 1) + Count(arr, 2) + Count(arr, 3).

Returns:

A tuple containing the sum expression representing the total number of occurrences, and an empty list of constraints (no auxiliary variables needed)

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the bounds of the global function

Returns:

A tuple of (lower bound, upper bound) for the among count value

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The number of variables in arr that take a value present in vals, or None if any element in arr is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.Count(arr: list[Expression], val: int | Expression)[source]

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

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of the Count global function.

Does not require the use of auxiliary variables, simply count the number of variables that take the given value.

Returns:

A tuple containing the sum expression representing the count, and an empty list of constraints (no auxiliary variables needed)

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the bounds of the global function

Returns:

A tuple of (lower bound, upper bound) for the count value

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The number of occurrences of val in arr, or None if val or any element in arr is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.Division(x: Expression, y: Expression)[source]

Computes the integer division of the arguments, rounding towards zero: int(x/y)

Warning: this is different from the Python’s floor division operator //, which floors the result: floor(x/y)

The difference exposes itself with negative numbers: -7/3 = -2.333..;
  • integer division (ours): -7 div 3 = int(-7/3) = -2 (truncation)

  • floor division (Python): -7 // 3 = math.floor(-7/3) = -3

property args
decompose()[source]

Decomposition of Integer Division global function, rounding towards zero.

x div y = q implemented as x = y * q + r with r the remainder and |r| < |y| r can be positive or negative, so also ensure that |y| * |q| <= |x|

Returns:

A tuple containing the auxiliary variable representing the integer division, and a list of constraints defining it

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds()[source]

Returns the bounds of the Division global function

Returns:

A tuple of (lower bound, upper bound) for the integer division

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value()[source]
Returns:

The integer division of the arguments, or None if the arguments are not assigned

Return type:

int

class cpmpy.expressions.globalfunctions.Element(arr: list[int | Expression], idx: Expression)[source]

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

Its return value will be the value of the array element at the index specified by the decision variable’s value.

When you index into a NDVarArray (e.g. when creating a Arr=boolvar(shape=…) or Arr=intvar(lb,ub, shape=…) using boolvar() or intvar()), or index into a list wrapped as Arr = cpm_array(lst) using cpm_array(), then using standard Python indexing, e.g. Arr[Idx] with Idx an integer decision variable, will automatically create this Element(Arr, Idx) object.

Note: because Element is a numeric global function, the return type of the Element function is always numeric, even if Arr only contains Boolean variables.

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of Element global function.

The index variable must be within the bounds of the array.

This decomposition uses an auxiliary variable and implication constraints.

Returns:

A tuple containing the auxiliary variable representing the element value, and a list of constraints defining it

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

decompose_linear() tuple[Expression, list[Expression]][source]

Decomposition of Element global function.

The index variable must be within the bounds of the array.

This decomposition uses a weighted sum over the array elements times Boolean indicator for the index.

Returns:

A tuple containing the expression representing the element value, and an empty list of constraints (no auxiliary variables needed)

Return type:

tuple[Expression, list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the bounds of the global function

Returns:

A tuple of (lower bound, upper bound) for the element value

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The value of the array element at the given index, or None if the index is not assigned or the array element is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.GlobalFunction(name, arg_list)[source]

Abstract superclass of GlobalFunction

Like all expressions it has a .name and .args property. It overwrites the is_bool() method to return False, as global functions are numeric.

property args
decompose() tuple[Expression, list[Expression]][source]

Returns a decomposition into smaller constraints as a tuple of (numerical expression, list of constraints defining auxiliary variables)

The first one will replace the GlobalFunction expression in-place, the second one will be added to the list of top-level constraints.

The decomposition might create auxiliary variables and use other global constraints as long as it does not create a circular dependency.

Returns:

A tuple containing the numerical expression and a list of constraints defining auxiliary variables

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]][source]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the bounds of the global function

Returns:

A tuple of (lower bound, upper bound)

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool[source]
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool[source]

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value()
class cpmpy.expressions.globalfunctions.Maximum(arg_list: list[Expression])[source]

Computes the maximum value of the arguments

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of Maximum global function.

Can only be decomposed by introducing an auxiliary variable and enforcing it to be larger or equal than each variable, while at the same time not being larger than all (e.g. it needs to be (smaller or) equal to one of them)

Returns:

A tuple containing the auxiliary variable representing the maximum value, and a list of constraints defining it

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the lowest and highest possible maximum value

Returns:

A tuple of (lower bound, upper bound) for the maximum value

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The maximum value of the arguments, or None if any argument is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.Minimum(arg_list: list[Expression])[source]

Computes the minimum value of the arguments

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of Minimum global function.

Can only be decomposed by introducing an auxiliary variable and enforcing it to be smaller or equal than each variable, while at the same time not being smaller than all (e.g. it needs to be (larger or) equal to one of them)

Returns:

A tuple containing the auxiliary variable representing the minimum value, and a list of constraints defining it

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the lowest and highest possible minimum value

Returns:

A tuple of (lower bound, upper bound) for the minimum value

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The minimum value of the arguments, or None if any argument is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.Modulo(x, y)[source]

Computes the modulo of the arguments, the remainder with integer division (rounding towards zero): x - (y * (x div y))

Warning: this is different from the Python’s modulo operator %, which gives the remainder of the float division x / y

There is also a difference in sign when using negative numbers:
  • modulo (ours): 7 mod -5 = 2 because 7 div -5 = -1 and 7 - (-5*-1) = 2. Note how the sign of x is preserved.

  • modulo (Python): 7 % -5 = -3 because 7 // -5 = -2 and 7 - (-5*-2) = -3. Note how the sign of y is preserved.

property args
decompose()[source]

Decomposition of Modulo global function, using integer division (rounding towards zero)

Decomposes x mod y = z as x = k * y + z with |z| < |y| and sign(x) = sign(z) https://en.wikipedia.org/wiki/Modulo https://marcelkliemannel.com/articles/2021/dont-confuse-integer-division-with-floor-division/

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds()[source]

Returns the bounds of the Modulo global function

Returns:

A tuple of (lower bound, upper bound) for the modulo

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value()[source]
Returns:

The modulo of the arguments, or None if the arguments are not assigned

Return type:

int

class cpmpy.expressions.globalfunctions.NValue(arr: list[Expression])[source]

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

For example, if variables [x1, x2, x3, x4] take values [1, 2, 1, 3] respectively, then NValue([x1, x2, x3, x4]) returns 3 (the distinct values are 1, 2, and 3).

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of the NValue global function.

NValue is decomposed by checking, for each possible value in the domain range, whether at least one variable takes that value. The sum of these Boolean checks gives the number of distinct values.

Based on “simple decomposition” from:

Bessiere, Christian, et al. “Decomposition of the NValue constraint.” International Conference on Principles and Practice of Constraint Programming. Berlin, Heidelberg: Springer Berlin Heidelberg, 2010.

Returns:

A tuple containing the sum expression representing the number of distinct values, and an empty list of constraints (no auxiliary variables needed)

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the bounds of the global function

Returns:

A tuple of (lower bound, upper bound) for the number of distinct values

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The number of distinct values in the array, or None if any element in arr is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.NValueExcept(arr: list[Expression], n: int)[source]

The NValueExcept global function counts the number of distinct values in an array, excluding a specified value.

For example, if variables [x1, x2, x3, x4] take values [1, 2, 1, 0] respectively, then NValueExcept([x1, x2, x3, x4], 0) returns 2 (the distinct values are 1 and 2, excluding 0).

property args
decompose() tuple[Expression, list[Expression]][source]

Decomposition of the NValueExcept global function.

NValueExcept is decomposed similarly to NValue, by checking for each possible value in the domain range (except the excluded value n) whether at least one variable takes that value, and counting for how many values that was the case.

Returns:

A tuple containing the sum expression representing the number of distinct values (excluding n), and an empty list of constraints (no auxiliary variables needed)

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds() tuple[int, int][source]

Returns the bounds of the global function

Returns:

A tuple of (lower bound, upper bound) for the number of distinct values (excluding n)

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value() int | None[source]
Returns:

The number of distinct values in the array, excluding value n, or None if any element in arr is not assigned

Return type:

Optional[int]

class cpmpy.expressions.globalfunctions.Power(base: Expression, exponent: int)[source]

Computes the power of the arguments, the base raised to the exponent: base ** exponent

Only non-negative constant integer exponents are supported.

property args
decompose()[source]

Decomposition of Power global function, using integer multiplication.

Decomposes base ** exp = _pow as _pow = base * base * … * base (exp times)

Returns:

A tuple containing the auxiliary variable representing the power, and a list of constraints defining it

Return type:

tuple[Expression, list[Expression]]

decompose_comparison(cmp_op: str, cmp_rhs: Expression) tuple[list[Expression], list[Expression]]

DEPRECATED: returns a list of constraints representing the decomposed comparison of the global function (and any auxiliary variables introduced).

Parameters:
  • cmp_op (str) – Comparison operator

  • cmp_rhs (Expression) – Right-hand side expression for the comparison

Returns:

A tuple containing two lists: constraints representing the comparison, and constraints defining auxiliary variables

Return type:

tuple[list[Expression], list[Expression]]

deepcopy(memodict={})
get_bounds()[source]

Returns the bounds of the Power global function

Returns:

A tuple of (lower bound, upper bound) for the power

Return type:

tuple[int, int]

has_subexpr()

Does it contains nested Expressions (anything other than a _NumVarImpl or a constant)? Is of importance when deciding whether certain transformations are needed along particular paths of the expression tree. Results are cached for future calls and reset when the expression changes (in-place argument update).

implies(other)
is_bool() bool
Returns:

False, global functions are numeric

Return type:

bool

is_total() bool

Returns whether it is a total function. If true, its value is defined for all arguments

TODO: I do not find anywhere where we set it dynamically to False? TODO: REMOVE??

set_description(txt, override_print=True, full_print=False)
update_args(args)

Allows in-place update of the expression’s arguments. Resets all cached computations which depend on the expression tree.

value()[source]
Returns:

The power of the arguments, or None if the arguments are not assigned

Return type:

int

cpmpy.expressions.globalfunctions.element(arg_list: list[Expression]) Element[source]

DEPRECATED: Use Element(arr,idx) instead of element([arr,idx]).

Parameters:

arg_list (list[Expression]) – List containing array and index (2 elements)

Returns:

An Element global function instance

Return type:

Element