Skip to content

Releases: tjkessler/KoopmanGraph

v0.16.0

Choose a tag to compare

@tjkessler tjkessler released this 15 Oct 22:05
c2f9c34

Mass-action reaction-network datasets under
koopman_graph.datasets.reaction, with exact oracle references
(equilibria, conservation laws, Jacobian spectra and timescales) for
checking whether a learned latent operator recovers kinetic timescales
and respects conservation. ReactionNetworkBenchmark is the only new
name in koopman_graph.datasets; the root __all__, homogeneous
scientific defaults, and the linear latent operator contract are
unchanged (koopman=None still selects "pernode"). SciPy and Cantera
stay optional behind the new [reaction] / [cantera] extras.
FORMAT_VERSION stays 1.

Added

  • koopman_graph.datasets.reaction subpackage (pure PyTorch unless an
    optional extra is used) with the modules below and packaged FAIR cards
    under reaction/data/. Its names are exported from the subpackage;
    only ReactionNetworkBenchmark is added to koopman_graph.datasets,
    and the root __all__ is unchanged.

  • koopman_graph.datasets.reaction.system: frozen ReactionSystem
    (reactant / product stoichiometry, mass-action rates and right-hand side,
    stoichiometric matrix, linearity check, optional element matrix and
    per-reaction ArrheniusParams, at_temperature, dict round trip) and
    check_element_balance, which reports per-reaction element residuals
    (open-system source / sink reactions show up as unbalanced). Stored
    tensors are owned copies but not write-protected; treat them as
    read-only.

  • koopman_graph.datasets.reaction.transform: LogConcentrationTransform
    (floored log c, its inverse, a below-floor mask, and a serializable
    record of the floor) and element_balance_violation for element-total
    drift from a reference state.

  • koopman_graph.datasets.reaction.graphs: species_influence_graph
    (directed species graph matching the mass-action Jacobian's sparsity,
    weighted by linking-reaction count), reaction_hyperedge_index (one
    hyperedge per reaction), reaction_directed_hyperedges (reactant tail /
    product head incidences), and species_reaction_bipartite (PyG
    HeteroData with stoichiometric edge weights).

  • koopman_graph.datasets.reaction.integrate: exact augmented
    matrix-exponential propagation for linear systems (integrate_expm,
    linear_rate_equations), batched and differentiable torch RK4
    (integrate_rk4), SciPy BDF / Radau / LSODA with an exact mass-action
    Jacobian behind a lazy require_scipy() guard (integrate_stiff;
    [reaction] extra), the integrate_reaction_system dispatcher
    (method="auto"), and mass_action_jacobian.

  • koopman_graph.datasets.reaction.catalog: reference systems with frozen
    default parameters (first_order_chain, reversible_dimerization,
    michaelis_menten, brusselator, lotka_volterra). Closed systems carry
    an element matrix.

  • koopman_graph.datasets.reaction.oracles: conservation_laws (orthonormal
    left nullspace of N), stoichiometric_rank, equilibrium (exact for
    linear systems, damped non-negative Newton within the compatibility
    class otherwise), and oracle_spectrum / oracle_timescales /
    OracleSpectrum. These give the Jacobian, dynamic eigenvalues with the
    conservation zero modes removed, timescales -1/Re(λ), and flow-map
    eigenvalues exp(λ Δt) to compare with a learned discrete operator.

  • koopman_graph.datasets.reaction.random_network: sample_random_network
    builds seeded, element-balanced mass-action networks. Species
    compositions are sampled first, so every candidate reaction conserves
    elements; reaction order is capped at 2 (max_order=1 gives linear
    dissociation networks); rates are log-uniform. The returned
    SampledReactionNetwork records the seed and every sampler parameter.

  • koopman_graph.datasets.reaction.cstr: van_de_vusse_cstr /
    VanDeVusseCSTR, a Van de Vusse CSTR with Klatt & Engell (1998)
    Arrhenius kinetics. Reactor temperature and dilution rate are inputs,
    either constant or piecewise-constant schedules. It provides the
    controlled right-hand side, RK4 simulation, and a Newton steady state; the
    nominal point (114.2 °C, F/V = 14.19 1/h) gives c_A ≈ 2.14,
    c_B ≈ 1.09.

  • koopman_graph.datasets.reaction.gillespie: seeded Gillespie direct-method
    SSA (gillespie_ssa, SSATrajectory) with mass-action propensities
    (falling factorials, volume scaling) that match the ODE rates, plus
    last-value-hold binning onto a grid (bin_to_grid).

  • koopman_graph.datasets.reaction.cantera_io (lazy [cantera] boundary):

    • load_cantera_mechanism converts a Cantera gas mechanism (default the
      bundled h2o2.yaml, read from the installed package) to a mass-action
      ReactionSystem at a reference (T, P, X). Reversible reactions are
      split into forward and reverse. Elementary and mass-action three-body
      reactions convert exactly: [M] is expanded into one reaction per
      collider with rate k ε_s.
    • Falloff and other state-dependent rates are frozen at the reference
      state, skipped, or rejected (state_dependent=); frozen rates with a
      mass-action third body keep the per-collider [M] expansion.
      Reactions with non-mass-action orders are skipped or rejected
      (orders equal to the stoichiometry convert normally). Rate constants
      are read with Cantera's legacy rate-constant mode off, whatever the
      process setting. Duplicate reactions get unique names. Every frozen or
      skipped reaction is listed in CanteraProvenance, which also records
      the Cantera version, mechanism path and SHA-256, the reference state,
      the "illustration only" caveat, and the Cantera citation DOI.
    • simulate_cantera_reactor runs constant-pressure or constant-volume
      ideal-gas reactors, adiabatic or isothermal.
    • Also: require_cantera, resolve_mechanism_path (bare names prefer
      Cantera's bundled data over the working directory), and
      mechanism_sha256.
  • [reaction] extra (scipy>=1.11.0) for stiff reaction-network solvers
    and [cantera] extra (cantera>=3.2,<3.3) for Cantera mechanisms.

  • cantera pytest marker; marked tests are skipped automatically when the
    [cantera] extra is not installed.

  • CI test jobs and the release verify job install [reaction] and
    [cantera], so cantera-marked tests run there.

  • tests/test_import_hygiene.py: import koopman_graph must not load
    SciPy, Cantera, or torchdiffeq.

  • ReactionNetworkBenchmark (exported from koopman_graph.datasets and
    koopman_graph.datasets.reaction): card-defined, seeded reaction-network
    datasets.

    • Six packaged FAIR JSON cards under reaction/data/:
      reaction_chain_v1, reaction_michaelis_menten_v1,
      reaction_brusselator_v1, reaction_random_network_v1,
      reaction_van_de_vusse_v1 (piecewise-constant temperature /
      dilution-rate controls), and reaction_cantera_h2o2_v1 ([cantera]).
      Each card records the generator, simulator, time grid, seed,
      initial-condition ranges, log floor, graph encoding, oracle references
      (equilibrium, dynamic eigenvalues, timescales, conservation laws),
      units, license, limitations, and Cantera provenance.
    • generate returns a ReactionDataset (raw float64 concentrations,
      optional controls, per-trajectory GraphSnapshotSequence with species
      nodes, timestamps, and global control_inputs), with an optional
      Gillespie simulator="ssa". Also: deterministic trajectory split, and
      versioned save / load payloads (weights_only loading).
    • compute_card_oracle and scripts/build_reaction_cards.py (with
      --check) regenerate the oracle sections; tests recompute them to catch
      drift.
  • 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

  • STGODEBaseline now imports torchdiffeq on first fit / predict instead
    of at module import, so import koopman_graph with [baselines-ode]
    installed no longer loads SciPy. A missing torchdiffeq is no longer
    cached: installing the extra mid-session takes effect on the next call.
  • uv.lock relocked; it was missing extras already declared in
    pyproject.toml (export, control-lmi, ...).

Fixed

  • conservation_laws returns a canonical basis (Gram-Schmidt in species
    order on the basis-independent projector) instead of whatever an SVD
    returns. With two or more conservation laws the SVD basis differed
    between LAPACK builds, so the Michaelis-Menten, random-network, and
    Cantera cards did not reproduce on Linux CI. Card oracle values change
    only at rounding level (<= 3e-14) apart from the rotated laws.

  • equilibrium no longer returns a clamped Newton stall that is not
    stationary. It now requires |dc_s/dt| <= 1e-6 · gross turnover_s + 1e-12 · (peak initial turnover) and otherwise raises RuntimeError.
    Previously the converted Cantera h2o2 system could report a
    near-boundary point with one-way flux as its equilibrium.

v0.15.0

Choose a tag to compare

@tjkessler tjkessler released this 21 Aug 13:00
48bf83c

Integration increment on the 0.14 stack: opt-in closed-form
identification, identity-bound benchmark manifests, polynomial graph
filters, Nyquist / conditioning diagnostics, and labeled research MVPs
(graph-state closure, cochain dynamics, matrix-free algebra,
residual-tube MPC). Homogeneous scientific defaults and the linear
latent operator contract are unchanged (koopman=None still selects
"pernode"). FORMAT_VERSION stays 1.

Added

  • README Highlights for opt-in identification (closed-form $K$; default
    Adam fit unchanged; rank grid is not Ray Tune) and identity-bound
    benchmarks (koopman-graph benchmark run / verify; the runner does
    not train or invent MAE / RMSE; not a LibCity / BasicTS host). Featured
    tutorials list examples 47 and 48. Related software names PyDMD and
    kooplearn as flat-vector peers.
  • paper.bib method keys for the post-0.14 catalog:
    Guo2025ModularEDMD, LibCity2021, BasicTS2024, kooplearn2026,
    PyKoopman2024 (same work as Pan2024), and PyDMD2018. Existing
    method keys remain cited in source or Sphinx pages. No invented
    forecast numbers.
  • Sphinx guides for identity-bound benchmarks, opt-in identification,
    spectral diagnostics, predicted graph dynamics, matrix-free linear
    operators, the spectral-gap criticality monitor, and time /
    parameter conditioning (docs/source/benchmarks.rst,
    identification.rst, spectral_diagnostics.rst,
    graph_dynamics.rst, matrix_free.rst, criticality.rst,
    time_conditioning.rst). Narrative only; defaults and
    FORMAT_VERSION stay 1. No telemetry download.
  • Examples 48 and 51–54: identification report plus residual-aware
    reject of a polluted RMSE-only dictionary; non-normal / Nyquist
    SpectralDiagnostics toys; cycle Hodge harmonic split; latent-rank
    recovery on a linear Gaussian embedding; closing-gap criticality
    score (not a certificate). Teaching-thin; no METR-LA download.
  • Optional SpectralDiagnostics on KoopmanSpectrum (κ(V) after
    column normalization, per-mode Wilkinson κ_i, Frobenius departure
    from normality and a scale-free relative variant, Nyquist frequency
    1/(2Δt) in cycles per unit time on discrete spectra, per-mode
    aliasing flags, and sign(Re λ)). Populated by compute_spectrum /
    compute_generator_spectrum (nyquist_frequency is None on
    generators). Discrete compute_spectrum emits one UserWarning when
    any mode is Nyquist-adjacent. implied_timescales carries the same
    flag without changing the |λ| validity window. Not a
    finite-horizon stability certificate, not a sampling-theorem
    identification result, and not on the root façade.
    mode_amplitudes warns when κ(V) exceeds CONDITION_WARN
    (1e6) and raises DefectiveSpectrumError (a LinAlgError) when
    V is singular, with a Schur-subspace hint rather than a bare
    RuntimeError. matrix_log(..., defective="error") (default) raises
    the same error on Jordan / singular eigenbases instead of inverting
    V; defective="schur" uses SciPy logm (CPU; Al-Mohy–Higham).
    Neither path claims that defectivity marks every critical regime.
    monitor_critical_transition scores sliding-window spectral-gap
    closure and near-defectivity on a sequence of spectra (positive rate
    means the gap shrank). Diagnostic only — not a Ghosh-grade
    topology-criticality certificate, and not on the root façade.
  • Discrete koopman="graph" accepts koopman_filter_degree (default
    1, the one-tap I⊗K_self + Â⊗K_nbr map). P=0 is self only;
    P>1 is an opt-in monomial sum_k Â^k ⊗ K_k with globally shared
    extra hops. Dual random-walk remains an extra direction, not an extra
    hop. P=1 checkpoints and forwards stay bit-identical. Block-diagonal
    inverse and distributed inverse / Arnoldi require P=1; dense inverse
    uses the assembled polynomial. Eligible discrete spectrum uses
    Kronecker eig(B(λ_i)) with B(λ)=Σ_k λ^k K_k for any P>=0
    (not a sum of independent factor eigenvalues). Dual / orbit stay
    dense; continuous-graph Kronecker remains one-tap. The helper raises
    ValueError for dual adjacency; operator .spectrum still
    dense-routes. Kronecker still does not invert or cheapen
    eig-regularization. This does not
    attribute the example-38 path-diffusion gap (hold-out MSE approximately
    0.71 versus 0.019) to hop order.
  • GraphKoopmanModel.fit warns
    (ReceptiveFieldMismatchWarning, off the root façade) when a
    topology-aware encoder mixes more hops than discrete graph
    filter_degree. GCN/GAT/SAGE/Transformer stacks count one hop per
    layer; DiffConv counts num_layers * diffusion_steps. Encoder
    neighborhood mixing does not compensate for a one-hop Koopman
    factor. The check is warn-only and skips operators without
    receptive_field_hops.
  • Opt-in GraphKoopmanModel.fit(..., batch_graphs=True) collates
    independent homogeneous trajectories into one PyG Batch so shared
    K applies to the disconnected union with per-graph shifts.
    Reconstruction (and forward consistency when weighted) match the mean
    of the existing per-sequence MultiTrajectory loop on modest
    batches. The default Python loop is unchanged. This is vectorization,
    not a new multi-topology capability. Collate types stay off the root
    façade.
  • Example 38 adds a hop-matched degree-P arm (P in {0, 1, 2}, 40
    epochs) on the same path-diffusion surrogate as the historical one-tap
    versus joint least-squares comparison (80 epochs, unchanged numbers).
    Example 49 checks Kronecker polynomial spectrum against dense K_eff
    on a tiny P=2 path and exercises the hop-mismatch warning. Neither
    notebook attributes the historical hold-out MSE gap (approximately
    0.71 versus 0.019) to hop order.
  • koopman_graph.identification closed-form ridge / TLS / constrained
    least-squares solvers and opt-in
    GraphKoopmanModel.fit(..., identification=IdentificationConfig(...))
    (off the root façade). Default identification=None keeps the Adam
    path and does not import the package. Alternating fit freezes the
    encoder, writes dense per-node K, then takes encoder/decoder Adam
    steps. Discrete dense KoopmanOperator only; graph / hetero /
    continuous / controlled / delay / windowed / DDP layouts raise.
    solver="varpro" raises NotImplementedError. After an
    identification fit, model.identification_report holds one-step and
    short-rollout latent mean squared error (MSE) plus ρ(K). That
    record is not a Haseli–Cortés, ResDMD, or Lyapunov certificate, and
    is not ResKoopNet residual training.
  • Finite-sample subspace invariance leakage η via
    koopman_graph.identification.subspace_invariance_report (off the
    root façade) and opt-in evaluate(..., include_invariance=True) /
    GraphKoopmanModel.subspace_invariance_report. Default evaluate
    MAE / RMSE / MAPE are unchanged. The ratio is a truncated-SVD
    projection residual on encoded samples, not a Haseli–Cortés
    invariance-proximity certificate (HaseliCortes2023). Discrete
    dense per-node K only; graph / hetero / continuous / delay /
    controlled layouts raise. Closed-form fit still does not fill
    IdentificationReport.invariance.
  • Residual-aware dictionary selection
    (koopman_graph.identification.select_resdmd_gated, off the root
    façade) and opt-in ResDMDFitCallback(mode="gate"). Lowest train
    one-step mean squared error (MSE) wins unless the gate first drops
    candidates whose max finite-dictionary ResDMD residual exceeds
    1e-2 (same default as resdmd).
    IdentificationConfig.gate_resdmd=True fills
    IdentificationReport.spectral on the final identification fit;
    it does not abort training. Default callback mode remains
    "observe". This is not a certified infinite-dimensional residual
    bound.
  • MpEDMDBaseline (off the root façade): measure-preserving EDMD via a
    Gram-weighted Procrustes polar factor of the dictionary map
    (Colbrook2023mpEDMD, doi:10.1137/22M1521407). Same dictionaries and
    Data-only predict surface as EDMDBaseline. Unitarity is in the
    Gram inner product; this does not obsolete Euclidean conditioning on
    a general directed K_eff.
  • GEDMDBaseline (off the root façade): generator EDMD from supplied
    dictionary derivatives (Klus2020gEDMD,
    doi:10.1016/j.physd.2020.132416). Data.dx_dt or
    fit(..., derivatives=); polynomial dictionaries only. K stores
    the generator L. Irregular timestamps do not create L. Distinct
    from identify_sparse_dynamics(..., mode="derivative").
  • HankelDMDBaseline and HAVOKBaseline (off the root façade):
    teaching delay-row solvers on flattened snapshots
    (Arbabi2017HankelDMD, doi:10.1137/17M1125236;
    Brunton2017HAVOK, doi:10.1038/s41467-017-00030-8). Distinct from
    DelayEmbeddingEncoder. Optional history= supplies older delays
    (oldest → newest); omitted slots are zeros. HAVOK predict uses
    forcing u=0. Default n_delays=2; HAVOK havok_rank=3 must fit
    inside min(num_windows, n_delays * state_dim) at fit.
  • identify_sparse_graph_factors (off the root façade): STLSQ or
    teaching group-lasso on frozen K_self / K_nbr, then an
    unpenalized refit (Brunton2016SINDy; related literature
    Pan2021SparseSubspace, doi:10.1017/jfm.2021.271, not that paper's
    multi-task EDMD pruning). Distinct from identify_sparse_dynamics
    and KoopmanSparsityLoss, which still ship. Dual random-walk and
    polynomial P>1 maps are out of scope.
  • select_latent_rank (off the root façade): VAMP-2, ResDMD elbow, or
    stability-penalized held-out MSE over a truncated-SVD candidate grid
    on frozen encodings (Wu2020VAMP; deeptime2021,
    doi:10.1088/2632-2153/ac3de0, optional [msm] cross-check). Distinct
    from Ray Tune / koopman_graph.tuning HPO for encoder latent_dim.
    Does not train a model per candidate and does not fill
    IdentificationReport.selected_rank on fit.
  • ExperimentManifest (off the root façade): frozen
    benchmark_manifest_v1 records with ...
Read more

v0.14.0

Choose a tag to compare

@tjkessler tjkessler released this 14 Aug 01:41
b32726c

Remaining-limits close-out on the 0.13 stack: opt-in operator families,
analysis extras, scale helpers, protocol-matched evaluation, and restricted
export. Homogeneous scientific defaults and the linear latent operator
contract are unchanged (koopman=None still selects "pernode").

Added

  • Discrete parameterizations row_stochastic, doubly_stochastic
    (finite Sinkhorn), and symplectic (even latent_dim). Constraints
    apply to parameterized K, not decoded x.
  • Bilinear KoopmanMPC sequential-linearization (iterated QP) on per-node
    discrete operators; additive mode still solves one QP.
  • Factory kinds koopman="switched", "mixture", and "hodge", plus
    PredictedTopologyHead (AdaptiveAdjacency remains static Graph WaveNet).
  • Equivariant block K (EquivariantKoopmanOperator) and
    E3EquivariantEncoder(..., project_invariants=False); isotypic /
    orbit neighbor-factor tying.
  • Cell-complex degree cap 3; [tdl] TopologicX incidence bridge;
    [tda] 0-d persistence and PersistenceRegularizer.
  • Matrix-free hypergraph (Zhou-symmetric) and continuous-graph distributed
    paths; scipy.sparse helper; cluster subgraph sampler; injective
    remap_node_features; opt-in KOOPMAN_GRAPH_MULTINODE=1 Ray recipe.
  • evaluate(..., include_resdmd=True), ResDMDFitCallback, Kronecker
    dispersion plots, Granger-style causal MVP, optional [control-lmi].
  • LeaderboardProtocol (distinct from teaching ForecasterProtocol),
    STAEformer-class and spatiotemporal SSM teaching ports, Fourier neural
    operator encoder, ERA5-slice card, alanine-dipeptide teaching card.
  • Restricted koopman_graph.export (torch.export / TorchScript; ONNX
    behind [export]), SVD K compression, in-tree FedAvg, FDI feature
    corruption, and a K^2 VAE MVP ([probabilistic]).
  • Sphinx graphon page plus sample_graphon_adjacency.

Changed

  • explain_representation accepts delay embeddings and additive control
    when the explainer algebra is defined (hetero / hypergraph / adaptive
    remain rejected).
  • README and Sphinx quickstart keep the default constructor and add a
    second koopman="graph" snippet.
  • limitations.rst retires closed 0.13 bullets and records new ceilings
    (finite ResDMD, TDA extra, federated-not-DP, restricted export,
    leaderboard-not-SOTA, alanine-not-Folding@home).
  • Tests live in subdirectories that follow src/koopman_graph/ packages.
    Version-named coverage dump files were split into module-named tests.
  • Orbit neighbor-factor tying reuses the representative K_nbr /
    K_hedge module so a one-orbit graph matches the shared parameter
    count. Dual K_bwd and hetero K_r stay globally shared.

Notes

  • New operator kinds round-trip safetensors_v1; custom injected modules
    remain non-round-trippable. FORMAT_VERSION stays 1.
  • Export refuses hetero / hypergraph / control / switched. Federated
    averaging is not DP-SGD. Windows remains out of the CI matrix.

Full changelog: see CHANGELOG.md ([0.14.0] - 2026-08-13).

v0.13.0

Choose a tag to compare

@tjkessler tjkessler released this 12 Aug 20:25
c8ab6a0

Ops-and-trust release on the 0.12 stack: default safetensors checkpoints,
fit callbacks and tracking adapters, a config-driven CLI, thin Ray Tune
helpers, homogeneous representation-level explainability, and a broader CI
matrix. Homogeneous scientific defaults and the linear latent operator
contract are unchanged.

Added

  • Default checkpoint container safetensors_v1 (directory or .kgckpt /
    .zip bundle) with meta.json / config.json /
    model.safetensors. Core dependency safetensors>=0.4. Load
    auto-detects the safe layout and legacy format-1 .pt pickles. See
    SECURITY.md and Sphinx serialization docs.
  • Optional .kgckpt zip packaging of the safetensors directory layout.
  • Fit callback protocol (FitCallback / NoOpFitCallback) wired through
    run_fit_loop and GraphKoopmanModel.fit(..., callbacks=). In-tree
    CsvFitLogger and optional TensorBoardFitLogger; W&B / MLflow remain
    examples-only DIY (no cloud SDK pins).
  • Console script koopman-graph with train / predict subcommands,
    JSON configs in core and optional YAML via [cli] (PyYAML). Sphinx
    cli page and examples/cli/ smoke config.
  • Power-user koopman_graph.tuning: fit_history_metrics, lazy
    run_ray_tune, and example search-space scaffolds. Ray Tune example
    script migrated; Optuna stays examples-only.
  • Homogeneous explain_representation /
    RepresentationExplanation (GNNExplainer by default; optional Captum
    integrated gradients via [explain]). Interpretive / non-causal masks;
    not ResDMD and not ModeEnergyAttribution. Tutorial
    examples/46_representation_explain.ipynb. Bib keys
    Ying2019GNNExplainer, Sundararajan2017IntegratedGradients.
  • CI: Ubuntu pytest on Python 3.10, 3.11, and 3.12 (coverage on 3.12);
    macOS core smoke on 3.12 with
    -m "not slow and not distributed and not ray" (hard-fail). Notebook
    push shards extended through 46_*.

Changed

  • Behavior change: Model.save / the default checkpoint path write
    safetensors_v1 instead of a pickle-only format-1 .pt. Pass
    format="legacy_pt" only when you intentionally need the legacy pickle
    layout. Prefer loading trusted legacy_pt files only (see
    SECURITY.md).

Notes

  • Portable inference export (TorchScript / torch.export / ONNX) is
    not shipped in 0.13.0 (Phase 83 cut-candidate). Training checkpoints
    (safetensors_v1) remain the supported weight-sharing path; ONNX stays
    deferred.
  • Windows is best-effort community support and is not in the CI matrix.
  • Representation explain remains a homogeneous MVP (rejects hetero /
    RelGraph / hypergraph / adaptive topology / delays / controls).
  • Homogeneous training defaults are unchanged relative to 0.12.0.

Full changelog: see CHANGELOG.md ([0.13.0] - 2026-08-12).

v0.12.0

Choose a tag to compare

@tjkessler tjkessler released this 05 Aug 17:35
bd82ebd

Scale-and-honesty release on the 0.11 stack: Kronecker-sum exact spectrum
for eligible networked graph operators, and docs-only topology-criticality
honesty. Homogeneous scientific defaults and the linear latent operator
contract are unchanged.

Added

  • Exact Kronecker-sum spectrum path for eligible discrete and continuous
    graph operators (koopman_graph.operators.kronecker_spectrum;
    GraphKoopmanOperator.spectrum /
    ContinuousGraphKoopmanOperator.spectrum). Eligibility requires a
    shared self factor, adjacency in {"symmetric", "random_walk"}, and
    sparsity in {"dense", "block_diagonal"}. Eigenvalues and ambient
    eigenvectors match the dense assembly oracle within float tolerance on
    path/ring fixtures.
  • Three-path spectrum contract: distributed leading-modulus Arnoldi
    (discrete / multiplex hetero), Kronecker-sum exact reduction when
    eligible, otherwise dense assembly. Continuous distributed has no
    Arnoldi spectrum path and uses dense L_eff.
  • Sphinx Scale / architecture / FAQ prose distinguishing the three
    spectrum paths and residual dense ceilings for exact inverse, Jacobi /
    Richardson, and eig-regularization hinges. Tutorial
    examples/29_large_graph_block_diagonal.ipynb records a dense vs
    Kronecker spectrum timing probe at the existing probe (N).
  • Topology-criticality honesty in limitations (cross-linked from
    architecture / capabilities), with paper.bib entry Ghosh2025.
    Tutorial examples/18_networked_koopman_dynamic_topology.ipynb notes
    that dynamic topology remains mechanical (no spectral-degeneracy /
    early-warning diagnostic API).

Notes

  • Kronecker reduction applies to spectrum only. Exact inverse /
    Jacobi / Richardson and eig-regularization hinges remain dense
    ((N\cdot d)) ceilings.
  • No Kronecker-style spectrum for hetero / hypergraph ambient operators
    in this release.
  • Homogeneous training defaults are unchanged relative to 0.11.0.

Full changelog: see CHANGELOG.md ([0.12.0] - 2026-08-05).

v0.11.0

Choose a tag to compare

@tjkessler tjkessler released this 02 Aug 21:17
7a40521

Domain-and-structure release on the 0.10 stack: measured topology transfer,
directed hypergraph incidence, Ray Train model DDP, fixed-union presence-mask
churn, teaching traffic forecaster ports, in-repo sheaf / cell-complex MVPs,
GraphVAMP + molecular teaching path, and exact-automorphism isotypic
self-block ties. Homogeneous scientific defaults and the linear latent
operator contract are unchanged.

Added

  • Public measured cross-topology transfer API
    (koopman_graph.analysis.evaluate_topology_transfer /
    TopologyTransferReport) with mandatory pernode control; negative
    transfer advantage is a valid outcome. Tutorial
    examples/37_cross_topology_transfer.ipynb calls the API.
  • Directed hypergraph incidence modes on
    HypergraphKoopmanOperator: zhou_symmetric (default),
    forward_random_walk, dual_random_walk (factory
    koopman_hypergraph_incidence_mode). Forward walk follows Ducournau &
    Bretto (Ducournau2014DirectedHypergraphs); encode/advance orientations
    may differ by design.
  • Optional Ray Train model-DDP fit path
    (koopman_graph.distributed.run_ray_train_fit_loop, [ray] /
    [distributed] with ray[train]). Distinct from
    fit_ensemble_with_ray (ensemble members). Native DDP / Fabric remain
    the recommended multi-GPU defaults; multi-node Ray Train is outside CI.
  • Fixed-union node churn: allow_node_churn + presence_masks at capacity
    (N_{\max}) (typed hetero peers included). Losses ignore inactive nodes;
    matvecs stay at capacity. Tutorial
    examples/41_node_churn_presence_masks.ipynb.
  • Teaching traffic forecaster ports with ForecasterProtocol deviation
    tables: AGCRNBaseline (Bai2020AGCRN), MTGNNBaseline
    (Wu2020MTGNN), STGODEBaseline (Fang2021STGODE; optional
    [baselines-ode]), GraphCastBaseline (Lam2023GraphCast; small-mesh
    weather teaching slice). Tutorial
    examples/42_traffic_teaching_baselines.ipynb.
  • Sheaf and cell-complex encode/decode MVPs (encoder="sheaf" /
    "cell_complex"; Hansen2020SheafNeuralNetworks,
    Bodnar2022NeuralSheaf, Bodnar2021CWNetworks motivation). Same linear
    Koopman head as GNN / simplicial-1. Tutorial
    examples/43_tdl_sheaf_cell_ablation.ipynb.
  • Contact-graph GraphVAMP teaching baseline (GraphVAMPBaseline) with
    synthetic molecular oracle under koopman_graph.datasets.molecular and
    optional deeptime interop (koopman_graph.interop, [msm] / [md]).
    Positioning relative to GraphVAMPnets (Ghorbani2022GraphVAMPNet) /
    VAMPnets (Mardt2018VAMPnets, Wu2020VAMP). Tutorial
    examples/44_graphvamp_md.ipynb.
  • Exact-automorphism isotypic self-block ties
    (koopman_symmetry="isotypic"; compute_isotypic_decomposition;
    textbook (K_n) / (C_n) oracles — Serre1977LinearRepresentations).
    Tutorial examples/45_isotypic_symmetry.ipynb. Neighbor-factor
    ((K_{\mathrm{nbr}})) isotypic tying is not shipped.
  • Sphinx: rewritten limitations.rst / capabilities.rst, architecture
    v0.11 map, FAQ (Ray Train choice, transfer honesty, teaching vs
    leaderboard), API / installation extras, molecular dataset card and
    presence-vs-observation mask semantics, tutorials 37 / 41–45.

Notes

  • Teaching baselines are not LibCity / BasicTS leaderboard reproductions.
    GraphCast is not a PEMS sensor-graph forecaster and not ERA5-scale
    production training.
  • Presence-mask churn is a fixed-union (N_{\max}) MVP — not unbounded
    open-world graph growth.
  • Sheaf / cell MVPs are not full TopologicX / cellular TDL parity. An
    optional richer external-complex bridge was cut for this release.
  • GraphVAMP path is teaching / diagnostic — not Folding@home-scale MD, not
    a PyEMMA replacement. A public alanine-dipeptide loader was cut; CI
    uses the synthetic two-state oracle.
  • Isotypic mode requires exact Aut (pynauty); WL methods are refused. Do
    not read orbit-label ties as isotypic reduction. Sample-efficiency wins
    are not guaranteed.
  • Dense (N\cdot d) (or (N_{\max}\cdot d)) ceilings are unchanged by
    trainers or presence masks.
  • Remaining honesty boundaries (leaderboard protocols, multi-node Ray Train,
    infinite-dimensional ResDMD, equivariant latent (K), full DPK /
    (K^{2})VAE, etc.) are listed in Sphinx limitations without a deferred
    roadmap of the same shipped items.

Full changelog: see CHANGELOG.md ([0.11.0] - 2026-08-02).

v0.10.0

Choose a tag to compare

@tjkessler tjkessler released this 02 Aug 00:40
16bbcb7

Heterogeneous-operator completion, matrix-free sparsity, ResDMD MVP,
classical DMD peers, and topology-blind VAMP-2 precursor. Homogeneous
defaults and the 0.9 RelGraph hetero path remain the baseline; shared-(d)
bit-compat is preserved where rectangular maps are not requested.

Added

  • Windowed hetero fit, opt-in reverse-relation synthesis
    (synthesize_reverse_relations / synthesize_reverse_edge_types), and
    continuous hetero dynamics (dynamics_mode="continuous").
  • Per-type latent widths (d_\tau) with rectangular relation maps (K_r);
    joint structural certificate on (\rho(K_{\mathrm{eff}})) (Gershgorin-style
    bound via stability_certificate, distinct from factor-wise proxies).
  • Hetero parity for conformal UQ, GraphKoopmanEnv, hierarchical models
    (multiplex union-bank and typed per-type pooling; hetero fit uses
    hold_perm), and evaluate paths; hetero orbit ties
    (koopman_auto_orbits).
  • Operator flag sparsity="distributed": matrix-free matvec path (Lanczos /
    Arnoldi spectrum with num_modes; multi-step Neumann / fixed-point
    inverse). Distinct from multi-GPU trainer extras.
  • Finite-dictionary ResDMD MVP (koopman_graph.analysis.resdmd) and
    resolvent-norm grid (pseudospectra); tutorial
    examples/40_resdmd_pseudospectra.ipynb. Remains separate from
    diagnostic spectral_residuals.
  • Bayesian Laplace UQ over operator factors (koopman_graph.uq.bayesian)
    and opt-in stochastic latent dynamics; Ulam-style transfer-operator
    baseline.
  • Dask materialization helpers (koopman_graph.distributed.dask_prep,
    [dask] extra) — prep only; no Dask training loop.
  • Classical DMD family peers: fbDMD, tlsDMD, optDMD, streaming DMD,
    depth-2 mrDMD; EDMD Nyström / random-feature approximations.
  • Simplicial-1 / Hodge encode path (encoder="simplicial"); Tier A
    InvariantGeometryEncoder (rotation-invariant features; not equivariant
    (K)).
  • Optional Tier B E3EquivariantEncoder via e3nn ([equivariance]
    extra): steerable encode to invariant scalar latents for linear (K)
    (still not an equivariant operator). Citations: Thomas2018TFN,
    Geiger2022e3nn.
  • Topology-blind VAMP-2 precursor (vamp2_score / LossWeights.vamp2,
    optional [msm] deeptime oracles) — not GraphVAMPnets / MD toolchain.
  • Sphinx: limitations 0.11 roadmap, capabilities / architecture / FAQ /
    API / tutorials updates for the 0.10 surface.

Notes

  • Dense (N\cdot d) (or (\sum_\tau N_\tau d_\tau)) assembly ceilings still
    apply when spectrum / inverse require a dense effective matrix; the
    matrix-free path avoids assembly only under sparsity="distributed".
  • ResDMD MVP is finite-dictionary only (Colbrook & Townsend / related
    residual DMD literature; keys ColbrookTownsend2023ResDMD,
    Colbrook2023ResidualDMD). Do not treat spectral_residuals as ResDMD.
  • VAMP-2 precursor cites Wu & Noé (Wu2020VAMP) and Mardt et al.
    (Mardt2018VAMPnets); it is not a GraphVAMPnets or MSM production stack.
  • 0.11 targets (high level): variable node cardinality / churn, directed
    hypergraph incidence modes, public cross-topology transfer API, sheaf /
    cell TDL, GraphVAMPnets + MD/MSM toolchains, Ray Train as model DDP,
    isotypic symmetry / equivariant (K).

v0.9.0

Choose a tag to compare

@tjkessler tjkessler released this 30 Jul 22:59
3c20ade

KoopmanGraph 0.9.0

Opt-in heterogeneous / multiplex graph Koopman operators and RelGraph encode/decode, composed with the 0.8 trainer adapters. Homogeneous defaults unchanged.

Added

  • HeteroGraphSnapshotSequence and typed stacked latent layout helpers (koopman_graph.data.hetero_layout) for PyG HeteroData multiplex / multi-node-type sequences at a shared latent width (d).
  • R-GCN-lite RelGraphEncoder / RelGraphDecoder and HeteroGraphKoopmanOperator via factory koopman="hetero_graph" ((K_{\mathrm{eff}} = I\otimes K_{\mathrm{self}} + \sum_r \widehat{A}_r \otimes K_r); optional relation_tying="basis").
  • Optional HGTEncoder / HGTDecoder under koopman_graph.nn (PyG HGTConv; not factory defaults).
  • Hetero composition with native DDP (strategy="ddp"), Lightning Fabric, optional Lightning Trainer, and Ray ensemble helpers; exposed find_unused_parameters (default True for RelGraph hetero stacks).
  • Interpretive attribute_mode_energy / ModeEnergyAttribution in koopman_graph.analysis.
  • Typed IEEE-118 topology helpers and tutorial examples/39_heterogeneous_relational_koopman.ipynb.
  • Sphinx: limitations / FAQ / capabilities / architecture / API updates for hetero and trainer composition.

Notes

  • Dense (N\cdot d) spectrum / inverse ceilings are unchanged by multi-GPU trainer orchestration. Do not confuse trainers with the unimplemented operator flag sparsity="distributed".
  • Factor-wise Schur / Lyapunov / dissipative modes do not certify (\rho(K_{\mathrm{eff}})). Relational factorization must earn its keep in ablations (negative results allowed).
  • Deferred: per-type (d_\tau), auto reverse relations, continuous hetero operators, env / conformal / hierarchical hetero parity, joint structural certificates.

See CHANGELOG.md for the full entry.

v0.8.2

Choose a tag to compare

@tjkessler tjkessler released this 28 Jul 22:42
bdf0a60

[0.8.2] - 2026-07-28

Second patch re-release for Zenodo GitHub archival after tag 0.8.1 failed
with the same missing-zip ingest error (KoopmanGraph-0.8.1.zip, draft
21656413). No scientific API changes relative to 0.8.0.

Notes

  • Prefer installing koopman-graph==0.8.2 (or latest 0.8.x) from PyPI; the
    Zenodo version DOI will be recorded once an archive succeeds.

v0.8.1

Choose a tag to compare

@tjkessler tjkessler released this 28 Jul 22:19
2ddcb21

[0.8.1] - 2026-07-28

Patch re-release so Zenodo can archive the 0.8.0 software surface after the
GitHub→Zenodo webhook for tag 0.8.0 failed during Zenodo downtime (draft
ingest missing KoopmanGraph-0.8.0.zip). No scientific API changes relative
to 0.8.0.

Notes

  • Prefer installing koopman-graph==0.8.1 (or latest 0.8.x) from PyPI; the
    Zenodo version DOI for this tag will be recorded once the archive succeeds.