SciML / JumpProcesses.jl

Build and simulate jump equations like Gillespie simulations and jump diffusions with constant and state-dependent rates and mix with differential equations and scientific machine learning (SciML)
https://docs.sciml.ai/JumpProcesses/stable/
Other
136 stars 35 forks source link

Cannot set `save_everystep` keyword argument on `solve` or `init` #306

Closed lmshk closed 1 year ago

lmshk commented 1 year ago

(I am using JumpProcesses v9.6.0 on Julia v1.8.5.)

Consider the first example from the documentation:

(jl_K4YYAF) pkg> st
Status `/tmp/jl_K4YYAF/Project.toml`
  [ccbc3e58] JumpProcesses v9.6.0

julia> using JumpProcesses

julia> rate(u, p, t) = p.λ
rate (generic function with 1 method)

julia> affect!(integrator) = (integrator.u[1] += 1)
affect! (generic function with 1 method)

julia> crj = ConstantRateJump(rate, affect!)
ConstantRateJump{typeof(rate), typeof(affect!)}(rate, affect!)

julia> u₀ = [0]
1-element Vector{Int64}:
 0

julia> p = (λ = 2.0,)
(λ = 2.0,)

julia> tspan = (0.0, 10.0)
(0.0, 10.0)

julia> dprob = DiscreteProblem(u₀, tspan, p)
DiscreteProblem with uType Vector{Int64} and tType Float64. In-place: true
timespan: (0.0, 10.0)
u0: 1-element Vector{Int64}:
 0

julia> jprob = JumpProblem(dprob, Direct(), crj)
JumpProblem with problem DiscreteProblem with aggregator Direct
Number of jumps with discrete aggregation: 1
Number of jumps with continuous aggregation: 0
Number of mass action jumps: 0

According to ?solve(jprob, SSAStepper()) I should be able to set the save_everystep option, but:

julia> solve(jprob, SSAStepper(), save_everystep = false)

gives me a MethodError:

ERROR: MethodError: no method matching __init(::JumpProblem{true, DiscreteProblem{Vector{Int64}, Tuple{Float64, Float64}, true, NamedTuple{(:λ,), Tuple{Float64}}, DiscreteFunction{true, SciMLBase.FullSpecialize, SciMLBase.var"#200#201", Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, Direct, CallbackSet{Tuple{}, Tuple{DiscreteCallback{JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, typeof(SciMLBase.FINALIZE_DEFAULT)}}}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, Tuple{}, Nothing, Nothing, Random.TaskLocalRNG, Base.Pairs{Symbol, Nothing, Tuple{Symbol}, NamedTuple{(:callback,), Tuple{Nothing}}}}, ::SSAStepper; callback=nothing, save_everystep=false) Closest candidates are: __init(::JumpProblem, ::SSAStepper; save_start, save_end, seed, alias_jump, saveat, callback, tstops, numsteps_hint) at ~/.julia/packages/JumpProcesses/bCO22/src/SSA_stepper.jl:135 got unsupported keyword argument "save_everystep" __init(::SciMLBase.AbstractJumpProblem{P}, ::SciMLBase.AbstractDEAlgorithm) where P at ~/.julia/packages/JumpProcesses/bCO22/src/solve.jl:10 got unsupported keyword arguments "callback", "save_everystep" __init(::SciMLBase.AbstractJumpProblem{P}, ::SciMLBase.AbstractDEAlgorithm, ::Any) where P at ~/.julia/packages/JumpProcesses/bCO22/src/solve.jl:10 got unsupported keyword arguments "callback", "save_everystep" ... Stacktrace: [1] kwerr(::NamedTuple{(:callback, :save_everystep), Tuple{Nothing, Bool}}, ::Function, ::JumpProblem{true, DiscreteProblem{Vector{Int64}, Tuple{Float64, Float64}, true, NamedTuple{(:λ,), Tuple{Float64}}, DiscreteFunction{true, SciMLBase.FullSpecialize, SciMLBase.var"#200#201", Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, Direct, CallbackSet{Tuple{}, Tuple{DiscreteCallback{JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, typeof(SciMLBase.FINALIZE_DEFAULT)}}}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, Tuple{}, Nothing, Nothing, Random.TaskLocalRNG, Base.Pairs{Symbol, Nothing, Tuple{Symbol}, NamedTuple{(:callback,), Tuple{Nothing}}}}, ::SSAStepper) @ Base ./error.jl:165 [2] init_call(_prob::JumpProblem{true, DiscreteProblem{Vector{Int64}, Tuple{Float64, Float64}, true, NamedTuple{(:λ,), Tuple{Float64}}, DiscreteFunction{true, SciMLBase.FullSpecialize, SciMLBase.var"#200#201", Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, Direct, CallbackSet{Tuple{}, Tuple{DiscreteCallback{JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, typeof(SciMLBase.FINALIZE_DEFAULT)}}}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, Tuple{}, Nothing, Nothing, Random.TaskLocalRNG, Base.Pairs{Symbol, Nothing, Tuple{Symbol}, NamedTuple{(:callback,), Tuple{Nothing}}}}, args::SSAStepper; merge_callbacks::Bool, kwargshandle::KeywordArgError, kwargs::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:save_everystep,), Tuple{Bool}}}) @ DiffEqBase ~/.julia/packages/DiffEqBase/qPmC2/src/solve.jl:425 [3] init(prob::JumpProblem{true, DiscreteProblem{Vector{Int64}, Tuple{Float64, Float64}, true, NamedTuple{(:λ,), Tuple{Float64}}, DiscreteFunction{true, SciMLBase.FullSpecialize, SciMLBase.var"#200#201", Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, Direct, CallbackSet{Tuple{}, Tuple{DiscreteCallback{JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, typeof(SciMLBase.FINALIZE_DEFAULT)}}}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, Tuple{}, Nothing, Nothing, Random.TaskLocalRNG, Base.Pairs{Symbol, Nothing, Tuple{Symbol}, NamedTuple{(:callback,), Tuple{Nothing}}}}, args::SSAStepper; kwargs::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:save_everystep,), Tuple{Bool}}}) @ DiffEqBase ~/.julia/packages/DiffEqBase/qPmC2/src/solve.jl:442 [4] __solve(jump_prob::JumpProblem{true, DiscreteProblem{Vector{Int64}, Tuple{Float64, Float64}, true, NamedTuple{(:λ,), Tuple{Float64}}, DiscreteFunction{true, SciMLBase.FullSpecialize, SciMLBase.var"#200#201", Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, Direct, CallbackSet{Tuple{}, Tuple{DiscreteCallback{JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, typeof(SciMLBase.FINALIZE_DEFAULT)}}}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, Tuple{}, Nothing, Nothing, Random.TaskLocalRNG, Base.Pairs{Symbol, Nothing, Tuple{Symbol}, NamedTuple{(:callback,), Tuple{Nothing}}}}, alg::SSAStepper; kwargs::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:save_everystep,), Tuple{Bool}}}) @ JumpProcesses ~/.julia/packages/JumpProcesses/bCO22/src/SSA_stepper.jl:101 [5] solve(prob::JumpProblem{true, DiscreteProblem{Vector{Int64}, Tuple{Float64, Float64}, true, NamedTuple{(:λ,), Tuple{Float64}}, DiscreteFunction{true, SciMLBase.FullSpecialize, SciMLBase.var"#200#201", Nothing, Nothing, Nothing, Nothing, typeof(SciMLBase.DEFAULT_OBSERVED), Nothing}, Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}}}, Direct, CallbackSet{Tuple{}, Tuple{DiscreteCallback{JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, typeof(SciMLBase.FINALIZE_DEFAULT)}}}, JumpProcesses.DirectJumpAggregation{Float64, MassActionJump{Vector{Float64}, Vector{Vector{Pair{Int64, Int64}}}, Vector{Vector{Pair{Int64, Int64}}}, Nothing}, Tuple{typeof(rate)}, Tuple{typeof(affect!)}, Random.TaskLocalRNG}, Tuple{}, Nothing, Nothing, Random.TaskLocalRNG, Base.Pairs{Symbol, Nothing, Tuple{Symbol}, NamedTuple{(:callback,), Tuple{Nothing}}}}, args::SSAStepper; kwargs::Base.Pairs{Symbol, Bool, Tuple{Symbol}, NamedTuple{(:save_everystep,), Tuple{Bool}}}) @ DiffEqBase ~/.julia/packages/DiffEqBase/qPmC2/src/solve.jl:965 [6] top-level scope @ REPL[14]:1

The same happens when I use init instead, but the following workaround seems to do what I need:

julia> integrator = init(jprob, SSAStepper())
t: 0.0
u: 1-element Vector{Int64}:
 0

julia> integrator.save_everystep = false
false

julia> solve!(integrator)
retcode: Success
Interpolation: Piecewise constant interpolation
t: 2-element Vector{Float64}:
  0.0
 10.0
u: 2-element Vector{Vector{Int64}}:
 [0]
 [23]
isaacsas commented 1 year ago

That isn't currently a supported keyword for SSAStepper, but unfortunately I guess you are getting more general solve docs that mention it.

The way to disable saving every step is explained here:

https://docs.sciml.ai/JumpProcesses/dev/tutorials/discrete_stochastic_example/#save_positions_docs

You need to set it via the JumpProblem as jumps are handled like callbacks and this is how to indicate not to save when callbacks are executed.

lmshk commented 1 year ago

Thanks for the quick reply and the link. The specific entry I got was from solve(prob::DEProblem, alg::Union{DEAlgorithm,Nothing}; kwargs...).

I posted a follow-up question to Discourse.