summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sumofsquares/constraints.py12
-rw-r--r--sumofsquares/problems.py12
-rw-r--r--sumofsquares/solver/scs.py16
3 files changed, 26 insertions, 14 deletions
diff --git a/sumofsquares/constraints.py b/sumofsquares/constraints.py
index f287a23..5f5609f 100644
--- a/sumofsquares/constraints.py
+++ b/sumofsquares/constraints.py
@@ -64,19 +64,17 @@ class NonNegative(Constraint[E]):
the domain in set to `None` then it is interpreted as being non-negative
everywhere.
+ If the expression is a column vector, the interpretation is row-wise. In
+ other words each row must be non-negative on the domain (or everywhere if
+ not specified). In other words the vector is in the non-negative orthant of
+ R^n.
+
**Note:** In this package, non-negativitiy of non-affine constraint will
always eventually be replaced by the sufficient condition that the
expression can be written as a sum-of-squares, hence this constraint can
also be understood as `expression` being SOS.
"""
- # This was part of the docstring but is not implemented yet
- # TODO: implement what is says below
- #
- # If the expression is a column vector, the interpretation is row-wise. In
- # other words each row must be non-negative on the domain (or everywhere if
- # not specified).
-
expression: E
domain: BasicSemialgebraicSet[E] | None = None
diff --git a/sumofsquares/problems.py b/sumofsquares/problems.py
index e6ca747..6737341 100644
--- a/sumofsquares/problems.py
+++ b/sumofsquares/problems.py
@@ -228,9 +228,19 @@ class SOSProblem(Problem):
state, deg = c.expression.degree().apply(state)
+ if isinstance(c.expression.shape[0], int):
+ nrows = c.expression.shape[0]
+ else:
+ state, shape = c.expression.shape[0].apply(state)
+ nrows = shape.at(0, 0).constant()
+
+ # It is a vector column goes in the non-negative orthant
+ if nrows > 1:
+ constraints.append(c)
+
# Polynomial non-negativity contraints is converted to PSD
# constraint of SOS quadratic form
- if deg.scalar().constant() > 1:
+ elif deg.scalar().constant() > 1:
# TODO: it seems to work fine even without .symmetric(). Why?
cnew = c.expression.quadratic_in(x).symmetric()
constraints.append(PositiveSemiDefinite(cnew))
diff --git a/sumofsquares/solver/scs.py b/sumofsquares/solver/scs.py
index faad4e1..7217b2c 100644
--- a/sumofsquares/solver/scs.py
+++ b/sumofsquares/solver/scs.py
@@ -84,9 +84,9 @@ def solve_cone(prob: ConicProblem, verbose: bool = False,
# q second order cone
# s positive semidefinite cone
# ep exponential cone
- # ep* dual exponential cone
+ # ed dual exponential cone
# p power cone
- # p* dual power cone
+ # -p dual power cone
#
# In their documentation they call the linear coefficient c. Here we use q.
@@ -96,11 +96,15 @@ def solve_cone(prob: ConicProblem, verbose: bool = False,
if prob.q is not None:
q = prob.q
- if prob.constraints["z"]:
- raise NotImplementedError
+ for (linear, constant) in prob.constraints["z"]:
+ # -1 because RHS
+ b_rows.append(-constant)
+ A_rows.append(np.hstack(tuple(m for m in linear)))
- if prob.constraints["l"]:
- raise NotImplementedError
+ for (linear, constant) in prob.constraints["l"]:
+ # -1 because RHS
+ b_rows.append(-constant)
+ A_rows.append(np.hstack(tuple(m for m in linear)))
if prob.constraints["b"]:
raise NotImplementedError