summaryrefslogtreecommitdiffstats
path: root/examples/sostools/sosdemo2.py
blob: ece36b70a46393f6dfcd6c85cff712d2ebffb4fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""
Example adapted from SOSTOOLS sosdemo2.

See page 34 of PDF below for details.
https://github.com/oxfordcontrol/SOSTOOLS/blob/SOSTOOLS400/docs/SOSTOOLS_400.pdf
"""
import polymatrix as poly
import sumofsquares as sos

# TODO: Expose Solver class in sumofsquares.__init__
from sumofsquares.abc import Solver

# state variables and dynamics RHS
x1, x2, x3 = poly.from_names("x_1, x_2, x_3")
x = poly.give_name(poly.v_stack((x1, x2, x3)), "x")

f = poly.give_name(poly.v_stack((
    (-x1**3 - x1*x3**2) * (x3**2 + 1),
    (-x2 - x1**2 * x2) * (x3**2 + 1),
    (-x3 + 3*x1**2*x3) * (x3**2 + 1) - 3*x3
)), "f(x) * ((x_3 ** 2) + 1)")

# Create Lyapunov function parametrized by w
monomials = x ** 2
w = sos.from_name("w", shape=monomials.shape)

V = poly.give_name(w.T @ monomials, "V(x)")
dV = V.diff(x)

# Solve SOS problem
constraints = (
    sos.make_sos_constraint(V - (x.T @ x)), # last term to impose definiteness
    sos.make_sos_constraint(- (dV @ f)),
)

prob, state, result = sos.solve_problem(cost=None, constraints=constraints, solver=Solver.CVXOPT)
print(prob)

# TODO: create SolverStatus enumeration
assert result.solver_info.status == "optimal", f"Status {result.solver_info.status}"

V_sol = V.eval(result.values)
print(poly.to_sympy(V_sol).read(poly.make_state()))