@@ -157,13 +157,13 @@ function γ_step(solver, V, γ_min, degree_k, degree_s3; γ_tol = 1e-1, max_iter
157157 @info (" Iteration $num_iters /$max_iters : Solving with $(solver_name (model)) for `γ = $γ `" )
158158 optimize! (model)
159159 @info (" After $(solve_time (model)) seconds, terminated with $(termination_status (model)) ($(raw_status (model)) )" )
160- if primal_status (model) == MOI. FEASIBLE_POINT
161- @info (" Feasible solution found" )
160+ if primal_status (model) == MOI. FEASIBLE_POINT || primal_status (model) == MOI . NEARLY_FEASIBLE_POINT
161+ @info (" Feasible solution found : primal is $( primal_status (model)) " )
162162 γ_min = γ
163163 k_best = value .(k)
164164 s3_best = value (s3)
165165 elseif dual_status (model) == MOI. INFEASIBILITY_CERTIFICATE
166- @info (" Infeasibility certificate found" )
166+ @info (" Infeasibility certificate found : dual is $( dual_status (model)) " )
167167 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
168168 error (" The value `$γ0_min ` of `γ_min` provided is not feasible" )
169169 end
@@ -256,3 +256,89 @@ solution_summary(model)
256256
257257push! (Vs, V2 - γ2)
258258plot_lyapunovs (Vs, [1 , 2 ])
259+
260+ # ## Different starting point
261+
262+ # The LQR regulator we computed as starting point does not take the
263+ # the constraints `X` into account.
264+ # To take the constraint into account,
265+ # we compute an ellipsoidal control invariant set using [LJ21, Corollary 9]
266+ # For this, we first compute the descriptor system described in [LJ21, Proposition 5].
267+ #
268+ # [LJ21] Legat, Benoît, and Jungers, Raphaël M.
269+ # *Geometric control of algebraic systems.*
270+ # IFAC-PapersOnLine 54.5 (2021): 79-84.
271+
272+ nD = n_x + n_u
273+ E = sparse (1 : n_x, 1 : n_x, ones (n_x), n_x, nD)
274+ C = [A B]
275+
276+ # We know solve [LJ21, (13)]
277+
278+ using LinearAlgebra
279+ model = Model (solver)
280+ @variable (model, Q[1 : nD, 1 : nD] in PSDCone ())
281+ cref = @constraint (model, Symmetric (- C * Q * E' - E * Q * C' ) in PSDCone ())
282+ @constraint (model, rect_ref[i in 1 : nD], Q[i, i] <= rectangle[i]^ 2 )
283+ @variable (model, volume)
284+ q = [Q[i, j] for j in 1 : nD for i in 1 : j]
285+ @constraint (model, [volume; q] in MOI. RootDetConeTriangle (nD))
286+ @objective (model, Max, volume)
287+ optimize! (model)
288+ solution_summary (model)
289+
290+ # We now have the control-Lyapunov function `V(x, u) = [x, u]' inv(Q) [x, u]`.
291+ # In other words, The 1-sublevel set of `V(x, u)` is an invariant subset of `rectangle`
292+ # with any state-feedback `κ(x)` such that `V(x, κ(x)) ≤ 1` for any `x` such that
293+ # `min_u V(x, u) ≤ 1`.
294+ # Such candidate `κ(x)` can therefore be chosen as `argmin_u V(x, u)`.
295+ # Let `inv(Q) = U' * U` where `U = [Ux Uu]`. We have `V(x, u) = ||Ux * x + Uu * u||_2`.
296+ # `κ(x)` is therefore the least-square solution of `Uu * κ(x) = -Ux * x`.
297+ # This we find the linear state-feedback `κ(x) = K * x` where `K = -Uu \ Ux`.
298+
299+ P = inv (Symmetric (value .(Q)))
300+ using LinearAlgebra
301+ F = cholesky (P)
302+ K = - F. U[:, (n_x + 1 ): (nD)] \ F. U[:, 1 : n_x] # That gives the following state feedback in polynomial form:
303+
304+ # The corresponding polynomial form is given by:
305+
306+ κ0 = K * x
307+
308+ # We now have two equivalent ways to obtain the Lyapunov function.
309+ # Because `{V(x) ≤ 1} = {min_u V(x, u) ≤ 1}`,
310+ # see the left-hand side as the projection of the ellipsoid on `x, u`.
311+ # As the projection on the polar becomes simply cutting with the hyperplane `u = 0`,
312+ # the polar of the projection is simply `Q[1:6, 1:6]` ! So
313+
314+ Px = inv (Symmetric (value .(Q[1 : n_x, 1 : n_x])))
315+ Px_inv = Px # src
316+
317+ # An alternative way is to use our linear state feedback.
318+ # We know that `min_u V(x, u) = V(x, Kx)` so
319+ Px = [I; K]' * P * [I; K]
320+ @test Px ≈ Px_inv # src
321+
322+ # We can double check that this matrix is negative definite:
323+
324+ eigen (Symmetric (Px * (A + B * K) + (A + B * K)' * Px)). values
325+ @test all (v -> v < 0 , eigen (Symmetric (Px * (A + B * K) + (A + B * K)' * Px)). values) # src
326+
327+ # Let's use the `support_` prefix to differentiate since we obtained it
328+ # with the support function.
329+ # The corresponding Lyapunov is:
330+
331+ support_V0 = x' * Px * x
332+
333+ # `support_V0 - 1` is a controlled invariant set for the linearized system
334+ # but not for the nonlinear one. We can plot it to visualize but
335+ # it is not comparable to the ones found before which were
336+ # controlled invariant to the nonlinear system.
337+
338+ support_Vs = [support_V0 - 1 ]
339+ plot_lyapunovs (support_Vs, [1 , 2 ])
340+
341+ support_γ1, support_κ1, support_s3_1 = γ_step (solver, support_V0, 0.0 , [2 , 2 ], 2 )
342+ @test support_γ1 ≈ 0.0 atol = 1.e-1 # src
343+
344+ # We do not find it for any positive `γ` so the controlled invariant set is an empty set.
0 commit comments