diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13626eb..6f92b57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -286,6 +286,7 @@ jobs: "examples/52_cochain_hodge_modes.ipynb", "examples/53_latent_rank_selection.ipynb", "examples/54_criticality_monitor.ipynb", + "examples/55_reaction_network_oracles.ipynb", ] ), } @@ -307,12 +308,12 @@ jobs: ), }, { - "shard": "27-54", + "shard": "27-55", "pattern": ( "examples/2[7-9]_*.ipynb " "examples/3[0-9]_*.ipynb " "examples/4[0-9]_*.ipynb " - "examples/5[0-4]_*.ipynb" + "examples/5[0-5]_*.ipynb" ), }, ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 27195fc..63331bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,11 +115,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `compute_card_oracle` and `scripts/build_reaction_cards.py` (with `--check`) regenerate the oracle sections; tests recompute them to catch drift. -- `eigenvalue_timescales`: `-1/Re(λ)` with real parts below eigensolver - round-off (`100 · eps · max|λ|`) mapped to `inf`; - `OracleSpectrum.timescales` uses it. `ReactionNetworkBenchmark.generate` - refuses a Cantera card whose recorded mechanism SHA-256 differs from the - installed file. +- Example `55_reaction_network_oracles.ipynb` compares estimators against the + `ReactionNetworkBenchmark` oracles: + - exact DMD recovers the chain's `exp(λ Δt)` (errors ~1e-7) and conserves + mass in rollouts; + - DMD on the card's log features misses by up to ~0.13; + - a short `koopman="graph"` fit is approximate, and + `element_balance_violation` flags its rollout drift; + - a late-window DMD recovers the Michaelis-Menten slow mode against each + trajectory's own equilibrium linearization. + + Registered in the PR notebook smoke set and the full `27-55` shard. +- `ReactionDataset.sequence(..., graph_encoding=)` overrides the card's + encoding (e.g. drop `hyperedge_index` for `DMDBaseline`). +- `eigenvalue_timescales`: `-1/Re(λ)` with numerical zeros mapped to `inf` + (an optional absolute `zero_tolerance`, else eigensolver round-off + `100 · eps · max|λ|`); `OracleSpectrum.timescales` uses it with its own + `zero_tolerance`. `ReactionNetworkBenchmark.generate` refuses a Cantera + card whose recorded mechanism SHA-256 differs from the installed file. ### Changed diff --git a/docs/source/tutorials.rst b/docs/source/tutorials.rst index bee179d..8471ca2 100644 --- a/docs/source/tutorials.rst +++ b/docs/source/tutorials.rst @@ -115,6 +115,12 @@ Analysis and stability * - `54_criticality_monitor.ipynb `_ - Closing-gap diagonal toy: ``monitor_critical_transition`` score rises versus a constant-gap control (not a Ghosh certificate) + * - `55_reaction_network_oracles.ipynb `_ + - ``ReactionNetworkBenchmark`` card oracles: exact DMD recovers the + chain's :math:`e^{\lambda \Delta t}`, log features and a short + ``koopman="graph"`` fit do not, ``element_balance_violation`` flags + rollout drift, and a late-window DMD recovers the Michaelis-Menten + slow mode (linearization, not a production kinetics benchmark) * - `40_resdmd_pseudospectra.ipynb `_ - Finite-dictionary ResDMD MVP + resolvent-norm grid (≠ ``spectral_residuals``; not infinite-dim certificates) * - `46_representation_explain.ipynb `_ diff --git a/examples/55_reaction_network_oracles.ipynb b/examples/55_reaction_network_oracles.ipynb new file mode 100644 index 0000000..bd43ce5 --- /dev/null +++ b/examples/55_reaction_network_oracles.ipynb @@ -0,0 +1,628 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "t55-title", + "metadata": {}, + "source": [ + "# Reaction-network oracles: recovering kinetic timescales\n", + "\n", + "`ReactionNetworkBenchmark` ships mass-action reaction datasets whose FAIR\n", + "cards carry **oracle** references: the equilibrium, the conservation laws,\n", + "and the Jacobian eigenvalues $\\lambda$ that set the true kinetic\n", + "timescales $-1/\\mathrm{Re}(\\lambda)$. A discrete operator learned with\n", + "sample interval $\\Delta t$ should match $e^{\\lambda \\Delta t}$.\n", + "\n", + "This notebook checks three estimators against those oracles:\n", + "exact dynamic mode decomposition (DMD) on raw concentrations, DMD on the\n", + "card's log-concentration features, and a short `GraphKoopmanModel` fit\n", + "with `koopman=\"graph\"`. It then uses `element_balance_violation` to test\n", + "whether decoded rollouts conserve mass.\n", + "\n", + "**Honesty.** These are diagnostic / teaching datasets, not a production\n", + "kinetics benchmark. The oracle spectrum of a nonlinear system is its\n", + "**linearization** at one equilibrium, so it describes the late-time\n", + "approach, not the transient. The neural fit is a short CPU smoke run, not\n", + "a tuned model. This notebook does **not** download METR-LA and does not\n", + "need the `[cantera]` extra." + ] + }, + { + "cell_type": "markdown", + "id": "t55-setup", + "metadata": {}, + "source": [ + "## Setup\n", + "\n", + "Package version, seeds, and two cards: the linear chain\n", + "`reaction_chain_v1` (exact spectrum) and the nonlinear\n", + "`reaction_michaelis_menten_v1` (two conservation laws, boundary\n", + "equilibrium). `nearest_error` matches each oracle eigenvalue to the\n", + "closest estimated one." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "t55-imports", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:21:49.522062Z", + "iopub.status.busy": "2026-10-15T20:21:49.521891Z", + "iopub.status.idle": "2026-10-15T20:21:54.207192Z", + "shell.execute_reply": "2026-10-15T20:21:54.206832Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "koopman_graph 0.15.0\n", + "cards ('reaction_brusselator_v1', 'reaction_cantera_h2o2_v1', 'reaction_chain_v1', 'reaction_michaelis_menten_v1', 'reaction_random_network_v1', 'reaction_van_de_vusse_v1')\n" + ] + } + ], + "source": [ + "from __future__ import annotations\n", + "\n", + "import dataclasses\n", + "import math\n", + "import os\n", + "import warnings\n", + "\n", + "from tqdm.std import TqdmWarning\n", + "\n", + "warnings.filterwarnings(\"ignore\", category=TqdmWarning)\n", + "\n", + "import matplotlib\n", + "\n", + "if os.environ.get(\"PYTEST_CURRENT_TEST\"):\n", + " matplotlib.use(\"Agg\")\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import torch\n", + "\n", + "import koopman_graph\n", + "from koopman_graph import GNNDecoder, GNNEncoder, GraphKoopmanModel\n", + "from koopman_graph.baselines import DMDBaseline\n", + "from koopman_graph.data import GraphSnapshotSequence, MultiTrajectory\n", + "from koopman_graph.datasets import ReactionNetworkBenchmark\n", + "from koopman_graph.datasets.reaction import (\n", + " element_balance_violation,\n", + " equilibrium,\n", + " oracle_spectrum,\n", + ")\n", + "from koopman_graph.training import LossWeights\n", + "\n", + "SEED = 0\n", + "_ = torch.manual_seed(SEED)\n", + "EPOCHS = 40 # CI smoke budget; the Results text describes this run\n", + "\n", + "print(\"koopman_graph\", koopman_graph.__version__)\n", + "print(\"cards\", ReactionNetworkBenchmark.dataset_ids())\n", + "\n", + "\n", + "def nearest_error(estimated: torch.Tensor, oracle: torch.Tensor) -> list[float]:\n", + " estimated = estimated.to(torch.complex128)\n", + " return [float((estimated - target).abs().min()) for target in oracle]\n", + "\n", + "\n", + "def rollout_states(predictor, sequence: GraphSnapshotSequence) -> torch.Tensor:\n", + " first = sequence[0]\n", + " with torch.no_grad():\n", + " predicted = predictor.predict(first, sequence.num_timesteps - 1)\n", + " frames = [first.x] + [snapshot.x for snapshot in predicted]\n", + " return torch.stack([frame.squeeze(-1).to(torch.float64) for frame in frames])" + ] + }, + { + "cell_type": "markdown", + "id": "t55-motivation", + "metadata": {}, + "source": [ + "## Motivation and background\n", + "\n", + "Most graph-dynamics datasets only allow forecast-error comparisons.\n", + "Mass-action networks also come with exact structure: the stoichiometric\n", + "matrix $N$, conservation laws $W$ with $W N = 0$, and the Jacobian\n", + "$J = N\\,\\partial r/\\partial c$ at equilibrium. For a closed system,\n", + "$J$ has one zero eigenvalue per conservation law. The remaining\n", + "eigenvalues are the relaxation rates a learned latent operator should\n", + "recover. Their discrete-time images $e^{\\lambda \\Delta t}$ are what a\n", + "Koopman matrix trained at sample interval $\\Delta t$ can match, and a\n", + "conserved total maps to the eigenvalue $1$.\n", + "\n", + "The cards store these oracles under `oracle`. `compute_card_oracle` and\n", + "`scripts/build_reaction_cards.py --check` keep them in sync with the\n", + "code." + ] + }, + { + "cell_type": "markdown", + "id": "t55-minimal", + "metadata": {}, + "source": [ + "## Minimal example\n", + "\n", + "The chain $S_0 \\to S_1 \\to S_2 \\to S_3$ (rates $1, 0.5, 0.25$) is\n", + "linear, so exact DMD on **raw** concentrations should recover\n", + "$\\{1, e^{-0.25\\Delta t}, e^{-0.5\\Delta t}, e^{-\\Delta t}\\}$ from one\n", + "trajectory. The card's features are log-concentrations, so we switch the\n", + "transform off with `dataclasses.replace(..., transform=None)`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "t55-chain-dmd", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:21:54.208380Z", + "iopub.status.busy": "2026-10-15T20:21:54.208238Z", + "iopub.status.idle": "2026-10-15T20:21:54.213778Z", + "shell.execute_reply": "2026-10-15T20:21:54.213368Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "oracle state equilibrium_from_range_midpoints\n", + "dynamic eigenvalues [-0.25, -0.5, -1.0]\n", + "timescales [4.0, 2.0, 1.0]\n", + "conservation laws 1\n", + "oracle exp(lambda dt) [1.0, 0.939413, 0.882497, 0.778801]\n", + "DMD nearest errors ['0.0e+00', '6.7e-08', '6.9e-08', '5.7e-08']\n" + ] + } + ], + "source": [ + "chain_card = ReactionNetworkBenchmark.load_card(\"reaction_chain_v1\")\n", + "dt = chain_card[\"time_step\"]\n", + "oracle = chain_card[\"oracle\"]\n", + "print(\"oracle state\", oracle[\"state\"])\n", + "print(\"dynamic eigenvalues\", oracle[\"dynamic_eigenvalues_real\"])\n", + "print(\"timescales\", oracle[\"timescales\"])\n", + "print(\"conservation laws\", oracle[\"num_conservation_laws\"])\n", + "\n", + "chain_oracle = torch.tensor(\n", + " [1.0] + [math.exp(r * dt) for r in oracle[\"dynamic_eigenvalues_real\"]],\n", + " dtype=torch.complex128,\n", + ")\n", + "\n", + "chain = ReactionNetworkBenchmark.generate(\n", + " \"reaction_chain_v1\", num_trajectories=8, num_timesteps=48\n", + ")\n", + "chain_raw = dataclasses.replace(chain, transform=None)\n", + "dmd = DMDBaseline(time_step=dt).fit(chain_raw.sequence(0))\n", + "dmd_eigenvalues = dmd.spectrum().eigenvalues\n", + "dmd_error = nearest_error(dmd_eigenvalues, chain_oracle)\n", + "print(\"oracle exp(lambda dt)\", [round(abs(z), 6) for z in chain_oracle.tolist()])\n", + "print(\"DMD nearest errors\", [f\"{e:.1e}\" for e in dmd_error])\n", + "assert max(dmd_error) < 1e-5" + ] + }, + { + "cell_type": "markdown", + "id": "t55-deep-dive", + "metadata": {}, + "source": [ + "## Progressive deep dive\n", + "\n", + "**Feature transform.** The same DMD on the card's log-concentration\n", + "features no longer sees a linear system. `log` makes the chain\n", + "nonlinear, and the floor $10^{-8}$ saturates near-empty species, so the\n", + "eigenvalues move away from the oracle." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "t55-chain-log", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:21:54.214640Z", + "iopub.status.busy": "2026-10-15T20:21:54.214579Z", + "iopub.status.idle": "2026-10-15T20:21:54.217886Z", + "shell.execute_reply": "2026-10-15T20:21:54.217555Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "transform {'kind': 'log_concentration', 'floor': 1e-08}\n", + "DMD on log features, nearest errors [0.028, 0.082, 0.07, 0.134]\n" + ] + } + ], + "source": [ + "log_eigenvalues = DMDBaseline(time_step=dt).fit(chain.sequence(0)).spectrum().eigenvalues\n", + "log_error = nearest_error(log_eigenvalues, chain_oracle)\n", + "print(\"transform\", chain.card[\"transform\"])\n", + "print(\"DMD on log features, nearest errors\", [round(e, 3) for e in log_error])\n", + "assert max(log_error) > 0.05" + ] + }, + { + "cell_type": "markdown", + "id": "t55-neural", + "metadata": {}, + "source": [ + "**Neural operator.** `koopman=\"graph\"` couples species through the\n", + "influence graph (an edge $s \\to t$ when $s$ is a reactant of a reaction\n", + "that changes $t$), so its spectrum is graph-level and needs `edge_index`.\n", + "The default `koopman=\"pernode\"` applies one shared matrix to each node\n", + "and cannot represent the cross-species coupling that sets these modes.\n", + "The fit below uses raw concentrations, 8 trajectories, the CI epoch\n", + "budget, and `koopman_filter_degree=2` so the operator's mixing matches the\n", + "two-hop encoder (otherwise `ReceptiveFieldMismatchWarning`)." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "t55-neural-fit", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:21:54.218727Z", + "iopub.status.busy": "2026-10-15T20:21:54.218664Z", + "iopub.status.idle": "2026-10-15T20:22:04.329875Z", + "shell.execute_reply": "2026-10-15T20:22:04.329362Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "epochs 40, final loss 1.445e-01\n", + "effective operator eigenvalues 8\n", + "neural nearest errors [0.004, 0.005, 0.051, 0.155]\n" + ] + } + ], + "source": [ + "_ = torch.manual_seed(SEED)\n", + "latent_dim = 2\n", + "model = GraphKoopmanModel(\n", + " encoder=GNNEncoder(1, 16, latent_dim),\n", + " decoder=GNNDecoder(latent_dim, 16, 1),\n", + " latent_dim=latent_dim,\n", + " time_step=dt,\n", + " koopman=\"graph\",\n", + " koopman_filter_degree=2, # match the 2-hop GNNEncoder receptive field\n", + ")\n", + "train = MultiTrajectory([chain_raw.sequence(i) for i in range(chain_raw.num_trajectories)])\n", + "history = model.fit(\n", + " train,\n", + " epochs=EPOCHS,\n", + " lr=3e-3,\n", + " loss_weights=LossWeights(reconstruction=1.0, forward=1.0, rollout=1.0),\n", + " rollout_horizon=8,\n", + " rollout_start_seed=SEED,\n", + ")\n", + "model.eval()\n", + "graph = chain_raw.sequence(0)[0]\n", + "neural_spectrum = model.spectrum(\n", + " edge_index=graph.edge_index,\n", + " num_nodes=chain_raw.system.num_species,\n", + " edge_weight=graph.edge_weight,\n", + ")\n", + "neural_eigenvalues = neural_spectrum.eigenvalues.detach()\n", + "neural_error = nearest_error(neural_eigenvalues, chain_oracle)\n", + "print(f\"epochs {EPOCHS}, final loss {history.loss[-1]:.3e}\")\n", + "print(\"effective operator eigenvalues\", neural_eigenvalues.numel())\n", + "print(\"neural nearest errors\", [round(e, 3) for e in neural_error])\n", + "assert neural_eigenvalues.numel() == latent_dim * chain_raw.system.num_species\n", + "assert all(math.isfinite(e) for e in neural_error)" + ] + }, + { + "cell_type": "markdown", + "id": "t55-conservation", + "metadata": {}, + "source": [ + "**Conservation check.** The chain conserves total mass $\\sum_s c_s$\n", + "(one element `M`). `element_balance_violation` returns the drift\n", + "$E\\,(c_t - c_0)$ of a decoded rollout. DMD inherits conservation from\n", + "data that conserve it. A short neural fit does not, and the drift shows\n", + "that even where some eigenvalues look close." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "t55-drift", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:22:04.331145Z", + "iopub.status.busy": "2026-10-15T20:22:04.331077Z", + "iopub.status.idle": "2026-10-15T20:22:04.344561Z", + "shell.execute_reply": "2026-10-15T20:22:04.344239Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DMD max |drift| 3.53e-06, max |error| 3.31e-06\n", + "neural max |drift| 5.83e-01, max |error| 1.03e+00\n" + ] + } + ], + "source": [ + "held_out = chain_raw.sequence(1)\n", + "truth = chain.concentrations[1]\n", + "element_matrix = chain.system.element_matrix\n", + "\n", + "dmd_states = rollout_states(dmd, held_out)\n", + "neural_states = rollout_states(model, held_out)\n", + "dmd_drift = element_balance_violation(dmd_states, dmd_states[0], element_matrix).abs().squeeze(-1)\n", + "neural_drift = element_balance_violation(neural_states, neural_states[0], element_matrix).abs().squeeze(-1)\n", + "\n", + "print(f\"DMD max |drift| {float(dmd_drift.max()):.2e}, max |error| {float((dmd_states - truth).abs().max()):.2e}\")\n", + "print(f\"neural max |drift| {float(neural_drift.max()):.2e}, max |error| {float((neural_states - truth).abs().max()):.2e}\")\n", + "assert float(dmd_drift.max()) < 1e-4\n", + "assert bool(torch.isfinite(neural_drift).all())" + ] + }, + { + "cell_type": "markdown", + "id": "t55-nonlinear", + "metadata": {}, + "source": [ + "**Nonlinear card.** For Michaelis-Menten the card's oracle is the\n", + "linearization at the equilibrium reached from the **midpoint** of the\n", + "initial ranges. Each trajectory has its own conserved enzyme and substrate\n", + "totals, so its oracle must be recomputed with `equilibrium` and\n", + "`oracle_spectrum`. Near the boundary equilibrium ($S = ES = 0$) the\n", + "dynamics are close to linear, so DMD on a late window should recover the\n", + "slow mode. The fast mode has decayed below what the window can resolve;\n", + "DMD then reports a near-Nyquist alias for it (the `UserWarning` below),\n", + "which is a symptom of the unresolved mode, not of the slow one." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "t55-mm", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:22:04.345535Z", + "iopub.status.busy": "2026-10-15T20:22:04.345469Z", + "iopub.status.idle": "2026-10-15T20:22:04.470111Z", + "shell.execute_reply": "2026-10-15T20:22:04.469719Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "card oracle (range midpoint) exp(lambda dt) [0.8825, 0.2865]\n", + "this trajectory's oracle exp(lambda dt) [0.864, 0.2337]\n", + "conservation laws 2\n", + "slow-mode error by window start {0: 0.0952, 16: 0.0961, 32: 0.0479, 48: 0.0007}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/traviskessler/GitHub-Cursor/KoopmanGraph/.claude/worktrees/koopman-graph-pr-66-695880/src/koopman_graph/baselines/dmd.py:152: UserWarning: One or more discrete-time eigenvalues have argument within 0.001 rad of pi (Nyquist phase). Reported frequencies are principal values in cycles per unit time; phase unwrapping does not recover aliases. log(|lambda|) discards sign(Re lambda).\n", + " return compute_spectrum(self._require_operator(), self.time_step)\n" + ] + } + ], + "source": [ + "mm = ReactionNetworkBenchmark.generate(\n", + " \"reaction_michaelis_menten_v1\", num_trajectories=2, num_timesteps=64\n", + ")\n", + "mm_raw = dataclasses.replace(mm, transform=None)\n", + "mm_dt = mm.card[\"time_step\"]\n", + "c0 = mm.concentrations[0, 0]\n", + "own_equilibrium = equilibrium(mm.system, c0)\n", + "own_spectrum = oracle_spectrum(mm.system, own_equilibrium)\n", + "own_discrete = own_spectrum.discrete_eigenvalues(mm_dt)\n", + "card_discrete = [math.exp(r * mm_dt) for r in mm.card[\"oracle\"][\"dynamic_eigenvalues_real\"]]\n", + "print(\"card oracle (range midpoint) exp(lambda dt)\", [round(x, 4) for x in card_discrete])\n", + "print(\"this trajectory's oracle exp(lambda dt)\", [round(abs(z), 4) for z in own_discrete.tolist()])\n", + "print(\"conservation laws\", own_spectrum.num_conservation_laws)\n", + "\n", + "full = mm_raw.sequence(0, graph_encoding=\"species_influence\") # DMD rejects hyperedges\n", + "window_starts = (0, 16, 32, 48)\n", + "slow_errors = []\n", + "for start in window_starts:\n", + " window = GraphSnapshotSequence([full[i] for i in range(start, full.num_timesteps)])\n", + " estimate = DMDBaseline(time_step=mm_dt).fit(window).spectrum().eigenvalues\n", + " slow_errors.append(nearest_error(estimate, own_discrete[:1])[0])\n", + "print(\"slow-mode error by window start\", dict(zip(window_starts, [round(e, 4) for e in slow_errors])))\n", + "assert slow_errors[-1] < 0.005\n", + "assert slow_errors[-1] < slow_errors[0]" + ] + }, + { + "cell_type": "markdown", + "id": "t55-results", + "metadata": {}, + "source": [ + "## Results\n", + "\n", + "Figure 1 (left) places the estimates on the unit disk. Exact DMD on raw\n", + "chain concentrations sits on the oracle points (errors around\n", + "$10^{-7}$, float32 features), including the conservation eigenvalue at\n", + "$1$. DMD on log features misses by up to about $0.13$. The short neural\n", + "fit lands within roughly $0.004$-$0.16$ of individual oracle eigenvalues\n", + "and has twice as many eigenvalues as species (latent width 2 per node).\n", + "\n", + "The middle panel shows why eigenvalues alone are not enough: the DMD\n", + "rollout conserves total mass to about $10^{-6}$, while the neural rollout\n", + "drifts by order $0.1$-$1$ at this budget. The right panel shows the\n", + "Michaelis-Menten slow mode. Its error against the trajectory's own\n", + "linearization stays near $0.1$ while the window includes the transient,\n", + "halves from step 32, and falls below $10^{-3}$ from step 48, where the\n", + "trajectory is close to its equilibrium. The card's midpoint oracle\n", + "($0.8825$) differs from this trajectory's ($0.864$) because the enzyme\n", + "total differs." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "t55-figure", + "metadata": { + "execution": { + "iopub.execute_input": "2026-10-15T20:22:04.471045Z", + "iopub.status.busy": "2026-10-15T20:22:04.470972Z", + "iopub.status.idle": "2026-10-15T20:22:04.731124Z", + "shell.execute_reply": "2026-10-15T20:22:04.730783Z" + } + }, + "outputs": [ + { + "data": { + "image/png": "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LJFKlSqJTqdTGUOjRo1yXKAvKZMnRqffNaHAHxERERG5luaV8suEDgny5uK9MnvzWQkJ9JcRzcsy0OMieARNRFbr8QCDPK4BAZ6U/PXXX1KzZk1DgAfat28v06ZNkzNnzkixYsVSfY+6devKgAEDpGXLlipbqECBAlYDPAgAaoW54e7du5JZNXliEpOCPCEsukxERETkitpWLyTRsYny9q/7Zcp/JyUs0E8GNSnt7MUiRxReXrp0qdSoUUNy5swp9erVkzVr1qQ4PupF9OnTR0qVKqVOVnCScujQIX5ZRA6G5jrAII97QAZPoUKFTIYVLlzY8Jotpk6dquryREVFSaNGjWT9+vVWxx0/frwKAGk37b0yI5MnSgvysGctIiIiIpfVpW4RebdlefX4i1XHZPr6U85eJLJ3kGft2rXSqVMn6du3r+zZs0eeffZZddu/f7/VaV555RVp2LChuir977//SlBQkDz55JMW60gQkX2DPPj/sWct9xAbGyuhoaEmw7TneM0W+L7RbTq6T3/ttddUcy1r0IwLtXy02/nz5zMtk8cQ5GHPWkREREQurW+jEjL0mTLq8djfD8uCreecvUhez67NtT799FNp3ry5CtzA+++/r4qAoovemTNnWpzGvMve6dOnS9asWeWff/6RHj16eP0XRuTIIA+zeNwHetO6deuWyTAUYdZey2wICOGWqZIyee4nMJOHiIiIyF289lQpeRCboJptvfPbfgkJ9FXNucjDMnlQtHPjxo3SpEkTk+HPPPOMbNiwweb53L9/XxWANb9CTUT2g//vgwcP+L9zI1WrVpV9+/ap706DDMqAgAApX16fRuvyzIM8rMlDRERE5PLQGyoKL/esX1RwKDpsyT7568BlZy+W17JbkOfevXsqQJMnTx6T4Xh++bLtX/iwYcMkX7580qxZM6vjoPgnin4a34go/fCfQpfcYWFhXI1uokuXLqrL83nz5qnnqKvz9ddfS5s2bVQ2pDsFee7F+6l79q5FRERE5D6Bng9aV5QONQtJQqJOBi3cLWuPXnP2YnmlNAV5xowZI1myZEnxZl6o07yeB54bX2lOyccff6y68128eLGEh4c7tgAokRdDFg8wg851IOCNrtAXLVokFy5cUI9xQzfpULZsWfn+++9V4WT0koXi9djWItDjNpJq8tyN81H3zOQhIiIich++vj7y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4eG6MmXKqPv58+enOM3zzz+vlt942d54440Mzze9VqxYocuRI4euZMmSumzZsunq1Kmju3LlitXx582bl2zd5smTRxccHKy7f/++Guf8+fPqO6hRo4bJeOvWrcv05d+/f7+uc+fO6neK9/z1119TnSYuLk7XvXt3tcwVKlTQBQUF6caNG5fmcYiMXb16VVevXj31PypVqpQue/bsumXLlrnlSho7dqz6T5UvX17tBwoWLKi2Fe5uyJAhOl9fX12zZs107gr7MmxP8fuqVauW+q39+++/Onf9PkJCQnTVqlXTFS1aVO0bV65cqXN1x48f17300ktqeX18fHQ//PBDsnFwXDJo0CC179D2IUOHDtW5mhs3buiGDRumK1CggPouXn/99WTj/Pnnn7qqVauqcbRjr5EjRzpleT3BiBEjTH4Xr7zyislxrCew5XcFkydPVq9jX4P7du3a6WJiYnTuKjY2Vvfuu++qc6iKFSvqChUqpCtevLhuzZo1JuPdu3dP7YfCwsJ0ZcuWVfczZ87UuTN8ptdee02dU+D4P3fu3Op73blzp8l4//33ny5fvnxqm4/1VKlSJbucoznL8OHD1XFGkyZNkr2G/4Txfx/7CHf/79esWVN9l8bne+bnSxcuXNBVr15d/Tbwf8D3/vfff6fpfbwqyNOwYUP1A8IGBXDwkDNnTl1kZGSGpknPfNNj9+7d6uBo8eLFhhOkIkWKqIO+lIJCxhuLHTt2qJ3C1KlTkwV5cJJub7169VJ/VARl4Pvvv9cFBAToTpw4kWKQ59VXX830+aYHgjlZsmTRffzxx+p5VFSUrnbt2rrWrVvbPA9snBAgQkBEowV5Dh8+rLO3n376SQWecEBha5Dnk08+URsYbaeCnS82yMYbHFvGITLWpk0bddKtBarHjx+vToYuX77sVisqPj5e98477+hu3rxpGPbBBx+45Wcx9vvvv6sDzueee85tgzwIpGN7ixMhbK8B38nPP/+sczd//PGH2mZv2rTJMAwHvAheJSQk6FwZAlHTp09X/3UcqFsK8uB17F/37dunnm/fvl2Na68LNhk5Fvvss890169fVwfrlk7Gv/32W93evXsNzzdv3qw+y+zZsx28tO4PxyxYd9u2bTNcqMIJvvFxrCew5Xe1ZcsWdR6wfPly9fzixYsqKDRq1Cidu8K50pgxYwznTNiW4bwm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CJEGSOQRQgghRL7gvffecx9++GGe5mHhwoXu559/PuJ2b7/9ttuyZUuu5EkIIdKJrVu3uhkzZuQ4HcrqqVOnumOdr776yq1ZsyZP87Bp0ya3YsWKPM2D+H8k8gghhBAi11m5cqVbv3591Lrhw4e7sWPH5mmeunbt6ooUKXLEbTds2OC6dOmSK/kSQgjPL7/84iZPnmwfBI4FCxa4L7/80h06dCjTbefOnZvht4MHD7opU6bY7//++2+W084JH3zwgevUqVOO0/nss8/c7bff7vIDP/30k5s5c2aup/fff/+5Vq1aub/++itpaWaHggULWj5++OGHo5K+yBoSeYQQQgiR6wwdOtS9/PLLUevq1Knjqlevnmd34+GHH3a9evVyJ5988hG3vfvuu02kWrp0aa7kTQghANHltttuc6+99pp12EePHu2aNm3qzjnnHPseb9uWLVu6b7/9Nuo3BJxbb73Vft+5c2eW084JZcuWdbfcckta3dD333/fde7cOdfTe+mll9wZZ5zhGjdunLQ0s0OpUqVc27Zt3YABA45K+iJrnJDF7YUQQgghcjyKi7n+3r17bcQYmjVrZgJPWGBZvny5NV4rVKjgPvroIxttrlevnjv11FPdH3/84VatWuUKFy7sateu7U44IbpJEwSBiTBMqWL/yy677LB5+uSTT8zcfc6cOVHrN27caFY7pUuXdpdffrkrUKCArT/ppJNcu3bt3KhRo1yDBg30RAghcpWRI0e6c889N1LeTZo0yd1xxx1WriJWh6lbt66J6oMGDYoSByhPKWdzkrYHyx/SK1GiRMQyknK6RYsWEYsTpmghGiEI3HTTTZF9sf74+OOPbR3WOZTbVatWdeXLl89wHMrp3377zX4/3PQlyu1ixYq5q6++Oqp+yEo+41l1Ioj5acVXXXWVbYMFFNON2dfXaRdffLErU6aMW7JkiS2fcsop7oILLnCXXHJJVHr+3G+88UY7N+pG0o2X3qWXXpohP88++6zr1q1btvPo0+S469atszr3yiuvdKeffnrcPFJXcn+qVatmYl2YDh06uIYNG9ogzplnnpnp/RG5QCCEEEIIkYuMGTMmKFOmTHDBBRcE7dq1s8+WLVuC1q1bB/fee29kuyZNmgTVqlULypUrFzRv3jwoX758UKFCheCll16y76wrW7ZscO211wYHDx6M7Pfzzz8H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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axes = plt.subplots(1, 3, figsize=(12.0, 3.6))\n", + "theta = torch.linspace(0, 2 * math.pi, 200)\n", + "ax = axes[0]\n", + "ax.plot(torch.cos(theta), torch.sin(theta), color=\"0.8\", linewidth=1)\n", + "ax.scatter(chain_oracle.real, chain_oracle.imag, s=90, facecolors=\"none\", edgecolors=\"black\", label=\"oracle\")\n", + "ax.scatter(dmd_eigenvalues.real, dmd_eigenvalues.imag, marker=\"x\", label=\"DMD raw\")\n", + "ax.scatter(log_eigenvalues.real, log_eigenvalues.imag, marker=\"+\", label=\"DMD log\")\n", + "ax.scatter(neural_eigenvalues.real, neural_eigenvalues.imag, marker=\".\", label=\"graph Koopman\")\n", + "ax.set_xlim(-0.1, 1.15)\n", + "ax.set_ylim(-0.6, 0.6)\n", + "ax.set_aspect(\"equal\")\n", + "ax.set_title(\"chain: exp(lambda dt)\")\n", + "ax.legend(fontsize=7, loc=\"lower left\")\n", + "\n", + "ax = axes[1]\n", + "ax.semilogy(chain.times, dmd_drift.clamp(min=1e-12), label=\"DMD\")\n", + "ax.semilogy(chain.times, neural_drift.clamp(min=1e-12), label=\"graph Koopman\")\n", + "ax.set_xlabel(\"time (s)\")\n", + "ax.set_title(\"|mass drift| of rollout\")\n", + "ax.legend(fontsize=7)\n", + "\n", + "ax = axes[2]\n", + "ax.plot(window_starts, slow_errors, marker=\"o\")\n", + "ax.set_xlabel(\"DMD window start (step)\")\n", + "ax.set_title(\"MM slow-mode error\")\n", + "fig.suptitle(\"Figure 1. Estimates against card / trajectory oracles\")\n", + "fig.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "t55-interpretation", + "metadata": {}, + "source": [ + "## Interpretation / discussion\n", + "\n", + "The oracle is a property of the generating mechanism, so it tests the\n", + "**identification** a model performs, not just its forecasts. On a linear\n", + "network with raw features, exact DMD is the reference estimator. If a\n", + "learned operator cannot match it there, the problem is the model or the\n", + "training, not the data.\n", + "\n", + "Feature choices change what \"correct\" means. Log-concentration features\n", + "help when concentrations span decades (the Cantera card), but they turn a\n", + "linear chain into a nonlinear observable, and the floor flattens empty\n", + "species. Compare against the oracle in the coordinates where the oracle\n", + "holds.\n", + "\n", + "For nonlinear networks the oracle spectrum is a local linearization. It\n", + "matches late-time relaxation near one equilibrium, and each trajectory's\n", + "conserved totals select a different equilibrium. The card value is the\n", + "reference at the range midpoint; per-trajectory comparisons should\n", + "recompute it with `equilibrium` and `oracle_spectrum`. Fast modes decay\n", + "within a few samples and are poorly resolved at the card's $\\Delta t$.\n", + "\n", + "Conservation is a separate check. Close eigenvalues do not imply a\n", + "conservative rollout, and `element_balance_violation` catches the\n", + "difference cheaply." + ] + }, + { + "cell_type": "markdown", + "id": "t55-takeaways", + "metadata": {}, + "source": [ + "## Takeaways\n", + "\n", + "- **When to use.** Use the card oracles to check whether a learned\n", + " operator recovers kinetic timescales and conservation, alongside\n", + " forecast error.\n", + "- **Coordinates.** The oracle applies to raw concentrations. The card's\n", + " log transform is a modelling convenience, not oracle coordinates.\n", + "- **Operator choice.** Graph-level modes need a graph-coupled operator\n", + " (`koopman=\"graph\"`, spectrum with `edge_index`). `koopman=\"pernode\"`\n", + " shares one matrix across nodes.\n", + "- **Nonlinear cards.** Recompute the oracle at each trajectory's own\n", + " equilibrium. The card value is for the range midpoint.\n", + "- **Gotchas.** `DMDBaseline` rejects hyperedge sequences; pass\n", + " `graph_encoding=\"species_influence\"`. The neural fit here is a short\n", + " smoke run. Its drift shows it is not converged and says nothing about\n", + " tuned models." + ] + }, + { + "cell_type": "markdown", + "id": "t55-reading", + "metadata": {}, + "source": [ + "## Further reading\n", + "\n", + "- Sphinx: [api](../docs/source/api.rst) (`ReactionNetworkBenchmark`,\n", + " `koopman_graph.datasets.reaction`), [faq](../docs/source/faq.rst),\n", + " [installation](../docs/source/installation.rst) (`[reaction]`,\n", + " `[cantera]` extras)\n", + "- Feinberg (2019), *Foundations of Chemical Reaction Network Theory*,\n", + " Springer ([doi:10.1007/978-3-030-03858-8](https://doi.org/10.1007/978-3-030-03858-8))\n", + "- Schmid (2010), *J. Fluid Mech.* 656, 5-28\n", + " ([doi:10.1017/S0022112010001217](https://doi.org/10.1017/S0022112010001217);\n", + " dynamic mode decomposition)\n", + "- Goodwin et al., Cantera 3.2.0\n", + " ([doi:10.5281/zenodo.17620923](https://doi.org/10.5281/zenodo.17620923);\n", + " for the `reaction_cantera_h2o2_v1` card)\n", + "- Example [07_koopman_spectrum.ipynb](07_koopman_spectrum.ipynb)\n", + "- Example [44_graphvamp_md.ipynb](44_graphvamp_md.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "koopmangraph", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.14" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/koopman_graph/datasets/reaction/benchmark.py b/src/koopman_graph/datasets/reaction/benchmark.py index d8b3fc9..9a1d9af 100644 --- a/src/koopman_graph/datasets/reaction/benchmark.py +++ b/src/koopman_graph/datasets/reaction/benchmark.py @@ -185,7 +185,11 @@ def features(self, index: int, *, dtype: torch.dtype = torch.float32) -> Tensor: return values.unsqueeze(-1).to(dtype) def sequence( - self, index: int, *, dtype: torch.dtype = torch.float32 + self, + index: int, + *, + dtype: torch.dtype = torch.float32, + graph_encoding: GraphEncoding | None = None, ) -> GraphSnapshotSequence: """Return one trajectory as a species-node snapshot sequence. @@ -195,6 +199,10 @@ def sequence( Trajectory index in ``[0, num_trajectories)``. dtype : torch.dtype, optional Feature dtype. Default is ``torch.float32``. + graph_encoding : {"species_influence", "reaction_hyperedge"} or None + Override the card's encoding, e.g. ``"species_influence"`` to + drop ``hyperedge_index`` for consumers that reject hyperedges. + Default ``None`` uses :attr:`graph_encoding`. Returns ------- @@ -209,12 +217,21 @@ def sequence( ------ IndexError If ``index`` is out of range. + ValueError + If ``graph_encoding`` is not a known encoding. """ + encoding = self.graph_encoding if graph_encoding is None else graph_encoding + if encoding not in ("species_influence", "reaction_hyperedge"): + msg = ( + "graph_encoding must be 'species_influence' or " + f"'reaction_hyperedge', got {graph_encoding!r}" + ) + raise ValueError(msg) self._check_index(index) edge_index, edge_weight = species_influence_graph(self.system) hyperedge_index = ( reaction_hyperedge_index(self.system) - if self.graph_encoding == "reaction_hyperedge" + if encoding == "reaction_hyperedge" else None ) features = self.features(index, dtype=dtype) diff --git a/tests/datasets/test_reaction_benchmark.py b/tests/datasets/test_reaction_benchmark.py index ddb1fe1..e2671fb 100644 --- a/tests/datasets/test_reaction_benchmark.py +++ b/tests/datasets/test_reaction_benchmark.py @@ -261,6 +261,13 @@ def test_sequence_layout_and_encodings() -> None: assert not hasattr(raw.sequence(0)[0], "hyperedge_index") with pytest.raises(IndexError, match="out of range"): raw.sequence(5) + plain = dataset.sequence(1, graph_encoding="species_influence") + assert not hasattr(plain[0], "hyperedge_index") + assert torch.equal(plain[0].x, snapshot.x) + with_hyper = raw.sequence(0, graph_encoding="reaction_hyperedge") + assert with_hyper[0].hyperedge_index.shape[0] == 2 + with pytest.raises(ValueError, match="graph_encoding must be"): + raw.sequence(0, graph_encoding="bipartite") # type: ignore[arg-type] def test_cstr_controls_are_piecewise_constant_and_in_range() -> None: diff --git a/tests/package/test_notebooks_v015_guides.py b/tests/package/test_notebooks_v015_guides.py index 8144aa7..4001b3a 100644 --- a/tests/package/test_notebooks_v015_guides.py +++ b/tests/package/test_notebooks_v015_guides.py @@ -1,4 +1,4 @@ -"""Honesty locks for examples 48–49 and 51–54 (guides; no telemetry download).""" +"""Honesty locks for examples 48–49 and 51–55 (guides; no telemetry download).""" from __future__ import annotations @@ -84,6 +84,17 @@ "does not download metr-la", ), ), + "55_reaction_network_oracles.ipynb": ( + "# Reaction-network oracles: recovering kinetic timescales", + ( + "ReactionNetworkBenchmark", + "element_balance_violation", + "not a production kinetics benchmark", + "linearization", + "own equilibrium", + "does not download metr-la", + ), + ), } @@ -114,7 +125,7 @@ def _notebook_text(path: pathlib.Path) -> str: def test_v015_guide_notebooks_exist_with_scientific_arc() -> None: - """Examples 48–49 and 51–54 must exist and follow the scientific arc.""" + """Examples 48–49 and 51–55 must exist and follow the scientific arc.""" for name, (title, _needles) in _NOTEBOOKS.items(): path = _PROJECT_ROOT / "examples" / name assert path.is_file(), f"missing {name}"