Skip to content

Commit

Permalink
Merge pull request #313 from avik-pal/ap/nlls_tutorial
Browse files Browse the repository at this point in the history
Add a tutorial demonstrating NLLS methods for ODE Parameter Estim
  • Loading branch information
ChrisRackauckas authored Dec 9, 2023
2 parents 2a1d570 + 85857f5 commit 0d90093
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
NonlinearSolve = "8913a72c-1f9b-4ce2-8d82-65094dcecaec"
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
SimpleNonlinearSolve = "727e6d20-b764-4bd8-a329-72de5adea6c7"
Expand Down
3 changes: 2 additions & 1 deletion docs/pages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ pages = ["index.md",
"tutorials/large_systems.md",
"tutorials/modelingtoolkit.md",
"tutorials/small_compile.md",
"tutorials/iterator_interface.md"],
"tutorials/iterator_interface.md",
"tutorials/optimizing_parameterized_ode.md",],
"Basics" => Any["basics/NonlinearProblem.md",
"basics/NonlinearFunctions.md",
"basics/solve.md",
Expand Down
76 changes: 76 additions & 0 deletions docs/src/tutorials/optimizing_parameterized_ode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# [Optimizing a Parameterized ODE](@id optimizing-parameterized-ode)

Let us fit a parameterized ODE to some data. We will use the Lotka-Volterra model as an
example. We will use Single Shooting to fit the parameters.

```@example parameterized_ode
using OrdinaryDiffEq, NonlinearSolve, Plots
```

Let us simulate some real data from the Lotka-Volterra model.

```@example parameterized_ode
function lotka_volterra!(du, u, p, t)
x, y = u
α, β, δ, γ = p
du[1] = dx = α * x - β * x * y
du[2] = dy = -δ * y + γ * x * y
end
# Initial condition
u0 = [1.0, 1.0]
# Simulation interval and intermediary points
tspan = (0.0, 2.0)
tsteps = 0.0:0.1:10.0
# LV equation parameter. p = [α, β, δ, γ]
p = [1.5, 1.0, 3.0, 1.0]
# Setup the ODE problem, then solve
prob = ODEProblem(lotka_volterra!, u0, tspan, p)
sol = solve(prob, Tsit5(); saveat = tsteps)
# Plot the solution
using Plots
plot(sol; linewidth = 3)
savefig("LV_ode.png")
```

Let us now formulate the parameter estimation as a Nonlinear Least Squares Problem.

```@example parameterized_ode
function loss_function(ode_param, data)
sol = solve(prob, Tsit5(); p = ode_param, saveat = tsteps)
return vec(reduce(hcat, sol.u)) .- data
end
p_init = zeros(4)
nlls_prob = NonlinearLeastSquaresProblem(loss_function, p_init, vec(reduce(hcat, sol.u)))
```

Now, we can use any NLLS solver to solve this problem.

```@example parameterized_ode
res = solve(nlls_prob, LevenbergMarquardt(); maxiters = 1000, show_trace = Val(true),
trace_level = TraceAll())
```

We can also use Trust Region methods.

```@example parameterized_ode
res = solve(nlls_prob, TrustRegion(); maxiters = 1000, show_trace = Val(true),
trace_level = TraceAll())
```

Let's plot the solution.

```@example parameterized_ode
prob2 = remake(prob; tspan = (0.0, 10.0))
sol_fit = solve(prob2, Tsit5(); p = res.u)
sol_true = solve(prob2, Tsit5(); p = p)
plot(sol_true; linewidth = 3)
plot!(sol_fit; linewidth = 3, linestyle = :dash)
savefig("LV_ode_fit.png")
```

0 comments on commit 0d90093

Please sign in to comment.