picos.expressions.expression

Backend for expression type implementations.

Outline

Classes

Expression

Abstract base class for mathematical expressions, including mutables.

ExpressionType

The detailed type of an expression for predicting constraint outcomes.

Functions

refine_operands

Cast refined on both operands.

validate_prediction

Validate that the constraint outcome matches the predicted outcome.

Exceptions

NotValued

The operation cannot be performed due to a mutable without a value.

PredictedFailure

Denotes that comparing two expressions will not form a constraint.

Classes

Expression

class picos.expressions.expression.Expression(typeStr, symbStr)[source]

Bases: abc.ABC

Abstract base class for mathematical expressions, including mutables.

For mutables, this is the secondary base class, with Mutable or a subclass thereof being the primary one.

__init__(typeStr, symbStr)[source]

Perform basic initialization for Expression instances.

Parameters
  • typeStr (str) – Short string denoting the expression type.

  • symbStr (str) – Algebraic string description of the expression.

frozen(subset=None)[source]

The expression with valued mutables frozen to their current value.

If all mutables of the expression are valued (and in the subset unless subset=None), this is the same as the inversion operation ~.

If the mutables to be frozen do not appear in the expression, then the expression is not copied but returned as is.

Parameters

subset – An iterable of valued mutables or names thereof that should be frozen. If None, then all valued mutables are frozen to their current value. May include mutables that are not present in the expression, but may not include mutables without a value.

Returns Expression

The frozen expression, refined to a more suitable type if possible.

Example

>>> from picos import RealVariable
>>> x, y = RealVariable("x"), RealVariable("y")
>>> f = x + y; f
<1×1 Real Linear Expression: x + y>
>>> sorted(f.mutables, key=lambda mtb: mtb.name)
[<1×1 Real Variable: x>, <1×1 Real Variable: y>]
>>> x.value = 5
>>> g = f.frozen(); g  # g is f with x frozen at its current value of 5.
<1×1 Real Affine Expression: [x] + y>
>>> sorted(g.mutables, key=lambda mtb: mtb.name)
[<1×1 Real Variable: y>]
>>> x.value, y.value = 10, 10
>>> f.value  # x takes its new value in f.
20.0
>>> g.value  # x remains frozen at [x] = 5 in g.
15.0
>>> # If an expression is frozen to a constant, this is reversable:
>>> f.frozen().equals(~f) and ~f.frozen() is f
True
is_valued()[source]

Whether the expression is valued.

Deprecated since version 2.0: Use valued instead.

classmethod make_type(*args, **kwargs)[source]

Create a detailed expression type from subtype parameters.

replace_mutables(replacement)[source]

Return a copy of the expression concerning different mutables.

New mutables must have the same shape and vectorization format as the mutables that they replace. This means in particular that RealVariable, IntegerVariable and BinaryVariable of same shape are interchangeable.

If the mutables to be replaced do not appear in the expression, then the expression is not copied but returned as is.

Parameters

replacement (tuple or list or dict) – Either a map from mutables or mutable names to new mutables or an iterable of new mutables to replace existing mutables of same name with. See the section on advanced usage for additional options.

Returns Expression

The new expression, refined to a more suitable type if possible.

Advanced replacement

It is also possible to replace mutables with real affine expressions concerning pairwise disjoint sets of fresh mutables. This works only on real-valued mutables that have a trivial internal vectorization format (i.e. FullVectorization). The shape of the replacing expression must match the variable’s. Additional limitations depending on the type of expression that the replacement is invoked on are possible. The replacement argument must be a dictionary.

Example

>>> import picos
>>> x = picos.RealVariable("x"); x.value = 1
>>> y = picos.RealVariable("y"); y.value = 10
>>> z = picos.RealVariable("z"); z.value = 100
>>> c = picos.Constant("c", 1000)
>>> a = x + 2*y; a
<1×1 Real Linear Expression: x + 2·y>
>>> a.value
21.0
>>> b = a.replace_mutables({y: z}); b  # Replace y with z.
<1×1 Real Linear Expression: x + 2·z>
>>> b.value
201.0
>>> d = a.replace_mutables({x: 2*x + z, y: c}); d  # Advanced use.
<1×1 Real Affine Expression: 2·x + z + 2·c>
>>> d.value
2102.0
set_value(value)[source]

Set the value of an expression.

Deprecated since version 2.0: Use value instead.

property certain

Always True for certain expression types.

This can be False for Expression types that inherit from UncertainExpression (with priority).

property concave

Whether the expression is concave.

property constant

Whether the expression involves no mutables.

property convex

Whether the expression is convex.

property mutables

Return the set of mutables that are involved in the expression.

property parameters

The set of parameters that are involved in the expression.

property refined

A refined version of the expression.

The refined expression can be an instance of a different Expression subclass than the original expression, if that type is better suited for the mathematical object in question.

The refined expression is automatically used instead of the original one whenever a constraint is created, and in some other places.

The idea behind refined expressions is that operations that produce new expressions can be executed quickly without checking for exceptionnel cases. For instance, the sum of two ComplexAffineExpression instances could have the complex part eliminated so that storing the result as an AffineExpression would be prefered, but checking for this case on every addition would be too slow. Refinement is used sparingly to detect such cases at times where it makes the most sense.

property safe_value

Value of the expression, if defined.

Refer to value for when it is defined.

Returns

The value as a Python scalar or CVXOPT matrix.

Raises

NotValued – If the value is not defined.

Distinction

  • Unlike value, an undefined value raises an exception.

  • Like value, scalars are returned as scalar types.

property safe_value_as_matrix

Value of the expression as a CVXOPT matrix type, if defined.

Refer to value for when it is defined.

Returns

The value as a CVXOPT matrix.

Raises

NotValued – If the value is not defined.

Distinction

  • Unlike value, an undefined value raises an exception.

  • Unlike value, scalars are returned as 1 \times 1 matrices.

property scalar

Whether the expression is scalar.

property shape

Return the algebraic shape of the expression.

property size

The same as shape.

property square

Whether the expression is a square matrix.

property string

Symbolic string representation of the expression.

Use this over Python’s str if you want to output the symbolic representation even when the expression is valued.

property subtype

The subtype part of the expression’s detailed type.

Returns a hashable object that, together with the Python class part of the expression’s type, is sufficient to predict the constraint outcome (constraint class and subtype) of any comparison operation with any other expression.

By convention the object returned is a namedtuple instance.

property type

The expression’s detailed type for constraint prediction.

The returned value is suffcient to predict the detailed type of any constraint that can be created by comparing with another expression.

Since constraints are created from refined expressions only, the Python class part of the detailed type may differ from the type of the expression whose type is queried.

property uncertain

Always False for certain expression types.

This can be True for Expression types that inherit from UncertainExpression (with priority).

property value

Value of the expression, or None.

It is defined if the expression is constant or if all mutables involved in the expression are valued. Mutables can be valued directly by writing to their value attribute. Variables are also valued by PICOS when an optimization solution is found.

Some expressions can also be valued directly if PICOS can find a minimal norm mutable assignment that makes the expression have the desired value. In particular, this works with affine expressions whose linear part has an under- or well-determined coefficient matrix.

Returns

The value as a Python scalar or CVXOPT matrix, or None if it is not defined.

Distinction

Example

>>> from picos import RealVariable
>>> x = RealVariable("x", (1,3))
>>> y = RealVariable("y", (1,3))
>>> e = x - 2*y + 3
>>> print("e:", e)
e: x - 2·y + [3]
>>> e.value = [4, 5, 6]
>>> print("e: ", e, "\nx: ", x, "\ny: ", y, sep = "")
e: [ 4.00e+00  5.00e+00  6.00e+00]
x: [ 2.00e-01  4.00e-01  6.00e-01]
y: [-4.00e-01 -8.00e-01 -1.20e+00]
property value_as_matrix

Value of the expression as a CVXOPT matrix type, or None.

Refer to value for when it is defined (not None).

Returns

The value as a CVXOPT matrix, or None if it is not defined.

Distinction

  • Like value, an undefined value is returned as None.

  • Unlike value, scalars are returned as 1 \times 1 matrices.

property valued

Whether the expression is valued.

Note

Querying this attribute is not faster than immediately querying value and checking whether it is None. Use it only if you do not need to know the value, but only whether it is available.

Example

>>> from picos import RealVariable
>>> x = RealVariable("x", 3)
>>> x.valued
False
>>> x.value
>>> print((x|1))
∑(x)
>>> x.value = [1, 2, 3]
>>> (x|1).valued
True
>>> print((x|1))
6.0
property variables

The set of decision variables that are involved in the expression.

ExpressionType

class picos.expressions.expression.ExpressionType(theClass, subtype)[source]

Bases: picos.containers.DetailedType

The detailed type of an expression for predicting constraint outcomes.

This is suffcient to predict the detailed type of any constraint that can be created by comparing with another expression.

predict(relation, other)[source]

Predict the constraint outcome of comparing expressions.

Parameters
  • relation – An object from the operator namespace representing the operation being predicted.

  • other (ExpressionType) – Another expression type representing the right hand side operand.

Example

>>> import operator, picos
>>> a = picos.RealVariable("x") + 1
>>> b = picos.RealVariable("y") + 2
>>> (a <= b).type == a.type.predict(operator.__le__, b.type)
True

Functions

refine_operands

picos.expressions.expression.refine_operands(stop_at_affine=False)[source]

Cast refined on both operands.

If the left hand side operand (i.e. self) is refined to an instance of a different type, then, instead of the decorated method, the method with the same name on the refined type is invoked with the (refined) right hand side operand as its argument.

This decorator is supposed to be used on all constraint creating binary operator methods so that degenerated instances (e.g. a complex affine expression with an imaginary part of zero) can occur but are not used in constraints. This speeds up many computations involving expressions as these degenerate cases do not need to be detected. Note that Expression.type also refers to the refined version of an expression.

Parameters

stop_at_affine (bool) – Do not refine any affine expressions, in particular do not refine complex affine expressions to real ones.

validate_prediction

picos.expressions.expression.validate_prediction(the_operator)[source]

Validate that the constraint outcome matches the predicted outcome.

Exceptions

NotValued

exception picos.expressions.expression.NotValued[source]

Bases: RuntimeError

The operation cannot be performed due to a mutable without a value.

Note that the value and value_as_matrix attributes do not raise this exception, but return None.

__init__(*args, **kwargs)

Initialize self. See help(type(self)) for accurate signature.

__new__(**kwargs)

Create and return a new object. See help(type) for accurate signature.

PredictedFailure

exception picos.expressions.expression.PredictedFailure[source]

Bases: TypeError

Denotes that comparing two expressions will not form a constraint.

__init__(*args, **kwargs)

Initialize self. See help(type(self)) for accurate signature.

__new__(**kwargs)

Create and return a new object. See help(type) for accurate signature.