7.3 Power Cone Optimization¶
Conic optimization is a generalization of linear optimization, allowing constraints of the type
where \(x^t\) is a subset of the problem variables and \(\K_t\) is a convex cone. Since the set \(\real^n\) of real numbers is also a convex cone, we can simply write a compound conic constraint \(x\in \K\) where \(\K=\K_1\times\cdots\times\K_l\) is a product of smaller cones and \(x\) is the full problem variable.
MOSEK can solve conic optimization problems of the form
where the domain restriction, \(x \in \K\), implies that all variables are partitioned into convex cones
In this tutorial we describe how to use the power cone. The primal power cone of dimension \(n\) with parameter \(0<\alpha<1\) is defined as:
In particular, the most important special case is the three-dimensional power cone family:
For example, the conic constraint \((x,y,z)\in\POW_3^{0.25,0.75}\) is equivalent to \(x^{0.25}y^{0.75}\geq |z|\), or simply \(xy^3\geq z^4\) with \(x,y\geq 0\).
MOSEK also supports the dual power cone:
For other types of cones supported by MOSEK see Sec. 7.2 (Conic Quadratic Optimization), Sec. 7.4 (Conic Exponential Optimization), Sec. 7.5 (Semidefinite Optimization). See Domain
for a list and definitions of available cone types. Different cone types can appear together in one optimization problem.
In Fusion the coordinates of a cone are not restricted to single variables. They can be arbitrary linear expressions, and an auxiliary variable will be substituted by Fusion in a way transparent to the user.
7.3.1 Example POW1¶
Consider the following optimization problem which involves powers of variables:
With \((x,y,z)=(x_0,x_1,x_2)\) we convert it into conic form using auxiliary variables as bounds for the power expressions:
We start by creating the optimization model:
with Model('pow1') as M:
We then define the variable x
corresponding to the original problem (7.3), and auxiliary variables appearing in the conic reformulation (7.4).
x = M.variable('x', 3, Domain.unbounded())
x3 = M.variable()
x4 = M.variable()
The linear constraint is defined using the dot product operator Expr.dot
:
# Create the linear constraint
M.constraint(Expr.dot(x, [1.0, 1.0, 0.5]), Domain.equalsTo(2.0))
The primal power cone is referred to via Domain.inPPowerCone
with an appropriate list of variables or expressions in each case.
# Create the power cone constraints
M.constraint(Var.vstack(x.slice(0,2), x3), Domain.inPPowerCone(0.2))
M.constraint(Expr.vstack(x.index(2), 1.0, x4), Domain.inPPowerCone(0.4))
We only need the objective function:
# Set the objective function
M.objective(ObjectiveSense.Maximize, Expr.dot([1.0,1.0,-1.0], Var.vstack(x3, x4, x.index(0))))
Calling the Model.solve
method invokes the solver:
M.solve()
The primal and dual solution values can be retrieved using Variable.level
, Constraint.level
and Variable.dual
, Constraint.dual
. Here we just display the primal solution
# Get the linear solution values
solx = x.level()
print('x,y,z = %s' % str(solx))
which is
[ 0.06389298 0.78308564 2.30604283 ]
from mosek.fusion import *
with Model('pow1') as M:
x = M.variable('x', 3, Domain.unbounded())
x3 = M.variable()
x4 = M.variable()
# Create the linear constraint
M.constraint(Expr.dot(x, [1.0, 1.0, 0.5]), Domain.equalsTo(2.0))
# Create the power cone constraints
M.constraint(Var.vstack(x.slice(0,2), x3), Domain.inPPowerCone(0.2))
M.constraint(Expr.vstack(x.index(2), 1.0, x4), Domain.inPPowerCone(0.4))
# Set the objective function
M.objective(ObjectiveSense.Maximize, Expr.dot([1.0,1.0,-1.0], Var.vstack(x3, x4, x.index(0))))
# Solve the problem
M.solve()
# Get the linear solution values
solx = x.level()
print('x,y,z = %s' % str(solx))