picos.tools

Many of the tools, in particular the algebraic functions, are also available in the picos namespace. For example, you can write picos.sum instead of picos.tools.sum. In the future, we are looking to split the toolbox into mutltiple modules, so that it is clear which of the functions are imported into the picos namespace.

Members

exception picos.tools.DualizationError(msg)

Bases: Exception

Exception raised when a non-standard conic problem is being dualized.

exception picos.tools.NonConvexError(msg)

Bases: Exception

Exception raised when non-convex quadratic constraints are passed to a solver which cannot handle them.

exception picos.tools.NotAppropriateSolverError(msg)

Bases: Exception

Exception raised when trying to solve a problem with a solver which cannot handle it

exception picos.tools.QuadAsSocpError(msg)

Bases: Exception

Exception raised when the problem can not be solved in the current form, because quad constraints are not handled. User should try to convert the quads as socp.

class picos.tools.NonWritableDict

Bases: dict

picos.tools.ball(r, p=2)

returns a Ball object representing:

  • a L_p Ball of radius r (\{x: \Vert x \Vert_p \geq r \}) if p \geq 1

  • the convex set \{x\geq 0: \Vert x \Vert_p \geq r \} p < 1.

Example

>>> import picos as pic
>>> P = pic.Problem()
>>> x = P.add_variable('x', 3)
>>> x << pic.ball(2,3)  #doctest: +NORMALIZE_WHITESPACE
<p-Norm Constraint: ‖x‖_3 ≤ 2>
>>> x << pic.ball(1,0.5)
<Generalized p-Norm Constraint: ‖x‖_(1/2) ≥ 1>
picos.tools.blocdiag(X, n)

makes diagonal blocs of X, for indices in [sub1,sub2[ n indicates the total number of blocks (horizontally)

picos.tools.block_idx(i, sizes)
picos.tools.break_cols(mat, sizes)
picos.tools.break_rows(mat, sizes)
picos.tools.copy_exp_to_new_vars(exp, cvars, complex=None)
picos.tools.cplx_vecmat_to_real_vecmat(M, sym=True, times_i=False)
If the columns of M are vectorizations of matrices of the form A +iB:
  • If times_i is False (default), return vectorizations of the block matrix [A, -B; B, A] otherwise, return vectorizations of the block matrix [-B, -A; A, -B].

  • If sym=True, returns the columns with respect to the sym-vectorization of the variables of the LMI.

picos.tools.detect_range(sequence, asQuadruple=False, asStringTemplate=False, shortString=False)

Detects a Python range object yielding the same sequence as the given integer sequence.

By default, returns a range object mirroring the input sequence.

Parameters
  • sequence – An integer sequence that can be mirrored by a Python range.

  • asQuadruple (bool) – Whether to return a quadruple with factor, inner shift, outer shift, and length, formally (a, i, o, n) such that [a*(x+i)+o for x in range(n)] mirrors the input sequence.

  • asStringTemplate (bool) – Whether to return a format string that, if instanciated with numbers from 0 to len(sequence) - 1, yields math expression strings that describe the input sequence members.

  • shortString (bool) – Whether to return condensed string templates that are designed to be instanciated with an index character string. Requires asStringTemplate to be True.

Raises
  • TypeError – If the input is not an integer sequence.

  • ValueError – If the input cannot be mirrored by a Python range.

Returns

A range object, a quadruple of numbers, or a format string.

Example

>>> from picos.tools import detect_range as dr
>>> R = range(7,30,5)
>>> S = list(R)
>>> S
[7, 12, 17, 22, 27]
>>> # By default, returns a matching range object:
>>> dr(S)
range(7, 28, 5)
>>> dr(S) == R
True
>>> # Sequence elements can also be decomposed w.r.t. range(len(S)):
>>> a, i, o, n = dr(S, asQuadruple=True)
>>> [a*(x+i)+o for x in range(n)] == S
True
>>> # The same decomposition can be returned in a string representation:
>>> dr(S, asStringTemplate=True)
'5·({} + 1) + 2'
>>> # Short string representations are designed to accept index names:
>>> dr(S, asStringTemplate=True, shortString=True).format("i")
'5(i+1)+2'
>>> dr(range(0,100,5), asStringTemplate=True, shortString=True).format("i")
'5i'
>>> dr(range(10,100), asStringTemplate=True, shortString=True).format("i")
'i+10'

Example

>>> # This works with decreasing ranges as well.
>>> R2 = range(10,4,-2)
>>> S2 = list(R2)
>>> S2
[10, 8, 6]
>>> dr(S2)
range(10, 5, -2)
>>> dr(S2) == R2
True
>>> a, i, o, n = dr(S2, asQuadruple=True)
>>> [a*(x+i)+o for x in range(n)] == S2
True
>>> T = dr(S2, asStringTemplate=True, shortString=True)
>>> [T.format(i) for i in range(len(S2))]
['-2(0-5)', '-2(1-5)', '-2(2-5)']
picos.tools.detrootn(exp)

returns a DetRootN_Exp object representing the determinant of the n th-root of the symmetric matrix exp, where n is the dimension of the matrix. This can be used to enter constraints of the form (\operatorname{det} X)^{1/n} \geq t. Note that X is forced to be positive semidefinite when a constraint of this form is entered in PICOS. Determinant inequalities are internally reformulated as a set of Linear Matrix Inequalities (SDP).

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> X = prob.add_variable('X',(3,3),'symmetric')
>>> t = prob.add_variable('t',1)
>>> t < pic.detrootn(X)
<n-th Root of a Determinant Constraint: det(X)^(1/3) ≥ t>
picos.tools.diag(exp, dim=1)

if exp is an affine expression of size (n,m), diag(exp,dim) returns a diagonal matrix of size dim*n*m \times dim*n*m, with dim copies of the vectorized expression exp[:] on the diagonal.

In particular:

  • when exp is scalar, diag(exp,n) returns a diagonal matrix of size n \times n, with all diagonal elements equal to exp.

  • when exp is a vector of size n, diag(exp) returns the diagonal matrix of size n \times n with the vector exp on the diagonal

Example

>>> import picos as pic
>>> prob=pic.Problem()
>>> x=prob.add_variable('x',1)
>>> y=prob.add_variable('y',1)
>>> pic.diag(x-y,4)
<4×4 Affine Expression: Diag(x - y)>
>>> pic.diag(x//y)
<2×2 Affine Expression: Diag([x; y])>
picos.tools.diag_vect(exp)

Returns the vector with the diagonal elements of the matrix expression exp

Example

>>> import picos as pic
>>> prob=pic.Problem()
>>> X=prob.add_variable('X',(3,3))
>>> pic.diag_vect(X)
<3×1 Affine Expression: diag(X)>
picos.tools.drawGraph(G, capacity='capacity')

“Draw a given Graph

picos.tools.eval_dict(dict_of_variables)

if dict_of_variables is a dictionary mapping variable names (strings) to variables, this function returns the dictionary names -> variable values.

picos.tools.exp(x)

Exponentiation of a PICOS, CVXOPT, NumPy, or numeric expression.

picos.tools.expcone()

returns a ExponentialCone object representing the set \operatorname{closure}\ \{(x,y,z): y>0, y\exp(x/y)\leq z \}

Example

>>> import picos as pic
>>> P = pic.Problem()
>>> x = P.add_variable('x', 3)
>>> pic.expcone()
<Exponential Cone: cl{[x; y; z] : y·exp(z/y) ≤ x, x > 0, y > 0}>
>>> x << pic.expcone()
<Exponential Cone Constraint: x[0] ≥ x[1]·exp(x[2]/x[1])>
picos.tools.flatten(l)

flatten a (recursive) list of list

picos.tools.flow_Constraint(G, f, source, sink, flow_value, capacity=None, graphName='')

Constructs a network flow constraint.

Parameters
  • G (networkx DiGraph.) – A directed graph.

  • f (dict) – A dictionary of variables indexed by the edges of G.

  • source – Either a node of G or a list of nodes in case of a multi-source flow.

  • sink – Either a node of G or a list of nodes in case of a multi-sink flow.

  • flow_value – The value of the flow, or a list of values in case of a single-source/multi-sink flow. In the latter case, the values represent the demands of each sink (resp. of each source for a multi-source/single-sink flow). The values can be either constants or affine expressions.

  • capacity – Either None or a string. If this is a string, it indicates the key of the edge dictionaries of G that is used for the capacity of the links. Otherwise, edges have an unbounded capacity.

  • graphName (str) – Name of the graph as used in the string representation of the constraint.

picos.tools.geomean(exp)

returns a GeoMeanExp object representing the geometric mean of the entries of exp[:]. This can be used to enter inequalities of the form t <= geomean(x). Note that geometric mean inequalities are internally reformulated as a set of SOC inequalities.

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> x = prob.add_variable('x',1)
>>> y = prob.add_variable('y',3)
>>> # Add the constraint x <= (y0*y1*y2)**(1./3) to the problem:
>>> prob.add_constraint(x<pic.geomean(y))
<Geometric Mean Constraint: x ≤ geomean(y)>
picos.tools.import_cbf(filename)

Imports the data from a CBF file, and creates a Problem object.

The created problem contains one (multidimmensional) variable for each cone specified in the section VAR of the .cbf file, and one (multidimmensional) constraint for each cone specified in the sections CON and PSDCON.

Semidefinite variables defined in the section PSDVAR of the .cbf file are represented by a matrix picos variable X with X.vtype = 'symmetric'.

This function returns a tuple (P,x,X,data), where:

  • P is the imported picos Problem object.

  • x is a list of Variable objects, representing the (multidimmensional) scalar variables.

  • X is a list of Variable objects, representing the symmetric semidefinite positive variables.

  • data is a dictionary containing picos parameters (AffinExp objects) used to define the problem. Indexing is with respect to the blocks of variables as defined in the sections VAR and CON of the .cbf file.

picos.tools.is_idty(mat, vtype='continuous')
picos.tools.is_integer(x)
picos.tools.is_numeric(x)
picos.tools.is_realvalued(x)
picos.tools.kron(A, B)

Kronecker product of 2 expression, at least one of which must be constant

Example:

>>> import picos as pic
>>> import cvxopt as cvx
>>> import numpy as np
>>> P = pic.Problem()
>>> X = P.add_variable('X',(4,3))
>>> X.value = cvx.matrix(range(12),(4,3))
>>> I = pic.new_param('I',np.eye(2))
>>> print(pic.kron(I,X)) #doctest: +NORMALIZE_WHITESPACE
[ 0.00e+00  4.00e+00  8.00e+00  0.00e+00  0.00e+00  0.00e+00]
[ 1.00e+00  5.00e+00  9.00e+00  0.00e+00  0.00e+00  0.00e+00]
[ 2.00e+00  6.00e+00  1.00e+01  0.00e+00  0.00e+00  0.00e+00]
[ 3.00e+00  7.00e+00  1.10e+01  0.00e+00  0.00e+00  0.00e+00]
[ 0.00e+00  0.00e+00  0.00e+00  0.00e+00  4.00e+00  8.00e+00]
[ 0.00e+00  0.00e+00  0.00e+00  1.00e+00  5.00e+00  9.00e+00]
[ 0.00e+00  0.00e+00  0.00e+00  2.00e+00  6.00e+00  1.00e+01]
[ 0.00e+00  0.00e+00  0.00e+00  3.00e+00  7.00e+00  1.10e+01]
picos.tools.kullback_leibler(x, y=None)

A shorthand for KullbackLeibler.

If the second optional argument is passed, the resulting expression is the Kullback-Leibler divergence \sum_i x_i \log(x_i / y_i), otherwise it is the (negative) entropy \sum_i x_i \log(x_i).

picos.tools.lambda_max(exp)

largest eigenvalue of a square matrix expression (cf. pic.sum_k_largest(exp,1))

>>> import picos as pic
>>> prob = pic.Problem()
>>> X = prob.add_variable('X',(3,3),'symmetric')
>>> pic.lambda_max(X) < 2
<Sum of Largest Eigenvalues Constraint: λ_max(X) ≤ 2>
picos.tools.lambda_min(exp)

smallest eigenvalue of a square matrix expression (cf. pic.sum_k_smallest(exp,1))

>>> import picos as pic
>>> prob = pic.Problem()
>>> X = prob.add_variable('X',(3,3),'symmetric')
>>> pic.lambda_min(X) > -1
<Sum of Smallest Eigenvalues Constraint: λ_min(X) ≥ -1>
picos.tools.log(x)

The logarithm of a PICOS, CVXOPT, NumPy, or numeric expression.

picos.tools.logsumexp(exp)

A shorthand for LogSumExp.

Example

>>> import picos as pic
>>> import cvxopt as cvx
>>> prob=pic.Problem()
>>> x=prob.add_variable('x',3)
>>> A=pic.new_param('A',cvx.matrix([[1,2],[3,4],[5,6]]))
>>> pic.lse(A*x)<0
<LSE Constraint: log∘sum∘exp(A·x) ≤ 0>
picos.tools.lowtri(exp)

if exp is a square affine expression of size (n,n), lowtri(exp) returns the (n(n+1)/2)-vector of the lower triangular elements of exp.

Example

>>> import picos as pic
>>> import cvxopt as cvx
>>> prob=pic.Problem()
>>> X=prob.add_variable('X',(4,4),'symmetric')
>>> pic.tools.lowtri(X)
<10×1 Affine Expression: lowtri(X)>
>>> X0 = cvx.matrix(range(16),(4,4))
>>> X.value = X0 * X0.T
>>> print(X) #doctest: +NORMALIZE_WHITESPACE
[ 2.24e+02  2.48e+02  2.72e+02  2.96e+02]
[ 2.48e+02  2.76e+02  3.04e+02  3.32e+02]
[ 2.72e+02  3.04e+02  3.36e+02  3.68e+02]
[ 2.96e+02  3.32e+02  3.68e+02  4.04e+02]
>>> print(pic.tools.lowtri(X)) #doctest: +NORMALIZE_WHITESPACE
[ 2.24e+02]
[ 2.48e+02]
[ 2.72e+02]
[ 2.96e+02]
[ 2.76e+02]
[ 3.04e+02]
[ 3.32e+02]
[ 3.36e+02]
[ 3.68e+02]
[ 4.04e+02]
picos.tools.lse(exp)

A shorthand for LogSumExp.

Example

>>> import picos as pic
>>> import cvxopt as cvx
>>> prob=pic.Problem()
>>> x=prob.add_variable('x',3)
>>> A=pic.new_param('A',cvx.matrix([[1,2],[3,4],[5,6]]))
>>> pic.lse(A*x)<0
<LSE Constraint: log∘sum∘exp(A·x) ≤ 0>
picos.tools.ltrim1(vec, uptri=True, offdiag_fact=1.0)

If vec is a vector or an affine expression of size n(n+1)/2, ltrim1(vec) returns a (n,n) matrix with the elements of vec in the lower triangle. If uptri == False, the upper triangle is 0, otherwise the upper triangle is the symmetric of the lower one.

picos.tools.new_param(name, value)

Declare a parameter for the problem, that will be stored as a cvxopt sparse matrix. It is possible to give a list or a dictionary of parameters. The function returns a constant AffinExp (or a list or a dict of AffinExp) representing this parameter.

Note

Declaring parameters is optional, since the expression can as well be given by using normal variables. (see Example below). However, if you use this function to declare your parameters, the names of the parameters will be displayed when you print an Expression or a Constraint

Parameters
  • name (str) – The name given to this parameter.

  • value – The value (resp list of values, dict of values) of the parameter. The type of value (resp. the elements of the list value, the values of the dict value) should be understandable by the function retrieve_matrix().

Returns

A constant affine expression (AffinExp) (resp. a list of AffinExp of the same length as value, a dict of AffinExp indexed by the keys of value)

Example:

>>> import picos as pic
>>> import cvxopt as cvx
>>> prob=pic.Problem()
>>> x=prob.add_variable('x',3)
>>> B={'foo':17.4,'matrix':cvx.matrix([[1,2],[3,4],[5,6]]),'ones':'|1|(4,1)'}
>>> B['matrix']*x+B['foo']
<2×1 Affine Expression: [2×3]·x + [17.4]>
>>> #(in the string above, |17.4| represents the 2-dim vector [17.4,17.4])
>>> B=pic.new_param('B',B)
>>> #now that B is a param, we have a nicer display:
>>> B['matrix']*x+B['foo']
<2×1 Affine Expression: B[matrix]·x + [B[foo]]>
picos.tools.norm(exp, num=2, denom=1)

returns a NormP_Exp object representing the (generalized-) p-norm of the entries of exp[:]. This can be used to enter constraints of the form \Vert x \Vert_p \leq t with p\geq1. Generalized norms are also defined for p<1, by using the usual formula \operatorname{norm}(x,p) := \Big(\sum_i x_i^p\Big)^{1/p}. Note that this function is concave (for p<1) over the set of vectors with nonnegative coordinates. When a constraint of the form \operatorname{norm}(x,p) > t with p\leq1 is entered, PICOS implicitely assumes that x is a nonnegative vector.

This function can also be used to represent the Lp,q- norm of a matrix (for p,q \geq 1): \operatorname{norm}(X,(p,q)) := \Big(\sum_i (\sum_j x_{ij}^q )^{p/q}\Big)^{1/p}, that is, the p-norm of the vector formed with the q-norms of the rows of X.

The exponent p of the norm must be specified either by a couple numerator (2d argument) / denominator (3d arguments), or directly by a float p given as second argument. In the latter case a rational approximation of p will be used. It is also possible to pass 'inf' as second argument for the infinity-norm (aka max-norm).

For the case of (p,q)-norms, p and q must be specified by a tuple of floats in the second argument (rational approximations will be used), and the third argument will be ignored.

Example:

>>> import picos as pic
>>> P = pic.Problem()
>>> x = P.add_variable('x',1)
>>> y = P.add_variable('y',3)
>>> pic.norm(y,7,3) < x
<p-Norm Constraint: ‖y‖_(7/3) ≤ x>
>>> pic.norm(y,-0.4) > x
<Generalized p-Norm Constraint: ‖y‖_(-2/5) ≥ x>
>>> X = P.add_variable('X',(3,2))
>>> pic.norm(X,(1,2)) < 1
<(p,q)-Norm Constraint: ‖X‖_1,2 ≤ 1>
>>> pic.norm(X,('inf',1)) < 1
<(p,q)-Norm Constraint: ‖X‖_inf,1 ≤ 1>
picos.tools.offset_in_lil(lil, offset, lower)

substract the offset from all elements of the (recursive) list of lists lil which are larger than lower.

picos.tools.parameterized_string(strings, replace='\\d+', placeholders='ijklpqr', fallback='?')

Given a list of strings with similar structure, finds a single string with placeholders and an expression that denotes how to instantiate the placeholders in order to obtain each string in the list.

The function is designed to take a number of symbolic string representations of math expressions that differ only with respect to indices.

Parameters
  • strings (list) – The list of strings to compare.

  • replace (str) – A regular expression describing the bits to replace with placeholders.

  • placeholders – An iterable of placeholder strings. Usually a string, so that each of its characters becomes a placeholder.

  • fallback (str) – A fallback placeholder string, if the given placeholders are not sufficient.

Returns

A tuple of two strings, the first being the template string and the second being a description of the placeholders used.

Example

>>> from picos.tools import parameterized_string as ps
>>> ps(["A[{}]".format(i) for i in range(5, 31)])
('A[i+5]', 'i ∈ [0…25]')
>>> ps(["A[{}]".format(i) for i in range(5, 31, 5)])
('A[5(i+1)]', 'i ∈ [0…5]')
>>> S=["A[0]·B[2]·C[3]·D[5]·F[0]",
...    "A[1]·B[1]·C[6]·D[6]·F[0]",
...    "A[2]·B[0]·C[9]·D[9]·F[0]"]
>>> ps(S)
('A[i]·B[-(i-2)]·C[3(i+1)]·D[j]·F[0]', '(i,j) ∈ zip([0…2],[5,6,9])')
picos.tools.partial_trace(X, k=1, dim=None)

Partial trace of an Affine Expression, with respect to the k``th subsystem or to every subsystems in ``k for a tensor product of dimensions dim. If X is a matrix AffinExp that can be written as X = A_0 \otimes \cdots \otimes A_{n-1} for some matrices A_0,\ldots,A_{n-1} of respective sizes dim[0] x dim[0], … , dim[n-1] x dim[n-1] (dim is a list of ints if all matrices are square), or dim[0][0] x dim[0][1], …,``dim[n-1][0] x dim[n-1][1]`` (dim is a list of 2-tuples if any of them except the k th one is rectangular), this function returns the matrix Y = \operatorname{trace}(A_k)\quad A_0 \otimes \cdots A_{k-1} \otimes A_{k+1} \otimes \cdots \otimes A_{n-1} if k is an int or a list of one element, Y = \operatorname{trace}(A_{k_0,k_1,\ldots,k_m}) \quad A_0 \otimes \cdots A_{k_0-1} \otimes A_{k_0+1} \otimes \cdots \otimes A_{k_m-1} \otimes A_{k_m+1} \otimes \cdots \otimes A_{n-1} if k is a list of subsystems.

The default value dim=None automatically computes the size of the subblocks, assuming that X is a n^2 \times n^2-square matrix with blocks of size n \times n, in this case only bipartite subsystem is assume, hence k as to be either 0 or 1.

Example:

>>> import picos as pic
>>> import cvxopt as cvx
>>> P = pic.Problem()
>>> X = P.add_variable('X',(4,4))
>>> Y = P.add_variable('Y',(8,8))
>>> X.value = cvx.matrix(range(16),(4,4))
>>> Y.value = cvx.matrix(range(64),(8,8))
>>> print(X) #doctest: +NORMALIZE_WHITESPACE
[ 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]
>>> # Partial trace with respect to second subsystem (k=1):
>>> print(pic.partial_trace(X)) #doctest: +NORMALIZE_WHITESPACE
[ 5.00e+00  2.10e+01]
[ 9.00e+00  2.50e+01]
>>> # And with respect to first subsystem (k=0):
>>> print(pic.partial_trace(X,0)) #doctest: +NORMALIZE_WHITESPACE
[ 1.00e+01  1.80e+01]
[ 1.20e+01  2.00e+01]
>>> #Partial trace in a multiple subsystem scenario:
>>> print(pic.partial_trace(Y,k=[0,2],dim=[2,2,2])) #doctest: +NORMALIZE_WHITESPACE
[ 9.00e+01  1.54e+02]
[ 9.80e+01  1.62e+02]
picos.tools.partial_transpose(exp, dims_1=None, subsystems=None, dims_2=None)

Partial transpose of an Affine Expression, with respect to given subsystems. If X is a matrix AffinExp that can be written as X = A_0 \otimes \cdots \otimes A_{n-1} for some matrices A_0,\ldots,A_{n-1} of respective sizes dims_1[0] x dims_2[0], … , dims_1[n-1] x dims_2[n-1], this function returns the matrix Y = B_0 \otimes \cdots \otimes B_{n-1}, where B_i=A_i^T if i in subsystems, and B_i=A_i otherwise.

The optional parameters dims_1 and dims_2 are tuples specifying the dimension of each subsystem A_i. The argument subsystems must be a tuple (or an int) with the index of all subsystems to be transposed.

The default value dims_1=None automatically computes the size of the subblocks, assuming that exp is a n^k \times n^k-square matrix, for the smallest appropriate value of k \in [2,6], that is dims_1=(n,)*k.

If dims_2 is not specified, it is assumed that the subsystems A_i are square, i.e., dims_2=dims_1. If subsystems is not specified, the default assumes that only the last system must be transposed, i.e., subsystems = (len(dims_1)-1,)

Example:

>>> import picos as pic
>>> import cvxopt as cvx
>>> P = pic.Problem()
>>> X = P.add_variable('X',(4,4))
>>> X.value = cvx.matrix(range(16),(4,4))
>>> print(X) #doctest: +NORMALIZE_WHITESPACE
[ 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]
>>> # Standard partial transpose with respect to the 2x2 blocks and 2nd subsystem:
>>> print(X.Tx) #doctest: +NORMALIZE_WHITESPACE
[ 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]
>>> # Now with respect to the first subsystem:
>>> print(pic.partial_transpose(X,(2,2),0)) #doctest: +NORMALIZE_WHITESPACE
[ 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]
picos.tools.quad2norm(qd)

transform the list of bilinear terms qd in an equivalent squared norm (x.T Q x) -> ||Q**0.5 x||**2

picos.tools.remove_in_lil(lil, elem)

remove the element elem from a (recursive) list of list lil. empty lists are removed if any

picos.tools.retrieve_matrix(mat, exSize=None)

parses the variable mat and convert it to a cvxopt sparse matrix. If the variable exSize is provided, the function tries to return a matrix that matches this expected size, or raise an error.

Warning

If there is a conflit between the size of mat and the expected size exsize, the function might still return something without raising an error !

Parameters

mat

The value to be converted into a cvx.spmatrix. The function will try to parse this variable and format it to a vector/matrix. mat can be of one of the following types:

  • list [creates a vecor of dimension len(list)]

  • cvxopt matrix

  • cvxopt sparse matrix

  • numpy array

  • int or real [creates a vector/matrix of the size exSize (or of size (1,1) if exSize is None), whith all entries equal to mat.

  • following strings:

    • |a|’ for a matrix with all terms equal to a

    • |a|(n,m)’ for a matrix forced to be of size n x m, with all terms equal to a

    • e_i(n,m)’ matrix of size (n,m), with a 1 on the ith coordinate (and 0 elsewhere)

    • e_i,j(n,m)’ matrix of size (n,m), with a 1 on the (i,j)-entry (and 0 elsewhere)

    • I’ for the identity matrix

    • I(n)’ for the identity matrix, forced to be of size n x n.

    • a%s’, where %s is one of the above string: the matrix that should be returned when mat == %s, multiplied by the scalar a.

Returns

A tuple of the form (M, s), where M is the conversion of mat into a cvxopt sparse matrix, and s is a string representation of mat

Example:

>>> import picos as pic
>>> pic.tools.retrieve_matrix([1,2,3])
(<3x1 sparse matrix, tc='d', nnz=3>, '[3×1]')
>>> pic.tools.retrieve_matrix('e_5(7,1)')
(<7x1 sparse matrix, tc='d', nnz=1>, 'e_5')
>>> print(pic.tools.retrieve_matrix('e_11(7,2)')[0]) #doctest: +NORMALIZE_WHITESPACE
[   0        0       ]
[   0        0       ]
[   0        0       ]
[   0        0       ]
[   0        1.00e+00]
[   0        0       ]
[   0        0       ]
>>> print(pic.tools.retrieve_matrix('5.3I',(2,2)))
(<2x2 sparse matrix, tc='d', nnz=2>, '5.3·I')
picos.tools.simplex(gamma=1)

returns a TruncatedSimplex object representing the set \{x\geq 0: ||x||_1 \leq \gamma \}.

Example

>>> import picos as pic
>>> P = pic.Problem()
>>> x = P.add_variable('x', 3)
>>> x << pic.simplex()
<Standard Simplex Constraint: x ∈ {x ≥ 0 : ∑(x) ≤ 1}>
>>> x << pic.simplex(2)
<Simplex Constraint: x ∈ {x ≥ 0 : ∑(x) ≤ 2}>
picos.tools.spmatrix(*args, **kwargs)

A wrapper around cvxopt.spmatrix that converts indices to int, if necessary.

It works around PICOS sometimes passing indices as numpy.int64.

picos.tools.sum(lst, it=None, indices=None)

This is a replacement for Python’s sum that produces sensible string representations when summing PICOS expressions.

Parameters
  • lst (list or tuple or AffinExp) – A list of expressions, or a single affine expression whose elements shall be summed.

  • it – DEPRECATED

  • indices – DEPRECATED

Example:

>>> import picos
>>> P = picos.Problem()
>>> x = P.add_variable("x", 5)
>>> e = [x[i]*x[i+1] for i in range(len(x) - 1)]
>>> sum(e)
<Quadratic Expression: x[0]·x[1] + x[1]·x[2] + x[2]·x[3] + x[3]·x[4]>
>>> picos.sum(e)
<Quadratic Expression: ∑(x[i]·x[i+1] : i ∈ [0…3])>
>>> picos.sum(x) # The same as (x|1).
<1×1 Affine Expression: ∑(x)>
picos.tools.sum_k_largest(exp, k)

returns a Sum_k_Largest_Exp object representing the sum of the k largest elements of an affine expression exp. This can be used to enter constraints of the form \sum_{i=1}^k x_{i}^{\downarrow} \leq t. This kind of constraints is reformulated internally as a set of linear inequalities.

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> x = prob.add_variable('x',3)
>>> t = prob.add_variable('t',1)
>>> pic.sum_k_largest(x,2) < 1
<Sum of Largest Elements Constraint: sum_2_largest(x) ≤ 1>
>>> pic.sum_k_largest(x,1) < t
<Sum of Largest Elements Constraint: max(x) ≤ t>
picos.tools.sum_k_largest_lambda(exp, k)

returns a Sum_k_Largest_Exp object representing the sum of the k largest eigenvalues of a square matrix affine expression exp. This can be used to enter constraints of the form \sum_{i=1}^k \lambda_{i}^{\downarrow}(X) \leq t. This kind of constraints is reformulated internally as a set of linear matrix inequalities (SDP). Note that exp is assumed to be symmetric (picos does not check).

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> X = prob.add_variable('X',(3,3),'symmetric')
>>> t = prob.add_variable('t',1)
>>> pic.sum_k_largest_lambda(X,3) < 1
<Sum of Largest Eigenvalues Constraint: trace(X) ≤ 1>
>>> pic.sum_k_largest_lambda(X,2) < t
<Sum of Largest Eigenvalues Constraint: sum_2_largest_λ(X) ≤ t>
picos.tools.sum_k_smallest(exp, k)

returns a Sum_k_Smallest_Exp object representing the sum of the k smallest elements of an affine expression exp. This can be used to enter constraints of the form \sum_{i=1}^k x_{i}^{\uparrow} \geq t. This kind of constraints is reformulated internally as a set of linear inequalities.

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> x = prob.add_variable('x',3)
>>> t = prob.add_variable('t',1)
>>> pic.sum_k_smallest(x,2) > t
<Sum of Smallest Elements Constraint: sum_2_smallest(x) ≥ t>
>>> pic.sum_k_smallest(x,1) > 3
<Sum of Smallest Elements Constraint: min(x) ≥ 3>
picos.tools.sum_k_smallest_lambda(exp, k)

returns a Sum_k_Smallest_Exp object representing the sum of the k smallest eigenvalues of a square matrix affine expression exp. This can be used to enter constraints of the form \sum_{i=1}^k \lambda_{i}^{\uparrow}(X) \geq t. This kind of constraints is reformulated internally as a set of linear matrix inequalities (SDP). Note that exp is assumed to be symmetric (picos does not check).

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> X = prob.add_variable('X',(3,3),'symmetric')
>>> t = prob.add_variable('t',1)
>>> pic.sum_k_smallest_lambda(X,1) > 1
<Sum of Smallest Eigenvalues Constraint: λ_min(X) ≥ 1>
>>> pic.sum_k_smallest_lambda(X,2) > t
<Sum of Smallest Eigenvalues Constraint: sum_2_smallest_λ(X) ≥ t>
picos.tools.sumexp(x, y=None)

A shorthand for SumExponential.

If the second optional argument is passed, the resulting expression is the sum of perspectives of exponentials \sum_i y_i \exp(x_i / y_i), otherwise it is a sum of exponentials \sum_i \exp(x_i).

picos.tools.svec(mat, ignore_sym=False)

returns the svec representation of the cvx matrix mat. (see Dattorro, ch.2.2.2.1)

If ignore_sym = False (default), the function raises an Exception if mat is not symmetric. Otherwise, elements in the lower triangle of mat are simply ignored.

picos.tools.svecm1(vec, triu=False)
picos.tools.svecm1_identity(vtype, size)

row wise svec-1 transformation of the identity matrix of size size[0]*size[1]

picos.tools.svecm1_identity_factor(factors, variable)
Returns

Whether the variable coefficients are the svec-1 transformation of the identity.

picos.tools.trace(exp)

trace of a square AffinExp

picos.tools.tracepow(exp, num=1, denom=1, coef=None)

Returns a TracePow_Exp object representing the trace of the pth-power of the symmetric matrix exp, where exp is an AffinExp which we denote by X. This can be used to enter constraints of the form \operatorname{trace} X^p \leq t with p\geq1 or p < 0, or \operatorname{trace} X^p \geq t with 0 \leq p \leq 1. Note that X is forced to be positive semidefinite when a constraint of this form is entered in PICOS.

It is also possible to specify a coef matrix (M) of the same size as exp, in order to represent the expression \operatorname{trace} (M X^p). The constraint \operatorname{trace} (M X^p)\geq t can be reformulated with SDP constraints if M is positive semidefinite and 0<p<1.

Trace of power inequalities are internally reformulated as a set of Linear Matrix Inequalities (SDP), or second order cone inequalities if exp is a scalar.

The exponent p of the norm must be specified either by a couple numerator (2d argument) / denominator (3d arguments), or directly by a float p given as second argument. In the latter case a rational approximation of p will be used.

Example:

>>> import picos as pic
>>> prob = pic.Problem()
>>> X = prob.add_variable('X',(3,3),'symmetric')
>>> t = prob.add_variable('t',1)
>>> pic.tracepow(X,7,3) < t
<Trace of Power Constraint: trace(X^(7/3)) ≤ t>
>>> pic.tracepow(X,0.6) > t
<Trace of Power Constraint: trace(X^(3/5)) ≥ t>
>>> import cvxopt as cvx
>>> A = cvx.normal(3,3);A=A*A.T # A random semidefinite positive matrix
>>> A = pic.new_param('A',A)
>>> pic.tracepow(X,0.25,coef=A) > t
<Trace of Power Constraint: trace(A·X^(1/4)) ≥ t>
picos.tools.truncated_simplex(gamma=1, sym=False)

returns a TruncatedSimplex object representing the set:

  • \{x \geq  0: ||x||_\infty \leq 1,\ ||x||_1 \leq \gamma \} if sym=False (default)

  • \{x: ||x||_\infty \leq 1,\ ||x||_1 \leq \gamma \} if sym=True.

Example

>>> import picos as pic
>>> P = pic.Problem()
>>> x = P.add_variable('x', 3)
>>> x << pic.truncated_simplex(2)
<Truncated Simplex Constraint: x ∈ {0 ≤ x ≤ 1 : ∑(x) ≤ 2}>
>>> x << pic.truncated_simplex(2,sym=True)
<Symmetrized Truncated Simplex Constraint: x ∈ {-1 ≤ x ≤ 1 : ∑(|x|) ≤ 2}>
picos.tools.utri(mat)

return elements of the (strict) upper triangular part of a cvxopt matrix