@@ -481,18 +481,19 @@ 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
490490end
491491
492492"""
493- get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel) -> Jfunc, gfunc
493+ get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel) -> Jfunc, gfuncs
494494
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).
496497
497498Inspired from: [User-defined operators with vector outputs](https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/tips_and_tricks/#User-defined-operators-with-vector-outputs)
498499"""
@@ -513,89 +514,91 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
513514 û0_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nu), Ncache)
514515 g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Ncache)
515516 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 }
537518 if any (new != = old for (new, old) in zip (ΔŨtup, ΔŨ)) # new ΔŨtup, update predictions:
519+ ΔŨ1 = ΔŨtup[begin ]
538520 for i in eachindex (ΔŨtup)
539521 ΔŨ[i] = ΔŨtup[i] # ΔŨ .= ΔŨtup seems to produce a type instability
540522 end
541523 Ŷe, Ue = get_tmp (Ŷe_cache, ΔŨ1), get_tmp (Ue_cache, ΔŨ1)
542524 Ȳ, Ū = get_tmp (Ȳ_cache, ΔŨ1), get_tmp (Ū_cache, ΔŨ1)
543525 x̂0, x̂0next = get_tmp (x̂0_cache, ΔŨ1), get_tmp (x̂0next_cache, ΔŨ1)
544526 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)
546528 Ŷ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, ΔŨ)
548530 ϵ = (nϵ ≠ 0 ) ? ΔŨ[end ] : zero (T) # ϵ = 0 if nϵ == 0 (meaning no relaxation)
549531 gc = con_custom! (gc, mpc, Ue, Ŷe, ϵ)
550532 g = con_nonlinprog! (g, mpc, model, x̂0end, Ŷ0, gc, ϵ)
551533 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)
552549 return g[i]:: T
553550 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
556559end
557560
558- function init_nonlincon! (mpc:: NonLinMPC , :: LinModel , gfunc :: Vector{<:Function} )
561+ function init_nonlincon! (mpc:: NonLinMPC , :: LinModel , gfuncs :: Vector{<:Function} )
559562 optim, con = mpc. optim, mpc. con
560563 nΔŨ = length (mpc. ΔŨ)
561564 if length (con. i_g) ≠ 0
562565 i_base = 0
563566 for i in 1 : con. nc
564567 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)
566569 end
567570 end
568571 return nothing
569572end
570573
571- function init_nonlincon! (mpc:: NonLinMPC , :: NonLinModel , gfunc :: Vector{<:Function} )
574+ function init_nonlincon! (mpc:: NonLinMPC , :: NonLinModel , gfuncs :: Vector{<:Function} )
572575 optim, con = mpc. optim, mpc. con
573576 ny, nx̂, Hp, nΔŨ = mpc. estim. model. ny, mpc. estim. nx̂, mpc. Hp, length (mpc. ΔŨ)
574577 if length (con. i_g) ≠ 0
575578 i_base = 0
576579 for i in eachindex (con. Y0min)
577580 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)
579582 end
580583 i_base = 1 Hp* ny
581584 for i in eachindex (con. Y0max)
582585 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)
584587 end
585588 i_base = 2 Hp* ny
586589 for i in eachindex (con. x̂0min)
587590 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)
589592 end
590593 i_base = 2 Hp* ny + nx̂
591594 for i in eachindex (con. x̂0max)
592595 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)
594597 end
595598 i_base = 2 Hp* ny + 2 nx̂
596599 for i in 1 : con. nc
597600 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)
599602 end
600603 end
601604 return nothing
0 commit comments