DifferentailEquations.jl error on multiple_shooting_objective

I’m still exploring the excellent DifferentialEquations.jl and came across this error today.
I wanted to compare the different objective functions created by two_stage_method, build_loss_objective and multiple_shooting_objective.

using DifferentialEquations
using DiffEqParamEstim

function floudas_one(dz_dt, z, phi, t)
    r_1 = phi[1]*z[1]
    r_2 = phi[2]*z[2]

    dz_dt[1] = -r_1
    dz_dt[2] = r_1 - r_2
end

phi = [5.0035 1.0]
data = [1.0 0.57353 0.328937 0.188654 0.108198 0.0620545 0.0355906 0.0204132 0.011708 0.00671499;
        0.0 0.401566 0.589647 0.659731 0.666112 0.639512 0.597179 0.54867 0.499168 0.451377]
t = [0.0, 0.111111, 0.222222, 0.333333, 0.444444, 0.555556, 0.666667, 0.777778, 0.888889, 1.0]

ode_fun = floudas_one

t_span = (t[1], t[end])
de_prob = ODEProblem(ode_fun,data[:,1],t_span)
obj_ts = two_stage_method(de_prob,t,data)
obj_ss = build_loss_objective(de_prob,Tsit5(),L2Loss(t,data))
obj_ms = multiple_shooting_objective(de_prob,Tsit5(),L2Loss(t,data))

println(obj_ts(phi))
println(obj_ss(phi))
println(obj_ms(phi))

Calling obj_ts and obj_ss give me the expected results. However obj_ms returns:

MethodError: no method matching length(::Nothing)
Closest candidates are:
  length(!Matched::Core.SimpleVector) at essentials.jl:561
  length(!Matched::Base.MethodList) at reflection.jl:801
  length(!Matched::Core.MethodTable) at reflection.jl:875
  ...
in top-level scope at base/none
in  at DiffEqParamEstim/mNjO8/src/build_loss_objective.jl:24
in  at DiffEqParamEstim/mNjO8/src/multiple_shooting_objective.jl:33

Any guidance would be appreciated.


So shortly after writing this I figured I left the parameter p out of the constructor. I thought I should give it a try.

p0 = [0.1 0.1]
t_span = (t[1], t[end])
de_prob = ODEProblem(ode_fun,data[:,1],t_span,p0)
obj_ts = two_stage_method(de_prob,t,data)
obj_ss = build_loss_objective(de_prob,Tsit5(),L2Loss(t,data))
obj_ms = multiple_shooting_objective(de_prob,Tsit5(),L2Loss(t,data))

Now obj_ms returns:

InexactError: Int64(Inf)
in top-level scope at base/none
in  at DiffEqParamEstim/mNjO8/src/build_loss_objective.jl:24
in  at DiffEqParamEstim/mNjO8/src/multiple_shooting_objective.jl:34
in Type at base/float.jl:703 

So I decided to formulate my original ODE as a BVP, just in case multiple_shooting_objective is only fit to receive a BVProblem and not a ODEProblem.

function bc1(residual, u)
    residual[1] = u[end÷2][1] - data[1,end÷2]
    residual[2] = u[end][1] - data[1,end]
    residual[3] = u[end÷2][2] - data[2,end÷2]
    residual[4] = u[end][2] - data[2,end]
end

p0 = [0.1 0.1]
t_span = (t[1], t[end])
de_prob = ODEProblem(ode_fun,data[:,1],t_span,p0)
obj_ts = two_stage_method(de_prob,t,data)
obj_ss = build_loss_objective(de_prob,Tsit5(),L2Loss(t,data))
bv_prob = BVProblem(ode_fun, bc1, data[:,1], t_span, p0)
obj_ms = multiple_shooting_objective(bv_prob,Tsit5(),L2Loss(t,data))

But I still get the same error as above.

1 Like

Hi, the parameters that the cost function in multiple shooting objective takes is different from the parameters of the ODE, you need to pass the intermediate starting points as well with the parameters of the ODE. Take a look at the examples here http://docs.juliadiffeq.org/latest/analysis/parameter_estimation.html#Optimization-Based-ODE-Inference-Examples-1, so to get the value you would have to pass something like p0 = [1.0,0.0,0.0,0.0,0.1,0.1]. I hope this is clear? Take a look at DiffEqDocs.jl/parameter_estimation.md at master · SciML/DiffEqDocs.jl · GitHub to understand what the multiple shooting method is trying to do, that would make it clearer.

1 Like

Thanks for the reply @Vaibhavdixit02! I missed the BVP example at the examples page.

The examples cleared some doubts on how to use it but raised others on how it works. To my surprise, the code behind it was simple enough so that I could gather its workings after some investigation. I still have to wrap my head around some parts of it, but it still much more readable than I expected!