@@ -481,18 +481,19 @@ function init_optimization!(mpc::NonLinMPC, model::SimModel, optim)
481
481
JuMP. set_attribute (optim, " nlp_scaling_max_gradient" , 10.0 / C)
482
482
end
483
483
end
484
- Jfunc, gfunc = get_optim_functions (mpc, mpc. optim)
484
+ Jfunc, gfuncs = get_optim_functions (mpc, mpc. optim)
485
485
@operator (optim, J, nΔŨ, Jfunc)
486
486
@objective (optim, Min, J (ΔŨvar... ))
487
- init_nonlincon! (mpc, model, gfunc )
487
+ init_nonlincon! (mpc, model, gfuncs )
488
488
set_nonlincon! (mpc, model, mpc. optim)
489
489
return nothing
490
490
end
491
491
492
492
"""
493
- get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel) -> Jfunc, gfunc
493
+ get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel) -> Jfunc, gfuncs
494
494
495
- Get the objective `Jfunc` and constraints `gfunc` functions for [`NonLinMPC`](@ref).
495
+ Get the objective `Jfunc` function and constraint `gfuncs` function vector for
496
+ [`NonLinMPC`](@ref).
496
497
497
498
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)
498
499
"""
@@ -513,89 +514,91 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
513
514
û0_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Ncache)
514
515
g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Ncache)
515
516
gc_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nc), Ncache)
516
- function Jfunc (ΔŨtup:: T... ) where T<: Real
517
- ΔŨ1 = ΔŨtup[begin ]
518
- ΔŨ, g = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (g_cache, ΔŨ1)
519
- for i in eachindex (ΔŨtup)
520
- ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
521
- end
522
- Ŷe, Ue = get_tmp (Ŷe_cache, ΔŨ1), get_tmp (Ue_cache, ΔŨ1)
523
- Ȳ, Ū = get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
524
- x̂0, x̂0next = get_tmp (x̂0_cache, ΔŨ1), get_tmp (x̂0next_cache, ΔŨ1)
525
- u0, û0 = get_tmp (u0_cache, ΔŨ1), get_tmp (û0_cache, ΔŨ1)
526
- gc = get_tmp (gc_cache, ΔŨ1)
527
- Ŷ0, x̂0end = predict! (Ȳ, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
528
- Ue, Ŷe = extended_predictions! (Ue, Ŷe, Ū, mpc, model, Ŷ0, ΔŨ)
529
- ϵ = (nϵ ≠ 0 ) ? ΔŨ[end ] : zero (T) # ϵ = 0 if nϵ == 0 (meaning no relaxation)
530
- gc = con_custom! (gc, mpc, Ue, Ŷe, ϵ)
531
- g = con_nonlinprog! (g, mpc, model, x̂0end, Ŷ0, gc, ϵ)
532
- return obj_nonlinprog! (Ȳ, Ū, mpc, model, Ue, Ŷe, ΔŨ):: T
533
- end
534
- function gfunc_i (i, ΔŨtup:: NTuple{N, T} ) where {N, T<: Real }
535
- ΔŨ1 = ΔŨtup[begin ]
536
- ΔŨ, g = get_tmp (ΔŨ_cache, ΔŨ1), get_tmp (g_cache, ΔŨ1)
517
+ function update_simulations! (ΔŨ, ΔŨtup:: NTuple{N, T} ) where {N, T<: Real }
537
518
if any (new != = old for (new, old) in zip (ΔŨtup, ΔŨ)) # new ΔŨtup, update predictions:
519
+ ΔŨ1 = ΔŨtup[begin ]
538
520
for i in eachindex (ΔŨtup)
539
521
ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
540
522
end
541
523
Ŷe, Ue = get_tmp (Ŷe_cache, ΔŨ1), get_tmp (Ue_cache, ΔŨ1)
542
524
Ȳ, Ū = get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
543
525
x̂0, x̂0next = get_tmp (x̂0_cache, ΔŨ1), get_tmp (x̂0next_cache, ΔŨ1)
544
526
u0, û0 = get_tmp (u0_cache, ΔŨ1), get_tmp (û0_cache, ΔŨ1)
545
- gc = get_tmp (gc_cache, ΔŨ1)
527
+ gc, g = get_tmp (gc_cache, ΔŨ1), get_tmp (g_cache , ΔŨ1)
546
528
Ŷ0, x̂0end = predict! (Ȳ, x̂0, x̂0next, u0, û0, mpc, model, ΔŨ)
547
- Ue, Ŷe = extended_predictions! (Ue, Ŷe , Ū, mpc, model, Ŷ0, ΔŨ)
529
+ Ŷe, Ue = extended_predictions! (Ŷe, Ue , Ū, mpc, model, Ŷ0, ΔŨ)
548
530
ϵ = (nϵ ≠ 0 ) ? ΔŨ[end ] : zero (T) # ϵ = 0 if nϵ == 0 (meaning no relaxation)
549
531
gc = con_custom! (gc, mpc, Ue, Ŷe, ϵ)
550
532
g = con_nonlinprog! (g, mpc, model, x̂0end, Ŷ0, gc, ϵ)
551
533
end
534
+ return nothing
535
+ end
536
+ function Jfunc (ΔŨtup:: Vararg{T, N} ) where {N, T<: Real }
537
+ ΔŨ1 = ΔŨtup[begin ]
538
+ ΔŨ = get_tmp (ΔŨ_cache, ΔŨ1)
539
+ update_simulations! (ΔŨ, ΔŨtup)
540
+ Ȳ, Ū = get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
541
+ Ŷe, Ue = get_tmp (Ŷe_cache, ΔŨ1), get_tmp (Ue_cache, ΔŨ1)
542
+ return obj_nonlinprog! (Ȳ, Ū, mpc, model, Ue, Ŷe, ΔŨ):: T
543
+ end
544
+ function gfunc_i (i, ΔŨtup:: NTuple{N, T} ) where {N, T<: Real }
545
+ ΔŨ1 = ΔŨtup[begin ]
546
+ ΔŨ = get_tmp (ΔŨ_cache, ΔŨ1)
547
+ update_simulations! (ΔŨ, ΔŨtup)
548
+ g = get_tmp (g_cache, ΔŨ1)
552
549
return g[i]:: T
553
550
end
554
- gfunc = [(ΔŨ... ) -> gfunc_i (i, ΔŨ) for i in 1 : ng]
555
- return Jfunc, gfunc
551
+ gfuncs = Vector {Function} (undef, ng)
552
+ for i in 1 : ng
553
+ # this is another syntax for anonymous function, allowing parameters T and N:
554
+ gfuncs[i] = function (ΔŨtup:: Vararg{T, N} ) where {N, T<: Real }
555
+ return gfunc_i (i, ΔŨtup)
556
+ end
557
+ end
558
+ return Jfunc, gfuncs
556
559
end
557
560
558
- function init_nonlincon! (mpc:: NonLinMPC , :: LinModel , gfunc :: Vector{<:Function} )
561
+ function init_nonlincon! (mpc:: NonLinMPC , :: LinModel , gfuncs :: Vector{<:Function} )
559
562
optim, con = mpc. optim, mpc. con
560
563
nΔŨ = length (mpc. ΔŨ)
561
564
if length (con. i_g) ≠ 0
562
565
i_base = 0
563
566
for i in 1 : con. nc
564
567
name = Symbol (" g_c_$i " )
565
- 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)
566
569
end
567
570
end
568
571
return nothing
569
572
end
570
573
571
- function init_nonlincon! (mpc:: NonLinMPC , :: NonLinModel , gfunc :: Vector{<:Function} )
574
+ function init_nonlincon! (mpc:: NonLinMPC , :: NonLinModel , gfuncs :: Vector{<:Function} )
572
575
optim, con = mpc. optim, mpc. con
573
576
ny, nx̂, Hp, nΔŨ = mpc. estim. model. ny, mpc. estim. nx̂, mpc. Hp, length (mpc. ΔŨ)
574
577
if length (con. i_g) ≠ 0
575
578
i_base = 0
576
579
for i in eachindex (con. Y0min)
577
580
name = Symbol (" g_Y0min_$i " )
578
- 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)
579
582
end
580
583
i_base = 1 Hp* ny
581
584
for i in eachindex (con. Y0max)
582
585
name = Symbol (" g_Y0max_$i " )
583
- 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)
584
587
end
585
588
i_base = 2 Hp* ny
586
589
for i in eachindex (con. x̂0min)
587
590
name = Symbol (" g_x̂0min_$i " )
588
- 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)
589
592
end
590
593
i_base = 2 Hp* ny + nx̂
591
594
for i in eachindex (con. x̂0max)
592
595
name = Symbol (" g_x̂0max_$i " )
593
- 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)
594
597
end
595
598
i_base = 2 Hp* ny + 2 nx̂
596
599
for i in 1 : con. nc
597
600
name = Symbol (" g_c_$i " )
598
- 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)
599
602
end
600
603
end
601
604
return nothing
0 commit comments