Skip to content

Commit bc88e97

Browse files
committed
Remove almost zero terms
1 parent f6ec125 commit bc88e97

File tree

1 file changed

+57
-17
lines changed

1 file changed

+57
-17
lines changed

docs/src/tutorials/Systems and Control/quadrotor.jl

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,17 @@ n_u = size(g, 2)
5757
using SumOfSquares
5858
rectangle = [1.7, 0.85, 0.8, 1, π/12, π/2, 1.5, π/12]
5959
X = BasicSemialgebraicSet(FullSpace(), typeof(x[1] + 1.0)[])
60-
for i in eachindex(x)
61-
lower = x[i] + rectangle[i] # x[i] >= -rectangle[i]
62-
upper = rectangle[i] - x[i] # x[i] <= rectangle[i]
63-
addinequality!(X, lower * upper) # -rectangle[i] <= x[i] <= rectangle[i]
60+
function rect(vars, bounds)
61+
R = BasicSemialgebraicSet(FullSpace(), typeof(vars[1] + 1.0)[])
62+
for (var, bound) in zip(vars, bounds)
63+
lower = var + bound # var >= -bound
64+
upper = bound - var # var <= bound
65+
addinequality!(R, lower * upper) # -bound <= var <= bound
66+
end
67+
return R
6468
end
65-
X
69+
X = rect(x, rectangle[1:n_x])
70+
U = rect(u, rectangle[n_x .+ (1:n_u)])
6671

6772
## Controller for the linearized system
6873

@@ -101,19 +106,25 @@ P, _, _ = MatrixEquations.arec(A - B * K, 0.0, 10.0)
101106

102107
V0 = x' * P * x
103108

109+
# We can see that many terms have a coefficient that is almost zero:
110+
111+
zero_V0 = [monomial(t) for t in terms(V0) if abs(DynamicPolynomials.coefficient(t)) < 1e-8] #src
112+
[monomial(t) for t in terms(V0) if abs(DynamicPolynomials.coefficient(t)) < 1e-8]
113+
114+
# This might cause troubles in the optimization so let's drop them:
115+
116+
V0 = mapcoefficients(c -> (abs(c) < 1e-8 ? 0.0 : c), V0)
117+
104118
# ## γ-step
105119

106120
# It is a Lyapunov function for the linear system but not necessarily for the nonlinear system as well.
107121
# We can however say that the γ-sublevel set `{x | x' P x ≤ γ}` is a (trivial) controlled invariant set for `γ = 0` (since it is empty).
108122
# We can try to see if there a larger `γ` such that the γ-sublevel set is also controlled invariant using
109123
# the γ step of [YAP21, Algorithm 1]
110124

111-
function _create(model, d, P)
125+
function _create(model, d)
112126
if d isa Int
113-
if P == SOSPoly # `d` is the maxdegree while for `SOSPoly`,
114-
d = div(d, 2) # it is the monomial basis of the squares
115-
end
116-
return @variable(model, variable_type = P(monomials(x, 0:d)))
127+
return @variable(model, variable_type = Poly(monomials(x, 0:d)))
117128
else
118129
return d
119130
end
@@ -122,11 +133,16 @@ end
122133
using LinearAlgebra
123134
function base_model(solver, V, k, s3, γ)
124135
model = SOSModel(solver)
125-
V = _create(model, V, Poly)
126-
k = _create.(model, k, Poly)
127-
s3 = _create(model, s3, SOSPoly)
136+
V = _create(model, V)
137+
k = _create.(model, k)
128138
= differentiate # Let's use a fancy shortcut
129-
@constraint(model, (V, x) (f + g * k) <= s3 * (V - γ)) # [YAP21, (E.2)]
139+
dV = (V, x) (f + g * k)
140+
# [YAP21, (E.2)]
141+
if s3 isa Int
142+
@constraint(model, con, dV <= 0, domain = @set(V <= γ))
143+
else
144+
@constraint(model, dV <= s3 * (V - γ))
145+
end
130146
for r in inequalities(X) # `{V ≤ γ} ⊆ {r ≥ 0}` iff `r ≤ 0 => V ≥ γ`
131147
@constraint(model, V >= γ, domain = @set(r <= 0)) # [YAP21, (E.3)]
132148
end
@@ -152,7 +168,7 @@ function γ_step(solver, V, γ_min, degree_k, degree_s3; γ_tol = 1e-1, max_iter
152168
else
153169
break
154170
end
155-
model, V, k, s3 = base_model(solver, V, degree_k, degree_s3, γ)
171+
model, V, k = base_model(solver, V, degree_k, degree_s3, γ)
156172
num_iters += 1
157173
@info("Iteration $num_iters/$max_iters : Solving with $(solver_name(model)) for `γ = `")
158174
optimize!(model)
@@ -161,7 +177,7 @@ function γ_step(solver, V, γ_min, degree_k, degree_s3; γ_tol = 1e-1, max_iter
161177
@info("Feasible solution found : primal is $(primal_status(model))")
162178
γ_min = γ
163179
k_best = value.(k)
164-
s3_best = value(s3)
180+
s3_best = lagrangian_multipliers(model[:con])[1]
165181
elseif dual_status(model) == MOI.INFEASIBILITY_CERTIFICATE
166182
@info("Infeasibility certificate found : dual is $(dual_status(model))")
167183
if γ == γ0_min # This corresponds to the case above where we reached the tol or max iteration and we just did a last run at the value of `γ_min` provided by the user
@@ -186,6 +202,15 @@ import CSDP
186202
solver = optimizer_with_attributes(CSDP.Optimizer, MOI.Silent() => true)
187203
γ1, κ1, s3_1 = γ_step(solver, V0, 0.0, [2, 2], 2)
188204
@test γ1 0.5 atol = 1.e-1 #src
205+
nothing # hide
206+
207+
# The best `γ` found is
208+
209+
γ1
210+
211+
# with state feedback:
212+
213+
κ1
189214

190215
# Let's visualize now the controlled invariant set we have found:
191216

@@ -231,9 +256,12 @@ function V_step(solver, V0, γ, k, s3)
231256
end
232257

233258
model, V1 = V_step(solver, V0, γ1, κ1, s3_1)
234-
solution_summary(model)
259+
nothing # hide
235260

236261
# We can see that the solver found a feasible solution.
262+
263+
solution_summary(model)
264+
237265
# Let's compare it:
238266

239267
push!(Vs, V1 - γ1)
@@ -246,6 +274,7 @@ plot_lyapunovs(Vs, [1, 2])
246274
# want to find a better `κ` so let's set `max_iters` to zero
247275

248276
γ2, κ2, s3_2 = γ_step(solver, V0, γ1, [2, 2], 2, max_iters = 0)
277+
nothing # hide
249278

250279
# Let's see if this new controller allows to find a better Lyapunov.
251280

@@ -330,6 +359,17 @@ eigen(Symmetric(Px * (A + B * K) + (A + B * K)' * Px)).values
330359

331360
support_V0 = x' * Px * x
332361

362+
# We can see that `support_V0` shares the same monomial with almost zero coefficient
363+
# with `V0`.
364+
365+
zero_support_V0 = [monomial(t) for t in terms(support_V0) if abs(DynamicPolynomials.coefficient(t)) < 1e-8] #src
366+
@test zero_support_V0 == zero_V0
367+
[monomial(t) for t in terms(support_V0) if abs(DynamicPolynomials.coefficient(t)) < 1e-8]
368+
369+
# Let's drop them for `support_V0` as well:
370+
371+
support_V0 = mapcoefficients(c -> (abs(c) < 1e-8 ? 0.0 : c), support_V0)
372+
333373
# `support_V0 - 1` is a controlled invariant set for the linearized system
334374
# but not for the nonlinear one. We can plot it to visualize but
335375
# it is not comparable to the ones found before which were

0 commit comments

Comments
 (0)