Skip to content

Commit 2ac29c8

Browse files
feat: add BCR jacobian benchmark
1 parent cff34a7 commit 2ac29c8

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

benchmarks/Symbolics/BCR.jmd

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
---
2+
title: BCR Symbolic Jacobian
3+
author: Aayush Sabharwal, Bowen Zhu, Chris Rackauckas
4+
---
5+
6+
The following benchmark is of 1122 ODEs with 24388 terms that describe a stiff
7+
chemical reaction network modeling the BCR signaling network from [Barua et
8+
al.](https://doi.org/10.4049/jimmunol.1102003). We use
9+
[`ReactionNetworkImporters`](https://github.com/isaacsas/ReactionNetworkImporters.jl)
10+
to load the BioNetGen model files as a
11+
[Catalyst](https://github.com/SciML/Catalyst.jl) model, and then use
12+
[ModelingToolkit](https://github.com/SciML/ModelingToolkit.jl) to convert the
13+
Catalyst network model to ODEs.
14+
15+
The resultant large model is used to benchmark the time taken to compute a symbolic
16+
jacobian, generate a function to calculate it and call the function.
17+
18+
19+
```julia
20+
using OrdinaryDiffEq, Catalyst, ReactionNetworkImporters,
21+
Plots, TimerOutputs, LinearAlgebra, ModelingToolkit, BenchmarkTools,
22+
LinearSolve, Symbolics, SymbolicUtils.Code, SparseArrays
23+
24+
datadir = joinpath(dirname(pathof(ReactionNetworkImporters)),"../data/bcr")
25+
const to = TimerOutput()
26+
tf = 100000.0
27+
28+
# generate ModelingToolkit ODEs
29+
prnbng = loadrxnetwork(BNGNetwork(), joinpath(datadir, "bcr.net"))
30+
show(to)
31+
rn = complete(prnbng.rn; split = false)
32+
obs = [eq.lhs for eq in observed(rn)]
33+
osys = convert(ODESystem, rn)
34+
35+
rhs = [eq.rhs for eq in full_equations(osys)]
36+
vars = unknowns(osys)
37+
pars = parameters(osys)
38+
39+
SymbolicUtils.ENABLE_HASHCONSING[] = false
40+
@timeit to "Calculate jacobian - without hashconsing" jac_nohc = Symbolics.sparsejacobian(rhs, vars);
41+
SymbolicUtils.ENABLE_HASHCONSING[] = true
42+
SymbolicUtils.toggle_caching!(Symbolics.occursin_info, false)
43+
@timeit to "Calculate jacobian - hashconsing, without caching" jac_hc_nocache = Symbolics.sparsejacobian(rhs, vars);
44+
SymbolicUtils.toggle_caching!(Symbolics.occursin_info, true)
45+
stats = SymbolicUtils.get_stats(Symbolics.occursin_info)
46+
@assert stats.hits == stats.misses == 0
47+
@timeit to "Calculate jacobian - hashconsing and caching" jac_hc_cache = Symbolics.sparsejacobian(rhs, vars);
48+
49+
@assert isequal(jac_nohc, jac_hc_nocache)
50+
@assert isequal(jac_hc_nocache, jac_hc_cache)
51+
52+
jac = jac_hc_cache
53+
args = (vars, pars, ModelingToolkit.get_iv(osys))
54+
# out of place versions run into an error saying the expression is too large
55+
# due to the `SymbolicUtils.Code.create_array` call. `iip_config` prevents it
56+
# from trying to build the function.
57+
kwargs = (; iip_config = (false, true), expression = Val{false})
58+
@timeit to "Build jacobian - no CSE" _, jac_nocse_iip = build_function(jac, args...; cse = false, kwargs...);
59+
@timeit to "Build jacobian - CSE" _, jac_cse_iip = build_function(jac, args...; cse = true, kwargs...);
60+
61+
defs = defaults(osys)
62+
u = Float64[Symbolics.fixpoint_sub(var, defs) for var in vars]
63+
buffer_cse = SparseMatrixCSC{Float64, Int}(undef, length(u), length(u))
64+
buffer_nocse = SparseMatrixCSC{Float64, Int}(undef, length(u), length(u))
65+
p = Float64[Symbolics.fixpoint_sub(par, defs) for par in pars]
66+
tt = 0.0
67+
68+
@timeit to "Compile jacobian - CSE" jac_cse_iip(buffer_cse, u, p, tt)
69+
@timeit to "Compute jacobian - CSE" jac_cse_iip(buffer_cse, u, p, t)
70+
71+
@timeit to "Compile jacobian - no CSE" jac_nocse_iip(buffer_nocse, u, p, tt)
72+
@timeit to "Compute jacobian - no CSE" jac_nocse_iip(buffer_nocse, u, p, t)
73+
74+
@assert isapprox(buffer_cse, buffer_nocse, rtol = 1e-10)
75+
76+
show(to)
77+
```

benchmarks/Symbolics/Project.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[deps]
2+
Catalyst = "479239e8-5488-4da2-87a7-35f2df7eef83"
3+
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
4+
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
5+
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
6+
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
7+
OrdinaryDiffEq = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed"
8+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
9+
ReactionNetworkImporters = "b4db0fb7-de2a-5028-82bf-5021f5cfa881"
10+
SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"
11+
Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7"
12+
TimerOutputs = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f"
13+
14+
[compat]
15+
ModelingToolkit = "9"
16+
SymbolicUtils = "3.17"
17+
Symbolics = "6.29.1"

0 commit comments

Comments
 (0)