MMSB: Mathematical Modeling in Systems Biology / Sep 15 2020
div.ProseMirror
Gillespie Algorithm
Python implementation
"""
Stochastic chemical reaction: Gillespie Algorithm
Adapted from: Chemical and Biomedical Enginnering Calculations Using Python Ch.4-3
Reaction of A <-> B with rate constants k1 & k2
"""
from random import choices, expovariate
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
class Gillespie():
def __init__(self, propensityFuncs, actionFuncs, parameters=None):
self.propensityFuncs = propensityFuncs
self.actionFuncs = actionFuncs
self.parameters = parameters
def run(self, u0, tend, tstart=0):
# Setup
t = tstart
p = self.parameters
u = np.asarray(u0)
us = [u.copy()]
ts = [t]
while t < tend:
# propensities of reactions
ps = [f(u, p, t) for f in self.propensityFuncs]
pTotal = sum(ps)
dt = expovariate(pTotal)
# Choose an action by the weight of each propensities, and update the state variable
act = choices(actionFuncs, weights=ps)[0]
u = np.asarray(act(u, p, t))
t += dt
us.append(u.copy())
ts.append(t)
return np.array(ts), np.array(us)
0.4s
Python
parameters = {"k1": 1.0, "k2": 0.5}
propensityFuncs = (lambda u, p, t: p["k1"] * u[0],
lambda u, p, t: p["k2"] * u[1])
actionFuncs = (lambda u, p, t: [u[0] - 1, u[1] + 1],
lambda u, p, t: [u[0] + 1, u[1] - 1])
ssa = Gillespie(propensityFuncs = propensityFuncs,
actionFuncs = actionFuncs,
parameters = parameters)
ts, us = ssa.run([175, 25], 10.0)
fig, ax = plt.subplots()
ax.plot(ts, us[:, 0], label="A")
ax.plot(ts, us[:, 1], label="B")
ax.set_xlabel('time')
ax.set_ylabel('number of molecules')
ax.legend(loc='best')
0.6s
Python
<matplotlib.legend.Legend at 0x7f1b6834fe90>
Julia implementation
Setup packages
# Packages
using Pkg
pkg"up; add StatsBase Plots DifferentialEquations"
39.4s
Julia
Hand-crafted code
# Coded in the same manner as the Python counterpart
struct Gillespie
propensityFuncs
actionFuncs
parameters
end
function (g::Gillespie)(u0, tend, tstart=zero(tend))
t = tstart
ts = [t] # Records time
u = copy(u0)
us = copy(u)
end
0.1s
Julia
#=
Stochastic chemical reaction: Gillespie Algorithm
Adapted from: Chemical and Biomedical Enginnering Calculations Using Python Ch.4-3
Reaction of A <-> B with rate constants k1 & k2
=#
using StatsBase, Random
# Coded in the same manner as the Python counterpart
struct Gillespie
propensityFuncs
actionFuncs
parameters
end
function (g::Gillespie)(u0, tend, tstart=zero(tend))
t = tstart
ts = [t]
u = copy(u0)
us = copy(transpose(u))
p = g.parameters
while t < tend
# propensities of reactions
ps = [f(u, p, t) for f in g.propensityFuncs]
pTotal = sum(ps)
dt = randexp() / pTotal
f = sample(g.actionFuncs, Weights(ps))
u = f(u, p, t)
t += dt
us = vcat(us, transpose(u))
push!(ts, t) # Record t
end
return (ts = ts, us = us)
end
0.7s
Julia
parameters = (k1=1.0, k2=0.5)
propensityFuncs = [(u, p, t) -> p.k1 * u[1], (u, p, t) -> p.k2 * u[2]]
actionFuncs = [(u, p, t) -> u .+ [-1, 1] , (u, p, t) -> u .+ [1, -1]]
ssa = Gillespie(propensityFuncs, actionFuncs, parameters)
0.6s
Julia
Gillespie(Function[#3, #4], Function[#7, #8], (k1 = 1.0, k2 = 0.5))
ts, us = ssa([175, 25], 10.0)
1.5s
Julia
(ts = [0.0, 0.00252744, 0.00587012, 0.00632856, 0.0263267, 0.0277462, 0.0355282, 0.0357995, 0.0387831, 0.041265 … 9.95378, 9.96648, 9.96689, 9.96691, 9.96923, 9.97425, 9.98564, 9.98734, 9.99885, 10.0057], us = [175 25; 174 26; … ; 67 133; 66 134])
using Plots
plot(ts, us, xlabel="time", ylabel="# of molecules", title = "SSA", label=["A" "B"])
83.5s
Julia