Skip to content

Commit bf76a60

Browse files
shashiYingboMa
andcommitted
jump system stuff
Co-authored-by: "Yingbo Ma" <[email protected]>
1 parent 664139b commit bf76a60

File tree

3 files changed

+67
-52
lines changed

3 files changed

+67
-52
lines changed

src/systems/jumps/jumpsystem.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractSystem
3232
"""
3333
eqs::U
3434
"""The independent variable, usually time."""
35-
iv::Variable
35+
iv::Any
3636
"""The dependent variables, representing the state of the system."""
37-
states::Vector{Variable}
37+
states::Vector
3838
"""The parameters of the system."""
39-
ps::Vector{Variable}
40-
pins::Vector{Variable}
39+
ps::Vector
40+
pins::Vector
4141
observed::Vector{Equation}
4242
"""The name of the system."""
4343
name::Symbol
@@ -46,7 +46,7 @@ struct JumpSystem{U <: ArrayPartition} <: AbstractSystem
4646
end
4747

4848
function JumpSystem(eqs, iv, states, ps;
49-
pins = Variable[],
49+
pins = [],
5050
observed = Equation[],
5151
systems = JumpSystem[],
5252
name = gensym(:JumpSystem))
@@ -64,7 +64,7 @@ function JumpSystem(eqs, iv, states, ps;
6464
end
6565
end
6666

67-
JumpSystem{typeof(ap)}(ap, convert(Variable,iv), convert.(Variable, states), convert.(Variable, ps), pins, observed, name, systems)
67+
JumpSystem{typeof(ap)}(ap, value(iv), value.(states), value.(ps), pins, observed, name, systems)
6868
end
6969

7070
generate_rate_function(js, rate) = build_function(rate, states(js), parameters(js),

src/systems/reaction/reactionsystem.jl

Lines changed: 60 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ Notes:
4242
- The three-argument form assumes all reactant and product stoichiometric coefficients
4343
are one.
4444
"""
45-
struct Reaction{S <: Variable, T <: Number}
45+
struct Reaction{S, T <: Number}
4646
"""The rate function (excluding mass action terms)."""
4747
rate
4848
"""Reaction substrates."""
49-
substrates::Vector{Operation}
49+
substrates::Vector
5050
"""Reaction products."""
51-
products::Vector{Operation}
51+
products::Vector
5252
"""The stoichiometric coefficients of the reactants."""
5353
substoich::Vector{T}
5454
"""The stoichiometric coefficients of the products."""
@@ -65,20 +65,22 @@ end
6565
function Reaction(rate, subs, prods, substoich, prodstoich;
6666
netstoich=nothing, only_use_rate=false, kwargs...)
6767

68-
(isnothing(prods)&&isnothing(subs)) && error("A reaction requires a non-nothing substrate or product vector.")
69-
(isnothing(prodstoich)&&isnothing(substoich)) && error("Both substrate and product stochiometry inputs cannot be nothing.")
70-
if isnothing(subs)
71-
subs = Vector{Operation}()
68+
(isnothing(prods)&&isnothing(subs)) && error("A reaction requires a non-nothing substrate or product vector.")
69+
(isnothing(prodstoich)&&isnothing(substoich)) && error("Both substrate and product stochiometry inputs cannot be nothing.")
70+
if isnothing(subs)
71+
subs = Vector{Term}()
7272
!isnothing(substoich) && error("If substrates are nothing, substrate stiocihometries have to be so too.")
7373
substoich = typeof(prodstoich)()
7474
end
7575
if isnothing(prods)
76-
prods = Vector{Operation}()
76+
prods = Vector{Term}()
7777
!isnothing(prodstoich) && error("If products are nothing, product stiocihometries have to be so too.")
7878
prodstoich = typeof(substoich)()
7979
end
80+
subs = value.(subs)
81+
prods = value.(prods)
8082
ns = isnothing(netstoich) ? get_netstoich(subs, prods, substoich, prodstoich) : netstoich
81-
Reaction(rate, subs, prods, substoich, prodstoich, ns, only_use_rate)
83+
Reaction(value(rate), subs, prods, substoich, prodstoich, ns, only_use_rate)
8284
end
8385

8486

@@ -93,11 +95,10 @@ end
9395
# calculates the net stoichiometry of a reaction as a vector of pairs (sub,substoich)
9496
function get_netstoich(subs, prods, sstoich, pstoich)
9597
# stoichiometry as a Dictionary
96-
nsdict = Dict{Variable,eltype(sstoich)}(sub.op => -sstoich[i] for (i,sub) in enumerate(subs))
98+
nsdict = Dict{Any, eltype(sstoich)}(sub => -sstoich[i] for (i,sub) in enumerate(subs))
9799
for (i,p) in enumerate(prods)
98100
coef = pstoich[i]
99-
prod = p.op
100-
@inbounds nsdict[prod] = haskey(nsdict, prod) ? nsdict[prod] + coef : coef
101+
@inbounds nsdict[p] = haskey(nsdict, p) ? nsdict[p] + coef : coef
101102
end
102103

103104
# stoichiometry as a vector
@@ -124,12 +125,12 @@ struct ReactionSystem <: AbstractSystem
124125
"""The reactions defining the system."""
125126
eqs::Vector{Reaction}
126127
"""Independent variable (usually time)."""
127-
iv::Variable
128+
iv::Any
128129
"""Dependent (state) variables representing amount of each species."""
129-
states::Vector{Variable}
130+
states::Vector
130131
"""Parameter variables."""
131-
ps::Vector{Variable}
132-
pins::Vector{Variable}
132+
ps::Vector
133+
pins::Vector
133134
observed::Vector{Equation}
134135
"""The name of the system"""
135136
name::Symbol
@@ -138,15 +139,13 @@ struct ReactionSystem <: AbstractSystem
138139
end
139140

140141
function ReactionSystem(eqs, iv, species, params;
141-
pins = Variable[],
142-
observed = Operation[],
142+
pins = [],
143+
observed = [],
143144
systems = ReactionSystem[],
144145
name = gensym(:ReactionSystem))
145146

146147
isempty(species) && error("ReactionSystems require at least one species.")
147-
paramvars = map(v -> convert(Variable,v), params)
148-
specvars = map(s -> convert(Variable,s), species)
149-
ReactionSystem(eqs, convert(Variable,iv), specvars, paramvars,
148+
ReactionSystem(eqs, value(iv), value.(species), value.(params),
150149
pins, observed, name, systems)
151150
end
152151

@@ -187,15 +186,15 @@ function oderatelaw(rx; combinatoric_ratelaw=true)
187186
end
188187

189188
function assemble_drift(rs; combinatoric_ratelaws=true)
190-
D = Differential(rs.iv())
191-
eqs = [D(x(rs.iv())) ~ 0 for x in rs.states]
189+
D = Differential(rs.iv)
190+
eqs = [D(x) ~ 0 for x in rs.states]
192191
species_to_idx = Dict((x => i for (i,x) in enumerate(rs.states)))
193192

194193
for rx in rs.eqs
195194
rl = oderatelaw(rx; combinatoric_ratelaw=combinatoric_ratelaws)
196195
for (spec,stoich) in rx.netstoich
197196
i = species_to_idx[spec]
198-
if iszero(eqs[i].rhs)
197+
if _iszero(eqs[i].rhs)
199198
signedrl = (stoich > zero(stoich)) ? rl : -rl
200199
rhs = isone(abs(stoich)) ? signedrl : stoich * rl
201200
else
@@ -209,7 +208,7 @@ function assemble_drift(rs; combinatoric_ratelaws=true)
209208
end
210209

211210
function assemble_diffusion(rs, noise_scaling; combinatoric_ratelaws=true)
212-
eqs = Expression[Constant(0) for x in rs.states, y in rs.eqs]
211+
eqs = fill(Num(0), length(rs.states), length(rs.eqs))
213212
species_to_idx = Dict((x => i for (i,x) in enumerate(rs.states)))
214213

215214
for (j,rx) in enumerate(rs.eqs)
@@ -281,7 +280,7 @@ end
281280
"""
282281
```julia
283282
ismassaction(rx, rs; rxvars = get_variables(rx.rate),
284-
haveivdep = any(var -> isequal(rs.iv,convert(Variable,var)), rxvars),
283+
haveivdep = any(var -> isequal(rs.iv,var), rxvars),
285284
stateset = Set(states(rs)))
286285
```
287286
@@ -297,7 +296,7 @@ explicitly on the independent variable (usually time).
297296
- Optional: `stateset`, set of states which if the rxvars are within mean rx is non-mass action.
298297
"""
299298
function ismassaction(rx, rs; rxvars = get_variables(rx.rate),
300-
haveivdep = any(var -> isequal(rs.iv,convert(Variable,var)), rxvars),
299+
haveivdep = any(isequal(rs.iv), rxvars),
301300
stateset = Set(states(rs)))
302301
# if no dependencies must be zero order
303302
(length(rxvars)==0) && return true
@@ -311,7 +310,7 @@ end
311310
@inline function makemajump(rx; combinatoric_ratelaw=true)
312311
@unpack rate, substrates, substoich, netstoich = rx
313312
zeroorder = (length(substoich) == 0)
314-
reactant_stoch = Vector{Pair{Operation,eltype(substoich)}}(undef, length(substoich))
313+
reactant_stoch = Vector{Pair{Term,eltype(substoich)}}(undef, length(substoich))
315314
@inbounds for i = 1:length(reactant_stoch)
316315
reactant_stoch[i] = var2op(substrates[i].op) => substoich[i]
317316
end
@@ -321,27 +320,22 @@ end
321320
#push!(rates, rate)
322321
net_stoch = [Pair(var2op(p[1]),p[2]) for p in netstoich]
323322
#push!(nstoich, net_stoch)
324-
MassActionJump(rate, reactant_stoch, net_stoch, scale_rates=false, useiszero=false)
323+
324+
#XXX: vv--- this sucks
325+
MassActionJump(Num(rate), reactant_stoch, net_stoch, scale_rates=false, useiszero=false)
325326
end
326327

327328
function assemble_jumps(rs; combinatoric_ratelaws=true)
328329
meqs = MassActionJump[]; ceqs = ConstantRateJump[]; veqs = VariableRateJump[]
329330
stateset = Set(states(rs))
330331
#rates = []; rstoich = []; nstoich = []
331-
rxvars = Operation[]
332-
ivname = rs.iv.name
332+
rxvars = []
333333

334334
isempty(equations(rs)) && error("Must give at least one reaction before constructing a JumpSystem.")
335335
for rx in equations(rs)
336336
empty!(rxvars)
337-
(rx.rate isa Operation) && get_variables!(rxvars, rx.rate)
338-
haveivdep = false
339-
@inbounds for i = 1:length(rxvars)
340-
if rxvars[i].op.name == ivname
341-
haveivdep = true
342-
break
343-
end
344-
end
337+
(rx.rate isa Term) && get_variables!(rxvars, rx.rate)
338+
haveivdep = any(isequal(rs.iv), rxvars)
345339
if ismassaction(rx, rs; rxvars=rxvars, haveivdep=haveivdep, stateset=stateset)
346340
push!(meqs, makemajump(rx, combinatoric_ratelaw=combinatoric_ratelaws))
347341
else
@@ -379,6 +373,9 @@ function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem; combinatoric_rate
379373
systems=convert.(ODESystem,rs.systems))
380374
end
381375

376+
makeparam(s::Sym) = Sym{Parameter{Number}}(s.name)
377+
makeparam(s::Sym{<:Parameter}) = s
378+
382379
"""
383380
```julia
384381
Base.convert(::Type{<:SDESystem},rs::ReactionSystem)
@@ -400,12 +397,30 @@ Finally, a `Vector{Operation}` can be provided (the length must be equal to the
400397
Here the noise for each reaction is scaled by the corresponding parameter in the input vector.
401398
This input may contain repeat parameters.
402399
"""
403-
function Base.convert(::Type{<:SDESystem},rs::ReactionSystem, combinatoric_ratelaws=true; noise_scaling=nothing::Union{Vector{Operation},Operation,Nothing})
404-
(typeof(noise_scaling) <: Vector{Operation}) && (length(noise_scaling)!=length(rs.eqs)) && error("The number of elements in 'noise_scaling' must be equal to the number of reactions in the reaction system.")
405-
(typeof(noise_scaling) <: Operation) && (noise_scaling = fill(noise_scaling,length(rs.eqs)))
400+
function Base.convert(::Type{<:SDESystem},rs::ReactionSystem, combinatoric_ratelaws=true; noise_scaling=nothing)
401+
402+
if noise_scaling isa Vector
403+
(length(noise_scaling)!=length(rs.eqs)) &&
404+
error("The number of elements in 'noise_scaling' must be equal " *
405+
"to the number of reactions in the reaction system.")
406+
noise_scaling = value.(noise_scaling)
407+
elseif !isnothing(noise_scaling)
408+
noise_scaling = fill(value(noise_scaling),length(rs.eqs))
409+
end
410+
406411
eqs = assemble_drift(rs; combinatoric_ratelaws=combinatoric_ratelaws)
407-
noiseeqs = assemble_diffusion(rs,noise_scaling; combinatoric_ratelaws=combinatoric_ratelaws)
408-
SDESystem(eqs,noiseeqs,rs.iv,rs.states,(noise_scaling===nothing) ? rs.ps : union(rs.ps,Variable{ModelingToolkit.Parameter{Number}}.(noise_scaling)),name=rs.name,systems=convert.(SDESystem,rs.systems))
412+
413+
noiseeqs = assemble_diffusion(rs,noise_scaling;
414+
combinatoric_ratelaws=combinatoric_ratelaws)
415+
416+
SDESystem(eqs,
417+
noiseeqs,
418+
rs.iv,
419+
rs.states,
420+
(noise_scaling===nothing) ?
421+
rs.ps :
422+
union(rs.ps,makeparam.(noise_scaling)),
423+
name=rs.name,systems=convert.(SDESystem,rs.systems))
409424
end
410425

411426
"""
@@ -499,7 +514,7 @@ function DiffEqBase.SteadyStateProblem(rs::ReactionSystem, u0::Union{AbstractArr
499514
end
500515

501516
# determine which species a reaction depends on
502-
function get_variables!(deps::Set{Operation}, rx::Reaction, variables)
517+
function get_variables!(deps::Set, rx::Reaction, variables)
503518
(rx.rate isa Operation) && get_variables!(deps, rx.rate, variables)
504519
for s in rx.substrates
505520
push!(deps, s)

test/reactionsystem.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ jumps[18] = ConstantRateJump((u,p,t) -> p[18]*u[2], integrator -> (integrator.u[
149149
jumps[19] = VariableRateJump((u,p,t) -> p[19]*u[1]*t, integrator -> (integrator.u[1] -= 1; integrator.u[2] += 1))
150150
jumps[20] = VariableRateJump((u,p,t) -> p[20]*t*u[1]*binomial(u[2],2)*u[3], integrator -> (integrator.u[2] -= 2; integrator.u[3] -= 1; integrator.u[4] += 2))
151151

152-
statetoid = Dict(convert(Variable,state) => i for (i,state) in enumerate(states(js)))
152+
statetoid = Dict(state => i for (i,state) in enumerate(states(js)))
153153
parammap = map((x,y)->Pair(x(),y),parameters(js),pars)
154154
for i in midxs
155155
maj = MT.assemble_maj(js.eqs[i], statetoid, ModelingToolkit.substituter(parammap),eltype(pars))

0 commit comments

Comments
 (0)