Skip to content

Commit 45a8b7a

Browse files
committed
save progress
1 parent 63ffa92 commit 45a8b7a

File tree

3 files changed

+266
-0
lines changed

3 files changed

+266
-0
lines changed

test/meta/mtk_problem_inputs.jl

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,188 @@ let
158158
end
159159
end
160160

161+
### Vector Species/Parameters Tests ###
162+
163+
begin
164+
# Declares the model (with vector species/parameters, with/without default values, and observables).
165+
@species X(t)[1:2] Y(t)[1:2] = [10.0, 20.0] XY(t)[1:2]
166+
@parameters p[1:2] d[1:2] = [0.2, 0.5]
167+
rxs = [
168+
Reaction(p[1], [], [X[1]]),
169+
Reaction(p[2], [], [X[2]]),
170+
Reaction(d[1], [X[1]], []),
171+
Reaction(d[2], [X[2]], []),
172+
Reaction(p[1], [], [Y[1]]),
173+
Reaction(p[2], [], [Y[2]]),
174+
Reaction(d[1], [Y[1]], []),
175+
Reaction(d[2], [Y[2]], [])
176+
]
177+
observed = [XY[1] ~ X[1] + Y[1], XY[2] ~ X[2] + Y[2]]
178+
@named model_vec = ReactionSystem(rxs, t; observed)
179+
model_vec = complete(model_vec)
180+
181+
# Declares various u0 versions.
182+
u0_alts_vec = [
183+
# Vectors not providing default values.
184+
[X => [1.0, 2.0]],
185+
[X[1] => 1.0, X[2] => 2.0],
186+
[model_vec.X => [1.0, 2.0]],
187+
[model_vec.X[1] => 1.0, model_vec.X[2] => 2.0],
188+
[:X => [1.0, 2.0]],
189+
# Vectors providing default values.
190+
[X => [1.0, 2.0], Y => [10.0, 20.0]],
191+
[X[1] => 1.0, X[2] => 2.0, Y[1] => 10.0, Y[2] => 20.0],
192+
[model_vec.X => [1.0, 2.0], model_vec.Y => [10.0, 20.0]],
193+
[model_vec.X[1] => 1.0, model_vec.X[2] => 2.0, model_vec.Y[1] => 10.0, model_vec.Y[2] => 20.0],
194+
[:X => [1.0, 2.0], :Y => [10.0, 20.0]],
195+
# Dicts not providing default values.
196+
Dict([X => [1.0, 2.0]]),
197+
Dict([X[1] => 1.0, X[2] => 2.0]),
198+
Dict([model_vec.X => [1.0, 2.0]]),
199+
Dict([model_vec.X[1] => 1.0, model_vec.X[2] => 2.0]),
200+
Dict([:X => [1.0, 2.0]]),
201+
# Dicts providing default values.
202+
Dict([X => [1.0, 2.0], Y => [10.0, 20.0]]),
203+
Dict([X[1] => 1.0, X[2] => 2.0, Y[1] => 10.0, Y[2] => 20.0]),
204+
Dict([model_vec.X => [1.0, 2.0], model_vec.Y => [10.0, 20.0]]),
205+
Dict([model_vec.X[1] => 1.0, model_vec.X[2] => 2.0, model_vec.Y[1] => 10.0, model_vec.Y[2] => 20.0]),
206+
Dict([:X => [1.0, 2.0], :Y => [10.0, 20.0]]),
207+
# Tuples not providing default values.
208+
(X => [1.0, 2.0]),
209+
(X[1] => 1.0, X[2] => 2.0),
210+
(model_vec.X => [1.0, 2.0]),
211+
(model_vec.X[1] => 1.0, model_vec.X[2] => 2.0),
212+
(:X => [1.0, 2.0]),
213+
# Tuples providing default values.
214+
(X => [1.0, 2.0], Y => [10.0, 20.0]),
215+
(X[1] => 1.0, X[2] => 2.0, Y[1] => 10.0, Y[2] => 20.0),
216+
(model_vec.X => [1.0, 2.0], model_vec.Y => [10.0, 20.0]),
217+
(model_vec.X[1] => 1.0, model_vec.X[2] => 2.0, model_vec.Y[1] => 10.0, model_vec.Y[2] => 20.0),
218+
(:X => [1.0, 2.0], :Y => [10.0, 20.0]),
219+
]
220+
221+
# Declares various ps versions.
222+
p_alts_vec = [
223+
# Vectors not providing default values.
224+
[p => [1.0, 2.0]],
225+
[p[1] => 1.0, p[2] => 2.0],
226+
[model_vec.p => [1.0, 2.0]],
227+
[model_vec.p[1] => 1.0, model_vec.p[2] => 2.0],
228+
[:p => [1.0, 2.0]],
229+
# Vectors providing default values.
230+
[p => [4.0, 5.0], d => [0.2, 0.5]],
231+
[p[1] => 4.0, p[2] => 5.0, d[1] => 10.0, d[2] => 20.0],
232+
[model_vec.p => [4.0, 5.0], model_vec.d => [0.2, 0.5]],
233+
[model_vec.p[1] => 4.0, model_vec.p[2] => 5.0, model_vec.d[1] => 10.0, model_vec.d[2] => 20.0],
234+
[:p => [4.0, 5.0], :d => [0.2, 0.5]],
235+
# Dicts not providing default values.
236+
Dict([p => [1.0, 2.0]]),
237+
Dict([p[1] => 1.0, p[2] => 2.0]),
238+
Dict([model_vec.p => [1.0, 2.0]]),
239+
Dict([model_vec.p[1] => 1.0, model_vec.p[2] => 2.0]),
240+
Dict([:p => [1.0, 2.0]]),
241+
# Dicts providing default values.
242+
Dict([p => [4.0, 5.0], d => [0.2, 0.5]]),
243+
Dict([p[1] => 4.0, p[2] => 5.0, d[1] => 10.0, d[2] => 20.0]),
244+
Dict([model_vec.p => [4.0, 5.0], model_vec.d => [0.2, 0.5]]),
245+
Dict([model_vec.p[1] => 4.0, model_vec.p[2] => 5.0, model_vec.d[1] => 10.0, model_vec.d[2] => 20.0]),
246+
Dict([:p => [4.0, 5.0], :d => [0.2, 0.5]]),
247+
# Tuples not providing default values.
248+
(p => [1.0, 2.0]),
249+
(p[1] => 1.0, p[2] => 2.0),
250+
(model_vec.p => [1.0, 2.0]),
251+
(model_vec.p[1] => 1.0, model_vec.p[2] => 2.0),
252+
(:p => [1.0, 2.0]),
253+
# Tuples providing default values.
254+
(p => [4.0, 5.0], d => [0.2, 0.5]),
255+
(p[1] => 4.0, p[2] => 5.0, d[1] => 10.0, d[2] => 20.0),
256+
(model_vec.p => [4.0, 5.0], model_vec.d => [0.2, 0.5]),
257+
(model_vec.p[1] => 4.0, model_vec.p[2] => 5.0, model_vec.d[1] => 10.0, model_vec.d[2] => 20.0),
258+
(:p => [4.0, 5.0], :d => [0.2, 0.5]),
259+
]
260+
261+
# Declares a timespan.
262+
tspan = (0.0, 10.0)
263+
end
264+
265+
# Perform ODE simulations (singular and ensemble).
266+
let
267+
# Creates normal and ensemble problems.
268+
base_oprob = ODEProblem(model_vec, u0_alts_vec[1], tspan, p_alts_vec[1])
269+
base_sol = solve(base_oprob, Tsit5(); saveat = 1.0)
270+
base_eprob = EnsembleProblem(base_oprob)
271+
base_esol = solve(base_eprob, Tsit5(); trajectories = 2, saveat = 1.0)
272+
273+
# Simulates problems for all input types, checking that identical solutions are found.
274+
for u0 in u0_alts_vec, p in p_alts_vec
275+
oprob = remake(base_oprob; u0, p)
276+
@test base_sol == solve(oprob, Tsit5(); saveat = 1.0)
277+
eprob = remake(base_eprob; u0, p)
278+
@test base_esol == solve(eprob, Tsit5(); trajectories = 2, saveat = 1.0)
279+
end
280+
end
281+
282+
# Perform SDE simulations (singular and ensemble).
283+
let
284+
# Creates normal and ensemble problems.
285+
base_sprob = SDEProblem(model, u0_alts_vec[1], tspan, p_alts_vec[1])
286+
base_sol = solve(base_sprob, ImplicitEM(); seed, saveat = 1.0)
287+
base_eprob = EnsembleProblem(base_sprob)
288+
base_esol = solve(base_eprob, ImplicitEM(); seed, trajectories = 2, saveat = 1.0)
289+
290+
# Simulates problems for all input types, checking that identical solutions are found.
291+
for u0 in u0_alts_vec, p in p_alts_vec
292+
sprob = remake(base_sprob; u0, p)
293+
@test base_sol == solve(sprob, ImplicitEM(); seed, saveat = 1.0)
294+
eprob = remake(base_eprob; u0, p)
295+
@test base_esol == solve(eprob, ImplicitEM(); seed, trajectories = 2, saveat = 1.0)
296+
end
297+
end
298+
299+
# Perform jump simulations (singular and ensemble).
300+
let
301+
# Creates normal and ensemble problems.
302+
base_dprob = DiscreteProblem(model, u0_alts_vec[1], tspan, p_alts_vec[1])
303+
base_jprob = JumpProblem(model, base_dprob, Direct(); rng)
304+
base_sol = solve(base_jprob, SSAStepper(); seed, saveat = 1.0)
305+
base_eprob = EnsembleProblem(base_jprob)
306+
base_esol = solve(base_eprob, SSAStepper(); seed, trajectories = 2, saveat = 1.0)
307+
308+
# Simulates problems for all input types, checking that identical solutions are found.
309+
for u0 in u0_alts_vec, p in p_alts_vec
310+
jprob = remake(base_jprob; u0, p)
311+
@test base_sol == solve(base_jprob, SSAStepper(); seed, saveat = 1.0)
312+
eprob = remake(base_eprob; u0, p)
313+
@test base_esol == solve(eprob, SSAStepper(); seed, trajectories = 2, saveat = 1.0)
314+
end
315+
end
316+
317+
# Solves a nonlinear problem (EnsembleProblems are not possible for these).
318+
let
319+
base_nlprob = NonlinearProblem(model, u0_alts_vec[1], p_alts_vec[1])
320+
base_sol = solve(base_nlprob, NewtonRaphson())
321+
for u0 in u0_alts_vec, p in p_alts_vec
322+
nlprob = remake(base_nlprob; u0, p)
323+
@test base_sol == solve(nlprob, NewtonRaphson())
324+
end
325+
end
326+
327+
# Perform steady state simulations (singular and ensemble).
328+
let
329+
# Creates normal and ensemble problems.
330+
base_ssprob = SteadyStateProblem(model, u0_alts_vec[1], p_alts_vec[1])
331+
base_sol = solve(base_ssprob, DynamicSS(Tsit5()))
332+
base_eprob = EnsembleProblem(base_ssprob)
333+
base_esol = solve(base_eprob, DynamicSS(Tsit5()); trajectories = 2)
334+
335+
# Simulates problems for all input types, checking that identical solutions are found.
336+
for u0 in u0_alts_vec, p in p_alts_vec
337+
ssprob = remake(base_ssprob; u0, p)
338+
@test base_sol == solve(ssprob, DynamicSS(Tsit5()))
339+
eprob = remake(base_eprob; u0, p)
340+
@test base_esol == solve(eprob, DynamicSS(Tsit5()); trajectories = 2)
341+
end
342+
end
161343

162344
### Checks Errors On Faulty Inputs ###
163345

test/network_analysis/conservation_laws.jl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,25 @@ let
7373
@test length(cons_laws_constants) == 2
7474
@test count(isequal.(conserved_quantity, Num(0))) == 2
7575
end
76+
77+
# Conservation law simulations for vectorised species.
78+
let
79+
# Prepares the model.
80+
t = default_t()
81+
@species X(t)[1:2]
82+
@parameters k[1:2]
83+
rxs = [
84+
Reaction(k[1], [X[1]], [X[2]]),
85+
Reaction(k[2], [X[2]], [X[1]])
86+
]
87+
@named rs = ReactionSystem(rxs, t)
88+
rs = complete(rs)
89+
90+
# Checks that simulation reaches known equilibrium
91+
u0 = [:X => [3.0, 9.0]]
92+
ps = [:k => [1.0, 2.0]]
93+
oprob = ODEProblem(rs, u0, (0.0, 1000.0), ps; remove_conserved = true)
94+
sol = solve(oprob, Vern7())
95+
@test sol[X[1]] 8.0
96+
@test sol[X[2]] 4.0
97+
end

test/reactionsystem_structure/reactionsystem.jl

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,68 @@ let
279279
end
280280
end
281281

282+
### Nich Model Declarations ###
283+
284+
# Checks model with vector species and parameters.
285+
# Checks that it works for programmatic/dsl-based modelling.
286+
# Checks that all forms of model input (parameter/initial condition and vector/non-vector) are
287+
# handled properly.
288+
let
289+
# Declares programmatic model.
290+
@parameters p[1:2] k d1 d2
291+
@species (X(t))[1:2] Y1(t) Y2(t)
292+
rxs = [
293+
Reaction(p[1], [], [X[1]]),
294+
Reaction(p[2], [], [X[2]]),
295+
Reaction(k, [X[1]], [Y1]),
296+
Reaction(k, [X[2]], [Y2]),
297+
Reaction(d1, [Y1], []),
298+
Reaction(d2, [Y2], []),
299+
]
300+
rs_prog = complete(ReactionSystem(rxs, t; name = :rs))
301+
302+
# Declares DSL-based model.
303+
rs_dsl = @reaction_network rs begin
304+
@parameters p[1:2] k d1 d2
305+
@species (X(t))[1:2] Y1(t) Y2(t)
306+
(p[1],p[2]), 0 --> (X[1],X[2])
307+
k, (X[1],X[2]) --> (Y1,Y2)
308+
(d1,d2), (Y1,Y2) --> 0
309+
end
310+
311+
# Checks equivalence.
312+
rs_dsl == rs_prog
313+
314+
# Creates all possible initial conditions and parameter values.
315+
u0_alts = [
316+
[X => [2.0, 5.0], Y1 => 0.2, Y2 => 0.5],
317+
[X[1] => 2.0, X[2] => 5.0, Y1 => 0.2, Y2 => 0.5],
318+
[rs_dsl.X => [2.0, 5.0], rs_dsl.Y1 => 0.2, rs_dsl.Y2 => 0.5],
319+
[rs_dsl.X[1] => 2.0, X[2] => 5.0, rs_dsl.Y1 => 0.2, rs_dsl.Y2 => 0.5],
320+
[:X => [2.0, 5.0], :Y1 => 0.2, :Y2 => 0.5]
321+
]
322+
ps_alts = [
323+
[p => [1.0, 10.0], d1 => 5.0, d2 => 4.0, k => 2.0],
324+
[p[1] => 1.0, p[2] => 10.0, d1 => 5.0, d2 => 4.0, k => 2.0],
325+
[rs_dsl.p => [1.0, 10.0], rs_dsl.d1 => 5.0, rs_dsl.d2 => 4.0, rs_dsl.k => 2.0],
326+
[rs_dsl.p[1] => 1.0, p[2] => 10.0, rs_dsl.d1 => 5.0, rs_dsl.d2 => 4.0, rs_dsl.k => 2.0],
327+
[:p => [1.0, 10.0], :d1 => 5.0, :d2 => 4.0, :k => 2.0]
328+
]
329+
330+
# Loops through all inputs and check that the correct steady state is reached
331+
# Target steady state: (X1, X2, Y1, Y2) = (p1/k, p2/k, p1/d1, p2/d2).
332+
# Technically only one model needs to be check. However, "equivalent" models in MTK can still
333+
# have slight differences, so checking for both here to be certain.
334+
for rs in [rs_prog, rs_dsl]
335+
oprob = ODEProblem(rs, u0_alts[1], (0.0, 10000.), ps_alts[1])
336+
for rs in [rs_prog, rs_dsl], u0 in u0_alts, p in ps_alts
337+
oprob_remade = remake(oprob; u0, p)
338+
sol = solve(oprob_remade, Vern7(); abstol = 1e-8, reltol = 1e-8)
339+
@test sol[end] [0.5, 5.0, 0.2, 2.5]
340+
end
341+
end
342+
end
343+
282344
### Other Tests ###
283345

284346
# Test for https://github.com/SciML/ModelingToolkit.jl/issues/436.

0 commit comments

Comments
 (0)