picos.problem¶

The Problem class represents your optimization problem and is your main way of interfacing PICOS. After you create a problem instance, you can add variables to it via add_variable and use standard Python algebraic operators (Cheat Sheet) and algebraic functions (picos.tools) to create expressions and constraints involving these variables.

Members¶

class picos.problem.Problem(**options)

Bases: object

PICOS’ representation of an optimization problem.

Example

>>> import picos
>>> P = picos.Problem(verbose = 0)
>>> X = P.add_variable("X", (2,2), lower = 0)
>>> # 1|X is the dot prouct of X with a matrix of all ones.
>>> C = P.add_constraint(1|X < 10)
>>> P.set_objective("max", picos.trace(X))
>>> # PICOS will select a suitable solver if you don't specify one.
>>> solution = P.solve(solver = "cvxopt")
>>> solution["status"]
'optimal'
>>> solution["time"] #doctest: +SKIP
0.00034999847412109375
>>> round(P.obj_value(), 1)
10.0
>>> print(X) #doctest: +SKIP
[ 0.00e+00  0.00e+00]
[ 0.00e+00  1.00e+01]
>>> round(C.dual, 1)
1.0

Creates an empty problem and optionally sets initial solver options.

Parameters

options – A parameter sequence of solver options.

Adds a constraint to the problem.

Parameters
• constraint (Constraint) – The constraint to be added.

• key (str) – Optional name of the constraint.

Returns

The constraint that was added to the problem, which may be a MetaConstraint that contains further references to auxiliary constraints that were also added, as well as potentially references to new auxiliary variables.

add_list_of_constraints(lst, it=None, indices=None, key=None)

Adds a list of constraints to the problem, enabling the use of Python list comprehensions (see the example below).

Parameters
• lst (list) – A list of constraints.

• it – DEPRECATED

• indices – DEPRECATED

• key (str) – A name describing the list of constraints.

Returns

A list of all constraints that were added.

Example

>>> import picos as pic
>>> import cvxopt as cvx
>>> from pprint import pprint
>>> prob=pic.Problem()
>>> x=[prob.add_variable('x[{0}]'.format(i),2) for i in range(5)]
>>> pprint(x)
[<2×1 Continuous Variable: x>,
<2×1 Continuous Variable: x>,
<2×1 Continuous Variable: x>,
<2×1 Continuous Variable: x>,
<2×1 Continuous Variable: x>]
>>> IJ=[(1,2),(2,0),(4,2)]
>>> w={}
>>> for ij in IJ:
...
>>> u=pic.new_param('u',cvx.matrix([2,5]))
>>> C1=prob.add_list_of_constraints([u.T*x[i] < y[i] for i in range(5)])
>>> C2=prob.add_list_of_constraints([abs(w[i,j])<y[j] for (i,j) in IJ])
>>> C3=prob.add_list_of_constraints([y[t] > y[t+1] for t in range(4)])
>>> print(prob) #doctest: +NORMALIZE_WHITESPACE
---------------------
optimization problem (SOCP):
24 variables, 9 affine constraints, 12 vars in 3 SO cones
<BLANKLINE>
w   : dict of 3 variables, (3, 1), continuous
x   : list of 5 variables, (2, 1), continuous
y   : (5, 1), continuous
<BLANKLINE>
find vars
such that
uᵀ·x[i] ≤ y[i] ∀ i ∈ [0…4]
‖w[i,j]‖ ≤ y[j] ∀ (i,j) ∈ zip([1,2,4],[2,0,2])
y[i] ≥ y[i+1] ∀ i ∈ [0…3]
---------------------
add_variable(name, size=1, vtype='continuous', lower=None, upper=None)

Adds a variable to the problem and returns it for use in constraints.

Parameters
• name (str) – The name of the variable.

• size (int or tuple) –

The size of the variable. Can be either

• an int , in which case the variable is an -dimensional vector,

• or a tuple , in which case the variable is a matrix.

• vtype (str) –

Domain of the variable. Can be any of

• 'continuous' – real valued,

• 'binary' – either zero or one,

• 'integer' – integer valued,

• 'symmetric' – symmetric matrix,

• 'antisym' – antisymmetric matrix,

• 'complex' – complex matrix,

• 'hermitian' – complex hermitian matrix,

• 'semicont' – zero or real valued and satisfying its bounds (supported by CPLEX and Gurobi only), or

• 'semiint' – zero or integer valued and satisfying its bounds (supported by CPLEX and Gurobi only).

• lower (anything recognized by retrieve_matrix) –

A lower bound for the variable.

Can be either a vector or matrix of the same size as the variable or a scalar that is then broadcasted so that all elements of the variable have the same lower bound.

• upper (anything recognized by retrieve_matrix) –

An upper bound for the variable.

Can be either a vector or matrix of the same size as the variable or a scalar that is then broadcasted so that all elements of the variable have the same upper bound.

Returns

A Variable instance.

Example

>>> prob=picos.Problem()
>>> x
<3×1 Continuous Variable: x>
as_dual()

Returns the Lagrangian dual problem of the problem.

To this end the problem is put in a canonical primal form (see the note on dual variables), and the corresponding dual form is returned as a new Problem.

as_real()

Returns a modified copy of the problem, where hermitian matrices are replaced by symmetric matrices.

as_socp()
check_current_value_feasibility(tol=1e-05, inttol=0.001)

Checks whether all variables that appear in constraints are valued and satisfy the constraints up to the given tolerance. In other words, checks whether the variables are valued to form a feasible solution.

Parameters
• tol (float) – Largest tolerated absolute violation of a constraint. If None, the fesatol or tol solver option is used.

• inttol (float) – Largest tolerated absolute violation of integrality of an integral variable.

Returns

A tuple (feasible, violation) where feasible is a bool stating whether the solution is feasible and violation is either None, if feasible == True, or the amount of violation, otherwise.

Replaces quadratic constraints with equivalent second order cone constraints.

Replaces a quadratic objective with an equivalent quadratic constraint.

copy()

Creates an independent copy of the problem, using new variables.

Note

Your existing variable, constraint, and metaconstraint references will refer to the original variables, so you cannot query these for solution details after solving the copy. Access the copy’s constraints and variables instead.

get_constraint(ind)

Returns a constraint of the problem, given its index.

Parameters

ind (int or tuple) –

There are three ways to index a constraint:

• If ind is an int , then the -th constraint (starting from ) is returned, where constraints are counted in the order in which they where passed to the problem.

• if ind is a tuple , then the -th constraint from the -th group of constraints is returned (both starting from ). Here group of constraints refers to a list of constraints added together via add_list_of_constraints.

• If ind is a tuple of length , then the -th group of constraints is returned as a list.

Returns

A constraint or a list thereof.

Example

>>> import picos as pic
>>> import cvxopt as cvx
>>> from pprint import pprint
>>> prob=pic.Problem()
>>> x=[prob.add_variable('x[{0}]'.format(i),2) for i in range(5)]
>>> Cx=prob.add_list_of_constraints([(1|x[i]) < y[i] for i in range(5)])
>>> print(prob) #doctest: +NORMALIZE_WHITESPACE
---------------------
optimization problem (LP):
15 variables, 10 affine constraints
<BLANKLINE>
x   : list of 5 variables, (2, 1), continuous
y   : (5, 1), continuous
<BLANKLINE>
find vars
such that
⟨, x[i]⟩ ≤ y[i] ∀ i ∈ [0…4]
y ≥ 0
---------------------
>>> # Retrieve the 3nd constraint (counted from 0):
>>> prob.get_constraint(1)
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>
>>> # Retrieve the 4th consraint from the 1st group:
>>> prob.get_constraint((0,3))
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>
>>> # Retrieve the unique constraint of the 2nd 'group':
>>> prob.get_constraint((1,))
<5×1 Affine Constraint: y ≥ 0>
>>> # Retrieve the whole 1st group of constraints:
>>> pprint(prob.get_constraint((0,)))
[<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>]
get_valued_variable(name)

Returns the value or values of a variable or of a collection of variables with a common base name.

Parameters

name (str) – Name of a single variable or of a collection of variables (see get_variable on how to specify collections).

Raises

An exception if any of the variables is not valued, in particular when the problem was not yet solved.

Returns

A CVXOPT matrix, if name refers to a single variable, or a list or a dictionary thereof, if the collection of variables specified by name is a list or a dictionary, respectively.

get_variable(name)

Returns a single variable with the given name or a list or dictionary of variables with the given name as a common base name. In the latter case the variables must be named name[index] or name[key] with index taken from a set of integer strings and key taken from a set of arbitrary strings.

Parameters

name (str) – Name of a single variable or of a collection of variables.

Returns

A PICOS variable, if name refers to a single variable, or a list or a dictionary thereof, if the collection of variables specified by name is a list or a dictionary, respectively.

is_complex()
Returns

True, if the problem has a complex variable or if there is a complex coefficient or constant inside a constraint.

is_continuous()
Returns

True, if all variables are continuous.

is_pure_integer()
Returns

True, if all variables are integer.

maximize(obj, **options)

Sets the objective to maximize the given objective function and calls the solver with the given sequence of options.

Parameters
• obj (Expression) – The objective function to maximize.

• options – A sequence of optional solver options.

Returns

A dictionary, see solve.

Warning

This is equivalent to set_objective followed by solve and will thus override any existing objective function and direction.

Further, any supplied options will be stored in the problem as if they were set via set_option.

minimize(obj, **options)

Sets the objective to minimize the given objective function and calls the solver with the given sequence of options.

Parameters
• obj (Expression) – The objective function to minimize.

• options – A sequence of optional solver options.

Returns

A dictionary, see solve.

Warning

This is equivalent to set_objective followed by solve and will thus override any existing objective function and direction.

Further, any supplied options will be stored in the problem as if they were set via set_option.

obj_value()

Returns the objective value after the problem was solved.

Raises

AttributeError, if the problem was not yet solved.

remove_all_constraints()

Removes all constraints from the problem.

This function does not remove bounds set directly on variables; use remove_all_variable_bounds to do so.

remove_all_variable_bounds()

Removes all lower and upper bounds from all variables.

remove_constraint(ind)

Deletes a constraint from the problem.

Parameters

ind (int or tuple) –

There are three ways to index a constraint:

• If ind is an int , then the -th constraint (starting from ) is deleted, where constraints are counted in the order in which they where passed to the problem.

• if ind is a tuple , then the -th constraint from the -th group of constraints is deleted (both starting from ). Here group of constraints refers to a list of constraints added together via add_list_of_constraints.

• If ind is a tuple of length , then the whole -th group of constraints is deleted.

Example

>>> import picos as pic
>>> import cvxopt as cvx
>>> from pprint import pprint
>>> prob=pic.Problem()
>>> x=[prob.add_variable('x[{0}]'.format(i),2) for i in range(4)]
>>> Cxy=prob.add_list_of_constraints([(1|x[i])<y[i] for i in range(4)])
>>> Cx0to2=prob.add_list_of_constraints([x[i]<2 for i in range(3)])
>>> pprint(prob.constraints) #doctest: +NORMALIZE_WHITESPACE
[<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<4×1 Affine Constraint: y ≥ 0>,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >]
>>> # Delete the 2nd constraint (counted from 0):
>>> prob.remove_constraint(1)
>>> pprint(prob.constraints) #doctest: +NORMALIZE_WHITESPACE
[<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<4×1 Affine Constraint: y ≥ 0>,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >]
>>> # Delete the 2nd group of constraints, i.e. the constraint y > 0:
>>> prob.remove_constraint((1,))
>>> pprint(prob.constraints) #doctest: +NORMALIZE_WHITESPACE
[<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >]
>>> # Delete the 3rd remaining group of constraints, i.e. x < :
>>> prob.remove_constraint((2,))
>>> pprint(prob.constraints) #doctest: +NORMALIZE_WHITESPACE
[<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >]
>>> # Delete 2nd constraint of the 2nd remaining group, i.e. x < |2|:
>>> prob.remove_constraint((1,1))
>>> pprint(prob.constraints) #doctest: +NORMALIZE_WHITESPACE
[<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<1×1 Affine Constraint: ⟨, x⟩ ≤ y>,
<2×1 Affine Constraint: x ≤ >,
<2×1 Affine Constraint: x ≤ >]
remove_variable(name)

Removes a variable from the problem.

Parameters

name (str) – Name of the variable to remove.

Warning

This method does not check if some constraint still involves the variable to be removed.

reset(resetOptions=False)

Resets the problem instance to its initial empty state.

Parameters

resetOptions (bool) – Whether also solver options should be reset to their default values.

reset_solver_instances()

Resets all solver instances, so that the problem will be reimported and solved from scratch.

set_all_options_to_default()

Sets all solver options to their default value.

set_objective(typ, expr)

Sets the objective function and optimization direction of the problem.

Parameters
• typ (str) – Can be either 'max', 'min', or 'find', for a maximization, minimization, and feasibility problem, respectively.

• expr (Expression) – The objective function to be minimized or maximized. This parameter is ignored if typ == 'find'.

set_option(key, val)

Sets a single solver option to the given value.

Parameters
• key (str) – String name of the option, see below for a list.

• val – New value for the option.

The following options are available and are listed with their default values.

• General options common to all solvers:

• strict_options = False – If True, unsupported general options will raise an UnsupportedOptionError exception, instead of printing a warning.

• verbose = 1 – Verbosity level.

• -1 attempts to suppress all output, even errors.

• 0 only outputs warnings and errors.

• 1 generates standard informative output.

• 2 prints all available information for debugging purposes.

• allow_license_warnings = True – Whether solvers are allowed to ignore the verbose option to print licensing related warnings.

Using this option to surpress licensing related warnings is done at your own legal responsibility.

• solver = None – Solver to use.

• None lets PICOS select a suitable solver for you.

• 'cplex' for CPLEX.

• 'cvxopt' for CVXOPT.

• 'glpk' for GLPK.

• 'mosek' for MOSEK.

• 'gurobi' for Gurobi.

• 'scip' for SCIP (formerly ZIBOpt).

• 'smcp' for SMCP.

• tol = 1e-8 – Relative gap termination tolerance for interior-point optimizers (feasibility and complementary slackness).

This option is currently ignored by GLPK. SCIP will only lower its precision for large values and not increase it for small ones.

• maxit = None – Maximum number of iterations for simplex or interior-point optimizers). Currently ignored by SCIP.

• lp_root_method = None – Algorithm used to solve continuous linear problems, including the root relaxation of mixed integer problems.

• None lets PICOS or the solver select it fo you.

• 'psimplex' for primal Simplex.

• 'dsimplex' for dual Simplex.

• 'interior' for the interior point method.

This option currently works only with CPLEX, Gurobi and MOSEK. With GLPK it works for LPs but not for the MIP root relaxation.

• lp_node_method = None – Algorithm used to solve subproblems at non-root nodes of the branching tree built when solving mixed integer programs.

• None lets PICOS or the solver select it fo you.

• 'psimplex' for primal Simplex.

• 'dsimplex' for dual Simplex.

• 'interior' for the interior point method.

This option currently works only with CPLEX, Gurobi and MOSEK.

• timelimit = None – Total time limit for the solver, in seconds. The default None means no time limit.

This option is not supported by CVXOPT and SMCP.

• treememory = None – Bound on the memory used by the branch and bound tree, in Megabytes.

This option currently works only with CPLEX and SCIP.

• gaplim = 1e-4 – For mixed integer problems, the solver returns a solution as soon as this value for the relative gap between the primal and the dual bound is reached.

• noprimals = False – If True, do not retrieve a primal solution from the solver.

• noduals = False – If True, do not retrieve optimal values for the dual variables. This can speed up solvers that do not produce a dual solution as part of their primal solution process.

• nbsol = None – Maximum number of feasible solution nodes visited when solving a mixed integer problem, before returning the best one found.

If you want to obtain all feasible solutions that the solver encountered, use pool_size instead.

• pool_size = None – Maximum number of mixed integer feasible solutions returned, instead of just a single one.

If you merely want to set a limit on the number of feastble solution nodes that are visited, use nbsol instead.

This option currently works only with CPLEX.

• pool_absgap = None – Discards solutions from the solution pool as soon as a better solution is found that beats it by the given absolute gap tolerance with respect to the objective function.

This option currently works only with CPLEX.

• pool_relgap = None – Discards solutions from the solution pool as soon as a better solution is found that beats it by the given relative gap tolerance with respect to the objective function.

This option currently works only with CPLEX.

• hotstart = False – If True, tells the mixed integer optimizer to start from the (partial) solution specified in the variables’ value attributes.

This option currently works only with CPLEX, Gurobi and MOSEK.

• solve_via_dual = None – If set to True, the Lagrangian Dual (computed with the function as_dual) is passed to the solver, instead of the problem itself. In some scenarios this can yield a signficant speed-up. If set to None, PICOS chooses automatically whether the problem itself or its dual should be passed to the solver.

• Specific options available for CPLEX:

• cplex_params = {} – A dictionary of CPLEX parameters to be set before the CPLEX optimizer is called.

For example, cplex_params = {'mip.limits.cutpasses': 5} will limit the number of cutting plane passes when solving the root node to 5.

• uboundlimit = None – Tells CPLEX to stop as soon as an upper bound smaller than this value is found.

• lboundlimit = None – Tells CPLEX to stop as soon as a lower bound larger than this value is found.

• boundMonitor = True – Tells CPLEX to store information about the evolution of the bounds during the solving process. At the end of the computation, a list of triples (time,lowerbound,upperbound) will be provided in the field bounds_monitor` of the dictionary returned by solve.

• Specific options available for CVXOPT, SMCP and ECOS:

• feastol = None – Feasibility tolerance passed to cvx.solvers.options If None, then the value of the option tol is used.

• abstol = None – Absolute tolerance passed to cvx.solvers.options If None, then the value of the option tol is used.

• reltol = None – relative tolerance passed to cvx.solvers.options If None, then ten times the value of the option tol is used.

• Specific options available for Gurobi:

• gurobi_params = {} – A dictionary of Gurobi parameters to be set before the Gurobi optimizer is called.

For example, gurobi_params = {'NodeLimit': 25} limits the number of nodes visited by the MIP optimizer to 25.

• Specific options available for MOSEK:

• Specific options available for SCIP:

• scip_params = {} – A dictionary of SCIP parameters to be set before the SCIP optimizer is called.

For example, scip_params = {'lp/threads': 4} sets the number of threads to solve LPs with to 4.

Note

Options can also be passed as a parameter sequence of the form key = value when the Problem is created or later to the function solve.

set_var_value(name, value, optimalvar=False)

Sets the value of the given variable.

Parameters
• or tuple name (str) – Name of the variable.

• value (Anything recognized by retrieve_matrix) – The value to be set.

Example

>>> prob=picos.Problem()
>>> prob.set_var_value('x', [3,4]) # equivalent to x.value = [3,4]
>>> abs(x)**2
>>> print(abs(x)**2)
25.0

Note

The hotstart option allows certain solvers to leverage variables that were valued manually or by a preceding solution search.

solve(**options)

Hands the problem to a solver.

You can select the solver manually with the solver option. Otherwise a suitable solver will be selected among those that are available on the platform.

Once the problem has been solved, the optimal solution can be obtained by querying the value property of the variables and the optimal dual values can be accessed via the dual property of the constraints.

Parameters

options – A sequence of optional solver options. In particular, you can use this to select a solver via the solver option.

Returns

A dictionary that contains the following common entries, and potentially further solver-specific or option-specific fields:

• 'status' – The solution status as a human readable string, such as 'optimal' or 'infeasible'. The exact wording and available phrases depend on the solver being used.

• 'time' – The time spent searching for a solution in seconds, excluding any overhead produced by PICOS when exporting the problem or configuring the solver.

• 'primals' – A dictionary mapping PICOS variables to their value in the solution produced by the solver.

• 'duals' – A list of dual values produced by the solver, in the order in which the constraints were added.

Warning

Any supplied options will be stored in the problem as if they were set via set_option.

Note

If the problem is dualized or cast as a SOCP during solution search, then it will be solved from scratch upon subsequent searches, even if the solver supports problem updates efficiently.

update_options(**options)

Sets multiple solver options at once.

Parameters

options – A parameter sequence of the form key = value.

For a list of available options and their default values, see the documentation of set_option.

verbosity()
Returns

The problem’s current verbosity level.

write_to_file(filename, writer='picos')

Writes the problem to a file.

Parameters
• filename (str) –

Path and name of the output file. The export format is inferred from the file extension. Supported extensions and their associated format are:

• '.cbf' – Conic Benchmark Format.

This format is suitable for optimization problems involving second order and/or semidefinite cone constraints. This is a standard choice for conic optimization problems. Visit the website of The Conic Benchmark Library or read A benchmark library for conic mixed-integer and continuous optimization by Henrik A. Friberg for more information.

• '.lp'LP format.

This format handles only linear constraints, unless the writer 'cplex' is used. In the latter case the extended CPLEX LP format is used instead.

• '.mps'MPS format.

As the writer, you need to choose one of 'cplex', 'gurobi' or 'mosek'.

• '.opf'OPF format.

As the writer, you need to choose 'mosek'.

• '.dat-s'Sparse SDPA format.

This format is suitable for semidefinite programs. Second order cone constraints are stored as semidefinite constraints on an arrow shaped matrix.

• writer (str) – The default 'picos' denotes PICOS’ internal writer, which can export to LP, CBF, and Sparse SDPA formats. If CPLEX, Gurobi or MOSEK is installed, you can choose 'cplex', 'gurobi', or 'mosek', respectively, to make use of that solver’s export function and get access to more formats.

Warning

For problems involving a symmetric matrix variable (typically, semidefinite programs), the expressions involving are stored in PICOS as a function of , the symmetric vectorized form of (see Dattorro, ch.2.2.2.1), and are also exported in that form. As a result, using an external solver on a problem description file exported by PICOS will also yield a solution in this symmetric vectorized form.

The CBF writer tries to write symmetric variables in the section PSDVAR of the .cbf file. However, this is possible only if the constraint appears in the problem, and no other LMI involves . If these two conditions are not satisfied, then the symmetric vectorization of is used as a (free) variable of the section VAR in the .cbf file, as explained in the previous paragraph.

property options
property status

The solution status of the problem.

property type

The problem type as a string, such as ‘LP’, ‘MILP’ or ‘SOCP’.