@@ -508,7 +508,7 @@ function init_optimization!(mpc::NonLinMPC, model::SimModel, optim)
508508 Jfunc, ∇Jfunc!, gfuncs, geqfuncs, ∇geqfuncs! = get_optim_functions (mpc, optim)
509509 @operator (optim, J, nZ̃, Jfunc, ∇Jfunc!)
510510 @objective (optim, Min, J (Z̃var... ))
511- init_nonlincon! (mpc, model, transcription, gfuncs, geqfuncs)
511+ init_nonlincon! (mpc, model, transcription, gfuncs, geqfuncs, ∇geqfuncs! )
512512 set_nonlincon! (mpc, model, optim)
513513 return nothing
514514end
@@ -541,6 +541,7 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
541541 gc_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, nc), Ncache)
542542 g_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, ng), Ncache)
543543 geq_cache:: DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache (zeros (JNT, neq), Ncache)
544+ # --------------------- update simulation function ------------------------------------
544545 function update_simulations! (
545546 Z̃arg:: Union{NTuple{N, T}, AbstractVector{T}} , Z̃cache
546547 ) where {N, T<: Real }
@@ -568,81 +569,30 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
568569 end
569570 return nothing
570571 end
571- # force specialization using Vararg, see https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing
572- function Jfunc (Z̃arg:: Vararg{T, N} ) where {N, T<: Real }
573- return Jfunc (Z̃arg, get_tmp (Z̃_cache, T)):: T
574- end
575- # method with the additional cache argument:
576- function Jfunc (Z̃arg:: Union{NTuple{N, T}, AbstractVector{T}} , Z̃cache) where {N, T<: Real }
577- update_simulations! (Z̃arg, Z̃cache)
572+ # --------------------- objective function --------------------------------------------
573+ function Jfunc (Z̃arg:: Vararg{T, N} ) where {N, T<: Real } # force specialization with Vararg, see https://docs.julialang.org/en/v1/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing
574+ update_simulations! (Z̃arg, get_tmp (Z̃_cache, T))
578575 ΔŨ = get_tmp (ΔŨ_cache, T)
579576 Ue, Ŷe = get_tmp (Ue_cache, T), get_tmp (Ŷe_cache, T)
580577 U0, Ŷ0 = get_tmp (U0_cache, T), get_tmp (Ŷ0_cache, T)
581- return obj_nonlinprog! (Ŷ0, U0, mpc, model, Ue, Ŷe, ΔŨ)
578+ return obj_nonlinprog! (Ŷ0, U0, mpc, model, Ue, Ŷe, ΔŨ):: T
582579 end
583- Jfunc_vec (Z̃vec) = Jfunc (Z̃vec, get_tmp (Z̃_cache, Z̃vec[1 ]))
580+ function Jfunc_vec (Z̃arg:: AbstractVector{T} ) where T<: Real
581+ update_simulations! (Z̃arg, get_tmp (Z̃_cache, T))
582+ ΔŨ = get_tmp (ΔŨ_cache, T)
583+ Ue, Ŷe = get_tmp (Ue_cache, T), get_tmp (Ŷe_cache, T)
584+ U0, Ŷ0 = get_tmp (U0_cache, T), get_tmp (Ŷ0_cache, T)
585+ return obj_nonlinprog! (Ŷ0, U0, mpc, model, Ue, Ŷe, ΔŨ):: T
586+ end
584587 Z̃vec = Vector {JNT} (undef, nZ̃)
585588 ∇Jbuffer = GradientBuffer (Jfunc_vec, Z̃vec)
586589 function ∇Jfunc! (∇J, Z̃arg:: Vararg{T, N} ) where {N, T<: Real }
587590 Z̃vec .= Z̃arg
588- gradient! (∇J, ∇Jbuffer, Z̃vec)
589- return nothing
590- end
591-
592-
593- function gfunceq_i (i, Z̃arg:: NTuple{N, T} ) where {N, T<: Real }
594- update_simulations! (Z̃arg, get_tmp (Z̃_cache, T))
595- geq = get_tmp (geq_cache, T)
596- return geq[i]:: T
597- end
598- geqfuncs = Vector {Function} (undef, neq)
599- for i in 1 : neq
600- geqfuncs[i] = function (Z̃arg:: Vararg{T, N} ) where {N, T<: Real }
601- return gfunceq_i (i, Z̃arg)
602- end
603- end
604-
605-
606- ∇geqfuncs! = nothing
607- #=
608- function geqfunc!(geq, Z̃)
609- update_simulations!(Z̃, get_tmp(Z̃_cache, T))
610- geq = get_tmp(geq_cache, T)
611- return
612- end
613- =#
614-
615- #=
616-
617-
618-
619- ∇geq = Matrix{JNT}(undef, neq, nZ̃) # Jacobian of geq
620- function ∇geqfunc_vec!(∇geq, Z̃vec)
621- update_simulations!(Z̃arg, get_tmp(Z̃_cache, T))
622- return nothing
623- end
624-
625-
626-
627-
628-
629- function ∇geqfuncs_i!(∇geq_i, i, Z̃arg::NTuple{N, T}) where {N, T<:Real}
630- Z̃arg_vec .= Z̃arg
631- ForwardDiff
632-
633-
591+ return gradient! (∇J, ∇Jbuffer, Z̃vec)
634592 end
635-
636- ∇geqfuncs! = Vector{Function}(undef, neq)
637- for i in 1:neq
638- ∇eqfuncs![i] = function (∇geq, Z̃arg::Vararg{T, N}) where {N, T<:Real}
639- return ∇geqfuncs_i!(∇geq, i, Z̃arg)
640- end
641- end
642- =#
643-
644-
593+ # --------------------- inequality constraint functions -------------------------------
645594 # TODO :re-déplacer en haut:
595+ # TODO : modifier pour combiner en 1 seule fonction comme pour geqfuncs
646596 function gfunc_i (i, Z̃arg:: NTuple{N, T} ) where {N, T<: Real }
647597 update_simulations! (Z̃arg, get_tmp (Z̃_cache, T))
648598 g = get_tmp (g_cache, T)
@@ -655,12 +605,38 @@ function get_optim_functions(mpc::NonLinMPC, ::JuMP.GenericModel{JNT}) where JNT
655605 return gfunc_i (i, Z̃arg)
656606 end
657607 end
608+ # --------------------- equality constraint functions ---------------------------------
609+ geqfuncs = Vector {Function} (undef, neq)
610+ for i in eachindex (geqfuncs)
611+ func_i = function (Z̃arg:: Vararg{T, N} ) where {N, T<: Real } # see comment above
612+ update_simulations! (Z̃arg, get_tmp (Z̃_cache, T))
613+ geq = get_tmp (geq_cache, T)
614+ return geq[i]:: T
615+ end
616+ geqfuncs[i] = func_i
617+ end
618+ function geqfunc_vec! (geq, Z̃vec:: AbstractVector{T} ) where T<: Real
619+ update_simulations! (Z̃vec, get_tmp (Z̃_cache, T))
620+ geq .= get_tmp (geq_cache, T)
621+ return geq
622+ end
623+ ∇geq = Matrix {JNT} (undef, neq, nZ̃) # Jacobian of geq
624+ geqvec = Vector {JNT} (undef, neq)
625+ ∇geqfuncs! = Vector {Function} (undef, neq)
626+ for i in eachindex (∇geqfuncs!)
627+ ∇geqfuncs![i] = function (∇geq_i, Z̃arg:: Vararg{T, N} ) where {N, T<: Real }
628+ Z̃vec .= Z̃arg
629+ ForwardDiff. jacobian! (∇geq, geqfunc_vec!, geqvec, Z̃vec)
630+ ∇geq_i .= @views ∇geq[i, :]
631+ return ∇geq_i
632+ end
633+ end
658634 return Jfunc, ∇Jfunc!, gfuncs, geqfuncs, ∇geqfuncs!
659635end
660636
661637"""
662638 init_nonlincon!(
663- mpc::NonLinMPC, model::LinModel, ::TranscriptionMethod, gfuncs, geqfuncs
639+ mpc::NonLinMPC, model::LinModel, ::TranscriptionMethod, gfuncs, geqfuncs, ∇geqfuncs!
664640 )
665641
666642Init nonlinear constraints for [`LinModel`](@ref).
@@ -669,7 +645,7 @@ The only nonlinear constraints are the custom inequality constraints `gc`.
669645"""
670646function init_nonlincon! (
671647 mpc:: NonLinMPC , :: LinModel , :: TranscriptionMethod ,
672- gfuncs:: Vector{<:Function} , geqfuncs :: Vector{<:Function}
648+ gfuncs:: Vector{<:Function} , _ , _
673649)
674650 optim, con = mpc. optim, mpc. con
675651 nZ̃ = length (mpc. Z̃)
685661
686662"""
687663 init_nonlincon!(
688- mpc::NonLinMPC, model::NonLinModel, ::MultipleShooting, gfuncs, geqfuncs
664+ mpc::NonLinMPC, model::NonLinModel, ::MultipleShooting, gfuncs, geqfuncs, ∇geqfuncs!
689665 )
690666
691667Init nonlinear constraints for [`NonLinModel`](@ref) and [`MultipleShooting`](@ref).
@@ -695,7 +671,7 @@ constraints `gc` and all the nonlinear equality constraints `geq`.
695671"""
696672function init_nonlincon! (
697673 mpc:: NonLinMPC , :: NonLinModel , :: MultipleShooting ,
698- gfuncs:: Vector{<:Function} , geqfuncs:: Vector{<:Function}
674+ gfuncs:: Vector{<:Function} , geqfuncs:: Vector{<:Function} , ∇geqfuncs! :: Vector{<:Function}
699675)
700676 optim, con = mpc. optim, mpc. con
701677 ny, nx̂, Hp, nZ̃ = mpc. estim. model. ny, mpc. estim. nx̂, mpc. Hp, length (mpc. Z̃)
@@ -719,9 +695,10 @@ function init_nonlincon!(
719695 end
720696 # --- nonlinear equality constraints ---
721697 Z̃var = optim[:Z̃var ]
722- for i in 1 : con . neq
698+ for i in eachindex (geqfuncs)
723699 name = Symbol (" geq_$i " )
724- geqfunc_i = optim[name] = JuMP. add_nonlinear_operator (optim, nZ̃, geqfuncs[i]; name)
700+ geqfunc_i = JuMP. add_nonlinear_operator (optim, nZ̃, geqfuncs[i], ∇geqfuncs![i]; name)
701+ optim[name] = geqfunc_i
725702 # set with @constrains here instead of set_nonlincon!, since the number of nonlinear
726703 # equality constraints is known and constant (±Inf are impossible):
727704 @constraint (optim, geqfunc_i (Z̃var... ) == 0 )
731708
732709"""
733710 init_nonlincon!(
734- mpc::NonLinMPC, model::NonLinModel, ::SingleShooting, gfuncs, geqfuncs
711+ mpc::NonLinMPC, model::NonLinModel, ::SingleShooting, gfuncs, geqfuncs, ∇geqfuncs!
735712 )
736713
737714Init nonlinear constraints for [`NonLinModel`](@ref) and [`SingleShooting`](@ref).
@@ -741,7 +718,7 @@ prediction `Ŷ` bounds and the terminal state `x̂end` bounds.
741718"""
742719function init_nonlincon! (
743720 mpc:: NonLinMPC , :: NonLinModel , :: SingleShooting ,
744- gfuncs:: Vector{<:Function} , geqfuncs :: Vector{<:Function}
721+ gfuncs:: Vector{<:Function} , _ , _
745722)
746723 optim, con = mpc. optim, mpc. con
747724 ny, nx̂, Hp, nZ̃ = mpc. estim. model. ny, mpc. estim. nx̂, mpc. Hp, length (mpc. Z̃)
0 commit comments