Skip to content

Commit fec8f90

Browse files
committed
added: use Vararg{T, N} instead of splatting to force specialization
The performance is a bit better for `NonLinMPC` and `MovingHorizonEstimator`
1 parent 341f107 commit fec8f90

File tree

2 files changed

+34
-21
lines changed

2 files changed

+34
-21
lines changed

src/controller/nonlinmpc.jl

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,10 @@ function init_optimization!(mpc::NonLinMPC, model::SimModel, optim)
481481
JuMP.set_attribute(optim, "nlp_scaling_max_gradient", 10.0/C)
482482
end
483483
end
484-
Jfunc, gfunc = get_optim_functions(mpc, mpc.optim)
484+
Jfunc, gfuncs = get_optim_functions(mpc, mpc.optim)
485485
@operator(optim, J, nΔŨ, Jfunc)
486486
@objective(optim, Min, J(ΔŨvar...))
487-
init_nonlincon!(mpc, model, gfunc)
487+
init_nonlincon!(mpc, model, gfuncs)
488488
set_nonlincon!(mpc, model, mpc.optim)
489489
return nothing
490490
end
@@ -532,7 +532,7 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
532532
end
533533
return nothing
534534
end
535-
function Jfunc(ΔŨtup::T...) where T<:Real
535+
function Jfunc(ΔŨtup::Vararg{T, N}) where {N, T<:Real}
536536
ΔŨ1 = ΔŨtup[begin]
537537
ΔŨ = get_tmp(ΔŨ_cache, ΔŨ1)
538538
update_simulations!(ΔŨ, ΔŨtup)
@@ -547,51 +547,58 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
547547
g = get_tmp(g_cache, ΔŨ1)
548548
return g[i]::T
549549
end
550-
gfunc = [(ΔŨ...) -> gfunc_i(i, ΔŨ) for i in 1:ng]
551-
return Jfunc, gfunc
550+
gfuncs = Vector{Function}(undef, ng)
551+
for i in 1:ng
552+
# this is another syntax for anonymous function, allowing parameters T and N:
553+
gfuncs[i] = function (ΔŨtup::Vararg{T, N}) where {N, T<:Real}
554+
return gfunc_i(i, ΔŨtup)
555+
end
556+
end
557+
#gfunc = [(ΔŨ::Vararg{T, N}) -> gfunc_i(i, ΔŨ) where {N, T<:Real} for i in 1:ng]
558+
return Jfunc, gfuncs
552559
end
553560

554-
function init_nonlincon!(mpc::NonLinMPC, ::LinModel, gfunc::Vector{<:Function})
561+
function init_nonlincon!(mpc::NonLinMPC, ::LinModel, gfuncs::Vector{<:Function})
555562
optim, con = mpc.optim, mpc.con
556563
nΔŨ = length(mpc.ΔŨ)
557564
if length(con.i_g) 0
558565
i_base = 0
559566
for i in 1:con.nc
560567
name = Symbol("g_c_$i")
561-
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfunc[i_base+i]; name)
568+
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfuncs[i_base+i]; name)
562569
end
563570
end
564571
return nothing
565572
end
566573

567-
function init_nonlincon!(mpc::NonLinMPC, ::NonLinModel, gfunc::Vector{<:Function})
574+
function init_nonlincon!(mpc::NonLinMPC, ::NonLinModel, gfuncs::Vector{<:Function})
568575
optim, con = mpc.optim, mpc.con
569576
ny, nx̂, Hp, nΔŨ = mpc.estim.model.ny, mpc.estim.nx̂, mpc.Hp, length(mpc.ΔŨ)
570577
if length(con.i_g) 0
571578
i_base = 0
572579
for i in eachindex(con.Y0min)
573580
name = Symbol("g_Y0min_$i")
574-
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfunc[i_base+i]; name)
581+
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfuncs[i_base+i]; name)
575582
end
576583
i_base = 1Hp*ny
577584
for i in eachindex(con.Y0max)
578585
name = Symbol("g_Y0max_$i")
579-
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfunc[i_base+i]; name)
586+
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfuncs[i_base+i]; name)
580587
end
581588
i_base = 2Hp*ny
582589
for i in eachindex(con.x̂0min)
583590
name = Symbol("g_x̂0min_$i")
584-
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfunc[i_base+i]; name)
591+
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfuncs[i_base+i]; name)
585592
end
586593
i_base = 2Hp*ny + nx̂
587594
for i in eachindex(con.x̂0max)
588595
name = Symbol("g_x̂0max_$i")
589-
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfunc[i_base+i]; name)
596+
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfuncs[i_base+i]; name)
590597
end
591598
i_base = 2Hp*ny + 2nx̂
592599
for i in 1:con.nc
593600
name = Symbol("g_c_$i")
594-
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfunc[i_base+i]; name)
601+
optim[name] = JuMP.add_nonlinear_operator(optim, nΔŨ, gfuncs[i_base+i]; name)
595602
end
596603
end
597604
return nothing

src/estimator/mhe/construct.jl

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,36 +1251,36 @@ function init_optimization!(
12511251
JuMP.set_attribute(optim, "nlp_scaling_max_gradient", 10.0/C)
12521252
end
12531253
end
1254-
Jfunc, gfunc = get_optim_functions(estim, optim)
1254+
Jfunc, gfuncs = get_optim_functions(estim, optim)
12551255
@operator(optim, J, nZ̃, Jfunc)
12561256
@objective(optim, Min, J(Z̃var...))
12571257
nV̂, nX̂ = estim.He*estim.nym, estim.He*estim.nx̂
12581258
if length(con.i_g) 0
12591259
for i in eachindex(con.X̂0min)
12601260
name = Symbol("g_X̂0min_$i")
12611261
optim[name] = JuMP.add_nonlinear_operator(
1262-
optim, nZ̃, gfunc[i]; name
1262+
optim, nZ̃, gfuncs[i]; name
12631263
)
12641264
end
12651265
i_end_X̂min = nX̂
12661266
for i in eachindex(con.X̂0max)
12671267
name = Symbol("g_X̂0max_$i")
12681268
optim[name] = JuMP.add_nonlinear_operator(
1269-
optim, nZ̃, gfunc[i_end_X̂min + i]; name
1269+
optim, nZ̃, gfuncs[i_end_X̂min + i]; name
12701270
)
12711271
end
12721272
i_end_X̂max = 2*nX̂
12731273
for i in eachindex(con.V̂min)
12741274
name = Symbol("g_V̂min_$i")
12751275
optim[name] = JuMP.add_nonlinear_operator(
1276-
optim, nZ̃, gfunc[i_end_X̂max + i]; name
1276+
optim, nZ̃, gfuncs[i_end_X̂max + i]; name
12771277
)
12781278
end
12791279
i_end_V̂min = 2*nX̂ + nV̂
12801280
for i in eachindex(con.V̂max)
12811281
name = Symbol("g_V̂max_$i")
12821282
optim[name] = JuMP.add_nonlinear_operator(
1283-
optim, nZ̃, gfunc[i_end_V̂min + i]; name
1283+
optim, nZ̃, gfuncs[i_end_V̂min + i]; name
12841284
)
12851285
end
12861286
end
@@ -1324,7 +1324,7 @@ function get_optim_functions(
13241324
end
13251325
return nothing
13261326
end
1327-
function Jfunc(Z̃tup::T...)::T where {T <: Real}
1327+
function Jfunc(Z̃tup::Vararg{T, N}) where {N, T<:Real}
13281328
Z̃1 = Z̃tup[begin]
13291329
= get_tmp(Z̃_cache, Z̃1)
13301330
update_simulations!(Z̃, Z̃tup)
@@ -1338,6 +1338,12 @@ function get_optim_functions(
13381338
g = get_tmp(g_cache, Z̃1)
13391339
return g[i]
13401340
end
1341-
gfunc = [(Z̃...) -> gfunc_i(i, Z̃) for i in 1:ng]
1342-
return Jfunc, gfunc
1341+
gfuncs = Vector{Function}(undef, ng)
1342+
for i in 1:ng
1343+
# this is another syntax for anonymous function, allowing parameters T and N:
1344+
gfuncs[i] = function (ΔŨtup::Vararg{T, N}) where {N, T<:Real}
1345+
return gfunc_i(i, ΔŨtup)
1346+
end
1347+
end
1348+
return Jfunc, gfuncs
13431349
end

0 commit comments

Comments
 (0)