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 the best JAX for your platform (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.5.1.tar.gz (20.2 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.5.1-py3-none-any.whl (81.9 kB view details)

Uploaded Python 3

File details

Details for the file icrn-0.5.1.tar.gz.

File metadata

  • Download URL: icrn-0.5.1.tar.gz
  • Upload date:
  • Size: 20.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for icrn-0.5.1.tar.gz
Algorithm Hash digest
SHA256 654e9af777d844df4f989abc5d1852bbc8a7dc95c57a1fc18633f6d5a7c8e07a
MD5 16a47fc1a2d57d900bde6635bde3eca0
BLAKE2b-256 64ddfeeb732e839414f3e967e59a02b438713c2bddff630b1413f0dc728e9cc0

See more details on using hashes here.

Provenance

The following attestation bundles were made for icrn-0.5.1.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.5.1-py3-none-any.whl.

File metadata

  • Download URL: icrn-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 81.9 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.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0e7bf43cc8c5481250fcb7c1749f0ea6eaaefae42ab665ff3d5e472aae93b755
MD5 fc2b0f61da876acf55f68c07aa0ad5fe
BLAKE2b-256 33c7010af8f9412d6c958b38bd5f8975db19c87cc4d14822484607e8db595f8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for icrn-0.5.1-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