3. Usage

3.1. QSSA Example

Quasi-steady-state approximation (QSSA) assumes that selected fast states relax quickly compared with the states retained in the reduced model. For a Michaelis-Menten-style mechanism with enzyme conservation,

\[E = E_T - C,\]

the full symbolic system can be written as

\[\begin{split}\begin{aligned} \dot{S} &= -k_1(E_T - C)S + k_2C, \\ \dot{C} &= k_1(E_T - C)S - (k_2 + k_3)C, \\ \dot{P} &= k_3C. \end{aligned}\end{split}\]

If C is treated as the fast state, AutoReduce solves dot(C) = 0 and substitutes the resulting algebraic expression into the slow dynamics for S and P.

import numpy as np
from sympy import Symbol, simplify

from autoreduce import System, solve_timescale_separation

S = Symbol("S")
C = Symbol("C")
P = Symbol("P")
k1 = Symbol("k1")
k2 = Symbol("k2")
k3 = Symbol("k3")
E_total = Symbol("E_total")

E = E_total - C
x = [S, C, P]
f = [
    -k1 * E * S + k2 * C,
    k1 * E * S - (k2 + k3) * C,
    k3 * C,
]

system = System(
    x,
    f,
    params=[k1, k2, k3, E_total],
    params_values=[1.0, 0.5, 0.25, 1.0],
    x_init=[10.0, 0.0, 0.0],
    C=np.array([[1, 0, 0], [0, 0, 1]]),
)

reduced_system, collapsed_system = (
    solve_timescale_separation(
        system,
        [S, P],
        fast_states=[C],
    )
)

reduced_dynamics = [simplify(expr) for expr in reduced_system.f]

The reduced dynamics are

\[\begin{split}\begin{aligned} \dot{S} &= -\frac{E_T S k_1 k_3}{S k_1 + k_2 + k_3}, \\ \dot{P} &= \frac{E_T S k_1 k_3}{S k_1 + k_2 + k_3}. \end{aligned}\end{split}\]

3.2. Conservation-Law Example

Conservation laws remove states whose values are determined by invariant total quantities. For the enzyme-substrate mechanism,

\[E + C = E_T,\]

AutoReduce can eliminate E before applying other reductions.

import numpy as np
from sympy import Symbol, simplify

from autoreduce import System, solve_conservation_laws

S = Symbol("S")
E = Symbol("E")
C = Symbol("C")
P = Symbol("P")
k1 = Symbol("k1")
k2 = Symbol("k2")
k3 = Symbol("k3")

x = [S, E, C, P]
f = [
    -k1 * S * E + k2 * C,
    -k1 * S * E + (k2 + k3) * C,
    k1 * S * E - (k2 + k3) * C,
    k3 * C,
]

system = System(
    x,
    f,
    params=[k1, k2, k3],
    params_values=[1.0, 0.5, 0.25],
    x_init=[10.0, 1.0, 0.0, 0.0],
    C=np.eye(4),
)

conserved_system = solve_conservation_laws(
    system,
    total_quantities={"E_total": 1.0},
    conserved_sets=[[E, C]],
    states_to_eliminate=[E],
)

conserved_dynamics = [simplify(expr) for expr in conserved_system.f]

For more worked examples, see the Examples section.