Skip to main content

Indexed Chemical Reaction Networks in a differentiable, tensor-based framework

Project description

icrn

PyPI Python versions License DOI Tests Lint Docs

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, and grad.
  • Optional non-negativity guards (mode="strict" via checkify, or mode="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_diffusion with 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

icrn-0.3.0.tar.gz (19.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

icrn-0.3.0-py3-none-any.whl (66.3 kB view details)

Uploaded Python 3

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

Hashes for icrn-0.3.0.tar.gz
Algorithm Hash digest
SHA256 cfc30c507e132dc7932950b43469cdfa14229b2ac13f125da5e4d3b26ac0e284
MD5 22247e701a78d4ead5f1603d94edfda5
BLAKE2b-256 6aafcccfdb08b6f6a4f0ed72cf115af2629a680c541bf39b6fd13df81ed72c62

See more details on using hashes here.

Provenance

The following attestation bundles were made for icrn-0.3.0.tar.gz:

Publisher: release.yml on SwissChardLeaf/icrn

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for icrn-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bf33635d5348dec464b2bf838f5bbcbaa612b804a791715a4cec5dbd2c65dd01
MD5 1e5629b510e92706fa8e9fa493279f6a
BLAKE2b-256 3e41f6da74808997aabbbbedd3931d628543d77a264b082d56336f0eaf4a09f4

See more details on using hashes here.

Provenance

The following attestation bundles were made for icrn-0.3.0-py3-none-any.whl:

Publisher: release.yml on SwissChardLeaf/icrn

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page