Skip to content

Commit 91c49db

Browse files
committed
added: number of colors in getinfo for MPC
1 parent 88ce88a commit 91c49db

File tree

4 files changed

+41
-8
lines changed

4 files changed

+41
-8
lines changed

src/ModelPredictiveControl.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using RecipesBase
99

1010
using DifferentiationInterface: ADTypes.AbstractADType, AutoForwardDiff
1111
using DifferentiationInterface: AutoSparse, SecondOrder
12+
using DifferentiationInterface: Prep, SparseJacobianPrep, SparseHessianPrep
1213
using DifferentiationInterface: gradient, jacobian, hessian
1314
using DifferentiationInterface: value_and_gradient, value_and_jacobian
1415
using DifferentiationInterface: value_gradient_and_hessian
@@ -20,6 +21,7 @@ using SparseConnectivityTracer: TracerSparsityDetector
2021
using SparseMatrixColorings: GreedyColoringAlgorithm, sparsity_pattern
2122
using SparseMatrixColorings: NaturalOrder, LargestFirst, SmallestLast
2223
using SparseMatrixColorings: IncidenceDegree, DynamicLargestFirst, RandomOrder
24+
using SparseMatrixColorings: ncolors
2325

2426
import ProgressLogging
2527

src/controller/execute.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,17 @@ Lastly, the following fields are also available for [`NonLinMPC`](@ref) only:
117117
- `:gc`: custom nonlinear constraints values at the optimum, ``\mathbf{g_c}``
118118
- `:∇J` or *`:nablaJ`* : optimal gradient of the objective function, ``\mathbf{\nabla} J``
119119
- `:∇²J` or *`:nabla2J`* : optimal Hessian of the objective function, ``\mathbf{\nabla^2}J``
120+
- `:∇²J_ncolors` or *`:nabla2J_ncolors`* : number of colors in `:∇²J` sparsity pattern
120121
- `:g` : optimal nonlinear inequality constraint values, ``\mathbf{g}``
121122
- `:∇g` or *`:nablag`* : optimal Jacobian of the inequality constraint, ``\mathbf{\nabla g}``
123+
- `:∇g_ncolors` or *`:nablag_ncolors`* : number of colors in `:∇g` sparsity pattern
122124
- `:∇²ℓg` or *`:nabla2lg`* : optimal Hessian of the inequality Lagrangian, ``\mathbf{\nabla^2}\ell_{\mathbf{g}}``
125+
- `:∇²ℓg_ncolors` or *`:nabla2lg_ncolors`* : number of colors in `:∇²ℓg` sparsity pattern
123126
- `:geq` : optimal nonlinear equality constraint values, ``\mathbf{g_{eq}}``
124127
- `:∇geq` or *`:nablageq`* : optimal Jacobian of the equality constraint, ``\mathbf{\nabla g_{eq}}``
128+
- `:∇geq_ncolors` or *`:nablageq_ncolors`* : number of colors in `:∇geq` sparsity pattern
125129
- `:∇²ℓgeq` or *`:nabla2lgeq`* : optimal Hessian of the equality Lagrangian, ``\mathbf{\nabla^2}\ell_{\mathbf{g_{eq}}}``
130+
- `:∇²ℓgeq_ncolors` or *`:nabla2lgeq_ncolors`* : number of colors in `:∇²ℓgeq` sparsity pattern
126131
127132
Note that the inequality constraint vectors and matrices only include the non-`Inf` values.
128133

src/controller/nonlinmpc.jl

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -590,9 +590,13 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
590590
return obj_nonlinprog!(Ŷ0, U0, mpc, Ue, Ŷe, ΔŨ)
591591
end
592592
if !isnothing(hess)
593-
_, ∇J_opt, ∇²J_opt = value_gradient_and_hessian(J!, hess, mpc.Z̃, J_cache...)
593+
prep_∇²J = prepare_hessian(J!, hess, mpc.Z̃, J_cache...)
594+
_, ∇J_opt, ∇²J_opt = value_gradient_and_hessian(J!, prep_∇²J, hess, mpc.Z̃, J_cache...)
595+
∇²J_ncolors = get_ncolors(prep_∇²J)
594596
else
595-
∇J_opt, ∇²J_opt = gradient(J!, mpc.gradient, mpc.Z̃, J_cache...), nothing
597+
prep_∇J = prepare_gradient(J!, mpc.gradient, mpc.Z̃, J_cache...)
598+
∇J_opt = gradient(J!, prep_∇J, mpc.gradient, mpc.Z̃, J_cache...)
599+
∇²J_opt, ∇²J_ncolors = nothing, nothing
596600
end
597601
# --- inequality constraint derivatives ---
598602
∇g_cache = (
@@ -605,7 +609,9 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
605609
gi .= @views g[i_g]
606610
return nothing
607611
end
608-
g_opt, ∇g_opt = value_and_jacobian(gi!, gi, mpc.jacobian, mpc.Z̃, ∇g_cache...)
612+
prep_∇g = prepare_jacobian(gi!, gi, mpc.jacobian, mpc.Z̃, ∇g_cache...)
613+
g_opt, ∇g_opt = value_and_jacobian(gi!, gi, prep_∇g, mpc.jacobian, mpc.Z̃, ∇g_cache...)
614+
∇g_ncolors = get_ncolors(prep_∇g)
609615
if !isnothing(hess) && ngi > 0
610616
nonlincon = optim[:nonlinconstraint]
611617
λi = try
@@ -631,9 +637,11 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
631637
gi .= @views g[i_g]
632638
return dot(λi, gi)
633639
end
634-
∇²ℓg_opt = hessian(ℓ_gi, hess, mpc.Z̃, Constant(λi), ∇²g_cache...)
640+
prep_∇²ℓg = prepare_hessian(ℓ_gi, hess, mpc.Z̃, Constant(λi), ∇²g_cache...)
641+
∇²ℓg_opt = hessian(ℓ_gi, prep_∇²ℓg, hess, mpc.Z̃, Constant(λi), ∇²g_cache...)
642+
∇²ℓg_ncolors = get_ncolors(prep_∇²ℓg)
635643
else
636-
∇²ℓg_opt = nothing
644+
∇²ℓg_opt, ∇²ℓg_ncolors = nothing, nothing
637645
end
638646
# --- equality constraint derivatives ---
639647
geq_cache = (
@@ -645,7 +653,9 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
645653
update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K, X̂0, gc, g, geq, mpc, Z̃)
646654
return nothing
647655
end
648-
geq_opt, ∇geq_opt = value_and_jacobian(geq!, geq, mpc.jacobian, mpc.Z̃, geq_cache...)
656+
prep_∇geq = prepare_jacobian(geq!, geq, mpc.jacobian, mpc.Z̃, geq_cache...)
657+
geq_opt, ∇geq_opt = value_and_jacobian(geq!, geq, prep_∇geq, mpc.jacobian, mpc.Z̃, geq_cache...)
658+
∇geq_ncolors = get_ncolors(prep_∇geq)
649659
if !isnothing(hess) && con.neq > 0
650660
nonlinconeq = optim[:nonlinconstrainteq]
651661
λeq = try
@@ -670,25 +680,37 @@ function addinfo!(info, mpc::NonLinMPC{NT}) where NT<:Real
670680
update_predictions!(ΔŨ, x̂0end, Ue, Ŷe, U0, Ŷ0, Û0, K, X̂0, gc, g, geq, mpc, Z̃)
671681
return dot(λeq, geq)
672682
end
673-
∇²ℓgeq_opt = hessian(ℓ_geq, hess, mpc.Z̃, Constant(λeq), ∇²geq_cache...)
683+
prep_∇²ℓgeq = prepare_hessian(ℓ_geq, hess, mpc.Z̃, Constant(λeq), ∇²geq_cache...)
684+
∇²ℓgeq_opt = hessian(ℓ_geq, prep_∇²ℓgeq, hess, mpc.Z̃, Constant(λeq), ∇²geq_cache...)
685+
∇²ℓgeq_ncolors = get_ncolors(prep_∇²ℓgeq)
674686
else
675-
∇²ℓgeq_opt = nothing
687+
∇²ℓgeq_opt, ∇²ℓgeq_ncolors = nothing, nothing
676688
end
677689
info[:∇J] = ∇J_opt
678690
info[:∇²J] = ∇²J_opt
691+
info[:∇²J_ncolors] = ∇²J_ncolors
679692
info[:g] = g_opt
680693
info[:∇g] = ∇g_opt
694+
info[:∇g_ncolors] = ∇g_ncolors
681695
info[:∇²ℓg] = ∇²ℓg_opt
696+
info[:∇²ℓg_ncolors] = ∇²ℓg_ncolors
682697
info[:geq] = geq_opt
683698
info[:∇geq] = ∇geq_opt
699+
info[:∇geq_ncolors] = ∇geq_ncolors
684700
info[:∇²ℓgeq] = ∇²ℓgeq_opt
701+
info[:∇²ℓgeq_ncolors] = ∇²ℓgeq_ncolors
685702
# --- non-Unicode fields ---
686703
info[:nablaJ] = ∇J_opt
687704
info[:nabla2J] = ∇²J_opt
705+
info[:nabla2J_ncolors] = ∇²J_ncolors
688706
info[:nablag] = ∇g_opt
707+
info[:nablag_ncolors] = ∇g_ncolors
689708
info[:nabla2lg] = ∇²ℓg_opt
709+
info[:nabla2lg_ncolors] = ∇²ℓg_ncolors
690710
info[:nablageq] = ∇geq_opt
711+
info[:nablageq_ncolors] = ∇geq_ncolors
691712
info[:nabla2lgeq] = ∇²ℓgeq_opt
713+
info[:nabla2lgeq_ncolors] = ∇²ℓgeq_ncolors
692714
return info
693715
end
694716

src/general.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ dense_backend(backend::AbstractADType) = backend
140140
dense_backend(backend::AutoSparse) = backend.dense_ad
141141
dense_backend(backend::SecondOrder) = backend.inner
142142

143+
"Get the number of colors in preparation object `prep`, or `nothing` if not applicable."
144+
get_ncolors(::Prep) = nothing
145+
get_ncolors(prep::Union{SparseJacobianPrep, SparseHessianPrep}) = ncolors(prep)
146+
143147
"Validate `hessian` keyword argument and return the differentiation `backend`."
144148
function validate_hessian(hessian, gradient, default)
145149
if hessian == true

0 commit comments

Comments
 (0)