summaryrefslogtreecommitdiffstats
path: root/sumofsquares/cvxopt.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sumofsquares/cvxopt.py107
1 files changed, 62 insertions, 45 deletions
diff --git a/sumofsquares/cvxopt.py b/sumofsquares/cvxopt.py
index 4cd803c..6a1339f 100644
--- a/sumofsquares/cvxopt.py
+++ b/sumofsquares/cvxopt.py
@@ -11,7 +11,7 @@ from polymatrix.expression.expression import Expression
from polymatrix.polymatrix.index import MonomialIndex, VariableIndex
from .abc import Problem, SolverInfo
-from .constraints import NonNegative, EqualToZero
+from .constraints import NonNegative, EqualToZero, PositiveSemiDefinite, ExponentialCone
from .variable import OptVariable
@@ -25,7 +25,6 @@ class CVXOPTInfo(SolverInfo, UserDict):
return self[key]
-
def solve_sos_cone(prob: Problem, verbose: bool = False, *args, **kwargs) -> tuple[dict[OptVariable, float], CVXOPTInfo]:
r"""
Solve a conic problem in the cone of SOS polynomials :math:`\mathbf{\Sigma}_d(x)`.
@@ -85,47 +84,54 @@ def solve_sos_cone(prob: Problem, verbose: bool = False, *args, **kwargs) -> tup
x = poly.v_stack(prob.polynomial_variables)
for c in prob.constraints:
- # Convert constraints to affine expression in decision variables
- constr = poly.to_affine(c.expression.quadratic_in(x).read(prob.state))
- if constr.degree > 1:
- raise ValueError("CVXOpt can solve problem with constraints that are "
- f"at most linear, but {str(c.expression)} has degree {constr.degree}.")
-
- # For each constraint we add PSD matrix
- nrows, ncols = constr.shape
- s_dims.append(nrows)
-
- # Constant term
- c_coeff = constr.affine_coefficient(MonomialIndex.constant())
- c_stacked = c_coeff.T.reshape((nrows * ncols,))
-
- # Linear term
- l_stacked_rows = []
- for v in variable_indices.values():
- # Get the affine coefficient associated to this variable
- linear = MonomialIndex((v,))
- v_coeff = constr.affine_coefficient(linear)
-
- # stack the columns of coeff matrix into a fat row vector (column major order).
- v_stacked = v_coeff.T.reshape((nrows * ncols,))
- l_stacked_rows.append(v_stacked)
-
- l_stacked = np.vstack(l_stacked_rows)
-
- if isinstance(c, EqualToZero):
- A_rows.append(l_stacked)
- # Factor of -1 because it is on the right hand side
- b_rows.append(-1 * c_stacked)
-
- elif isinstance(c, NonNegative):
- if c.domain:
- raise ValueError("Cannot convert non-negativity constraint to CVXOPT format. "
- "Domain restricted non-negativity must be "
- "preprocessed by using a Positivstellensatz!")
-
- # Factor of -1 because it is on the right hand side
- G_rows.append(-1 * l_stacked)
- h_rows.append(c_stacked)
+ if isinstance(c, PositiveSemiDefinite):
+ raise NotImplementedError
+
+ elif isinstance(c, ExponentialCone):
+ raise NotImplementedError
+
+ elif isinstance(c, EqualToZero | NonNegative):
+ # Convert constraints to affine expression in decision variables
+ constr = poly.to_affine(c.expression.quadratic_in(x).read(prob.state))
+ if constr.degree > 1:
+ raise ValueError("CVXOpt can solve problem with constraints that are "
+ f"at most linear, but {str(c.expression)} has degree {constr.degree}.")
+
+ # For each constraint we add PSD matrix
+ nrows, ncols = constr.shape
+ s_dims.append(nrows)
+
+ # Constant term
+ c_coeff = constr.affine_coefficient(MonomialIndex.constant())
+ c_stacked = c_coeff.T.reshape((nrows * ncols,))
+
+ # Linear term
+ l_stacked_rows = []
+ for v in variable_indices.values():
+ # Get the affine coefficient associated to this variable
+ linear = MonomialIndex((v,))
+ v_coeff = constr.affine_coefficient(linear)
+
+ # stack the columns of coeff matrix into a fat row vector (column major order).
+ v_stacked = v_coeff.T.reshape((nrows * ncols,))
+ l_stacked_rows.append(v_stacked)
+
+ l_stacked = np.vstack(l_stacked_rows)
+
+ if isinstance(c, EqualToZero):
+ A_rows.append(l_stacked)
+ # Factor of -1 because it is on the right hand side
+ b_rows.append(-1 * c_stacked)
+
+ elif isinstance(c, NonNegative):
+ if c.domain:
+ raise ValueError("Cannot convert non-negativity constraint to CVXOPT format. "
+ "Domain restricted non-negativity must be "
+ "preprocessed by using a Positivstellensatz!")
+
+ # Factor of -1 because it is on the right hand side
+ G_rows.append(-1 * l_stacked)
+ h_rows.append(c_stacked)
else:
raise NotImplementedError(f"Cannot convert constraint of type {type(c)} "
@@ -139,17 +145,28 @@ def solve_sos_cone(prob: Problem, verbose: bool = False, *args, **kwargs) -> tup
b = cvxopt.matrix(np.hstack(b_rows)) if b_rows else None
dims = {'l': l_dims, 'q': q_dims, 's': s_dims}
+ # print(q)
+ # print(G)
+ # print(h)
+ # print(A)
+ # print(b)
+ # print(dims)
+
cvxopt.solvers.options['show_progress'] = verbose
if not any((G, h, A, b)):
raise ValueError("Optimization problem is unconstrained!")
+ # Add matrices for debugging
+ # info = {}
+ info = {"q": q, "G": G, "h": h, "A": A, "b": b, "dims": dims}
+
if is_qp:
P = cvxopt.matrix(P)
- info = cvxopt.solvers.coneqp(P=P, q=q, G=G, h=h, A=A, b=b,
+ info |= cvxopt.solvers.coneqp(P=P, q=q, G=G, h=h, A=A, b=b,
dims=dims, *args, **kwargs)
else:
- info = cvxopt.solvers.conelp(c=q, G=G, h=h, A=A, b=b,
+ info |= cvxopt.solvers.conelp(c=q, G=G, h=h, A=A, b=b,
*args, **kwargs)
results = {}