Using DifferentialEquations.jl
, I would like to solve several SDEs with the same driving Wiener noise. I am surprised to see that sol.u
and sol2.u
are different. Any suggestions how come?
function f2(du,u,p,t)
du[1] = p[1] * (u[2] - u[1])
du[2] = p[2] * (u[1] - u[2])
end
function g2(du,u,p,t)
du[1] = 0.1
du[2] = 0.1
end
tspan = (0.0, 2.0)
u0 = [0.0, 0.0]
p = [3.0, 1.0]
Z = WienerProcess(0.0, [0.0, 0.0])
prob = SDEProblem(f2, g2, u0, tspan, p, noise=Z)
sol = solve(prob, EM(false), dt=0.01)
prob2 = SDEProblem(f2, g2, u0, tspan, p, noise=Z)
sol2 = solve(prob2, EM(false), dt=0.01)
sol.W == sol2.W # true
sol.u == sol2.u # false
sol.t == sol2.t # true
To reproduce the same noise values with a NoiseProcess
, you'll need to fix the seed:
using StochasticDiffEq, DiffEqNoiseProcess, Random
function f2(du,u,p,t)
du[1] = p[1] * u[1]
end
function g2(du,u,p,t)
du[1] = 0.1
end
tspan = (0.0, 2.0)
u0 = [0.0]
p = [0.98]
Z = WienerProcess(0.0, [0.0])
Random.seed!(10)
prob = SDEProblem(f2, g2, u0, tspan, p, noise=Z)
sol = solve(prob, EM(false), dt=0.01, save_noise=true)
Random.seed!(10)
prob2 = SDEProblem(f2, g2, u0, tspan, p, noise=Z)
sol2 = solve(prob2, EM(false), dt=0.01, save_noise=true)
sol.W.W == sol2.W.W # true
sol.u == sol2.u # true
sol.t == sol2.t # true
using Plots
plot(sol)
plot!(sol2)
However, I am also a bit surprised that sol.W.W
in your example shows true.. I think that this is actually not the case and a new independent driving noise is drawn.
The correct way to re-use the noise values is to use NoiseWrapper
from DiffEqNoiseProcess:
Zrep = NoiseWrapper(sol.W)
prob2= SDEProblem(f2, g2, u0, tspan, p, noise=Zrep)
sol2 = solve(prob2, EM(false), dt=0.01, save_noise=false)
plot(sol)
plot!(sol2)
If a fixed grid with a non-adaptive solver should be used, then NoiseGrid
might also be a good choice, see https://diffeq.sciml.ai/latest/features/noise_process/#NoiseGrid-2.
Thanks.
That is confusing: you pass the noise to the function call, so why would you ever need to fix the seed? No random numbers need to be generated. I can work around this now of course, but the logic is not clear to me.
Looking at the "correct way" to do this, without save_noise=false
something would change?
I opened an issue regarding sol.W == sol2.W # true
https://github.com/SciML/StochasticDiffEq.jl/issues/412. In your example, I'd have expected that in sol2
a new, independent noise process is simulated. So it's weird that the same noise values are displayed.
The random seed is just to fix the generation of the Wiener noise values (assuming that the noise values are fully regenerated).
I wouldn't expect a difference with save_noise=false
; except that the noise values might grow a little because of floating point errors, i.e., if you step not exactly to the values of the time grid, a noise value will be sampled using the bridge distribution close to the time points of the grid, and this new noise value -- which will be very similar to the noise value on the grid -- would probably be stored as well.
Last updated: Dec 28 2024 at 04:38 UTC