Skip to content

Method ambiguity in __init from OrdinaryDiffEqCore v3.16.0 breaks StochasticDiffEq #3123

@isaacsas

Description

@isaacsas

Method ambiguity between OrdinaryDiffEqCore v3.16.0 and StochasticDiffEq

Description

OrdinaryDiffEqCore v3.16.0 introduced a broadened __init dispatch signature that creates a method ambiguity with StochasticDiffEq's existing __init method. Any solve call with an SDE problem + SDE algorithm (e.g., SDEProblem + ImplicitEM()) now fails.

Error

using StochasticDiffEq
f(du, u, p, t) = (du[1] = -u[1])
g(du, u, p, t) = (du[1] = 0.1u[1])
prob = SDEProblem(f, g, [1.0], (0.0, 1.0))
solve(prob, ImplicitEM())
ERROR: MethodError: __init(::SDEProblem{…}, ::ImplicitEM{…}) is ambiguous.

Candidates:
  __init(prob::Union{SciMLBase.AbstractDAEProblem, SciMLBase.AbstractODEProblem, SciMLBase.AbstractRODEProblem}, alg::Union{OrdinaryDiffEqCore.OrdinaryDiffEqAlgorithm, SciMLBase.AbstractRODEAlgorithm, SciMLBase.AbstractSDEAlgorithm, OrdinaryDiffEqCore.DAEAlgorithm}; ...)
    @ OrdinaryDiffEqCore ~/.julia/packages/OrdinaryDiffEqCore/tusSd/src/solve.jl:19
  __init(_prob::Union{JumpProcesses.JumpProblem, SciMLBase.AbstractRODEProblem}, alg::Union{StochasticDiffEqAlgorithm, StochasticDiffEqRODEAlgorithm}; saveat, tstops, d_discontinuities, save_idxs, save_everystep, save_noise, save_on, save_start, save_end, callback, dense, calck, dt, adaptive, gamma, abstol, reltol, qmin, qmax, qsteady_min, qsteady_max, beta2, beta1, qoldinit, controller, fullnormalize, failfactor, delta, maxiters, dtmax, dtmin, internalnorm, isoutofdomain, unstable_check, verbose, force_dtmin, timeseries_errors, dense_errors, advance_to_tstop, stop_at_next_tstop, initialize_save, progress, progress_steps, progress_name, progress_message, progress_id, userdata, initialize_integrator, seed, rng, alias, initializealg, kwargs...)
    @ StochasticDiffEq ~/.julia/packages/StochasticDiffEq/sGH0C/src/solve.jl:111

Possible fix, define
  __init(::SciMLBase.AbstractRODEProblem, ::Union{StochasticDiffEqAlgorithm, StochasticDiffEqRODEAlgorithm})

Stacktrace:
 [1] __solve(prob::SDEProblem{…}, alg::ImplicitEM{…}; kwargs::@Kwargs{})
   @ StochasticDiffEq ~/.julia/packages/StochasticDiffEq/sGH0C/src/solve.jl:16
 [2] __solve(prob::SDEProblem{…}, alg::ImplicitEM{…})
   @ StochasticDiffEq ~/.julia/packages/StochasticDiffEq/sGH0C/src/solve.jl:11
 [3] solve_call(_prob::SDEProblem{…}, args::ImplicitEM{…}; merge_callbacks::Bool, kwargshandle::Nothing, kwargs::@Kwargs{})
   @ DiffEqBase ~/.julia/packages/DiffEqBase/4RFWW/src/solve.jl:172
 [4] solve_call(_prob::SDEProblem{…}, args::ImplicitEM{…})
   @ DiffEqBase ~/.julia/packages/DiffEqBase/4RFWW/src/solve.jl:137
 [5] solve_up(prob::SDEProblem{…}, sensealg::Nothing, u0::Vector{…}, p::SciMLBase.NullParameters, args::ImplicitEM{…}; originator::SciMLBase.ChainRulesOriginator, kwargs::@Kwargs{})
   @ DiffEqBase ~/.julia/packages/DiffEqBase/4RFWW/src/solve.jl:630
 [6] solve(prob::SDEProblem{…}, args::ImplicitEM{…}; sensealg::Nothing, u0::Nothing, p::Nothing, wrap::Val{…}, kwargs::@Kwargs{})
   @ DiffEqBase ~/.julia/packages/DiffEqBase/4RFWW/src/solve.jl:587
 [7] solve(prob::SDEProblem{…}, args::ImplicitEM{…})
   @ DiffEqBase ~/.julia/packages/DiffEqBase/4RFWW/src/solve.jl:575
 [8] top-level scope
   @ REPL[7]:1
Some type information was truncated. Use `show(err)` to see complete types.

Root cause

PR #3119 (ChrisRackauckas-Claude/extract-build-integrator) broadened OrdinaryDiffEqCore's __init to accept:

prob::Union{AbstractODEProblem, AbstractDAEProblem, AbstractRODEProblem}
alg::Union{OrdinaryDiffEqAlgorithm, DAEAlgorithm, AbstractRODEAlgorithm, AbstractSDEAlgorithm}

StochasticDiffEq has:

prob::Union{AbstractRODEProblem, JumpProblem}
alg::Union{StochasticDiffEqAlgorithm, StochasticDiffEqRODEAlgorithm}

For any AbstractSDEProblem <: AbstractRODEProblem paired with any StochasticDiffEqAlgorithm <: AbstractSDEAlgorithm, both methods match and neither is more specific.

Suggested fix

Option A (OrdinaryDiffEqCore side): Split the union and add a disambiguation method, or narrow the OrdinaryDiffEqCore dispatch to exclude types that StochasticDiffEq handles (e.g., exclude AbstractRODEAlgorithm/AbstractSDEAlgorithm from OrdinaryDiffEqCore's union, or add an explicit method for AbstractRODEProblem + AbstractSDEAlgorithm that delegates to StochasticDiffEq).

Option B (StochasticDiffEq side): Split Union{AbstractRODEProblem, JumpProblem} into two separate methods — one for AbstractRODEProblem (more specific than OrdinaryDiffEqCore's union, resolves ambiguity) and one for JumpProblem.

Reproducer

using Pkg
Pkg.activate(; temp=true)
Pkg.add(["StochasticDiffEq", "OrdinaryDiffEq"])
# Ensure StochasticDiffEq v6.95.0 + OrdinaryDiffEqCore v3.16.0

using StochasticDiffEq
f(du, u, p, t) = (du[1] = -u[1])
g(du, u, p, t) = (du[1] = 0.1u[1])
prob = SDEProblem(f, g, [1.0], (0.0, 1.0))
solve(prob, ImplicitEM())  # MethodError: ambiguous

Versions

  • OrdinaryDiffEqCore v3.16.0
  • StochasticDiffEq v6.95.0
  • Julia 1.10+

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions