diff options
Diffstat (limited to '')
-rw-r--r-- | sumofsquares/constraints.py | 12 | ||||
-rw-r--r-- | sumofsquares/problems.py | 12 | ||||
-rw-r--r-- | sumofsquares/solver/scs.py | 16 |
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 |