Skip to content

Reaction-network oracles example notebook (#65) - #75

Merged
tjkessler merged 4 commits into
mainfrom
feature/reaction-notebook
Oct 15, 2026
Merged

tjkessler merged 4 commits into
mainfrom
feature/reaction-notebook

Conversation

@tjkessler

Copy link
Copy Markdown
Owner

Closes #65 once the stack merges. This is the last planned piece. Stacked on #74 (→ #73 → #72 → #71 → #70 → #69). Merge in order #69 → … → #74 → this one. Each PR retargets to main when the one below it merges, and CI starts then.

Changes

examples/55_reaction_network_oracles.ipynb follows the repo's scientific arc (Setup → … → Further reading), with outputs committed. It checks estimators against the ReactionNetworkBenchmark card oracles, with every claim asserted in the notebook:

Check Result (asserted)
Exact DMD on raw reaction_chain_v1 concentrations vs oracle exp(λΔt) max error 6.9e-8 (< 1e-5), including the conservation eigenvalue 1
DMD on the card's log-concentration features misses by up to 0.134 (> 0.05): log makes the linear chain a nonlinear observable
40-epoch GraphKoopmanModel(koopman="graph", koopman_filter_degree=2) within 0.004–0.155 of individual oracle eigenvalues; 8 = 2 × 4 eigenvalues
element_balance_violation on held-out rollouts DMD drift 3.5e-6 (< 1e-4); neural drift 0.58, showing the short fit hasn't learned conservation
Michaelis-Menten late-window DMD vs the trajectory's own equilibrium linearization slow-mode error 0.095 → 0.0007 as the window moves to step 48 (< 0.005)

Each finding is spelled out in the notebook:

  • The oracle applies in raw-concentration coordinates.
  • koopman="pernode" can't represent cross-species coupling, so the fit uses koopman="graph" (its spectrum needs edge_index).
  • A nonlinear card's oracle is a linearization at one equilibrium. Each trajectory's conserved totals pick a different one: the card's midpoint gives 0.8825 and this trajectory 0.864.
  • The fast Michaelis-Menten mode is unresolved at the card's Δt, and DMD reports a near-Nyquist alias for it (the remaining UserWarning).
  • The neural fit is a CPU smoke run, not a tuned model.

The notebook doesn't download data and doesn't need [cantera].

Registration

  • CI: added to the PR notebooks (smoke) list, and the full shard widens from 27-54 / 5[0-4] to 27-55 / 5[0-5].
  • docs/source/tutorials.rst: new table row.
  • tests/package/test_notebooks_v015_guides.py: honesty-lock entry pinning the title, the arc headings, and the needles ReactionNetworkBenchmark, element_balance_violation, not a production kinetics benchmark, linearization, own equilibrium, and no METR-LA download.

Small API addition: ReactionDataset.sequence(index, *, graph_encoding=None) overrides the card's encoding. DMDBaseline rejects hyperedge sequences, so reaction_michaelis_menten_v1 (hyperedge card) needs graph_encoding="species_influence". A test covers it.

Verification (macOS arm64, Python 3.13)

  • OMP/MKL/OPENBLAS/TORCH_NUM_THREADS=1 pytest --nbmake examples/55_reaction_network_oracles.ipynb: passed in 17.7 s.
  • The honesty-lock test passes.
  • ruff check and ruff format --check on src/ tests/ scripts/ pass.
  • Full suite -m "not slow and not distributed and not ray" --cov-fail-under=90: 3516 passed, 26 skipped, 97.30%.
  • sphinx-build -W --keep-going passes.
  • Not checked: the Ubuntu notebook job's runtime. It runs once this PR retargets to main.

🤖 Generated with Claude Code

Refs #65. examples/55_reaction_network_oracles.ipynb (scientific arc,
executed outputs) checks estimators against ReactionNetworkBenchmark card
oracles:

- exact DMD on raw chain concentrations recovers exp(lambda dt) (~1e-7)
  and its rollout conserves mass (~1e-6);
- DMD on the card's log features misses by up to ~0.13;
- a 40-epoch koopman="graph" fit (koopman_filter_degree=2) is within
  ~0.004-0.16 of oracle eigenvalues but drifts ~0.6 in mass, which
  element_balance_violation flags;
- late-window DMD recovers the Michaelis-Menten slow mode against the
  trajectory's own equilibrium linearization (7e-4 from step 48).

Registered in the PR notebook smoke list and the full 27-55 shard, the
tutorials table, and the guide honesty-lock test. Adds
ReactionDataset.sequence(graph_encoding=) so hyperedge cards can feed
DMDBaseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tjkessler
tjkessler added this pull request to stack #76 October 15, 2026 20:43
tjkessler and others added 3 commits October 15, 2026 17:01
Carries the reviewed #69-#74 fixes up to #75 and clears its conflict.
benchmark.py: keep the graph_encoding validation in
ReactionDataset.sequence and use #74's _check_index helper. CHANGELOG:
keep the notebook / graph_encoding entries and #74's eigenvalue_timescales
and Cantera SHA-256 entry (updated for the optional zero_tolerance).

The notebook re-executed on the merged code prints the same numbers as
its committed outputs, so the outputs are left unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/koopman_graph/datasets/reaction/benchmark.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Base automatically changed from feature/reaction-benchmark to main October 15, 2026 21:36
@tjkessler
tjkessler merged commit 298abd5 into main Oct 15, 2026
13 checks passed
@tjkessler
tjkessler deleted the feature/reaction-notebook branch October 15, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Mass-action reaction-network datasets (koopman_graph.datasets.reaction)

1 participant