with one click
catalyst-chemical
Chemical reaction network modeling with Catalyst.jl. Autopoietic systems, unit-aware ODEs, and interacting subsystems.
Menu
Chemical reaction network modeling with Catalyst.jl. Autopoietic systems, unit-aware ODEs, and interacting subsystems.
Based on SOC occupation classification
| name | catalyst-chemical |
| description | Chemical reaction network modeling with Catalyst.jl. Autopoietic systems, unit-aware ODEs, and interacting subsystems. |
| source | SciML/Catalyst.jl + GitHub issues research |
| license | MIT |
| gf3_category | ZERO |
Addresses: Catalyst.jl #1341 (DynamicQuantities units), #1336 (interacting subsystems)
Catalyst.jl is a symbolic modeling package for chemical reaction networks (CRNs). It enables:
using Catalyst
# Define a simple reaction network
rn = @reaction_network begin
k1, A + B --> C # A + B → C with rate k1
k2, C --> A + B # C → A + B with rate k2
k3, C --> D # C → D with rate k3
end
# Convert to ODE system
osys = convert(ODESystem, rn)
# Solve
using DifferentialEquations
u0 = [:A => 1.0, :B => 1.0, :C => 0.0, :D => 0.0]
ps = [:k1 => 1.0, :k2 => 0.5, :k3 => 0.1]
tspan = (0.0, 10.0)
prob = ODEProblem(rn, u0, tspan, ps)
sol = solve(prob, Tsit5())
Pattern for coupling reaction networks through observables:
using Catalyst, ModelingToolkit
# Subsystem 1: Gene expression
@reaction_network gene_expr begin
@parameters α β
@species mRNA(t) Protein(t)
α, ∅ --> mRNA # Transcription
β, mRNA --> mRNA + Protein # Translation
1.0, mRNA --> ∅ # mRNA decay
0.1, Protein --> ∅ # Protein decay
end
# Subsystem 2: Metabolic network (depends on Protein from subsystem 1)
@reaction_network metabolism begin
@parameters v_max K_m
@species Substrate(t) Product(t)
# Michaelis-Menten kinetics with enzyme = Protein
(v_max * Protein * Substrate) / (K_m + Substrate), Substrate --> Product
0.05, Product --> ∅
end
# Compose via shared variable
function compose_systems(gene::ReactionSystem, metab::ReactionSystem)
# Connect Protein from gene_expr to metabolism
@named coupled = compose(gene, metab)
# Add coupling equation: Protein in metabolism = Protein in gene_expr
eqs = [metab.Protein ~ gene.Protein]
extend(coupled, eqs)
end
coupled_system = compose_systems(gene_expr, metabolism)
Unit-aware reaction modeling:
using Catalyst, DynamicQuantities
# Define units
const mM = u"mmol/L"
const s⁻¹ = u"s^-1"
const mM_s⁻¹ = u"mmol/L/s"
# Reaction network with units
rn_units = @reaction_network begin
@parameters k1::typeof(1.0mM_s⁻¹) k2::typeof(1.0s⁻¹)
@species A(t)::typeof(1.0mM) B(t)::typeof(1.0mM)
k1, ∅ --> A # Zero-order production
k2, A --> B # First-order conversion
end
# Solve with unit-aware initial conditions
u0_units = [:A => 1.0mM, :B => 0.0mM]
ps_units = [:k1 => 0.1mM_s⁻¹, :k2 => 0.05s⁻¹]
tspan_units = (0.0u"s", 100.0u"s")
# Note: Full unit propagation through ODE solve is WIP
Identify self-maintaining organizations in CRNs:
"""
Check if a set of species forms an autopoietic organization.
An organization is autopoietic if:
1. It is closed under the reaction network (all products are in the set)
2. It is self-maintaining (can regenerate all consumed species)
"""
function is_autopoietic(rn::ReactionSystem, species_set::Set{Symbol})
reactions = Catalyst.reactions(rn)
# Check closure: all products must be in set
for rx in reactions
# Check if any reactant is in our set
reactant_syms = [Symbol(sp) for sp in rx.substrates]
if !isempty(intersect(reactant_syms, species_set))
# Then all products must also be in set
product_syms = [Symbol(sp) for sp in rx.products]
if !issubset(product_syms, species_set)
return false
end
end
end
# Check self-maintenance: each species can be produced
for sp in species_set
can_produce = false
for rx in reactions
if Symbol(sp) in [Symbol(p) for p in rx.products]
can_produce = true
break
end
end
if !can_produce
return false
end
end
return true
end
# Example: check if {A, B, C} is autopoietic
species = Set([:A, :B, :C])
is_autopoietic(rn, species)
Map reaction network dynamics to balanced ternary:
"""
Assign GF(3) trits to reactions for conservation checking.
- Production reactions (∅ → X): PLUS (+1)
- Degradation reactions (X → ∅): MINUS (-1)
- Conversion reactions (X → Y): ZERO (0)
"""
function reaction_trits(rn::ReactionSystem)
trits = Dict{Reaction, Int}()
for rx in Catalyst.reactions(rn)
n_substrates = length(rx.substrates)
n_products = length(rx.products)
if n_substrates == 0 && n_products > 0
trits[rx] = 1 # PLUS: production
elseif n_substrates > 0 && n_products == 0
trits[rx] = -1 # MINUS: degradation
else
trits[rx] = 0 # ZERO: conversion
end
end
# Verify conservation
total = sum(values(trits))
balanced = total % 3 == 0
return trits, balanced
end
using Catalyst, MethodOfLines, DomainSets
# Reaction-diffusion PDE
@parameters D_A D_B
@variables x t A(x,t) B(x,t)
# Spatial domain
domain = [x ∈ Interval(0.0, 1.0)]
# Reaction network in each spatial point
rn_spatial = @reaction_network begin
k1, A + B --> 2B # Autocatalysis
k2, B --> A # Reversion
end
# Add diffusion terms
∂t = Differential(t)
∂x = Differential(x)
∂xx = ∂x ∘ ∂x
eqs = [
∂t(A) ~ D_A * ∂xx(A) + reaction_rate(rn_spatial, :A),
∂t(B) ~ D_B * ∂xx(B) + reaction_rate(rn_spatial, :B),
]
# Solve with MethodOfLines.jl
Custom event handling for stochastic CRNs:
using Catalyst, JumpProcesses
# Define reaction network with events
rn_events = @reaction_network begin
@parameters k_div k_death threshold
@species Cells(t) Resources(t)
k_div * Resources, Cells --> 2Cells # Division uses resources
k_death, Cells --> ∅ # Cell death
1.0, ∅ --> Resources # Resource replenishment
end
# Custom affect: cell division only when resources > threshold
function division_affect!(integrator)
if integrator[:Resources] > integrator.p[:threshold]
integrator[:Cells] += 1
integrator[:Resources] -= 1
end
end
# Attach to jump process
# (Full ImperativeAffect DSL support is WIP per issue #1335)
just catalyst-demo # Run Catalyst demonstration
just catalyst-autopoietic # Autopoietic closure detection
just catalyst-spatial # Reaction-diffusion example
just catalyst-gf3 # GF(3) conservation check
GF(3) Category: ZERO (Coordination/Ergodic) | Chemical computing for multi-agent dynamics
Part of: alife-commons. Family: chemical-reaction-networks. Canonical: catalyst-chemical.
Query and explore the 2600: The Hacker Quarterly magazine archive (1984-present) via DuckDB. Provides structured access to 168+ issues covering hacker culture, security, privacy, telephony, and digital rights without loading full content into context.
ACSets (Attributed C-Sets): Algebraic databases with Specter-style bidirectional navigation. Category-theoretic formalism for relational databases.
Attributed C-Sets as algebraic databases. Category-theoretic data structures generalizing graphs and dataframes with Gay.jl color integration.
ACSets (Attributed C-Sets): Algebraic databases with Specter-style bidirectional
Bridge active inference theory with robot control using K-Scale's JAX/MuJoCo stack. Use when connecting predictive coding to locomotion policies, mapping KL divergence minimization to RL training, applying mean field approximation to robotics state estimation, or implementing sim2real as inference about future observations.
Implement affective valence as directional derivative of interoceptive energy landscapes for AI alignment. Use when building alignment-aware RL agents, validating GF(3) conservation in reward signals, training Langevin-based policies, or analyzing fold-change detection signals in POMDP environments.