Koopman inference fails for simple example while SINDy works fine

Hi All,

I’m trying to put together a DataDrivenDiffEq.jl example for my demo system of an SIR epidemiological model.

using OrdinaryDiffEq
using DataDrivenDiffEq
using ModelingToolkit

function sir_ode(u,p,t)
    (s,i,r) = u
    (β,γ) = p
    ds = -β*s*i
    di = β*s*i - γ*i
    dr = γ*i
    [ds,di,dr]
end

p = [0.5,0.25]
u0 = [0.99, 0.01, 0.0]
tspan = (0.0, 40.0)
solver = ExplicitRK()
sir_prob = ODEProblem(sir_ode, u0, tspan, p)
sir_sol = solve(sir_prob, solver)

I use a sufficient basis to capture the above dynamics.

dd_prob = ContinuousDataDrivenProblem(sir_sol)
@parameters t
@variables u[1:3](t)
Ψ = Basis([u; u[1]*u[2]], u, independent_variable = t)

Koopman inference generates the correct set of equations, but the parameter values are incorrect.

res_koopman = solve(dd_prob, Ψ, DMDPINV(), digits = 1)
sys_koopman = result(res_koopman)
julia> equations(sys_koopman)
3-element Vector{Equation}:
 Differential(t)(u[1](t)) ~ p₁*u[1](t)*u[2](t)
 Differential(t)(u[2](t)) ~ p₂*u[2](t) + p₃*u[1](t)*u[2](t)
 Differential(t)(u[3](t)) ~ p₄*u[2](t)
julia> parameter_map(res_koopman)
4-element Vector{Pair{Sym{Real, Base.ImmutableDict{DataType, Any}}, Float64}}:
 p₁ => -0.5
 p₂ => -0.2
 p₃ => 0.5
 p₄ => 0.2

p₂ and p₄ should be -0.25 and 0.25, while the rest of the solution is correct. The true values of all parameters are correctly identified using SINDy.

res_sindy = solve(dd_prob, Ψ, STLSQ(), digits = 1)
sys_sindy = result(res_sindy)
julia> parameter_map(res_sindy)
4-element Vector{Pair{Sym{Real, Base.ImmutableDict{DataType, Any}}, Float64}}:
 p₁ => -0.5
 p₂ => -0.25
 p₃ => 0.5
 p₄ => 0.25

Does anyone have an idea why Koopman inference comes so close, but doesn’t get it correct?

Open an issue and Julius will take a look.