picos.expressions.exp_affine¶
Implements affine expression types.
Outline¶
Classes¶
A multidimensional real affine expression. 

A multidimensional complex affine expression. 
Classes¶
AffineExpression¶

class
picos.expressions.exp_affine.
AffineExpression
(string, shape=1, 1, coefficients={}, constant=0j)[source]¶ Bases:
picos.expressions.exp_affine.ComplexAffineExpression
A multidimensional real affine expression.

property
H
¶ The regular transpose of the
AffineExpression
.

property
conj
¶ The
AffineExpression
as is.

property
exp
¶ The exponential function applied to the expression.

property
imag
¶ A zero of same shape as the
AffineExpression
.

property
isreal
¶ Always true for
AffineExpression
instances.

property
log
¶ The Logarithm of the expression.

property
real
¶ The
AffineExpression
as is.

property
ComplexAffineExpression¶

class
picos.expressions.exp_affine.
ComplexAffineExpression
(string, shape=1, 1, coefficients={}, constant=0j)[source]¶ Bases:
picos.expressions.expression.Expression
A multidimensional complex affine expression.
Base class for the real
AffineExpression
.
Htranspose
()[source]¶ Return the conjugate (or Hermitian) transpose.
Deprecated since version 2.0: Use
H
instead.

__init__
(string, shape=1, 1, coefficients={}, constant=0j)[source]¶ Initialize a (complex) affine expression.
This constructor is meant for internal use. As a user, you will most likely want to build expressions starting from
variables
or aConstant
. Parameters
Warning
If the given coefficients and constant are already of the desired (numeric) type and shape, they are stored by reference. Modifying such data can lead to unexpected results as PICOS expressions are supposed to be immutable (to allow caching of results).
If you create affine expressions by any other means than this constructor, PICOS makes a copy of your data to prevent future modifications to it from causing inconsistencies.

broadcasted
(shape)[source]¶ Return the expression broadcasted to the given shape.
 Example
>>> from picos import Constant >>> C = Constant("C", range(6), (2, 3)) >>> print(C) [ 0.00e+00 2.00e+00 4.00e+00] [ 1.00e+00 3.00e+00 5.00e+00] >>> print(C.broadcasted((6, 6))) [ 0.00e+00 2.00e+00 4.00e+00 0.00e+00 2.00e+00 4.00e+00] [ 1.00e+00 3.00e+00 5.00e+00 1.00e+00 3.00e+00 5.00e+00] [ 0.00e+00 2.00e+00 4.00e+00 0.00e+00 2.00e+00 4.00e+00] [ 1.00e+00 3.00e+00 5.00e+00 1.00e+00 3.00e+00 5.00e+00] [ 0.00e+00 2.00e+00 4.00e+00 0.00e+00 2.00e+00 4.00e+00] [ 1.00e+00 3.00e+00 5.00e+00 1.00e+00 3.00e+00 5.00e+00]

copy
()[source]¶ Return a deep copy of the expression.
Deprecated since version 2.0: PICOS expressions are now immutable.

dupdiag
(n)[source]¶ Return a matrix with the (repeated) expression on the diagonal.
Vectorization is performed in columnmajor order.
 Parameters
n (int) – Number of times to duplicate the vectorization.

dupvec
(n)[source]¶ Return a (repeated) columnmajor vectorization of the expression.
 Parameters
n (int) – Number of times to duplicate the vectorization.
 Returns
A column vector.
 Example
>>> from picos import Constant >>> A = Constant("A", [[1, 2], [3, 4]]) >>> A.dupvec(1) is A.vec True >>> A.dupvec(3).equals(A.vec // A.vec // A.vec) True

equals
(other, absTol=None, relTol=None)[source]¶ Check mathematical equality with another affine expression.
Checks whether the affine expression involves the same variables with the same coefficients and an equal constant term as the given PICOS (affine) expression or constant term.
The type of both expressions may differ. In particular, a
ComplexAffineExpression
with real coefficients and constant can be equal to anAffineExpression
.If the argument is a constant term, no reshaping or broadcasting is used to bring it to the same shape as this expression. In particular,
 Parameters
other – Another PICOS expression or a constant numeric data value supported by
load_data
.absTol – As long as all absolute differences between scalar entries of the coefficient matrices and the constant terms being compared does not exceed this bound, consider the expressions equal.
relTol – As long as all absolute differences between scalar entries of the coefficient matrices and the constant terms being compared divided by the maximum absolute value found in either term does not exceed this bound, consider the expressions equal.
 Example
>>> from picos import Constant >>> A = Constant("A", 0, (5,5)) >>> repr(A) '<5×5 Real Constant: A>' >>> A.is0 True >>> A.equals(0) False >>> A.equals("0(5,5)") True >>> repr(A*1j) '<5×5 Complex Constant: A·1j>' >>> A.equals(A*1j) True

classmethod
fromMatrix
(matrix, size=None)[source]¶ Create a
ComplexAffineExpression
from a numeric matrix.Deprecated since version 2.0: Use
from_constant
instead.

classmethod
fromScalar
(scalar)[source]¶ Create a
ComplexAffineExpression
from a numeric scalar.Deprecated since version 2.0: Use
from_constant
instead.

classmethod
from_constant
(constant, shape=None, name=None)[source]¶ Create a class instance from the given numeric constant.
Loads the given constant as a PICOS expression, optionally broadcasted or reshaped to the given shape and named as specified.
See
load_data
for supported data formats and broadcasting and reshaping rules.Unlike
Constant
, this class method always creates an instance of the class that it is called on, instead of tailoring towards the numeric type of the data.Note
When an operation involves both a PICOS expression and a constant value of another type, PICOS converts the constant on the fly so that you rarely need to use this method.

hadamard
(fact)[source]¶ Denote the elementwise (or Hadamard) product.
Deprecated since version 2.0: Use
object.__xor__
instead.

isconstant
()[source]¶ Whether the expression involves no variables.
Deprecated since version 2.0: Use
constant
instead.

kron
(other)[source]¶ Denote the Kronecker product from the right hand side.
Python 3 users can use the infix
@
operator instead.

leftkron
(other)[source]¶ Denote the Kronecker product from the left hand side.
Python 3 users can use the infix
@
operator instead.

partial_trace
(subsystems, dimensions=2)[source]¶ Return the partial trace over selected subsystems.
If the expression can be written as for matrices with shapes given in
dimensions
, then this returns with , ifi in subsystems
(with read as ), and , otherwise. Parameters
subsystems (int or tuple or list) – A collection of or a single subystem number, indexed from zero, corresponding to subsystems that shall be traced over. The value refers to the last subsystem.
dimensions (int or tuple or list) – Either an integer so that the subsystems are assumed to be all of shape , or a sequence of subsystem shapes where an integer within the sequence is read as . In any case, the elementwise product over all subsystem shapes must equal the expression’s shape.
 Raises
TypeError – If the subsystems do not match the expression or if a nonsquare subsystem is to be traced over.
IndexError – If the subsystem selection is invalid in any other way.
 Example
>>> from picos import Constant >>> A = Constant("A", range(16), (4, 4)) >>> print(A) [ 0.00e+00 4.00e+00 8.00e+00 1.20e+01] [ 1.00e+00 5.00e+00 9.00e+00 1.30e+01] [ 2.00e+00 6.00e+00 1.00e+01 1.40e+01] [ 3.00e+00 7.00e+00 1.10e+01 1.50e+01] >>> A0 = A.partial_trace(0); A0 <2×2 Real Constant: A.{tr([2×2])⊗[2×2]}> >>> print(A0) [ 1.00e+01 1.80e+01] [ 1.20e+01 2.00e+01] >>> A1 = A.partial_trace(1); A1 <2×2 Real Constant: A.{[2×2]⊗tr([2×2])}> >>> print(A1) [ 5.00e+00 2.10e+01] [ 9.00e+00 2.50e+01]

partial_transpose
(subsystems, dimensions=2)[source]¶ Return the expression with selected subsystems transposed.
If the expression can be written as for matrices with shapes given in
dimensions
, then this returns with , ifi in subsystems
(with read as ), and , otherwise. Parameters
subsystems (int or tuple or list) – A collection of or a single subystem number, indexed from zero, corresponding to subsystems that shall be transposed. The value refers to the last subsystem.
dimensions (int or tuple or list) – Either an integer so that the subsystems are assumed to be all of shape , or a sequence of subsystem shapes where an integer within the sequence is read as . In any case, the elementwise product over all subsystem shapes must equal the expression’s shape.
 Raises
TypeError – If the subsystems do not match the expression.
IndexError – If the subsystem selection is invalid.
 Example
>>> from picos import Constant >>> A = Constant("A", range(16), (4, 4)) >>> print(A) [ 0.00e+00 4.00e+00 8.00e+00 1.20e+01] [ 1.00e+00 5.00e+00 9.00e+00 1.30e+01] [ 2.00e+00 6.00e+00 1.00e+01 1.40e+01] [ 3.00e+00 7.00e+00 1.10e+01 1.50e+01] >>> A0 = A.partial_transpose(0); A0 <4×4 Real Constant: A.{[2×2]ᵀ⊗[2×2]}> >>> print(A0) [ 0.00e+00 4.00e+00 2.00e+00 6.00e+00] [ 1.00e+00 5.00e+00 3.00e+00 7.00e+00] [ 8.00e+00 1.20e+01 1.00e+01 1.40e+01] [ 9.00e+00 1.30e+01 1.10e+01 1.50e+01] >>> A1 = A.partial_transpose(1); A1 <4×4 Real Constant: A.{[2×2]⊗[2×2]ᵀ}> >>> print(A1) [ 0.00e+00 1.00e+00 8.00e+00 9.00e+00] [ 4.00e+00 5.00e+00 1.20e+01 1.30e+01] [ 2.00e+00 3.00e+00 1.00e+01 1.10e+01] [ 6.00e+00 7.00e+00 1.40e+01 1.50e+01]

reshaped
(shape)[source]¶ Return the expression reshaped in columnmajor order.
 Example
>>> from picos import Constant >>> C = Constant("C", range(6), (2, 3)) >>> print(C) [ 0.00e+00 2.00e+00 4.00e+00] [ 1.00e+00 3.00e+00 5.00e+00] >>> print(C.reshaped((3, 2))) [ 0.00e+00 3.00e+00] [ 1.00e+00 4.00e+00] [ 2.00e+00 5.00e+00]

reshaped_or_broadcasted
(shape)[source]¶ Return the expression
reshaped
orbroadcasted
.Unlike with
reshaped
andbroadcasted
, the target shape may not contain a wildcard character.If the wildcardfree target shape has the same number of elements as the current shape, then this is the same as
reshaped
, otherwise it is the same asbroadcasted
.

reshuffled
(permutation='ikjl', dimensions=None, order='C')[source]¶ Return the reshuffled or realigned expression.
This operation works directly on matrices. However, it is equivalent to the following sequence of operations:
The matrix is reshaped to a tensor with the given
dimensions
and according toorder
.The tensor’s axes are permuted according to
permutation
.The tensor is reshaped back to the shape of the original matrix according to
order
.
For comparison, the following function applies the same operation to a 2D NumPy
ndarray
:def reshuffle_numpy(matrix, permutation, dimensions, order): P = "{} > {}".format("".join(sorted(permutation)), permutation) reshuffled = numpy.reshape(matrix, dimensions, order) reshuffled = numpy.einsum(P, reshuffled) return numpy.reshape(reshuffled, matrix.shape, order)
 Parameters
permutation (str or tuple or list) – A sequence of comparable elements with length equal to the number of tensor dimensions. The sequence is compared to its ordered version and the resulting permutation pattern is used to permute the tensor indices. For instance, the string
"ikjl"
is compared to its sorted version"ijkl"
and denotes that the second and third axis should be swapped.dimensions (None or tuple or list) – If this is an integer sequence, then it defines the dimensions of the tensor. If this is
None
, then the tensor is assumed to be hypercubic and the number of dimensions is inferred from thepermutation
argument.order (str) – The indexing order to use for the virtual reshaping. Must be either
"F"
for Fortranorder (generalization of columnmajor) or"C"
for Corder (generalization of rowmajor). Note that PICOS usually reshapes in Fortranorder while NumPy defaults to Corder.
 Example
>>> from picos import Constant >>> A = Constant("A", range(16), (4, 4)) >>> print(A) [ 0.00e+00 4.00e+00 8.00e+00 1.20e+01] [ 1.00e+00 5.00e+00 9.00e+00 1.30e+01] [ 2.00e+00 6.00e+00 1.00e+01 1.40e+01] [ 3.00e+00 7.00e+00 1.10e+01 1.50e+01] >>> R = A.reshuffled(); R <4×4 Real Constant: shuffled(A,ikjl,C)> >>> print(R) [ 0.00e+00 4.00e+00 1.00e+00 5.00e+00] [ 8.00e+00 1.20e+01 9.00e+00 1.30e+01] [ 2.00e+00 6.00e+00 3.00e+00 7.00e+00] [ 1.00e+01 1.40e+01 1.10e+01 1.50e+01] >>> A.reshuffled("ji").equals(A.T) # Regular transposition. True >>> A.reshuffled("3214").equals(A.T0) # Partial transposition (1). True >>> A.reshuffled("1432").equals(A.T1) # Partial transposition (2). True

same_as
(other)[source]¶ Check mathematical equality with another affine expression.
Deprecated since version 2.0: Use
equals
instead.

soft_copy
()[source]¶ Return a shallow copy of the expression.
Deprecated since version 2.0: PICOS expressions are now immutable.

sparse_rows
(varOffsetMap, lowerTriangle=False, upperTriangle=False, indexFunction=None)[source]¶ Return a sparse list representation of the expression.
The method is intended for internal use: It simplifies passing affine constraints to solvers that support only scalar constraints. The idea is to pose the constraint as a single (multidimensional) affine expression bounded by zero, and use the coefficients and the constant term of this expression to fill the solver’s constraint matrix (with columns representing scalar variables and rows representing scalar constraints).
 Parameters
varOffsetMap (dict) – Maps variables to column offsets.
lowerTriangle (bool) – Whether to return only the lower triangular part of the expression.
upperTriangle (bool) – Whether to return only the upper triangular part of the expression.
indexFunction – Instead of adding the local variable index to the value returned by varOffsetMap, use the return value of this function, that takes as argument the variable and its local index, as the “column index”, which need not be an integer. When this parameter is passed, the parameter varOffsetMap is ignored.
 Returns
A list of triples (J, V, c) where J contains column indices (representing scalar variables), V contains coefficients for each column index and c is a constant term.

property
H
¶ Conjugate (or Hermitian) transpose.

property
T
¶ Matrix transpose.

property
T0
¶ Expression with the first subsystem transposed.
Only available for a matrix with all subsystems of shape . Use
partial_transpose
otherwise.

property
T1
¶ Expression with the second subsystem transposed.
Only available for a matrix with all subsystems of shape . Use
partial_transpose
otherwise.

property
T2
¶ Expression with the third subsystem transposed.
Only available for a matrix with all subsystems of shape . Use
partial_transpose
otherwise.

property
T3
¶ Expression with the fourth subsystem transposed.
Only available for a matrix with all subsystems of shape . Use
partial_transpose
otherwise.

property
Tl
¶ Expression with the last subsystem transposed.
Only available for a matrix with all subsystems of shape . Use
partial_transpose
otherwise.

property
Tx
¶ Autodetect few subsystems of same shape and transpose the last.
Deprecated since version 2.0: Use
partial_transpose
instead.

property
complex
¶ Whether the expression can be complexvalued.

property
conj
¶ Complex conjugate.

property
constant
¶ Whether the expression involves no variables.

property
cst
¶ Constant part of the affine expression.

property
diag
¶ Diagonal matrix with the expression on the main diagonal.
Vectorization is performed in columnmajor order.

property
hermitian
¶ Whether the expression is a hermitian (or symmetric) matrix.
A tolerance is used to compensate for small numeric errors that can occur when creating hermtian expressions by means of matrix multiplication, see
RELATIVE_HERMITIANNESS_TOLERANCE
.If PICOS still rejects your expression as not hermitian (or as not symmetric), you can use
hermitianized
to correct larger numeric errors or the effects of noisy data.

property
hermitianized
¶ The expression projected onto the subspace of hermitian matrices.
For a square (complex) affine expression , this is .
If the expression is not complex, then this is the projection onto the subspace of symmetric matrices.

property
imag
¶ Imaginary part of a complex affine expression.

property
is0
¶ Whether this is a constant scalar, vector or matrix of all zeros.

property
is1
¶ Whether this is a constant scalar or vector of all ones.

property
isI
¶ Whether this is a constant identity matrix.

property
isreal
¶ Whether the expression is always realvalued.

property
lin
¶ Linear part of the affine expression.

property
maindiag
¶ The main diagonal of the expression as a column vector.

property
real
¶ Real part of a complex affine expression.

property
scalar
¶ Whether this is a scalar affine expression.

property
square
¶ Whether the expression is a square matrix.

property
sum
¶ Sum over all scalar elements of the expression.

property
tr
¶ Trace of a square expression.

property
tr0
¶ Expression with the first subsystem traced out.
Only available for a matrix with all subsystems of shape . Use
partial_trace
otherwise.

property
tr1
¶ Expression with the second subsystem traced out.
Only available for a matrix with all subsystems of shape . Use
partial_trace
otherwise.

property
tr2
¶ Expression with the third subsystem traced out.
Only available for a matrix with all subsystems of shape . Use
partial_trace
otherwise.

property
tr3
¶ Expression with the fourth subsystem traced out.
Only available for a matrix with all subsystems of shape . Use
partial_trace
otherwise.

property
trilvec
¶ Columnmajor vectorization of the lower triangular part.
 Returns
A column vector of all elements that satisfy .
Note
If you want a rowmajor vectorization instead, write
A.T.triuvec
instead ofA.trilvec
. Example
>>> from picos import Constant >>> A = Constant("A", [[1, 2], [3, 4], [5, 6]]) >>> print(A) [ 1.00e+00 2.00e+00] [ 3.00e+00 4.00e+00] [ 5.00e+00 6.00e+00] >>> print(A.trilvec) [ 1.00e+00] [ 3.00e+00] [ 5.00e+00] [ 4.00e+00] [ 6.00e+00]

property
triuvec
¶ Columnmajor vectorization of the upper triangular part.
 Returns
A column vector of all elements that satisfy .
Note
If you want a rowmajor vectorization instead, write
A.T.trilvec
instead ofA.triuvec
. Example
>>> from picos import Constant >>> A = Constant("A", [[1, 2, 3], [4, 5, 6]]) >>> print(A) [ 1.00e+00 2.00e+00 3.00e+00] [ 4.00e+00 5.00e+00 6.00e+00] >>> print(A.triuvec) [ 1.00e+00] [ 2.00e+00] [ 5.00e+00] [ 3.00e+00] [ 6.00e+00]

property
trl
¶ Expression with the last subsystem traced out.
Only available for a matrix with all subsystems of shape . Use
partial_trace
otherwise.

property
vec
¶ Columnmajor vectorization of the expression as a column vector.
Note
Given an expression
A
,A.vec
andA[:]
produce the same result (up to its string description) butA.vec
is faster and its result is cached. Example
>>> from picos import Constant >>> A = Constant("A", [[1, 2], [3, 4]]) >>> A.vec.equals(A[:]) True >>> A[:] is A[:] False >>> A.vec is A.vec True

Functions¶
Constant¶

picos.expressions.exp_affine.
Constant
(name_or_value, value=None, shape=None)[source]¶ Create a constant PICOS expression.
Loads the given numeric value as a constant
ComplexAffineExpression
orAffineExpression
, depending on the value. Optionally, the value is broadcasted or reshaped according to the shape argument. Parameters
See
load_data
for supported data formats and broadcasting and reshaping rules. Example
>>> from picos import Constant >>> Constant(1) <1×1 Real Constant: 1> >>> Constant(1, shape=(2, 2)) <2×2 Real Constant: [1]> >>> Constant("one", 1) <1×1 Real Constant: one> >>> Constant("J", 1, (2, 2)) <2×2 Real Constant: J>
Data¶

picos.expressions.exp_affine.
RELATIVE_HERMITIANNESS_TOLERANCE
¶ Relative tolerance when checking if an expression is hermitian.
A square (complex) affine expression is considered hermitian if
where is this tolerance.
Used by
ComplexAffineExpression.hermitian
.