@@ -1003,63 +1003,11 @@ function init_optimization!(
10031003 JuMP. set_attribute (optim, " nlp_scaling_max_gradient" , 10.0 / C)
10041004 end
10051005 end
1006- He = estim. He
1007- nV̂, nX̂, ng = He* estim. nym, He* estim. nx̂, length (con. i_g)
1008- nx̂, nŷ, nu = estim. nx̂, model. ny, model. nu
1009- # see init_optimization!(mpc::NonLinMPC, optim) for details on the inspiration
1010- Jfunc, gfunc = let estim= estim, model= model, nZ̃= nZ̃, nV̂= nV̂, nX̂= nX̂, ng= ng, nx̂= nx̂, nu= nu, nŷ= nŷ
1011- Nc = nZ̃ + 3
1012- last_Z̃tup_float, last_Z̃tup_dual = nothing , nothing
1013- Z̃_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nZ̃), Nc)
1014- V̂_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nV̂), Nc)
1015- g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Nc)
1016- X̂_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nX̂), Nc)
1017- x̄_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
1018- û_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
1019- ŷ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŷ), Nc)
1020- function Jfunc (Z̃tup:: T... ):: T where {T <: Real }
1021- Z̃1 = Z̃tup[begin ]
1022- if T == JNT
1023- last_Z̃tup_float = Z̃tup
1024- else
1025- last_Z̃tup_dual = Z̃tup
1026- end
1027- Z̃, V̂ = get_tmp (Z̃_cache, Z̃1), get_tmp (V̂_cache, Z̃1)
1028- X̂ = get_tmp (X̂_cache, Z̃1)
1029- û, ŷ = get_tmp (û_cache, Z̃1), get_tmp (ŷ_cache, Z̃1)
1030- Z̃ .= Z̃tup
1031- V̂, X̂ = predict! (V̂, X̂, û, ŷ, estim, model, Z̃)
1032- g = get_tmp (g_cache, Z̃1)
1033- g = con_nonlinprog! (g, estim, model, X̂, V̂, Z̃)
1034- x̄ = get_tmp (x̄_cache, Z̃1)
1035- return obj_nonlinprog! (x̄, estim, model, V̂, Z̃):: T
1036- end
1037- function gfunc_i (i, Z̃tup:: NTuple{N, T} ):: T where {N, T <: Real }
1038- Z̃1 = Z̃tup[begin ]
1039- g = get_tmp (g_cache, Z̃1)
1040- if T == JNT
1041- isnewvalue = (Z̃tup != = last_Z̃tup_float)
1042- isnewvalue && (last_Z̃tup_float = Z̃tup)
1043- else
1044- isnewvalue = (Z̃tup != = last_Z̃tup_dual)
1045- isnewvalue && (last_Z̃tup_dual = Z̃tup)
1046- end
1047- if isnewvalue
1048- Z̃, V̂ = get_tmp (Z̃_cache, Z̃1), get_tmp (V̂_cache, Z̃1)
1049- X̂ = get_tmp (X̂_cache, Z̃1)
1050- û, ŷ = get_tmp (û_cache, Z̃1), get_tmp (ŷ_cache, Z̃1)
1051- Z̃ .= Z̃tup
1052- V̂, X̂ = predict! (V̂, X̂, û, ŷ, estim, model, Z̃)
1053- g = con_nonlinprog! (g, estim, model, X̂, V̂, Z̃)
1054- end
1055- return g[i]
1056- end
1057- gfunc = [(Z̃... ) -> gfunc_i (i, Z̃) for i in 1 : ng]
1058- (Jfunc, gfunc)
1059- end
1006+ Jfunc, gfunc = get_optim_functions (estim, optim)
10601007 register (optim, :Jfunc , nZ̃, Jfunc, autodiff= true )
10611008 @NLobjective (optim, Min, Jfunc (Z̃var... ))
1062- if ng ≠ 0
1009+ nV̂, nX̂ = estim. He* estim. nym, estim. He* estim. nx̂
1010+ if length (con. i_g) ≠ 0
10631011 for i in eachindex (con. X̂min)
10641012 sym = Symbol (" g_X̂min_$i " )
10651013 register (optim, sym, nZ̃, gfunc[i], autodiff= true )
@@ -1081,4 +1029,72 @@ function init_optimization!(
10811029 end
10821030 end
10831031 return nothing
1032+ end
1033+
1034+
1035+ """
1036+ get_optim_functions(estim::MovingHorizonEstimator, ::JuMP.GenericModel) -> Jfunc, gfunc
1037+
1038+ Get the objective `Jfunc` and constraints `gfunc` functions for [`MovingHorizonEstimator`](@ref).
1039+
1040+ Inspired from: [User-defined operators with vector outputs](https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/tips_and_tricks/#User-defined-operators-with-vector-outputs)
1041+ """
1042+ function get_optim_functions (
1043+ estim:: MovingHorizonEstimator , :: JuMP.GenericModel{JNT}
1044+ ) where {JNT <: Real }
1045+ model, con = estim. model, estim. con
1046+ nx̂, nym, nŷ, nu, He = estim. nx̂, estim. nym, model. ny, model. nu, estim. He
1047+ nV̂, nX̂, ng, nZ̃ = He* nym, He* nx̂, length (con. i_g), length (estim. Z̃)
1048+ Nc = nZ̃ + 3
1049+ last_Z̃tup_float, last_Z̃tup_dual = nothing , nothing
1050+ Z̃_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nZ̃), Nc)
1051+ V̂_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nV̂), Nc)
1052+ g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Nc)
1053+ X̂_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nX̂), Nc)
1054+ x̄_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nx̂), Nc)
1055+ û_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Nc)
1056+ ŷ_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nŷ), Nc)
1057+ function Jfunc (Z̃tup:: T... ):: T where {T <: Real }
1058+ Z̃1 = Z̃tup[begin ]
1059+ if T == JNT
1060+ last_Z̃tup_float = Z̃tup
1061+ else
1062+ last_Z̃tup_dual = Z̃tup
1063+ end
1064+ Z̃, V̂ = get_tmp (Z̃_cache, Z̃1), get_tmp (V̂_cache, Z̃1)
1065+ X̂ = get_tmp (X̂_cache, Z̃1)
1066+ û, ŷ = get_tmp (û_cache, Z̃1), get_tmp (ŷ_cache, Z̃1)
1067+ for i in eachindex (Z̃tup)
1068+ Z̃[i] = Z̃tup[i] # Z̃ .= Z̃tup seems to produce a type instability
1069+ end
1070+ V̂, X̂ = predict! (V̂, X̂, û, ŷ, estim, model, Z̃)
1071+ g = get_tmp (g_cache, Z̃1)
1072+ g = con_nonlinprog! (g, estim, model, X̂, V̂, Z̃)
1073+ x̄ = get_tmp (x̄_cache, Z̃1)
1074+ return obj_nonlinprog! (x̄, estim, model, V̂, Z̃):: T
1075+ end
1076+ function gfunc_i (i, Z̃tup:: NTuple{N, T} ):: T where {N, T <: Real }
1077+ Z̃1 = Z̃tup[begin ]
1078+ g = get_tmp (g_cache, Z̃1)
1079+ if T == JNT
1080+ isnewvalue = (Z̃tup != = last_Z̃tup_float)
1081+ isnewvalue && (last_Z̃tup_float = Z̃tup)
1082+ else
1083+ isnewvalue = (Z̃tup != = last_Z̃tup_dual)
1084+ isnewvalue && (last_Z̃tup_dual = Z̃tup)
1085+ end
1086+ if isnewvalue
1087+ Z̃, V̂ = get_tmp (Z̃_cache, Z̃1), get_tmp (V̂_cache, Z̃1)
1088+ X̂ = get_tmp (X̂_cache, Z̃1)
1089+ û, ŷ = get_tmp (û_cache, Z̃1), get_tmp (ŷ_cache, Z̃1)
1090+ for i in eachindex (Z̃tup)
1091+ Z̃[i] = Z̃tup[i] # Z̃ .= Z̃tup seems to produce a type instability
1092+ end
1093+ V̂, X̂ = predict! (V̂, X̂, û, ŷ, estim, model, Z̃)
1094+ g = con_nonlinprog! (g, estim, model, X̂, V̂, Z̃)
1095+ end
1096+ return g[i]
1097+ end
1098+ gfunc = [(Z̃... ) -> gfunc_i (i, Z̃) for i in 1 : ng]
1099+ return Jfunc, gfunc
10841100end
0 commit comments