Middle-End Reductions

The reductions listed here are not specific to a type of solver. They can be applied regardless of whether you wish to target, for example, a quadratic program solver or a conic solver.

Please see our disclaimer about the Reductions API before using these directly in your code.

Complex2Real

class cvxpy.reductions.complex2real.complex2real.Complex2Real[source]

Bases: Reduction

Lifts complex numbers to a real representation.

For DPP (Disciplined Parameterized Programming) support, this reduction tracks complex parameter mappings in canon_methods._parameters. At solve time, the real/imaginary parameter values are set from the original complex parameter values.

accepts(problem) bool[source]

States whether the reduction accepts a problem.

Parameters:
problem : Problem

The problem to check.

Returns:

True if the reduction can be applied, False otherwise.

Return type:

bool

apply(problem)[source]

Applies the reduction to a problem and returns an equivalent problem.

Parameters:
problem : Problem

The problem to which the reduction will be applied.

Returns:

  • Problem or dict – An equivalent problem, encoded either as a Problem or a dict.

  • InverseData, list or dict – Data needed by the reduction in order to invert this particular application.

invert(solution, inverse_data)[source]

Returns a solution to the original problem given the inverse_data.

Parameters:
solution : Solution

A solution to a problem that generated the inverse_data.

inverse_data

The data encoding the original problem.

Returns:

A solution to the original problem.

Return type:

Solution

param_backward(dparams)[source]

Combine real/imag gradients into complex gradient for backward diff.

For complex param -> (real_param, imag_param), we compute: param.gradient = dL/d(real_param) + 1j * dL/d(imag_param)

This follows PyTorch’s convention for complex gradients, treating the complex parameter as a pair of independent real parameters. This is the gradient needed for gradient descent (p -= lr * p.gradient).

Note: This is NOT the Wirtinger derivative. For Wirtinger calculus, dL/dz = (dL/da - j*dL/db)/2 for z = a + jb.

For Hermitian parameters, the imaginary gradient is stored in compact form (strict upper triangle) and must be expanded to skew-symmetric.

param_forward(param_deltas)[source]

Split complex deltas into real/imag deltas for forward diff.

For complex param -> (real_param, imag_param), we split the complex perturbation into its real and imaginary components: real_param.delta = Re(param.delta), imag_param.delta = Im(param.delta)

This treats the complex parameter as a pair of independent real parameters, consistent with the backward pass convention.

For Hermitian parameters, the imaginary delta is extracted as the strict upper triangle of the skew-symmetric imaginary part.

property param_id_map

Map from original to reduced parameter IDs.

Reductions that replace parameters (e.g., CvxAttr2Constr, Dgp2Dcp) override this to expose their mapping. Used by Chain.compose_param_id_map() to build a global mapping across the full reduction chain.

Returns:

{orig_param_id: [new_param_id, ...]} for every parameter that was replaced. Default: empty dict (no parameters replaced).

Return type:

dict

update_parameters(problem) None[source]

Update real/imag parameter values from complex parameters.

Called at solve time in the DPP fast path. Complex parameters are split into real/imag parameter pairs during canonicalization; this method sets their values from the original complex parameter values.

For Hermitian parameters, the imaginary part uses a compact representation (strict upper triangle only), so we extract those elements from the skew-symmetric imaginary part.

var_backward(del_vars)[source]

Split complex gradients into real/imag gradients for backward diff.

Transforms from outer (original complex) var IDs to inner (real/imag) var IDs.

var_forward(dvars)[source]

Combine real/imag deltas into complex deltas for forward diff.

Transforms from inner (real/imag) var IDs to outer (original complex) var IDs.

property var_id_map

Map from original to reduced variable IDs.

Reductions that replace variables (e.g., CvxAttr2Constr) override this to expose their mapping. Used by Chain.compose_var_id_map() to build a global mapping across the full reduction chain.

Returns:

{orig_var_id: [new_var_id, ...]} for every variable that was replaced. The list has one element for 1:1 mappings and multiple elements for 1:many (e.g., Complex2Real splits a complex variable into real and imaginary parts). Default: empty dict (no variables replaced).

Return type:

dict

CvxAttr2Constr

class cvxpy.reductions.cvx_attr2constr.CvxAttr2Constr(problem=None, reduce_bounds: bool = False)[source]

Bases: Reduction

Expand convex variable attributes into constraints.

accepts(problem) bool[source]

States whether the reduction accepts a problem.

Parameters:
problem : Problem

The problem to check.

Returns:

True if the reduction can be applied, False otherwise.

Return type:

bool

apply(problem)[source]

Applies the reduction to a problem and returns an equivalent problem.

Parameters:
problem : Problem

The problem to which the reduction will be applied.

Returns:

  • Problem or dict – An equivalent problem, encoded either as a Problem or a dict.

  • InverseData, list or dict – Data needed by the reduction in order to invert this particular application.

invert(solution, inverse_data) Solution[source]

Returns a solution to the original problem given the inverse_data.

Parameters:
solution : Solution

A solution to a problem that generated the inverse_data.

inverse_data

The data encoding the original problem.

Returns:

A solution to the original problem.

Return type:

Solution

param_backward(dparams)[source]

Recover full-size gradients from reduced-size gradients.

param_forward(param_deltas)[source]

Transform full-size deltas to reduced-size deltas.

property param_id_map

Map from original to reduced parameter IDs.

Reductions that replace parameters (e.g., CvxAttr2Constr, Dgp2Dcp) override this to expose their mapping. Used by Chain.compose_param_id_map() to build a global mapping across the full reduction chain.

Returns:

{orig_param_id: [new_param_id, ...]} for every parameter that was replaced. Default: empty dict (no parameters replaced).

Return type:

dict

reduction_attributes() list[str][source]

Returns the attributes that will be reduced.

update_parameters(problem) None[source]

Update reduced parameter values from original parameters.

var_backward(del_vars)[source]

Transform variable gradients from outer (original) to inner (reduced).

var_forward(dvars)[source]

Transform variable deltas from inner (reduced) to outer (original).

property var_id_map

Map from original to reduced variable IDs.

Reductions that replace variables (e.g., CvxAttr2Constr) override this to expose their mapping. Used by Chain.compose_var_id_map() to build a global mapping across the full reduction chain.

Returns:

{orig_var_id: [new_var_id, ...]} for every variable that was replaced. The list has one element for 1:1 mappings and multiple elements for 1:many (e.g., Complex2Real splits a complex variable into real and imaginary parts). Default: empty dict (no variables replaced).

Return type:

dict

Dgp2Dcp

class cvxpy.reductions.dgp2dcp.dgp2dcp.Dgp2Dcp(problem=None)[source]

Bases: Canonicalization

Reduce DGP problems to DCP problems.

This reduction takes as input a DGP problem and returns an equivalent DCP problem. Because every (generalized) geometric program is a DGP problem, this reduction can be used to convert geometric programs into convex form.

Example

>>> import cvxpy as cp
>>>
>>> x1 = cp.Variable(pos=True)
>>> x2 = cp.Variable(pos=True)
>>> x3 = cp.Variable(pos=True)
>>>
>>> monomial = 3.0 * x_1**0.4 * x_2 ** 0.2 * x_3 ** -1.4
>>> posynomial = monomial + 2.0 * x_1 * x_2
>>> dgp_problem = cp.Problem(cp.Minimize(posynomial), [monomial == 4.0])
>>>
>>> dcp2cone = cvxpy.reductions.Dcp2Cone()
>>> assert not dcp2cone.accepts(dgp_problem)
>>>
>>> gp2dcp = cvxpy.reductions.Dgp2Dcp(dgp_problem)
>>> dcp_problem = gp2dcp.reduce()
>>>
>>> assert dcp2cone.accepts(dcp_problem)
>>> dcp_problem.solve()
>>>
>>> dgp_problem.unpack(gp2dcp.retrieve(dcp_problem.solution))
>>> print(dgp_problem.value)
>>> print(dgp_problem.variables())
accepts(problem)[source]

A problem is accepted if it is DGP.

apply(problem)[source]

Converts a DGP problem to a DCP problem.

canonicalize_expr(expr: Expression, args: list, canonicalize_params: bool = True)[source]

Canonicalize an expression, w.r.t. canonicalized arguments.

Parameters:
expr: Expression

Expression to canonicalize.

args: list

Arguments to the expression.

canonicalize_params: bool = True

Should constant subtrees containing parameters be canonicalized?

Returns:

canonicalized expression, constraints

invert(solution, inverse_data)[source]

Returns a solution to the original problem given the inverse_data.

Parameters:
solution : Solution

A solution to a problem that generated the inverse_data.

inverse_data

The data encoding the original problem.

Returns:

A solution to the original problem.

Return type:

Solution

param_backward(dparams)[source]

Apply chain rule for log transformation in backward diff.

For DGP, param -> log(param), so d(loss)/d(log_param) contributes (1/param) * grad to the original parameter. The original parameter may also appear directly (e.g. as an exponent in power atoms), so we add the log-transformed gradient to any existing direct gradient.

param_forward(param_deltas)[source]

Apply chain rule for log transformation in forward diff.

For DGP, param -> log(param), so d(log_param) = d(param) / param. The original parameter may also appear directly (e.g. as an exponent in power atoms), so we keep the original delta and add the log-transformed delta.

property param_id_map

Map from original to reduced parameter IDs.

Reductions that replace parameters (e.g., CvxAttr2Constr, Dgp2Dcp) override this to expose their mapping. Used by Chain.compose_param_id_map() to build a global mapping across the full reduction chain.

Returns:

{orig_param_id: [new_param_id, ...]} for every parameter that was replaced. Default: empty dict (no parameters replaced).

Return type:

dict

update_parameters(problem) None[source]

Update log-parameter values from original parameters.

Called at solve time in the DPP fast path. Parameters are transformed to log-space during canonicalization; this method sets the log-parameter values from the original parameter values.

var_backward(del_vars)[source]

Apply chain rule for exp transformation in backward diff.

DGP variables are reparameterized as x_gp = exp(x_log), where x_log is the log-space variable that the downstream cone program actually optimizes over. Therefore dx_gp/dx_log = exp(x_log) = x_gp. Transforms from outer (original) var IDs to inner (log-space) var IDs.

var_forward(dvars)[source]

Apply chain rule for exp transformation in forward diff.

DGP variables are reparameterized as x_gp = exp(x_log), where x_log is the log-space variable that the downstream cone program actually optimizes over. Therefore dx_gp/dx_log = exp(x_log) = x_gp. Transforms from inner (log-space) var IDs to outer (original) var IDs.

property var_id_map

Map from original to reduced variable IDs.

Reductions that replace variables (e.g., CvxAttr2Constr) override this to expose their mapping. Used by Chain.compose_var_id_map() to build a global mapping across the full reduction chain.

Returns:

{orig_var_id: [new_var_id, ...]} for every variable that was replaced. The list has one element for 1:1 mappings and multiple elements for 1:many (e.g., Complex2Real splits a complex variable into real and imaginary parts). Default: empty dict (no variables replaced).

Return type:

dict

EvalParams

class cvxpy.reductions.eval_params.EvalParams(problem=None)[source]

Bases: Reduction

Replaces symbolic parameters with their constant values.

accepts(problem) bool[source]

States whether the reduction accepts a problem.

Parameters:
problem : Problem

The problem to check.

Returns:

True if the reduction can be applied, False otherwise.

Return type:

bool

apply(problem)[source]

Replace parameters with constant values.

Parameters:
problem : Problem

The problem whose parameters should be evaluated.

Returns:

A new problem where the parameters have been converted to constants.

Return type:

Problem

Raises:

ParameterError – If the problem has unspecified parameters (i.e., a parameter whose value is None).

invert(solution, inverse_data)[source]

Returns a solution to the original problem given the inverse_data.

FlipObjective

class cvxpy.reductions.flip_objective.FlipObjective(problem=None)[source]

Bases: Reduction

Flip a minimization objective to a maximization and vice versa.

accepts(problem) bool[source]

States whether the reduction accepts a problem.

Parameters:
problem : Problem

The problem to check.

Returns:

True if the reduction can be applied, False otherwise.

Return type:

bool

apply(problem)[source]

\(\max(f(x)) = -\min(-f(x))\)

Parameters:
problem : Problem

The problem whose objective is to be flipped.

Returns:

  • Problem – A problem with a flipped objective.

  • list – The inverse data.

invert(solution, inverse_data)[source]

Map the solution of the flipped problem to that of the original.

Parameters:
solution : Solution

A solution object.

inverse_data : list

The inverse data returned by an invocation to apply.

Returns:

A solution to the original problem.

Return type:

Solution