|
| 1 | +# [Solving the chemical master equation using FiniteStateProjection.jl](@id finite-state_projection) |
| 2 | + |
| 3 | +## [Finite state projection simulation of single-species model](@id state_projection_one_species) |
| 4 | +For this example we will use a simple [birth-death model](@ref basic_CRN_library_bd), where a single species ($X$) is created and degraded at constant rates ($p$ and $d$, respectively). |
| 5 | +```@example state_projection_one_species |
| 6 | +using Catalyst |
| 7 | +rs = @reaction_network begin |
| 8 | + (p,d), 0 <--> X |
| 9 | +end |
| 10 | +``` |
| 11 | +Next we perform jump simulations (using the [ensemble simulation interface](@ref ensemble_simulations_monte_carlo)) of the model. Here, we can see how the it develops from an initial condition and reaches a steady state distribution. |
| 12 | +```@example state_projection_one_species |
| 13 | +using JumpProcesses, Plots |
| 14 | +u0 = [:X => 5] |
| 15 | +tspan = (0.0, 10.0) |
| 16 | +ps = [:p => 20.0, :d => 0.5] |
| 17 | +jprob = JumpProblem(JumpInputs(rs, u0, tspan, ps)) |
| 18 | +eprob = EnsembleProblem(jprob) |
| 19 | +esol = solve(eprob, SSAStepper(); trajectories = 10) |
| 20 | +plot(esol; ylimit = (0.0, Inf)) |
| 21 | +``` |
| 22 | +Using chemical master equation simulations, we want to simulate how the *full probability distribution* of these jump simulations develop across the simulation time-frame. |
| 23 | + |
| 24 | +As a first step, we import the FiniteStateProjection package. Next, we convert our [`ReactionSystem`](@ref) to a `FSPSystem` (from which we later will generate an ODE). |
| 25 | +```@example state_projection_one_species |
| 26 | +using FiniteStateProjection |
| 27 | +fsp_sys = FSPSystem(rs) |
| 28 | +nothing # hide |
| 29 | +``` |
| 30 | +Next, we set our initial condition. For normal simulations, $X$'s initial condition would be a single value. Here, however, we will simulate $X$'s probability distribution. Hence, its initial condition will also be a probability distribution. In FiniteStateProjection's interface, the initial condition is a vector, where the $i$'th index is the probability that $X$ have an initial value of $i-1$. The total sum of all probabilities across the vector should be normalised to $1$. Here we assume that $X$'s initial conditions is known to be $5$ (hence the corresponding probability is $1$, and the remaining ones are $0$): |
| 31 | +```@example state_projection_one_species |
| 32 | +u0 = zeros(75) |
| 33 | +u0[6] = 1.0 |
| 34 | +bar(u0) |
| 35 | +``` |
| 36 | +We also plot the full distribution using the `bar` function. Finally, the initial condition vector also define the finite space onto which we project the chemical master equation. I.e. we will assume that, throughout the entire simulation, the probability of $X$ reaching values outside this initial vector is negligible. |
| 37 | +!!! warn |
| 38 | + This last fact is important. Even if the probability seems to ve very small on the boundary provided by the initial condition, there is still a risk that probability will "leak". Here, it can be good to make simulations using different projections, ensuring that the results are consistent (especially for longer simulations). |
| 39 | + |
| 40 | +Now, we can finally create an `ODEProblem` using out `FSPSystem`, our initial conditions, and the parameters declared previously. We can simulate this `ODEProblem` like any other ODE. |
| 41 | +```@example state_projection_one_species |
| 42 | +using OrdinaryDiffEqDefault |
| 43 | +oprob = ODEProblem(fsp_sys, u0, tspan, ps) |
| 44 | +osol = solve(oprob) |
| 45 | +nothing # hide |
| 46 | +``` |
| 47 | +Finally, we can plot the $X$'s probability distribution at various time point's of the simulation. Again, we will uset he `bar` function to plot teh distribution, and the interface described [here](@ref simulation_structure_interfacing_solutions) to acess the simulation at various timestamps. |
| 48 | +```@example state_projection_one_species |
| 49 | +bar(osol(1.0); width = 1.0, linecolor = 1, alpha = 0.7, linealpha = 0.7, label = "t = 1.0") |
| 50 | +bar!(osol(2.0); linecolor = 1, alpha = 0.7, linealpha = 0.7, label = "t = 2.0") |
| 51 | +bar!(osol(5.0); linecolor = 1, alpha = 0.7, linealpha = 0.7, label = "t = 5.0") |
| 52 | +bar!(osol(10.0); linecolor = 1, alpha = 0.7, linealpha = 0.7, label = "t = 10.0") |
| 53 | +``` |
| 54 | + |
| 55 | +## [Finite state projection simulation of multi-species model](@id state_projection_multi_species) |
| 56 | + |
| 57 | +```@example state_projection_multi_species |
| 58 | +using Catalyst # hide |
| 59 | +rs = @reaction_network begin |
| 60 | + (p,d), 0 <--> X |
| 61 | + (kB,kD), 2X <--> X2 |
| 62 | +end |
| 63 | +``` |
| 64 | + |
| 65 | +```@example state_projection_multi_species |
| 66 | +ps = [:p => 1.0, :d => 0.2, :kB => 2.0, :kD => 5.0] |
| 67 | +u0 = zeros(25,25) |
| 68 | +u0[1,1] = 1.0 |
| 69 | +``` |
| 70 | + |
| 71 | +```@example state_projection_multi_species |
| 72 | +using OrdinaryDiffEqRosenbrock, Plots # hide |
| 73 | +fsp_sys = FSPSystem(rs, [:X, :X2]) |
| 74 | +oprob = ODEProblem(fsp_sys, u0, 100.0, ps) |
| 75 | +@time osol = solve(oprob, Rodas5P()) |
| 76 | +heatmap(osol[end]; xguide = "X2", yguide = "X") |
| 77 | +``` |
| 78 | + |
| 79 | +## [Finite state projection steady state simulations](@id state_projection_steady_state_sim) |
| 80 | +Previously we described how the [SteadyStateDiffEq.jl](https://github.com/SciML/SteadyStateDiffEq.jl) package can be used to [find an ODE's steady state through forward simulation](@ref steady_state_stability). The same interface can be used for ODEs generated through FiniteStateProjection.jl. Below we use this to find the steady state of the dimerisation example studied in the last example. |
| 81 | +```@example state_projection_multi_species |
| 82 | +using SteadyStateDiffEq, OrdinaryDiffEqRosenbrock |
| 83 | +ssprob = SteadyStateProblem(fsp_sys, u0, ps) |
| 84 | +sssol = solve(ssprob, DynamicSS(Rodas5P())) |
| 85 | +heatmap(sssol; xguide = "X2", yguide = "X") |
| 86 | +``` |
0 commit comments