Skip to content

Commit 0e96aa9

Browse files
Merge pull request #49 from isaacsas/massaction-jumpproblems
Added conversions of jumps to MassActionJumps in JumpProblem
2 parents 392ef5e + d8a7534 commit 0e96aa9

File tree

6 files changed

+188
-5
lines changed

6 files changed

+188
-5
lines changed

REQUIRE

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
julia 0.6
22
DiffEqJump 4.2.0
3-
DiffEqBase 3.4.0
3+
DiffEqBase 3.11.0
44
Compat 0.17.0
5-
DataStructures 0.4.6
5+
DataStructures 0.8.1
66
Reexport 0.1.0
7-
SymEngine 0.3.0
7+
SymEngine 0.4.0
88
MacroTools 0.4.0

src/DiffEqBiological.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using Compat
1414

1515
include("reaction_network.jl")
1616
include("maketype.jl")
17+
include("massaction_jump_utils.jl")
1718
include("problem.jl")
1819

1920
export @reaction_network, @reaction_func

src/massaction_jump_utils.jl

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# collection of utility functions for getting mass action jumps out of
2+
# DiffEqBiological reaction network structures
3+
4+
# return a map from species symbol to species index
5+
function species_to_indices(network)
6+
specs = network.syms
7+
Dict( specs[i] => i for i in eachindex(specs) )
8+
end
9+
10+
# return a map from reaction param symbol to rate index
11+
function rate_to_indices(network)
12+
rates = network.params
13+
Dict( rates[i] => i for i in eachindex(rates) )
14+
end
15+
16+
# given a ReactionStruct and a species map construct a MassActionJump
17+
function make_majump(rs, specmap, ratemap, params)
18+
reactant_stoich = Vector{Pair{Int,Int}}()
19+
nsdict = Dict{Int,Int}()
20+
for substrate in rs.substrates
21+
specpair = specmap[substrate.reactant] => substrate.stoichiometry
22+
push!(reactant_stoich, specpair)
23+
specpair = specmap[substrate.reactant] => -substrate.stoichiometry
24+
push!(nsdict, specpair)
25+
end
26+
sort!(reactant_stoich)
27+
28+
for product in rs.products
29+
prodidx = specmap[product.reactant]
30+
if haskey(nsdict, prodidx)
31+
nsdict[prodidx] += product.stoichiometry
32+
else
33+
push!(nsdict, prodidx => product.stoichiometry)
34+
end
35+
end
36+
37+
net_stoich = Vector{Pair{Int,Int}}()
38+
for stoich_map in sort(collect(nsdict))
39+
push!(net_stoich, stoich_map)
40+
end
41+
42+
if isempty(net_stoich)
43+
error("Empty net stoichiometry vectors for mass action reactions are not allowed.")
44+
end
45+
46+
if typeof(rs.rate_org) == Symbol
47+
rateconst = params[ratemap[rs.rate_org]]
48+
elseif typeof(rs.rate_org) == Expr
49+
rateconst = eval(rs.rate_org)
50+
elseif typeof(rs.rate_org) <: Number
51+
rateconst = rs.rate_org
52+
else
53+
error("reaction_network.reactions.rate_org must have a type of Symbol, Expr, or Number.")
54+
end
55+
56+
MassActionJump(Float64(rateconst), reactant_stoich, net_stoich)
57+
end
58+
59+
# given a reaction network and species map, split the ConstantRateJumps and MassActionJumps
60+
function network_to_jumpset(rn, specmap, ratemap, params)
61+
62+
empty_majump = MassActionJump(0.0, [0=>1], [1=>1])
63+
majumpvec = Vector{typeof(empty_majump)}()
64+
cjumpvec = Vector{ConstantRateJump}()
65+
66+
for (i,rs) in enumerate(rn.reactions)
67+
if rs.is_pure_mass_action
68+
push!(majumpvec, make_majump(rs, specmap, ratemap, params))
69+
else
70+
push!(cjumpvec, rn.jumps[i])
71+
end
72+
end
73+
74+
if isempty(majumpvec)
75+
return JumpSet((), cjumpvec, nothing, nothing)
76+
else
77+
return JumpSet((), cjumpvec, nothing, majumpvec)
78+
end
79+
end

src/problem.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@ DiffEqBase.SDEProblem(rn::AbstractReactionNetwork, u0::Union{AbstractArray, Numb
33
SDEProblem(rn, rn.g, u0, args...;noise_rate_prototype=rn.p_matrix, kwargs...)
44

55
### JumpProblem ###
6-
function DiffEqJump.JumpProblem(prob,aggregator::Direct,rn::AbstractReactionNetwork; kwargs...)
6+
function DiffEqJump.JumpProblem(prob,aggregator,rn::AbstractReactionNetwork; kwargs...)
77
if typeof(prob)<:DiscreteProblem && any(issubtype.(typeof.(rn.jumps),VariableRateJump))
88
error("When using time dependant reaction rates a DiscreteProblem should not be used (try an ODEProblem). Also, use a continious solver.")
99
end
10-
JumpProblem(prob,aggregator::Direct,rn.jumps...;kwargs...)
10+
11+
# map from species symbol to index of species
12+
spec_to_idx = species_to_indices(rn)
13+
14+
# map from parameter symbol to index of parameter in prob.p
15+
param_to_idx = rate_to_indices(rn)
16+
17+
# get a JumpSet of the possible jumps
18+
jset = network_to_jumpset(rn, spec_to_idx, param_to_idx, prob.p)
19+
20+
JumpProblem(prob, aggregator, jset; kwargs...)
1121
end
1222

1323
### SteadyStateProblem ###

test/mass_act_jump_tests.jl

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using DiffEqBiological, DiffEqJump, DiffEqBase, Base.Test
2+
3+
dotestmean = true
4+
doprintmeans = false
5+
reltol = .01 # required test accuracy
6+
7+
# run the given number of SSAs and return the mean
8+
function runSSAs(jump_prob, Nsims, idx)
9+
Psamp = zeros(Int, Nsims)
10+
for i in 1:Nsims
11+
sol = solve(jump_prob, SSAStepper())
12+
Psamp[i] = sol[idx,end]
13+
end
14+
mean(Psamp)
15+
end
16+
17+
function execute_test(u0, tf, rates, rs, Nsims, expected_avg, idx, test_name)
18+
prob = DiscreteProblem(u0, (0.0, tf), rates)
19+
jump_prob = JumpProblem(prob, Direct(), rs)
20+
avg_val = runSSAs(jump_prob, Nsims, idx)
21+
22+
if dotestmean
23+
if doprintmeans
24+
println(test_name, ": mean = ", avg_val, ", act_mean = ", expected_avg)
25+
end
26+
@test abs(avg_val - expected_avg) < reltol * expected_avg
27+
end
28+
29+
end
30+
31+
# nonlinear reaction test
32+
Nsims = 32000
33+
tf = .01
34+
u0 = [200, 100, 150]
35+
expected_avg = 84.876015624999994
36+
rs = @reaction_network dtype begin
37+
k1, 2A --> B
38+
k2, B --> 2A
39+
k3, A + B --> C
40+
k4, C --> A + B
41+
k5, 3C --> 3A
42+
end k1 k2 k3 k4 k5
43+
rates = [1., 2., .5, .75, .25]
44+
execute_test(u0, tf, rates, rs, Nsims, expected_avg, 1, "Nonlinear rx test")
45+
46+
47+
# DNA repression model
48+
rs = @reaction_network ptype begin
49+
k1, DNA --> mRNA + DNA
50+
k2, mRNA --> mRNA + P
51+
k3, mRNA --> 0
52+
k4, P --> 0
53+
k5, DNA + P --> DNAR
54+
k6, DNAR --> DNA + P
55+
end k1 k2 k3 k4 k5 k6
56+
Nsims = 8000
57+
tf = 1000.0
58+
u0 = [1,0,0,0]
59+
expected_avg = 5.926553750000000e+02
60+
rates = [.5, (20*log(2.)/120.), (log(2.)/120.), (log(2.)/600.), .025, 1.]
61+
execute_test(u0, tf, rates, rs, Nsims, expected_avg, 3, "DNA test")
62+
63+
64+
# simple constant production with degratation
65+
rs = @reaction_network pdtype begin
66+
1000., 0 --> A
67+
10, A --> 0
68+
end
69+
rates = nothing
70+
Nsims = 16000
71+
tf = 1.0
72+
u0 = [0]
73+
expected_avg = 1000./10*(1. - exp(-10*tf))
74+
execute_test(u0, tf, rates, rs, Nsims, expected_avg, 1, "Zero order test")
75+
76+
77+
# this is just a test to make sure a mixture of jumps actually runs without crashes
78+
network = @reaction_network rnType begin
79+
0.01, (X,Y,Z) --> 0
80+
hill(X,3.,100.,-4), 0 --> Y
81+
hill(Y,3.,100.,-4), 0 --> Z
82+
hill(Z,4.5,100.,-4), 0 --> X
83+
hill(X,2.,100.,6), 0 --> R
84+
hill(Y,15.,100.,4)*0.002, R --> 0
85+
20, 0 --> S
86+
R*0.005, S --> SP
87+
0.01, SP + SP --> SP2
88+
0.05, SP2 --> 0
89+
end;
90+
prob = DiscreteProblem([200.,60.,120.,100.,50.,50.,50.], (0.,4000.))
91+
jump_prob = JumpProblem(prob, Direct(), network)
92+
sol = solve(jump_prob,SSAStepper());

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ tic()
88
@time @testset "Higher Order" begin include("higher_order_reactions.jl") end
99
@time @testset "Additional Functions" begin include("func_test.jl") end
1010
@time @testset "Steady state solver" begin include("steady_state.jl") end
11+
@time @testset "Mass Action Jumps" begin include("mass_act_jump_tests.jl") end
1112
toc()

0 commit comments

Comments
 (0)