Skip to content

Commit a07fd8a

Browse files
authored
Merge pull request #37 from JuliaControl/reduce_alloc
Remove useless allocations for in-place `NonLinModel`
2 parents 80dbd61 + a74b0f6 commit a07fd8a

File tree

9 files changed

+93
-75
lines changed

9 files changed

+93
-75
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ModelPredictiveControl"
22
uuid = "61f9bdb8-6ae4-484a-811f-bbf86720c31c"
33
authors = ["Francis Gagnon"]
4-
version = "0.18.0"
4+
version = "0.18.1"
55

66
[deps]
77
ControlSystemsBase = "aaaaaaaa-a6ca-5380-bf3e-84a91bcd477e"

src/controller/execute.jl

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,12 @@ julia> round.(getinfo(mpc)[:Ŷ], digits=3)
104104
"""
105105
function getinfo(mpc::PredictiveController{NT}) where NT<:Real
106106
info = Dict{Symbol, Union{JuMP._SolutionSummary, Vector{NT}, NT}}()
107-
Ŷ, x̂, u = similar(mpc.Ŷop), similar(mpc.estim.x̂), similar(mpc.estim.lastu0)
108-
Ŷ, x̂end = predict!(Ŷ, x̂, u, mpc, mpc.estim.model, mpc.ΔŨ)
107+
Ŷ, u = similar(mpc.Ŷop), similar(mpc.estim.lastu0)
108+
x̂, x̂next = similar(mpc.estim.x̂), similar(mpc.estim.x̂)
109+
Ŷ, x̂end = predict!(Ŷ, x̂, x̂next, u, mpc, mpc.estim.model, mpc.ΔŨ)
109110
U = mpc.*mpc.ΔŨ + mpc.T_lastu
110111
Ȳ, Ū = similar(Ŷ), similar(U)
111-
J = obj_nonlinprog!(Ȳ, Ū, mpc, mpc.estim.model, Ŷ, mpc.ΔŨ)
112+
J = obj_nonlinprog!(U, Ȳ, Ū, mpc, mpc.estim.model, Ŷ, mpc.ΔŨ)
112113
info[:ΔU] = mpc.ΔŨ[1:mpc.Hc*mpc.estim.model.nu]
113114
info[] = isinf(mpc.C) ? NaN : mpc.ΔŨ[end]
114115
info[:J] = J
@@ -297,15 +298,15 @@ function linconstraint!(mpc::PredictiveController, ::SimModel)
297298
end
298299

299300
@doc raw"""
300-
predict!(Ŷ, x̂, _ , mpc::PredictiveController, model::LinModel, ΔŨ) -> Ŷ, x̂end
301+
predict!(Ŷ, x̂, _ , _ , mpc::PredictiveController, model::LinModel, ΔŨ) -> Ŷ, x̂end
301302
302303
Compute the predictions `Ŷ` and terminal states `x̂end` if model is a [`LinModel`](@ref).
303304
304305
The method mutates `Ŷ` and `x̂` vector arguments. The `x̂end` vector is used for
305306
the terminal constraints applied on ``\mathbf{x̂}_{k-1}(k+H_p)``.
306307
"""
307308
function predict!(
308-
Ŷ, x̂, _ , mpc::PredictiveController, ::LinModel, ΔŨ::Vector{NT}
309+
Ŷ, x̂, _ , _ , mpc::PredictiveController, ::LinModel, ΔŨ::Vector{NT}
309310
) where {NT<:Real}
310311
# in-place operations to reduce allocations :
311312
Ŷ .= mul!(Ŷ, mpc.Ẽ, ΔŨ) .+ mpc.F
@@ -315,19 +316,18 @@ function predict!(
315316
end
316317

317318
@doc raw"""
318-
predict!(Ŷ, x̂, u, mpc::PredictiveController, model::SimModel, ΔŨ) -> Ŷ, x̂end
319+
predict!(Ŷ, x̂, x̂next, u, mpc::PredictiveController, model::SimModel, ΔŨ) -> Ŷ, x̂end
319320
320321
Compute both vectors if `model` is not a [`LinModel`](@ref).
321322
322-
The method mutates `Ŷ`, `x̂` and `u` arguments.
323+
The method mutates `Ŷ`, `x̂`, `x̂next` and `u` arguments.
323324
"""
324325
function predict!(
325-
Ŷ, x̂, u, mpc::PredictiveController, model::SimModel, ΔŨ::Vector{NT}
326+
Ŷ, x̂, x̂next, u, mpc::PredictiveController, model::SimModel, ΔŨ::Vector{NT}
326327
) where {NT<:Real}
327328
nu, ny, nd, Hp, Hc = model.nu, model.ny, model.nd, mpc.Hp, mpc.Hc
328329
u0 = u
329330
x̂ .= mpc.estim.
330-
x̂next = similar(x̂) # TODO: avoid this allocation if possible
331331
u0 .= mpc.estim.lastu0
332332
d0 = @views mpc.d0[1:end]
333333
for j=1:Hp
@@ -346,20 +346,20 @@ function predict!(
346346
end
347347

348348
"""
349-
obj_nonlinprog!( _ , _ , mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ)
349+
obj_nonlinprog!(U , _ , _ , mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ)
350350
351351
Nonlinear programming objective function when `model` is a [`LinModel`](@ref).
352352
353353
The function is called by the nonlinear optimizer of [`NonLinMPC`](@ref) controllers. It can
354354
also be called on any [`PredictiveController`](@ref)s to evaluate the objective function `J`
355-
at specific input increments `ΔŨ` and predictions `Ŷ` values.
355+
at specific input increments `ΔŨ` and predictions `Ŷ` values. It mutates the `U` argument.
356356
"""
357357
function obj_nonlinprog!(
358-
_ , _ , mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ::Vector{NT}
358+
U , _ , _ , mpc::PredictiveController, model::LinModel, Ŷ, ΔŨ::Vector{NT}
359359
) where {NT<:Real}
360360
J = obj_quadprog(ΔŨ, mpc.H̃, mpc.q̃) + mpc.p[]
361361
if !iszero(mpc.E)
362-
U = mpc.*ΔŨ .+ mpc.T_lastu
362+
U .= mul!(U, mpc., ΔŨ) .+ mpc.T_lastu
363363
UE = [U; U[(end - model.nu + 1):end]]
364364
ŶE = [mpc.ŷ; Ŷ]
365365
J += mpc.E*mpc.JE(UE, ŶE, mpc.D̂E)
@@ -368,14 +368,15 @@ function obj_nonlinprog!(
368368
end
369369

370370
"""
371-
obj_nonlinprog!(Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷ, ΔŨ)
371+
obj_nonlinprog!(U, Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷ, ΔŨ)
372372
373373
Nonlinear programming objective function when `model` is not a [`LinModel`](@ref). The
374374
function `dot(x, A, x)` is a performant way of calculating `x'*A*x`. This method mutates
375-
`Ȳ` and `Ū` vector arguments (output and input setpoint tracking error, respectively).
375+
`U`, `Ȳ` and `Ū` arguments (input over `Hp`, and output and input setpoint tracking error,
376+
respectively).
376377
"""
377378
function obj_nonlinprog!(
378-
Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷ, ΔŨ::Vector{NT}
379+
U, Ȳ, Ū, mpc::PredictiveController, model::SimModel, Ŷ, ΔŨ::Vector{NT}
379380
) where {NT<:Real}
380381
# --- output setpoint tracking term ---
381382
Ȳ .= mpc.R̂y .-
@@ -384,7 +385,7 @@ function obj_nonlinprog!(
384385
JΔŨ = dot(ΔŨ, mpc.Ñ_Hc, ΔŨ)
385386
# --- input over prediction horizon ---
386387
if !mpc.noR̂u || !iszero(mpc.E)
387-
U = mpc.*ΔŨ + mpc.T_lastu
388+
U .= mul!(U, mpc., ΔŨ) .+ mpc.T_lastu
388389
end
389390
# --- input setpoint tracking term ---
390391
if !mpc.noR̂u

src/controller/explicitmpc.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ The solution is ``\mathbf{ΔŨ = - H̃^{-1} q̃}``, see [`init_quadprog`](@ref)
197197
optim_objective!(mpc::ExplicitMPC) = lmul!(-1, ldiv!(mpc.ΔŨ, mpc.H̃_chol, mpc.q̃))
198198

199199
"Compute the predictions but not the terminal states if `mpc` is an [`ExplicitMPC`](@ref)."
200-
function predict!(Ŷ, x̂, _ , mpc::ExplicitMPC, ::LinModel, ΔŨ::Vector{NT}) where {NT<:Real}
200+
function predict!(
201+
Ŷ, x̂, _ , _ , mpc::ExplicitMPC, ::LinModel, ΔŨ::Vector{NT}
202+
) where {NT<:Real}
201203
# in-place operations to reduce allocations :
202204
Ŷ .= mul!(Ŷ, mpc.Ẽ, ΔŨ) .+ mpc.F
203205
x̂ .= NaN

src/controller/nonlinmpc.jl

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -302,49 +302,55 @@ function init_optimization!(mpc::NonLinMPC, optim::JuMP.GenericModel{JNT}) where
302302
nu, ny, nx̂, Hp, ng = model.nu, model.ny, mpc.estim.nx̂, mpc.Hp, length(con.i_g)
303303
# inspired from https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/tips_and_tricks/#User-defined-operators-with-vector-outputs
304304
Jfunc, gfunc = let mpc=mpc, model=model, ng=ng, nΔŨ=nΔŨ, nŶ=Hp*ny, nx̂=nx̂, nu=nu, nU=Hp*nu
305+
Nc = nΔŨ + 3
305306
last_ΔŨtup_float, last_ΔŨtup_dual = nothing, nothing
306-
Ŷ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), nΔŨ + 3)
307-
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), nΔŨ + 3)
308-
x̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), nΔŨ + 3)
309-
u_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nu), nΔŨ + 3)
310-
Ȳ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), nΔŨ + 3)
311-
Ū_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nU), nΔŨ + 3)
307+
Ŷ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), Nc)
308+
U_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nU), Nc)
309+
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), Nc)
310+
x̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
311+
x̂next_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
312+
u_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nu), Nc)
313+
Ȳ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŶ), Nc)
314+
Ū_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nU), Nc)
312315
function Jfunc(ΔŨtup::JNT...)
313316
ΔŨ1 = ΔŨtup[begin]
314317
= get_tmp(Ŷ_cache, ΔŨ1)
315318
ΔŨ = collect(ΔŨtup)
316319
if ΔŨtup !== last_ΔŨtup_float
317-
x̂, u = get_tmp(x̂_cache, ΔŨ1), get_tmp(u_cache, ΔŨ1)
318-
Ŷ, x̂end = predict!(Ŷ, x̂, u, mpc, model, ΔŨ)
320+
x̂, x̂next = get_tmp(x̂_cache, ΔŨ1), get_tmp(x̂next_cache, ΔŨ1)
321+
u = get_tmp(u_cache, ΔŨ1)
322+
Ŷ, x̂end = predict!(Ŷ, x̂, x̂next, u, mpc, model, ΔŨ)
319323
g = get_tmp(g_cache, ΔŨ1)
320324
g = con_nonlinprog!(g, mpc, model, x̂end, Ŷ, ΔŨ)
321325
last_ΔŨtup_float = ΔŨtup
322326
end
323-
Ȳ, Ū = get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
324-
return obj_nonlinprog!(Ȳ, Ū, mpc, model, Ŷ, ΔŨ)
327+
U, Ȳ, Ū = get_tmp(U_cache, ΔŨ1), get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
328+
return obj_nonlinprog!(U, Ȳ, Ū, mpc, model, Ŷ, ΔŨ)
325329
end
326330
function Jfunc(ΔŨtup::ForwardDiff.Dual...)
327331
ΔŨ1 = ΔŨtup[begin]
328332
= get_tmp(Ŷ_cache, ΔŨ1)
329333
ΔŨ = collect(ΔŨtup)
330334
if ΔŨtup !== last_ΔŨtup_dual
331-
x̂, u = get_tmp(x̂_cache, ΔŨ1), get_tmp(u_cache, ΔŨ1)
332-
Ŷ, x̂end = predict!(Ŷ, x̂, u, mpc, model, ΔŨ)
335+
x̂, x̂next = get_tmp(x̂_cache, ΔŨ1), get_tmp(x̂next_cache, ΔŨ1)
336+
u = get_tmp(u_cache, ΔŨ1)
337+
Ŷ, x̂end = predict!(Ŷ, x̂, x̂next, u, mpc, model, ΔŨ)
333338
g = get_tmp(g_cache, ΔŨ1)
334339
g = con_nonlinprog!(g, mpc, model, x̂end, Ŷ, ΔŨ)
335340
last_ΔŨtup_dual = ΔŨtup
336341
end
337-
Ȳ, Ū = get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
338-
return obj_nonlinprog!(Ȳ, Ū, mpc, model, Ŷ, ΔŨ)
342+
U, Ȳ, Ū = get_tmp(U_cache, ΔŨ1), get_tmp(Ȳ_cache, ΔŨ1), get_tmp(Ū_cache, ΔŨ1)
343+
return obj_nonlinprog!(U, Ȳ, Ū, mpc, model, Ŷ, ΔŨ)
339344
end
340345
function gfunc_i(i, ΔŨtup::NTuple{N, JNT}) where N
341346
ΔŨ1 = ΔŨtup[begin]
342347
g = get_tmp(g_cache, ΔŨ1)
343348
if ΔŨtup !== last_ΔŨtup_float
344-
x̂, u = get_tmp(x̂_cache, ΔŨ1), get_tmp(u_cache, ΔŨ1)
345349
= get_tmp(Ŷ_cache, ΔŨ1)
346350
ΔŨ = collect(ΔŨtup)
347-
Ŷ, x̂end = predict!(Ŷ, x̂, u, mpc, model, ΔŨ)
351+
x̂, x̂next = get_tmp(x̂_cache, ΔŨ1), get_tmp(x̂next_cache, ΔŨ1)
352+
u = get_tmp(u_cache, ΔŨ1)
353+
Ŷ, x̂end = predict!(Ŷ, x̂, x̂next, u, mpc, model, ΔŨ)
348354
g = con_nonlinprog!(g, mpc, model, x̂end, Ŷ, ΔŨ)
349355
last_ΔŨtup_float = ΔŨtup
350356
end
@@ -354,10 +360,11 @@ function init_optimization!(mpc::NonLinMPC, optim::JuMP.GenericModel{JNT}) where
354360
ΔŨ1 = ΔŨtup[begin]
355361
g = get_tmp(g_cache, ΔŨ1)
356362
if ΔŨtup !== last_ΔŨtup_dual
357-
x̂, u = get_tmp(x̂_cache, ΔŨ1), get_tmp(u_cache, ΔŨ1)
358363
= get_tmp(Ŷ_cache, ΔŨ1)
359364
ΔŨ = collect(ΔŨtup)
360-
Ŷ, x̂end = predict!(Ŷ, x̂, u, mpc, model, ΔŨ)
365+
x̂, x̂next = get_tmp(x̂_cache, ΔŨ1), get_tmp(x̂next_cache, ΔŨ1)
366+
u = get_tmp(u_cache, ΔŨ1)
367+
Ŷ, x̂end = predict!(Ŷ, x̂, x̂next, u, mpc, model, ΔŨ)
361368
g = con_nonlinprog!(g, mpc, model, x̂end, Ŷ, ΔŨ)
362369
last_ΔŨtup_dual = ΔŨtup
363370
end

src/estimator/execute.jl

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ function remove_op!(estim::StateEstimator, u, ym, d)
1515
end
1616

1717
@doc raw"""
18-
f̂!(x̂next, estim::StateEstimator, model::SimModel, x̂, u, d) -> x̂next
18+
f̂!(x̂next, estim::StateEstimator, model::SimModel, x̂, u, d) -> nothing
1919
2020
Mutating state function ``\mathbf{f̂}`` of the augmented model.
2121
@@ -33,24 +33,25 @@ function f̂!(x̂next, estim::StateEstimator, model::SimModel, x̂, u, d)
3333
# `@views` macro avoid copies with matrix slice operator e.g. [a:b]
3434
@views x̂d, x̂s = x̂[1:model.nx], x̂[model.nx+1:end]
3535
@views x̂d_next, x̂s_next = x̂next[1:model.nx], x̂next[model.nx+1:end]
36-
T = promote_type(eltype(x̂), eltype(u), eltype(d))
37-
u_us = Vector{T}(undef, model.nu) # TODO: avoid this allocation if possible
38-
u_us .= u .+ mul!(u_us, estim.Cs_u, x̂s)
39-
f!(x̂d_next, model, x̂d, u_us, d)
36+
T = promote_type(eltype(x̂), eltype(u))
37+
= Vector{T}(undef, model.nu) # TODO: avoid this allocation if possible
38+
.= u .+ mul!(, estim.Cs_u, x̂s)
39+
f!(x̂d_next, model, x̂d, , d)
4040
mul!(x̂s_next, estim.As, x̂s)
41-
return x̂next
41+
return nothing
4242
end
43+
4344
"Use the augmented model matrices if `model` is a [`LinModel`](@ref)."
4445
function f̂!(x̂next, estim::StateEstimator, ::LinModel, x̂, u, d)
4546
x̂next .= 0
4647
mul!(x̂next, estim.Â, x̂, 1, 1)
4748
mul!(x̂next, estim.B̂u, u, 1, 1)
4849
mul!(x̂next, estim.B̂d, d, 1, 1)
49-
return x̂next
50+
return nothing
5051
end
5152

5253
@doc raw"""
53-
ĥ!(ŷ, estim::StateEstimator, model::SimModel, x̂, d) ->
54+
ĥ!(ŷ, estim::StateEstimator, model::SimModel, x̂, d) -> nothing
5455
5556
Mutating output function ``\mathbf{ĥ}`` of the augmented model, see [`f̂!`](@ref).
5657
"""
@@ -59,14 +60,14 @@ function ĥ!(ŷ, estim::StateEstimator, model::SimModel, x̂, d)
5960
@views x̂d, x̂s = x̂[1:model.nx], x̂[model.nx+1:end]
6061
h!(ŷ, model, x̂d, d)
6162
mul!(ŷ, estim.Cs_y, x̂s, 1, 1)
62-
return
63+
return nothing
6364
end
6465
"Use the augmented model matrices if `model` is a [`LinModel`](@ref)."
6566
function ĥ!(ŷ, estim::StateEstimator, ::LinModel, x̂, d)
6667
ŷ .= 0
6768
mul!(ŷ, estim.Ĉ, x̂, 1, 1)
6869
mul!(ŷ, estim.D̂d, d, 1, 1)
69-
return
70+
return nothing
7071
end
7172

7273

src/estimator/mhe/construct.jl

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -990,21 +990,25 @@ function init_optimization!(
990990
end
991991
He = estim.He
992992
nV̂, nX̂, ng = He*estim.nym, He*estim.nx̂, length(con.i_g)
993+
nx̂, nŷ = estim.nx̂, model.ny
993994
# see init_optimization!(mpc::NonLinMPC, optim) for details on the inspiration
994-
Jfunc, gfunc = let estim=estim, model=model, nZ̃=nZ̃ , nV̂=nV̂, nX̂=nX̂, ng=ng, nx̂=estim.nx̂
995+
Jfunc, gfunc = let estim=estim, model=model, nZ̃=nZ̃ , nV̂=nV̂, nX̂=nX̂, ng=ng, nx̂=nx̂, nŷ=nŷ
996+
Nc = nZ̃ + 3
995997
last_Z̃tup_float, last_Z̃tup_dual = nothing, nothing
996-
V̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nV̂), nZ̃ + 3)
997-
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), nZ̃ + 3)
998-
X̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nX̂), nZ̃ + 3)
999-
x̄_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), nZ̃ + 3)
998+
V̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nV̂), Nc)
999+
g_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, ng), Nc)
1000+
X̂_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nX̂), Nc)
1001+
x̄_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nx̂), Nc)
1002+
ŷ_cache::DiffCache{Vector{JNT}, Vector{JNT}} = DiffCache(zeros(JNT, nŷ), Nc)
10001003
function Jfunc(Z̃tup::JNT...)
10011004
Z̃1 = Z̃tup[begin]
10021005
= get_tmp(V̂_cache, Z̃1)
10031006
= collect(Z̃tup)
10041007
if Z̃tup !== last_Z̃tup_float
10051008
g = get_tmp(g_cache, Z̃1)
10061009
= get_tmp(X̂_cache, Z̃1)
1007-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1010+
= get_tmp(ŷ_cache, Z̃1)
1011+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10081012
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10091013
last_Z̃tup_float = Z̃tup
10101014
end
@@ -1018,7 +1022,8 @@ function init_optimization!(
10181022
if Z̃tup !== last_Z̃tup_dual
10191023
g = get_tmp(g_cache, Z̃1)
10201024
= get_tmp(X̂_cache, Z̃1)
1021-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1025+
= get_tmp(ŷ_cache, Z̃1)
1026+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10221027
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10231028
last_Z̃tup_dual = Z̃tup
10241029
end
@@ -1029,10 +1034,11 @@ function init_optimization!(
10291034
Z̃1 = Z̃tup[begin]
10301035
g = get_tmp(g_cache, Z̃1)
10311036
if Z̃tup !== last_Z̃tup_float
1037+
= collect(Z̃tup)
10321038
= get_tmp(V̂_cache, Z̃1)
10331039
= get_tmp(X̂_cache, Z̃1)
1034-
= collect(Z̃tup)
1035-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1040+
= get_tmp(ŷ_cache, Z̃1)
1041+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10361042
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10371043
last_Z̃tup_float = Z̃tup
10381044
end
@@ -1042,10 +1048,11 @@ function init_optimization!(
10421048
Z̃1 = Z̃tup[begin]
10431049
g = get_tmp(g_cache, Z̃1)
10441050
if Z̃tup !== last_Z̃tup_dual
1051+
= collect(Z̃tup)
10451052
= get_tmp(V̂_cache, Z̃1)
10461053
= get_tmp(X̂_cache, Z̃1)
1047-
= collect(Z̃tup)
1048-
V̂, X̂ = predict!(V̂, X̂, estim, model, Z̃)
1054+
= get_tmp(ŷ_cache, Z̃1)
1055+
V̂, X̂ = predict!(V̂, X̂, ŷ, estim, model, Z̃)
10491056
g = con_nonlinprog!(g, estim, model, X̂, V̂, Z̃)
10501057
last_Z̃tup_dual = Z̃tup
10511058
end

0 commit comments

Comments
 (0)