Skip to content

Commit 51cc8ad

Browse files
authored
Merge pull request #298 from JuliaControl/lagrange_multiplier
added: fetching actual `LangrangeMultiplier` in `getinfo`
2 parents 399968e + 375ccdf commit 51cc8ad

File tree

4 files changed

+50
-31
lines changed

4 files changed

+50
-31
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "ModelPredictiveControl"
22
uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c"
3-
version = "1.14.1"
3+
version = "1.14.2"
44
authors = ["Francis Gagnon"]
55

66
[deps]

src/controller/execute.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,6 @@ are also available:
119119
- `:∇geq` or *`:nablageq`* : optimal Jacobian of the equality constraint, ``\mathbf{\nabla g_{eq}}``
120120
- `:∇²ℓgeq` or *`:nabla2lgeq`* : optimal Hessian of the equality Lagrangian, ``\mathbf{\nabla^2}\ell_{\mathbf{g_{eq}}}``
121121
122-
Note that retrieving optimal Hessians of Lagrangian are not fully supported yet. Their
123-
nonzero coefficients are random values for now.
124-
125122
# Examples
126123
```jldoctest
127124
julia> mpc = LinMPC(LinModel(tf(5, [2, 1]), 3), Nwt=[0], Hp=1, Hc=1);

src/controller/nonlinmpc.jl

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -587,22 +587,31 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
587587
end
588588
g, ∇g = value_and_jacobian(g!, g, mpc.jacobian, mpc.Z̃, ∇g_cache...)
589589
if !isnothing(mpc.hessian) && any(old_i_g)
590-
@warn(
591-
"Retrieving optimal Hessian of the Lagrangian is not fully supported yet.\n"*
592-
"Its nonzero coefficients are random values for now.", maxlog=1
593-
)
594-
function ℓ_g(Z̃, λ, ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K0, X̂0, gc, geq, g)
595-
update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K0, X̂0, gc, g, geq, mpc, Z̃)
596-
return dot(λ, g)
590+
nonlincon = optim[:nonlinconstraint]
591+
λi = try
592+
JuMP.get_attribute(nonlincon, MOI.LagrangeMultiplier())
593+
catch err
594+
if err isa MOI.GetAttributeNotAllowed{MOI.LagrangeMultiplier}
595+
@warn(
596+
"The optimizer does not support retrieving optimal Hessian of the Lagrangian.\n"*
597+
"Its nonzero coefficients will be random values.", maxlog=1
598+
)
599+
rand(sum(old_i_g))
600+
else
601+
rethrow()
602+
end
597603
end
604+
λ = zeros(NT, ng)
605+
λ[old_i_g] = λi
598606
∇²g_cache = (
599607
Cache(ΔŨ), Cache(x̂0end), Cache(Ue), Cache(Ŷe), Cache(U0), Cache(Ŷ0),
600608
Cache(Û0), Cache(K0), Cache(X̂0),
601609
Cache(gc), Cache(geq), Cache(g)
602610
)
603-
nonlincon = optim[:nonlinconstraint]
604-
λ = JuMP.dual.(nonlincon) # FIXME: does not work for now
605-
λ = rand(NT, ng)
611+
function ℓ_g(Z̃, λ, ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K0, X̂0, gc, geq, g)
612+
update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K0, X̂0, gc, g, geq, mpc, Z̃)
613+
return dot(λ, g)
614+
end
606615
∇²ℓg = hessian(ℓ_g, mpc.hessian, mpc.Z̃, Constant(λ), ∇²g_cache...)
607616
else
608617
∇²ℓg = nothing
@@ -620,10 +629,20 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
620629
end
621630
geq, ∇geq = value_and_jacobian(geq!, geq, mpc.jacobian, mpc.Z̃, geq_cache...)
622631
if !isnothing(mpc.hessian) && con.neq > 0
623-
@warn(
624-
"Retrieving optimal Hessian of the Lagrangian is not fully supported yet.\n"*
625-
"Its nonzero coefficients are random values for now.", maxlog=1
626-
)
632+
nonlinconeq = optim[:nonlinconstrainteq]
633+
λeq = try
634+
JuMP.get_attribute(nonlinconeq, MOI.LagrangeMultiplier())
635+
catch err
636+
if err isa MOI.GetAttributeNotAllowed{MOI.LagrangeMultiplier}
637+
@warn(
638+
"The optimizer does not support retrieving optimal Hessian of the Lagrangian.\n"*
639+
"Its nonzero coefficients will be random values.", maxlog=1
640+
)
641+
rand(con.neq)
642+
else
643+
rethrow()
644+
end
645+
end
627646
∇²geq_cache = (
628647
Cache(ΔŨ), Cache(x̂0end), Cache(Ue), Cache(Ŷe), Cache(U0), Cache(Ŷ0),
629648
Cache(Û0), Cache(K0), Cache(X̂0),
@@ -633,9 +652,6 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
633652
update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K0, X̂0, gc, g, geq, mpc, Z̃)
634653
return dot(λeq, geq)
635654
end
636-
nonlinconeq = optim[:nonlinconstrainteq]
637-
λeq = JuMP.dual.(nonlinconeq) # FIXME: does not work for now
638-
λeq = ones(NT, neq)
639655
∇²ℓgeq = hessian(ℓ_geq, mpc.hessian, mpc.Z̃, Constant(λeq), ∇²geq_cache...)
640656
else
641657
∇²ℓgeq = nothing

src/estimator/mhe/execute.jl

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,6 @@ For [`NonLinModel`](@ref), it also includes the following fields:
102102
- `:∇g` or *`:nablag`* : optimal Jacobian of the inequality constraint, ``\mathbf{\nabla g}``
103103
- `:∇²ℓg` or *`:nabla2lg`* : optimal Hessian of the inequality Lagrangian, ``\mathbf{\nabla^2}\ell_{\mathbf{g}}``
104104
105-
Note that retrieving optimal Hessians of Lagrangian are not fully supported yet. Their
106-
nonzero coefficients are random values for now.
107-
108105
# Examples
109106
```jldoctest
110107
julia> model = LinModel(ss(1.0, 1.0, 1.0, 0, 5.0));
@@ -221,18 +218,27 @@ function addinfo!(
221218
end
222219
g, ∇g = value_and_jacobian(g!, g, estim.jacobian, estim.Z̃, ∇g_cache...)
223220
if !isnothing(estim.hessian) && any(old_i_g)
224-
@warn(
225-
"Retrieving optimal Hessian of the Lagrangian is not fully supported yet.\n"*
226-
"Its nonzero coefficients are random values for now.", maxlog=1
227-
)
221+
nonlincon = optim[:nonlinconstraint]
222+
λi = try
223+
JuMP.get_attribute(nonlincon, MOI.LagrangeMultiplier())
224+
catch err
225+
if err isa MOI.GetAttributeNotAllowed{MOI.LagrangeMultiplier}
226+
@warn(
227+
"The optimizer does not support retrieving optimal Hessian of the Lagrangian.\n"*
228+
"Its nonzero coefficients will be random values.", maxlog=1
229+
)
230+
rand(sum(old_i_g))
231+
else
232+
rethrow()
233+
end
234+
end
235+
λ = zeros(NT, ng)
236+
λ[old_i_g] .= λi
228237
∇²g_cache = (Cache(V̂), Cache(X̂0), Cache(û0), Cache(k0), Cache(ŷ0), Cache(g))
229238
function ℓ_g(Z̃, λ, V̂, X̂0, û0, k0, ŷ0, g)
230239
update_prediction!(V̂, X̂0, û0, k0, ŷ0, g, estim, Z̃)
231240
return dot(λ, g)
232241
end
233-
nonlincon = optim[:nonlinconstraint]
234-
λ = JuMP.dual.(nonlincon) # FIXME: does not work for now
235-
λ = ones(NT, ng)
236242
∇²ℓg = hessian(ℓ_g, estim.hessian, estim.Z̃, Constant(λ), ∇²g_cache...)
237243
else
238244
∇²ℓg = nothing

0 commit comments

Comments
 (0)