# Reusing random numbers in EnsembleProblem

**URL:** https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514
**Category:** Numerics
**Tags:** differentialequation
**Created:** [March 30, 2025, 1:30pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514 "2025-03-30T13:30:43Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![aleCombi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alecombi/32/212382_2.png) [@aleCombi](https://discourse.julialang.org/u/aleCombi)
#### Post date: [March 30, 2025, 1:30pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/1 "2025-03-30T13:30:43Z")

</div>

I am trying to take derivatives of Montecarlo expectations against parameters using DifferentialEquations.jl. I am doing it using geometric brownian motion, and I want to bump the sigma and reevaluate (later I will try AD). My problem is that I can do it for a single path using the same seed, but I can’t do it with EnsembleProblem. If I fix the seed there, I get the same path many times, which doesn’t make much sense…

Is there a way to basically export one seed per trajectory from the ensembleProblem and reuse them in a subsequent ensembleProblem?

Below my snippet:

```julia
using DifferentialEquations
using DiffEqNoiseProcess
using Plots

# Parameters
μ = 0.05
σ = 0.2
t0 = 0.0
T = 1.0
W0 = 100.0
tspan = (t0, T)
N = 250
dt = (T - t0) / N

# Step 1: Simulate GBM with a fixed seed
gbm = GeometricBrownianMotionProcess(μ, σ, t0, W0)
gbm_noise = NoiseProblem(gbm, tspan, seed=1)
sol = DifferentialEquations.solve(gbm_noise, dt=dt)

# Step 2: Reuse the same seed with bumped σ
μ_bumped = μ
σ_bumped = σ + 0.05
gbm_bumped = GeometricBrownianMotionProcess(μ_bumped, σ_bumped, t0, W0)
gbm_bumped_noise = NoiseProblem(gbm_bumped, tspan, seed=1)
sol_bumped = DifferentialEquations.solve(gbm_bumped_noise, dt=dt)

# Step 3: Plot both
plot(sol.t, sol.u, label="μ = $μ", linewidth=2)
plot!(sol_bumped.t, sol_bumped.u, label="μ = $μ_bumped", linestyle=:dash, linewidth=2)
xlabel!("Time")
ylabel!("GBM Value")
title!("GBM with Drift Bump and Reused Seed")

```

I guess the obvious solution is to bypass EnsembleProblem and loop through many NoiseProblems, just wondering if there’s a more user-friendly way.

---

<div class="post-metadata">

### Author: ![JADekker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jadekker/32/210281_2.png) [@JADekker](https://discourse.julialang.org/u/JADekker)
#### Post date: [March 30, 2025, 2:11pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/2 "2025-03-30T14:11:12Z")

</div>

I’m not familiar with this package, but let me just provide an alternative solution as I like to implement such things from scratch sometimes. If you stick purely with GBM, you could circumvent the problem by using the analytical solution to the SDE and making appropriate adjustments based on the change in parameters. If I were to simulate things from scratch: simulate a bunch of standard-normal random variables which you keep fixed, then transform these to GBM paths depending on your choice of parameters.

If you set it up right, you can even make it work with automatic differentiation to compute derivatives

---

<div class="post-metadata">

### Author: ![aleCombi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alecombi/32/212382_2.png) [@aleCombi](https://discourse.julialang.org/u/aleCombi)
#### Post date: [March 30, 2025, 2:34pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/3 "2025-03-30T14:34:40Z")

</div>

In the package the analytical solution (for the final process value) is actually used. The point is how much low level I need to go to achieve this. If I can just export the seeds from the EnsembleProblem and reimport them in another EnsembleProblem that would save me some code.  
Also because eventually I want to be able to do so for any SDE where the result is differentiable against the parameters, hence I need the method to be rather abstract.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [April 4, 2025, 9:31pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/4 "2025-04-04T21:31:27Z")

</div>

Make your `prob_func` for the ensemble set the seed in the problem.

---

<div class="post-metadata">

### Author: ![aleCombi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alecombi/32/212382_2.png) [@aleCombi](https://discourse.julialang.org/u/aleCombi)
#### Post date: [April 9, 2025, 3:58pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/5 "2025-04-09T15:58:02Z")

</div>

That works perfectly, thanks a lot @ChrisRackauckas!  
This doubles allocation and time according to @btime, but I guess it’s a price to pay, given that NoiseProblem is immutable.

```julia
using DifferentialEquations

μ = 0.02
σ = 0.04
t0 = 0.0
W0 = 0.0
tspan = (0.0,1.0)
trajectories = 100
proc = GeometricBrownianMotionProcess(μ, σ, t0, W0, nothing)
noise = NoiseProblem(proc, tspan)
seeds = rand(UInt64,trajectories)
prob_func = (prob, i, repeat) -> remake(prob; seed=seeds[i])
problem = EnsembleProblem(noise; prob_func=prob_func)
sol = solve(problem, EM(); trajectories=trajectories, dt=1.0)

```

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [April 9, 2025, 4:27pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/6 "2025-04-09T16:27:59Z")

</div>

It’s because it needs to make new RNG objects in order to seed them 🤷 , I’m pretty sure that’s a fundamental cost. You could maybe make a global RNG that you `seed!` instead, but then making that work with multithreading would be an absolute pain.

---

<div class="post-metadata">

### Author: ![aleCombi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/alecombi/32/212382_2.png) [@aleCombi](https://discourse.julialang.org/u/aleCombi)
#### Post date: [April 14, 2025, 2:13pm UTC](https://discourse.julialang.org/t/reusing-random-numbers-in-ensembleproblem/127514/7 "2025-04-14T14:13:46Z")

</div>

Yeah that makes total sense. Thanks.
