Hi all, I am testing out using the SciML ecosystem to fit constrained splines inside of an ODE (some terms on the RHS of the ODE are given by evaluating a spline where the point of evaluation on the domain of the spline is one or more of the state variables of the ODE). I’m having difficulty using the ecosystem to do so, getting some errors I that don’t understand how to address: Trying to convert uninitialized tangent to ChainRules tangent.
In a nutshell, I’m using Mooncake for AD, plugging into OptimizationLBFGSB.jl to optimize the coefficients of the spline. I’ve mocked up an example using everyone’s favorite SIR example here: ode-spline-help.jl · GitHub
Some points:
- The construction of the matrices defining the constrained spline isn’t illuminating for this MWE so they are just pasted there
sir_psm!depends on some parameters that won’t change during the optimization call, so I use a little closure inODEProblemto forward to it- I use
consto implement constraints of the form Ap \geq b and Cp = 0 where p are the spline coefficients sir_pnll, the loss function, also depends onSbbut in my “full” problem that would be changing in an outer loop which is estimating the level of smoothing, so I keep it as another argument and use a closure to keep it constant when I init theOptimizationFunction
I’m looking for help both to figure out how to address the particular error here but also any advice on how to better use the SciML ecosystem for this task.
Stacktrace:
ERROR: Trying to convert uninitialized tangent to ChainRules tangent.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:44
[2] to_cr_tangent
@ ~/.julia/packages/LinearSolve/tZdeL/ext/LinearSolveMooncakeExt.jl:29 [inlined]
[3] map (repeats 4 times)
@ ./tuple.jl:361 [inlined]
[4] map(f::typeof(Mooncake.to_cr_tangent), t::Tuple{…})
@ Base ./tuple.jl:361
[5] map
@ ./tuple.jl:361 [inlined]
[6] map(::Function, ::@NamedTuple{…})
@ Base ./namedtuple.jl:263
[7] to_cr_tangent(t::Mooncake.MutableTangent{@NamedTuple{…}})
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/tools_for_rules.jl:330
[8] map
@ ./tuple.jl:360 [inlined]
[9] map (repeats 5 times)
@ ./tuple.jl:361 [inlined]
[10] map(f::typeof(Mooncake.to_cr_tangent), t::Tuple{…})
@ Base ./tuple.jl:361
[11] map(::Function, ::@NamedTuple{…})
@ Base ./namedtuple.jl:263
[12] to_cr_tangent(t::Mooncake.Tangent{@NamedTuple{…}})
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/tools_for_rules.jl:329
--- the above 4 lines are repeated 1 more time ---
[17] (::Mooncake.var"#pb!!#rrule_wrapper##3"{…})(y_rdata::Mooncake.NoRData)
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/tools_for_rules.jl:488
[18] pop!
@ ~/.julia/packages/Mooncake/qOVJE/src/stack.jl:33 [inlined]
[19] #solve#30
@ ~/.julia/packages/DiffEqBase/6sydR/src/solve.jl:537 [inlined]
[20] (::Tuple{…})(_2::Any)
@ Base.Experimental ./<missing>:0
[21] (::MistyClosures.MistyClosure{Core.OpaqueClosure{Tuple{Any}, NTuple{9, Mooncake.NoRData}}})(x::Mooncake.NoRData)
@ MistyClosures ~/.julia/packages/MistyClosures/2vtLL/src/MistyClosures.jl:22
[22] Pullback
@ ~/.julia/packages/Mooncake/qOVJE/src/interpreter/reverse_mode.jl:957 [inlined]
[23] solve
@ ~/.julia/packages/DiffEqBase/6sydR/src/solve.jl:535 [inlined]
[24] (::Tuple{Mooncake.Stack{…}, Base.RefValue{…}, Mooncake.LazyDerivedRule{…}, Mooncake.Stack{…}})(_2::Any)
@ Base.Experimental ./<missing>:0
[25] (::MistyClosures.MistyClosure{Core.OpaqueClosure{Tuple{Any}, NTuple{5, Mooncake.NoRData}}})(x::Mooncake.NoRData)
@ MistyClosures ~/.julia/packages/MistyClosures/2vtLL/src/MistyClosures.jl:22
[26] Pullback
@ ~/.julia/packages/Mooncake/qOVJE/src/interpreter/reverse_mode.jl:957 [inlined]
[27] (::Mooncake.RRuleWrapperPb{Mooncake.Pullback{…}, Mooncake.LazyZeroRData{…}})(dy::Mooncake.NoRData)
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/interpreter/reverse_mode.jl:324
[28] pop!
@ ~/.julia/packages/Mooncake/qOVJE/src/stack.jl:33 [inlined]
[29] sir_pnll
@ ~/Desktop/git/model-fitting/sir/help.jl:337 [inlined]
[30] (::Tuple{…})(_2::Any)
@ Base.Experimental ./<missing>:0
[31] (::MistyClosures.MistyClosure{Core.OpaqueClosure{Tuple{…}, Tuple{…}}})(x::Float64)
@ MistyClosures ~/.julia/packages/MistyClosures/2vtLL/src/MistyClosures.jl:22
[32] Pullback
@ ~/.julia/packages/Mooncake/qOVJE/src/interpreter/reverse_mode.jl:957 [inlined]
[33] (::Mooncake.RRuleWrapperPb{Mooncake.Pullback{…}, Mooncake.LazyZeroRData{…}})(dy::Float64)
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/interpreter/reverse_mode.jl:324
[34] pop!
@ ~/.julia/packages/Mooncake/qOVJE/src/stack.jl:33 [inlined]
[35] #36
@ ~/Desktop/git/model-fitting/sir/help.jl:355 [inlined]
[36] (::Tuple{…})(_2::Any)
@ Base.Experimental ./<missing>:0
[37] (::MistyClosures.MistyClosure{Core.OpaqueClosure{Tuple{…}, Tuple{…}}})(x::Float64)
@ MistyClosures ~/.julia/packages/MistyClosures/2vtLL/src/MistyClosures.jl:22
[38] (::Mooncake.Pullback{Tuple{…}, Tuple{…}, Tuple{…}, false, 3})(dy::Float64)
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/interpreter/reverse_mode.jl:957
[39] prepare_gradient_cache(::Function, ::Vararg{Any}; kwargs::@Kwargs{debug_mode::Bool, silence_debug_messages::Bool})
@ Mooncake ~/.julia/packages/Mooncake/qOVJE/src/interface.jl:539
[40] prepare_gradient_cache
@ ~/.julia/packages/Mooncake/qOVJE/src/interface.jl:534 [inlined]
[41] prepare_gradient_nokwarg(strict::Val{…}, f::var"#36#37", backend::AutoMooncake{…}, x::Vector{…}, contexts::DifferentiationInterface.Constant{…})
@ DifferentiationInterfaceMooncakeExt ~/.julia/packages/DifferentiationInterface/4n6vR/ext/DifferentiationInterfaceMooncakeExt/onearg.jl:124
[42] #prepare_gradient#34
@ ~/.julia/packages/DifferentiationInterface/4n6vR/src/first_order/gradient.jl:11 [inlined]
[43] prepare_gradient
@ ~/.julia/packages/DifferentiationInterface/4n6vR/src/first_order/gradient.jl:8 [inlined]
[44] instantiate_function(f::OptimizationFunction{…}, x::Vector{…}, adtype::AutoMooncake{…}, p::SciMLBase.NullParameters, num_cons::Int64; g::Bool, h::Bool, hv::Bool, fg::Bool, fgh::Bool, cons_j::Bool, cons_vjp::Bool, cons_jvp::Bool, cons_h::Bool, lag_h::Bool)
@ OptimizationBase ~/.julia/packages/OptimizationBase/R2xIG/src/OptimizationDIExt.jl:26
[45] instantiate_function
@ ~/.julia/packages/OptimizationBase/R2xIG/src/OptimizationDIExt.jl:17 [inlined]
[46] #instantiate_function#63
@ ~/.julia/packages/OptimizationBase/R2xIG/src/OptimizationDIExt.jl:312 [inlined]
[47] instantiate_function
@ ~/.julia/packages/OptimizationBase/R2xIG/src/OptimizationDIExt.jl:305 [inlined]
[48] OptimizationCache(prob::OptimizationProblem{…}, opt::LBFGSB; callback::OptimizationBase.NullCallback, maxiters::Nothing, maxtime::Nothing, abstol::Nothing, reltol::Nothing, progress::Bool, structural_analysis::Bool, manifold::Nothing, kwargs::@Kwargs{})
@ OptimizationBase ~/.julia/packages/OptimizationBase/R2xIG/src/cache.jl:62
[49] OptimizationCache
@ ~/.julia/packages/OptimizationBase/R2xIG/src/cache.jl:27 [inlined]
[50] #__init#8
@ ~/.julia/packages/OptimizationBase/R2xIG/src/cache.jl:90 [inlined]
[51] __init
@ ~/.julia/packages/OptimizationBase/R2xIG/src/cache.jl:82 [inlined]
[52] #init#4
@ ~/.julia/packages/OptimizationBase/R2xIG/src/solve.jl:191 [inlined]
[53] init
@ ~/.julia/packages/OptimizationBase/R2xIG/src/solve.jl:185 [inlined]
[54] solve(::OptimizationProblem{…}, ::LBFGSB; kwargs::@Kwargs{})
@ OptimizationBase ~/.julia/packages/OptimizationBase/R2xIG/src/solve.jl:96
[55] solve(::OptimizationProblem{…}, ::LBFGSB)
@ OptimizationBase ~/.julia/packages/OptimizationBase/R2xIG/src/solve.jl:93
Some type information was truncated. Use `show(err)` to see complete types.
Version info:
[a93c6f00] DataFrames v1.8.1
[0c46a032] DifferentialEquations v7.17.0
[31c24e10] Distributions v0.25.122
[da2b9cff] Mooncake v0.4.180
[7f7a1694] Optimization v5.1.0
[22f7324a] OptimizationLBFGSB v1.2.1
[1ed8b502] SciMLSensitivity v7.90.0
[10745b16] Statistics v1.11.1
[37e2e46d] LinearAlgebra v1.12.0
[9a3f8284] Random v1.11.0
and on Julia v1.12