Skip to content

Commit 7d114e9

Browse files
committed
added: quadratic objective for NonLinMPC and LinModel
The JuMP model will be built with a quadratic objective (`QuadExpr`) if `Ewt=0` the the model is a `LinModel`. It saves computations at each control periods, especially if `hessian=true`.
1 parent 6da3bc5 commit 7d114e9

4 files changed

Lines changed: 53 additions & 23 deletions

File tree

src/controller/execute.jl

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,9 @@ If first warm-starts the solver with [`set_warmstart!`](@ref). It then calls
494494
"""
495495
function optim_objective!(mpc::PredictiveController{NT}) where {NT<:Real}
496496
model, optim = mpc.estim.model, mpc.optim
497-
nu, Hc = model.nu, mpc.Hc
498497
Z̃var::Vector{JuMP.VariableRef} = optim[:Z̃var]
499498
Z̃s = set_warmstart!(mpc, mpc.transcription, Z̃var)
500-
set_objective_linear_coef!(mpc, Z̃var)
499+
set_objective_linear_coef!(mpc, model, Z̃var)
501500
try
502501
JuMP.optimize!(optim)
503502
catch err
@@ -534,8 +533,14 @@ function optim_objective!(mpc::PredictiveController{NT}) where {NT<:Real}
534533
return mpc.
535534
end
536535

537-
"By default, no need to modify the objective function."
538-
set_objective_linear_coef!(::PredictiveController, _ ) = nothing
536+
"By default, no need to update the objective function."
537+
set_objective_linear_coef!(::PredictiveController, ::SimModel, _ ) = nothing
538+
539+
"Update the linear coefficients of the quadratic objective with `mpc.q̃` if applicable."
540+
function set_objective_linear_coef!(mpc::PredictiveController, ::LinModel, Z̃var)
541+
mpc.weights.iszero_E && JuMP.set_objective_coefficient(mpc.optim, Z̃var, mpc.q̃)
542+
return nothing
543+
end
539544

540545
"""
541546
preparestate!(mpc::PredictiveController, ym, d=[]) -> x̂
@@ -794,9 +799,15 @@ function setmodel_controller!(mpc::PredictiveController, uop_old, x̂op_old)
794799
JuMP.delete(optim, optim[:linconstrainteq])
795800
JuMP.unregister(optim, :linconstrainteq)
796801
@constraint(optim, linconstrainteq, con.Aeq*Z̃var .== con.beq)
797-
set_objective_hessian!(mpc, Z̃var)
802+
set_objective_hessian!(mpc, model, Z̃var)
798803
return nothing
799804
end
800805

801-
"No need to set the objective Hessian by default (only needed for quadratic optimization)."
802-
set_objective_hessian!(::PredictiveController, _ ) = nothing
806+
"No need to set the objective Hessian by default (only needed for quadratic objective)."
807+
set_objective_hessian!(::PredictiveController, ::SimModel, _ ) = nothing
808+
809+
"Set the objective Hessian with `mpc.H̃` if the objective is quadratic."
810+
function set_objective_hessian!(mpc::PredictiveController, ::LinModel, Z̃var)
811+
mpc.weights.iszero_E && @objective(mpc.optim, Min, obj_quadprog(Z̃var, mpc.H̃, mpc.q̃))
812+
return nothing
813+
end

src/controller/linmpc.jl

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -329,18 +329,6 @@ function init_optimization!(mpc::LinMPC, model::LinModel, optim::JuMP.GenericMod
329329
Aeq = con.Aeq
330330
beq = con.beq
331331
@constraint(optim, linconstrainteq, Aeq*Z̃var .== beq)
332-
set_objective_hessian!(mpc, Z̃var)
333-
return nothing
334-
end
335-
336-
"For [`LinMPC`](@ref), set the QP linear coefficient `q̃` just before optimization."
337-
function set_objective_linear_coef!(mpc::LinMPC, Z̃var)
338-
JuMP.set_objective_coefficient(mpc.optim, Z̃var, mpc.q̃)
339-
return nothing
340-
end
341-
342-
"Update the quadratic objective function for [`LinMPC`](@ref) controllers."
343-
function set_objective_hessian!(mpc::LinMPC, Z̃var)
344-
@objective(mpc.optim, Min, obj_quadprog(Z̃var, mpc.H̃, mpc.q̃))
332+
set_objective_hessian!(mpc, model, Z̃var)
345333
return nothing
346334
end

src/controller/nonlinmpc.jl

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -733,9 +733,7 @@ end
733733
734734
Init the nonlinear optimization for [`NonLinMPC`](@ref) controllers.
735735
"""
736-
function init_optimization!(
737-
mpc::NonLinMPC, model::SimModel, optim::JuMP.GenericModel{JNT}
738-
) where JNT<:Real
736+
function init_optimization!(mpc::NonLinMPC, model::SimModel, optim::JuMP.GenericModel)
739737
# --- variables and linear constraints ---
740738
con = mpc.con
741739
nZ̃ = length(mpc.Z̃)
@@ -759,6 +757,36 @@ function init_optimization!(
759757
return nothing
760758
end
761759

760+
function init_optimization!(mpc::NonLinMPC, model::LinModel, optim::JuMP.GenericModel)
761+
# --- variables and linear constraints ---
762+
con = mpc.con
763+
nZ̃ = length(mpc.Z̃)
764+
JuMP.num_variables(optim) == 0 || JuMP.empty!(optim)
765+
JuMP.set_silent(optim)
766+
limit_solve_time(mpc.optim, model.Ts)
767+
@variable(optim, Z̃var[1:nZ̃])
768+
A = con.A[con.i_b, :]
769+
b = con.b[con.i_b]
770+
@constraint(optim, linconstraint, A*Z̃var .≤ b)
771+
Aeq = con.Aeq
772+
beq = con.beq
773+
@constraint(optim, linconstrainteq, Aeq*Z̃var .== beq)
774+
C = mpc.> 0 ? mpc.weights.Ñ_Hc[end, end] : Inf
775+
set_scaling_gradient!(optim, C)
776+
if mpc.weights.iszero_E
777+
set_objective_hessian!(mpc, model, Z̃var)
778+
else
779+
# --- nonlinear optimization init for the custom NL objective ---
780+
Jop = get_nonlinobj_op(mpc, optim)
781+
@objective(optim, Min, Jop(Z̃var...))
782+
end
783+
if con.nc > 0
784+
g_oracle, geq_oracle = get_nonlincon_oracle(mpc, optim)
785+
set_nonlincon!(mpc, optim, g_oracle, geq_oracle)
786+
end
787+
return nothing
788+
end
789+
762790
"""
763791
reset_nonlincon!(mpc::NonLinMPC)
764792

src/estimator/mhe/construct.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,6 +1499,7 @@ function init_optimization!(
14991499
)
15001500
C, con = estim.C, estim.con
15011501
nZ̃ = length(estim.Z̃)
1502+
# --- variables and linear constraints ---
15021503
JuMP.num_variables(optim) == 0 || JuMP.empty!(optim)
15031504
JuMP.set_silent(optim)
15041505
limit_solve_time(optim, model.Ts)
@@ -1508,7 +1509,9 @@ function init_optimization!(
15081509
@constraint(optim, linconstraint, A*Z̃var .≤ b)
15091510
@objective(optim, Min, obj_quadprog(Z̃var, estim.H̃, estim.q̃))
15101511
if con.nc > 0
1512+
# --- nonlinear optimization init for the custom NL constraints ---
15111513
set_scaling_gradient!(optim, C)
1514+
# constraints with vector nonlinear oracle
15121515
g_oracle = get_nonlincon_oracle(estim, optim)
15131516
set_nonlincon!(estim, optim, g_oracle)
15141517
end

0 commit comments

Comments
 (0)