Indexed Chemical Reaction Networks in a differentiable, tensor-based framework
Project description
icrn
Indexed Chemical Reaction Networks in a differentiable, tensor-based framework.
icrn is a JAX library for specifying chemical reaction networks with indexed species and rate constants, and simulating them as either well-mixed ODEs or reaction–diffusion PDEs. Because everything compiles to jax.numpy operations, simulations are JIT-able, batchable with jax.vmap, and differentiable end-to-end with jax.grad — so rate constants and initial conditions can be trained.
interfaces are subject to change.
Highlights
- Indexed reactions: write
M[i] + M[j] -> D[i, j]for a dimer system - Well-mixed and reaction–diffusion in one API (
solve_well_mixed,solve_reaction_diffusion). - Fast reactions for limiting-reagent-style annihilation (
FastReaction). - JAX-native: works under
jit,vmap, andgrad. - Optional non-negativity guards (
mode="strict"viacheckify, ormode="relu").
Installation
pip install icrn
This installs JAX and NumPy as runtime dependencies. The default JAX
wheel is CPU-only; for GPU/TPU, install JAX for your platform after icrn
(JAX installation guide).
Quick Start
Well Mixed Exponential Decay
import jax.numpy as jnp
from icrn import many_species, many_rate_constants, MassActionReaction, solve_well_mixed
A = many_species("A")
k = many_rate_constants("k")
rxns = [MassActionReaction(A, 0, k)] # A -> 0 with rate k
result = solve_well_mixed(
rxns,
conc_vals={A: jnp.array(1.0)},
rate_constant_vals={k: jnp.array(1.0)},
times=jnp.array([0.0, jnp.log(2), 1.0]),
dt=0.005,
)
print(result[A]) # ~ [1.0, 0.5, 0.3679]
Indexed Reactions
The thing that makes icrn different: species and rate constants can carry indices, and reactions involving them are compiled to a single tensor contraction.
import jax.numpy as jnp
from icrn import (
many_species, many_rate_constants, many_index_symbols,
MassActionReaction, solve_well_mixed,
)
n = 10
M, D = many_species("M, D")
K1, K2 = many_rate_constants("K_1, K_2")
i, j = many_index_symbols("i, j", n)
# Reversible all-vs-all dimerization
rxns = [
MassActionReaction(M[i] + M[j], D[i, j], K1[i, j]),
MassActionReaction(D[i, j], M[i] + M[j], K2[i, j]),
]
conc = {M: jnp.ones(n), D: jnp.zeros((n, n))}
rates = {K1: jnp.ones((n, n)) * 0.1, K2: jnp.ones((n, n)) * 0.05}
out = solve_well_mixed(rxns, conc, rates, times=jnp.array([1.0]), dt=1e-3)
Reaction–diffusion
The Gray-Scott system.
from icrn import solve_reaction_diffusion
U, V = many_species("U, V")
F, k = many_rate_constants("F, k")
rxns = [
MassActionReaction(U + 2 * V, 3 * V, 1),
MassActionReaction(V, 0, F + k),
MassActionReaction(0, U, F),
MassActionReaction(U, 0, F),
]
sim = solve_reaction_diffusion(
rxns,
conc_vals={U: U0, V: V0}, # 2-D fields
rate_constant_vals={F: jnp.array(0.037), k: jnp.array(0.06)},
diffusion_constant_vals={U: jnp.array(0.2), V: jnp.array(0.1)},
times=jnp.array([5e3]),
dt=1.0,
spatial_dims=(101, 101),
dspaces=(1.0, 1.0),
mode="relu",
)
Differentiable simulation
Because everything is JAX, you can jit, vmap, and grad straight through a solve:
import jax
@jax.jit
def loss(rate_vals):
out = solve_well_mixed(rxns, conc, {k: rate_vals}, times, dt)
return jnp.mean((out[A][-1] - target) ** 2)
grad_fn = jax.grad(loss)
Project layout
icrn/
symbols.py # symbolic DSL: Species, IndexSymbol, Complex, TensorExpression
reactions.py # MassActionReaction, FastReaction
solver.py # solve_well_mixed, solve_reaction_diffusion, solve_with_ops
operator.py # operator construction for the splitting integrator
_internal/ # private JAX kernels (mass-action, diffusion, time stepping)
utils/ # small helpers (dict_utils)
docs/ # MkDocs site (Material + mkdocstrings)
test/ # reference data for end-to-end tests
Contributing: see CONTRIBUTING.md. Release notes:
CHANGELOG.md. PyPI releases are continuously deployed: bump
icrn/__init__.py __version__ and merge to main to publish (see
Developer notes — Publishing to PyPI).
Development
git clone https://github.com/SwissChardLeaf/icrn
cd icrn
pip install -e ".[dev]"
# tests
python -m unittest discover -s icrn -t .
# lint
ruff check .
# docs
pip install -r docs/requirements.txt
mkdocs serve # live preview at http://127.0.0.1:8000
mkdocs build --strict # one-shot build into ./site
Status
- Stable-ish: symbolic DSL (
Species,IndexSymbol,Complex),MassActionReaction,solve_well_mixed,solve_reaction_diffusionwith spectral diffusion. - Experimental:
FastReaction,mode="strict"runtime checks, Strang splitting. - Planned: dedicated training utilities, convolutional diffusion solver, benchmarks.
Citation
If you use icrn in academic work, please cite the DNA 31 paper:
Inhoo Lee, Salvador Buse, and Erik Winfree. Differentiable Programming of Indexed Chemical Reaction Networks and Reaction-Diffusion Systems. In 31st International Conference on DNA Computing and Molecular Programming (DNA 31). Leibniz International Proceedings in Informatics (LIPIcs), Volume 347, pp. 4:1–4:23. Schloss Dagstuhl – Leibniz-Zentrum für Informatik, 2025. https://doi.org/10.4230/LIPIcs.DNA.31.4
@InProceedings{lee_et_al:LIPIcs.DNA.31.4,
author = {Lee, Inhoo and Buse, Salvador and Winfree, Erik},
title = {{Differentiable Programming of Indexed Chemical Reaction Networks and Reaction-Diffusion Systems}},
booktitle = {31st International Conference on DNA Computing and Molecular Programming (DNA 31)},
pages = {4:1--4:23},
series = {Leibniz International Proceedings in Informatics (LIPIcs)},
ISBN = {978-3-95977-399-7},
ISSN = {1868-8969},
year = {2025},
volume = {347},
editor = {Schaeffer, Josie and Zhang, Fei},
publisher = {Schloss Dagstuhl -- Leibniz-Zentrum f{\"u}r Informatik},
address = {Dagstuhl, Germany},
URL = {https://drops.dagstuhl.de/entities/document/10.4230/LIPIcs.DNA.31.4},
URN = {urn:nbn:de:0030-drops-238534},
doi = {10.4230/LIPIcs.DNA.31.4},
annote = {Keywords: Differentiable Programming, Chemical Reaction Networks, Reaction-Diffusion Systems}
}
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file icrn-0.3.0.tar.gz.
File metadata
- Download URL: icrn-0.3.0.tar.gz
- Upload date:
- Size: 19.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cfc30c507e132dc7932950b43469cdfa14229b2ac13f125da5e4d3b26ac0e284
|
|
| MD5 |
22247e701a78d4ead5f1603d94edfda5
|
|
| BLAKE2b-256 |
6aafcccfdb08b6f6a4f0ed72cf115af2629a680c541bf39b6fd13df81ed72c62
|
Provenance
The following attestation bundles were made for icrn-0.3.0.tar.gz:
Publisher:
release.yml on SwissChardLeaf/icrn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
icrn-0.3.0.tar.gz -
Subject digest:
cfc30c507e132dc7932950b43469cdfa14229b2ac13f125da5e4d3b26ac0e284 - Sigstore transparency entry: 1793130467
- Sigstore integration time:
-
Permalink:
SwissChardLeaf/icrn@4f086c30d772c318cd7b95943cb0d061dd754a1f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/SwissChardLeaf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4f086c30d772c318cd7b95943cb0d061dd754a1f -
Trigger Event:
push
-
Statement type:
File details
Details for the file icrn-0.3.0-py3-none-any.whl.
File metadata
- Download URL: icrn-0.3.0-py3-none-any.whl
- Upload date:
- Size: 66.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf33635d5348dec464b2bf838f5bbcbaa612b804a791715a4cec5dbd2c65dd01
|
|
| MD5 |
1e5629b510e92706fa8e9fa493279f6a
|
|
| BLAKE2b-256 |
3e41f6da74808997aabbbbedd3931d628543d77a264b082d56336f0eaf4a09f4
|
Provenance
The following attestation bundles were made for icrn-0.3.0-py3-none-any.whl:
Publisher:
release.yml on SwissChardLeaf/icrn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
icrn-0.3.0-py3-none-any.whl -
Subject digest:
bf33635d5348dec464b2bf838f5bbcbaa612b804a791715a4cec5dbd2c65dd01 - Sigstore transparency entry: 1793130867
- Sigstore integration time:
-
Permalink:
SwissChardLeaf/icrn@4f086c30d772c318cd7b95943cb0d061dd754a1f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/SwissChardLeaf
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@4f086c30d772c318cd7b95943cb0d061dd754a1f -
Trigger Event:
push
-
Statement type: