Skip to content

Commit 494fc0d

Browse files
committed
init
1 parent 5681fc3 commit 494fc0d

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# [Ensemble/Monte Carlo Simulations](@id ensemble_simulations)
2+
In many contexts, a single model is re-simulated under similar conditions. Examples include:
3+
- Performing Monte Carlo simulations of a stochastic model to gain insight in its behaviour.
4+
- Scanning the behaviour of a model for different parameter values and/or initial conditions.
5+
6+
While this can be handled using `for` loops, it is typically better to first create an `EnsembleProblem`, and then perform an ensemble simulation. Advantages include a more concise interface and the option for [automatic simulation parallelisation](@ref ref). Here we provide a short tutorial on how to perform parallel ensemble simulations, with a more extensive documentation being available [here](@ref https://docs.sciml.ai/DiffEqDocs/stable/features/ensemble/).
7+
8+
## [Monte Carlo simulations using unmodified conditions](@id ensemble_simulations_monte_carlo)
9+
We will first consider Monte Carlo simulations where the simulation conditions are identical in-between simulations. First, we declare a [simple self-activation loop](@ref ref) model
10+
```@example ensemble
11+
using Catalyst
12+
sa_model = @reaction_network begin
13+
v0 + hill(X,v,K,n), ∅ --> X
14+
deg, X --> ∅
15+
end
16+
u0 = [:X => 10.0]
17+
tspan = (0.0, 1000.0)
18+
ps = [:v0 => 0.1, :v => 2.5, :K => 40.0, :n => 4.0, :deg => 0.01]
19+
```
20+
We wish to simulate it as an SDE. Rather than performing a single simulation, however, we want to make multiple ones. Here, we first create a normal `SDEProblem`, and use it as the single input to a `EnsembleProblem` (similar for ODEs and jump simulations, but the `ODEProblem` or `JumpProblem` is used instead).
21+
```@example ensemble
22+
sprob = SDEProblem(sa_model, u0, tspan, ps)
23+
eprob = EnsembleProblem(sprob)
24+
nothing # hide
25+
```
26+
Next, the `EnsembleProblem` can be used as input to the `solve` command. Here, we use exactly the same inputs that we use for single simulations, however, we add a `trajectories` argument to denote how many simulations we wish to carry out. Here we perform 100 simulations:
27+
```@example ensemble
28+
sols = solve(eprob, STrapezoid(); trajectories = 100)
29+
nothing # hide
30+
```
31+
Finally, we can use our ensemble simulation solution as input to `plot` (just like normal simulations):
32+
```@example ensemble
33+
plot(sols; la = 0.5)
34+
```
35+
Here, each simulation is displayed as an individual trajectory. We also use the [`la` plotting option](@ref ref) to reduce the transparency of each individual line, improving the plot visual.
36+
37+
Various convenience functions are available for analysing and plotting ensemble simulations (a full list can be found [here]). Here, we use these to first create an `EnsembleSummary` (retrieving each simulation's value at time points `0.0, 1.0, 2.0, ... 1000.0`). Next, we use this as an input to the `plot` command, which automatically plots the mean $X$ activity across the ensemble, while also displaying the 5% and 95% quantiles as the shaded area:
38+
```@example ensemble
39+
e_sumary = EnsembleAnalysis.EnsembleSummary(sols, 0.0:1.0:1000.0)
40+
plot(e_sumary)
41+
```
42+
43+
## [Ensemble simulations using varying simulation conditions](@id ensemble_simulations_varying_conditions)
44+
Previously, we assumed that each simulation used the same initial conditions and parameter values. If this is not the case (when e.g. performing a parameter scan), a `prob_func` optional argument must be supplied to the `EnsembleProblem`, this describes how the problem should be modified for each individual simulation of the ensemble.
45+
46+
Here, we first create an `ODEProblem` of our previous self-activation loop:
47+
```@example ensemble
48+
oprob = ODEProblem(sa_model, u0, tspan, p)
49+
nothing # hide
50+
```
51+
Next, we wish to simulate the model for a range of initial conditions of $X$`. To do this we create a problem function, which takes the following arguments:
52+
- `prob`: The problem given to our `EnsembleProblem`, which is the problem that
53+
`prob_func` modifies in each iteration.
54+
- `i`: The number of this specific Monte Carlo iteration in the interval
55+
`1:trajectories`.
56+
- `repeat`: The iteration of the repeat of the simulation. Typically `1`, but potentially higher if [the simulation re-running option](https://docs.sciml.ai/DiffEqDocs/stable/features/ensemble/#Building-a-Problem) is used.
57+
58+
Here we will use the following problem function, which will provide a uniform range of initial conditions:
59+
```@example ensemble
60+
function prob_func(prob, i, repeat)
61+
remake(prob; u0 = [:X => i * 5.0])
62+
end
63+
nothing # hide
64+
```
65+
Next, we create our `EnsembleProblem`, and simulate it 10 times:
66+
```@example ensemble
67+
eprob = EnsembleProblem(oprob; prob_func)
68+
sols = solve(eprob, Tsit5(); trajectories = 10)
69+
plot(sols)
70+
```
71+
Here we see that the deterministic model (unlike the stochastic one), only activates for some initial conditions (while other tends to an inactive state).
72+
73+
The `EnsembleProblem` constructor accepts a few additional optional options (`output_func`, `reduction`, `u_init`, and `safetycopy`), which are described in more detail [here](https://docs.sciml.ai/DiffEqDocs/stable/features/ensemble/#Building-a-Problem). These can be used to e.g. rerun an individual simulation which does not fulfil some condition, or extract and save only some selected information from a simulation (rather than the full simulation).

0 commit comments

Comments
 (0)