Capabilities and datasets¶
This page is the detailed capability inventory for KoopmanGraph. The
repository README.md stays a short landing page; use this page (and
Tutorials) when you need the full surface area.
Capability groups¶
Topology-aware learning¶
GraphKoopmanModel— encode → Koopman advance → decode withfit,predict,evaluate, andencodeGNNEncoder/GATEncoder/SAGEEncoder/DiffConvEncoder/GraphTransformerEncoderand matchingGNNDecoder/GATDecoder/SAGEDecoder/DiffConvDecoder/GraphTransformerDecoder(GCN uses Kipf-normalized adjacency \(\widehat{A} = \tilde{D}^{-1/2} \tilde{A} \tilde{D}^{-1/2}\); GraphSAGE: Hamilton et al. 2017; DiffConv: DCRNN-style bidirectional diffusion, Li et al. 2018; Transformer: PyGTransformerConv/ Shi et al. masked attention on edges — typically denser compute than GCN/GAT/DiffConv per edge × heads)SeparableDictionaryEncoder/SeparableDictionaryDecoder(node-wise MLP;encoder_kind="separable"; zero graph hops). Pass the classes intoGraphKoopmanModel; there is no factoryencoder="separable". Homomorphism precondition (Peng2026KoopmanGKFA); not a GNN and not on the root façade.HypergraphEncoder/HypergraphDecoderwith incidencehyperedge_index(koopman="hypergraph"); directed incidence viatail_index/head_indexwhen using non-Zhouincidence_modeHeterogeneous / multiplex RelGraph peers (
RelGraphEncoder/RelGraphDecoder) withkoopman="hetero_graph"onHeteroGraphSnapshotSequence/ PyGHeteroData(R-GCN-lite per-relation messages; Schlichtkrull et al. 2018 motivation only). Shared latent width \(d\) is the default (stacked layout inkoopman_graph.data.hetero_layout); opt-in per-type widths \(d_\tau\) vialatent_dimsuse rectangular relation maps \(K_r\). Continuous hetero (dynamics_mode="continuous") is supported with documented dense \(\Phi\) cost. Optional HGT peers (HGTEncoder/HGTDecoderinkoopman_graph.nn) wrap PyGHGTConvand are not required for hetero support. Windowed single-processrun_fit_loopaccepts windowed hetero sequencesCombinatorial simplicial-1 / Hodge lifts via
SimplicialEncoder/SimplicialDecoder(koopman_graph.nn.simplicial; orientededge_index, optionalface_index)Sheaf MVP peers (
SheafGNNEncoder/SheafGNNDecoder; factoryencoder="sheaf") — diagonal restriction maps by default; opt-in dense maps under a documented channel ceiling. Not full TopologicX parity (see Scope and limitations)Cell-complex MVP peers (
CellComplex,CellComplexGNNEncoder/CellComplexGNNDecoder; factoryencoder="cell_complex";Data.face_indexrequired) — Hodge \(L_0\) mix with the same linear Koopman headInvariantGeometryEncoder(koopman_graph.nn.equivariant) — Tier A invariant distance / angle features fromData.poslifted by a GCN; invariant features do not make latent \(K\) E(n)/SE(3) equivariantOptional
E3EquivariantEncoder(e3nn,pip install "koopman-graph[equivariance]") — Tier B steerable encode to invariant scalar latents; still not an equivariant \(K\)DelayEmbeddingEncoder/n_delaysfor Takens-style channel stacking — notHankelDMDBaselineorHAVOKBaselinePer-snapshot
edge_index(dynamic topology) and end-to-endedge_weightsupport — mechanical rewiring only; not criticality / spectral-degeneracy analysis (see Topology criticality (non-goal))Opt-in fixed-union node churn:
allow_node_churn=Truewith \(N_{\max}\) capacity andpresence_masks(T, N_{\max})(losses ignore inactive nodes; matvecs stay at capacity — see Scope and limitations)EntityRemapplaces source nodes into a finite \(N_{\max}\) via a user-supplied injective index (not automatic identity resolution; changing \(N\) without a remap raises)Homogeneous
parameter_trajectoryandConditioningContextrecord \((\\mu, t, u)\) (off the root façade). This does not change the default operator.koopman="switched"/"mixture"are not \(K(\\mu)\). Opt-inkoopman="parametric"interpolates \(K(\\mu)=\\sum_j \\alpha_j(\\mu) K_j\).diurnal_control_features()anddiurnal_phase_index()are time-of-day recipes on existing control / switchedphase_index, not a calendar serializer. Discrete sequences still require uniform \(\\Delta t\).Optional self-adaptive pairwise topology (
learn_topology="self_adaptive";koopman_graph.nn.AdaptiveAdjacency)Optional symmetry-adapted orbit-tied
K_self(and, on discrete graph / hypergraph / Hodge operators, per-orbitK_nbr/K_hedge) (koopman_auto_orbits/koopman_orbit_partition; requirespip install "koopman-graph[symmetry]"for auto orbits)Opt-in isotypic self-block and neighbor-factor ties (
koopman_symmetry="isotypic"; exact automorphism groups;compute_isotypic_decomposition();examples/45_isotypic_symmetry.ipynb) — not a guaranteed sample-efficiency winPredicted next-step topology: default
SparseCandidateTopologyHeadwhenGraphDynamicsConfigis set (topology_head="sparse_candidate"; at mostcandidate_kdestinations per node).PredictedTopologyHeadremains thedense_mlppower-user path with an \(N\) ceiling of 64. Distinct fromlearn_topology="self_adaptive"/AdaptiveAdjacency(static Graph WaveNet); the two cannot be combined whentopology_headis notnone. Whenrecursive_trainingis true, omittedfuture_topologiesuses predicted \(\hat A_{t+1}=g_\phi(z_t)\) as sigmoid weights on the candidate COO (topology_policy="hold_last"restores the 0.14 control). Evaluate on dynamic sequences injects oracle futures only when that recursive path is off. Seeexamples/50_graph_state_closure.ipynb(wiring check versus hold-last; not a learned-forecast claim). Narrative guide: Predicted graph dynamics.
Dynamics¶
Discrete
KoopmanOperatorwith soft modes (dense,odo), structural guarantees (schur,dissipative,lyapunov), or structure-preserving maps (row_stochastic,doubly_stochastic,symplectic; those maps constrain parameterized \(K\), not decoded \(x\))Opt-in decoded-space constraint heads (
MassConservingDecoder,PositivityDecoder,LinearConservingDecoder). Softmax / affine mass, positivity, and \(Cx=c_0\) act after decode. Latent symplectic \(K\) alone does not conserve decoded mass (Greydanus2019HNN). IEEE-118 remains Laplacian diffusion, not AC power flowNetworked
GraphKoopmanOperator(koopman="graph") with self/neighbor coupling \(I_N \otimes K_{\mathrm{self}} + \widehat{A} \otimes K_{\mathrm{nbr}}\) by default (koopman_filter_degree=1). Degree \(P>1\) adds \(\sum_{k=2}^{P}\widehat{A}^{k}\otimes K_{k}\) (monomial; extra hops globally shared; factorykoopman_filter_degree). Factorized blocks inspired by compositional / networked Koopman constructions; cross-topology transfer is measured, not assumed — see Scope and limitations andexamples/37_cross_topology_transfer.ipynb. Degree-\(P\) ablation and Kronecker-versus-dense spectrum live inexamples/38_operator_factorization_ablation.ipynbandexamples/49_multi_hop_factorization.ipynb; they do not attribute the path-diffusion joint-LS gap to hop order..spectrumauto-routes Kronecker-sum reduction when eligible (shared self;symmetric/random_walk; any monomial \(P\ge 0\)); see Scope and limitations (Scale) for distributed Arnoldi, dense fall-backs, and inverse ceilings.fitwarns when encoder hops exceedfilter_degree; encoder mixing does not compensate for a one-hop \(K\)Matrix-free linear-operator protocol (
LinearOperatorProtocol) wrapping a degree-\(P\\ge 2\) graph polynomial and the existing one-tapmatrix_freehelpers. Dense assembly is refused aboveMAX_DENSE_LINEAR_OPERATOR_SIZE. Trainer DDP does not shrink that representation. Leading eigpairs are Arnoldi Ritz values, not Kronecker \(\\operatorname{eig}(B(\\lambda))\). \(10^{5}\)-node scaling is not a release gate. See Matrix-free linear operators.Pairwise
adjacencymodes on graph / continuous-graph operators:"symmetric"(default),"random_walk"(\(D_{\mathrm{out}}^{-1}A\)), and"dual_random_walk"(forward plus reverse); factory keywordkoopman_adjacency; format-1config.adjacency. Hypergraph operators do not exposeadjacency; useincidence_modeinsteadHypergraph
HypergraphKoopmanOperator(koopman="hypergraph") withincidence_mode"zhou_symmetric"(default),"forward_random_walk", or"dual_random_walk"(factorykoopman_hypergraph_incidence_mode; dual exposesK_hedge/K_bwd)Relational multiplex / typed
HeteroGraphKoopmanOperator(koopman="hetero_graph"): \(K_{\mathrm{eff}} = I\otimes K_{\mathrm{self}} + \sum_r \widehat{A}_r \otimes K_r\) (typed: block-diagonal per-type self). Optionalrelation_tying="basis". Dense \(N\cdot d\) spectrum / inverse ceiling unchanged — see Scope and limitationsGlobal/local non-stationary discrete operator (
GlobalLocalKoopmanOperator;koopman="global_local")Switched and mixture discrete maps (
koopman="switched"/"mixture"; piecewise-linear or softmax mixture of LTI modes, not a parameter interpolant \(K(\\mu)\))Opt-in parametric interpolant (
koopman="parametric";ParametricKoopmanOperator) \(K(\\mu)=\\sum_j \\alpha_j(\\mu) K_j\) with RBF or simplex weights. Convex combinations preserve dense / row-stochastic / doubly-stochastic factors; symplectic and other structural mixes raise. Export refuses the interpolant (Macesic2018Nonautonomous)Hodge / Laplacian-structured networked operator (
koopman="hodge")Degree-specific cochain maps (
CochainKoopmanOperator) on a static signed \(B_1\) for \(k\\le 1\). Not a factory kind; defaultkoopman=Nonestays"pernode". Face latents are stored, not evolved. Not TopologicX parityOrder-2 TDL teaching path (
order2_cochain_teaching()) binding that cochain operator to a filled triangle. Cell-complex degreeMAX_CELL_COMPLEX_DEGREE(3) is the ceiling. Sheaf restriction maps stay learned-optional. Not ecosystem parityCombinatorial Hodge split of stored Koopman mode shapes (
hodge_decompose_modes()). Analysis-only gradient / curl / harmonic blocks on a static signed \(B_1\) (\(k\\in\\{0,1\\}\)). Not physical circulation, not a factory kind, and notkoopman="hodge". Teaching notebook:examples/52_cochain_hodge_modes.ipynbEquivariant block operator (
EquivariantKoopmanOperator; vector channels are multiples of \(I_3\); optional \(l=2\) channels are multiples of \(I_5\)). Not a factory kind and not a molecular MD stack. Default encode may still project to invariantsContinuous-time
ContinuousKoopmanOperator(dynamics_mode="continuous"), irregular timestamps, andpredict_atContinuous networked generator
ContinuousGraphKoopmanOperator(koopman="graph"+dynamics_mode="continuous"orkoopman="continuous_graph";adjacencymodes match discreteGraphKoopmanOperator)..spectrumuses the same Kronecker eligibility as discrete graph when applicable; denseN·dmatrix-exp (\(\Phi=\exp(\Delta t\, L_{\mathrm{eff}})\)) remains a separate ceiling — prefer modestNorsparsity="block_diagonal"self-only shortcut for advances (see Scope and limitations)Continuous hetero generators on
koopman="hetero_graph"+dynamics_mode="continuous"(dense stacked \(\Phi\) cost; see Scope and limitations)Opt-in
dynamics_mode="stochastic"— discrete linear map plus learned diagonal process noise (not a continuous-time SDE).DriftDiffusionKoopmanis a separate Euler–Maruyama / Yosida stepper, not that factory stringJointCoverageSpecnames the conformal estimand (defaultper_node_marginal). Simultaneous / event targets are named but not implemented. Proper scoresgaussian_crps(),gaussian_nll(), andenergy_score()are not coverage certificatesInnovation-whiteness report (
markov_closure_report()) and a convolution MVP (FiniteMemoryKoopman). Not Mori–Zwanzig identification, not HAVOK, and notDelayEmbeddingEncoder. Not a factory kindContinuous
koopman_parameterization="auxiliary_spectral"— state-dependentgenerator_at(z)/ instantaneous spectrum (Lusch-style; locally linear, not a fixed global matrix). Prefer delay embeddings first for continuous- spectrum phenomenology; seeexamples/20_continuous_spectrum_auxiliary_network.ipynbAdditive control and optional bilinear / control-affine terms (
control_mode="bilinear")
Forecasting and training¶
Multi-step rollout from a single initial state
Consistency losses (forward / backward), optional eigenvalue regularization, fit-time PIKN-style Lie / PINN-style PDE residual terms, optional \(L_1\) / smoothed \(L_p\) Koopman sparsity, an optional worst-case (\(L_{\infty}\)-style) reconstruction term (robust training only — not a generalization bound), and optional topology-blind VAMP-2 precursor weight (
LossWeights.vamp2/vamp2_score(); not GraphVAMPnets)LR schedulers, per-term loss history,
MultiTrajectoryfit, and windowed mini-batchingTemporal train/val/test splits and per-horizon MAE, RMSE, and MAPE via
koopman_graph.metrics.evaluate_forecastMeasured cross-topology transfer via
evaluate_topology_transfer()(structured report; mandatorypernodecontrol; negative advantage allowed — see Scope and limitations andexamples/37_cross_topology_transfer.ipynb)Frozen identification config / report types and closed-form ridge / TLS / constrained least-squares solvers under
koopman_graph.identification(off root__all__).GraphKoopmanModel.fit(..., identification=IdentificationConfig(...))is opt-in; defaultidentification=Noneis the Adam path. Discrete dense per-node operators only. The report records latent one-step / short-rollout mean squared error (MSE) and \(\rho(K)\), not an invariance or ResDMD certificate.subspace_invariance_report()andevaluate(..., include_invariance=True)report finite-sample projection leakage \(\eta\) on a truncated-SVD encoding span (discrete dense per-node \(K\) only). That ratio is not a Haseli–Cortés invariance-proximity certificate.select_resdmd_gated()compares pre-scored dictionaries by train one-step mean squared error (MSE) after optionally dropping candidates whose max finite-dictionary ResDMD residual exceeds \(10^{-2}\).IdentificationConfig.gate_resdmd=Truefills the reportspectralblock; it does not abortfit.ResDMDFitCallbackmode="gate"raises at fit end when the observed max residual exceeds that cutoff. Default callback mode is"observe". None of these is a certified infinite-dimensional residual bound.identify_sparse_graph_factors()selects sparse \(K_{\\mathrm{self}}\) / \(K_{\\mathrm{nbr}}\) on frozen encodings (STLSQ or teaching group-lasso, then unpenalized refit; related literaturePan2021SparseSubspace, not that paper’s multi-task EDMD pruning). ExistingKoopmanSparsityLossandidentify_sparse_dynamics()still ship.select_latent_rank()scores truncated-SVD ranks of frozen encodings (in-tree VAMP-2, ResDMD elbow, or stability-penalized held-out MSE). It is not Ray Tune / AutoML for encoderlatent_dim(koopman_graph.tuningremains caller-owned HPO). Teaching notebooks:examples/48_identification_invariance.ipynbandexamples/53_latent_rank_selection.ipynb. See Operator identification.koopman_graph.benchmarkholds frozenExperimentManifestrecords (schemabenchmark_manifest_v1; JSON always, YAML via PyYAML /[cli]). Teaching GNN methods require non-emptydeviations. Dataset SHA-256 mismatch is rejected. The CLIbenchmark run/verifycommands write identity-bound summaries (dataset SHA-256 and a canonical digest). They do not train models, download telemetry, or host a LibCity / BasicTS leaderboard. Tracked smoke YAML underbenchmarks/v0.15/is what default CI verifies. See Identity-bound benchmarks andexamples/47_benchmark_manifest.ipynb.
Training performance¶
Internal training-path reuse (same scientific defaults; see Architecture and API layers and Scope and limitations):
Shared sequence latents (
SequenceLatentCache) when multiple pair losses share a window — each timestep is encoded once percompute_training_lossevaluationNetworked dense inverse reuse for static topology; DiffConv support cache (
clear_support_cache); hypergraph Zhou \(\hat{H}\) cache (clear_hyperedge_cache)Continuous dense \(\Phi\) / \(L_{\mathrm{eff}}\) reuse within one training-loss evaluation
Shared one-step predictions across reconstruction / PDE / worst-case terms when those losses are active together
Opt-in multi-graph
Batchcollate:fit(..., batch_graphs=True)vectorizes the existingMultiTrajectoryloop (reconstruction and forward consistency). Default per-sequence averaging is unchanged. Multi-topology training did not require this flag.Opt-in CUDA automatic mixed precision:
use_amp=TrueonGraphKoopmanModel.fit/run_fit_loop(FP32 fallback on CPU/MPS)Hierarchical
pool_schedule="hold_perm"to amortize TopK / SAG pooling across a sequenceEphemeral structural
K/Land low-rank bilinear assemblies; learned-topology materialize at most once per top-levelforward/ rollout-origin encode; multi-start rollout encodes each distinct origin once
Distributed training (optional)¶
Optional multi-process / multi-GPU trainer orchestration around the same
scientific fit loop (run_fit_loop / epoch helpers /
compute_training_loss). Import from
koopman_graph.distributed (power-user; not on root __all__).
This is not the operator flag sparsity="distributed" (matrix-free
inverse / spectrum; see FAQ and troubleshooting and Scope and limitations).
Native PyTorch DDP via
run_ddp_fit_loop()orGraphKoopmanModel.fit(..., strategy="ddp")(core install; typically launched withtorchrun). Homogeneous and hetero (HeteroData/HeteroGraphSnapshotSequence) models compose on this path;find_unused_parametersdefaults toTruefor RelGraph hetero stacksLightning Fabric via
fit_with_fabric()(requirespip install "koopman-graph[lightning]"); accepts hetero sequencesOptional Lightning
Trainersugar viaKoopmanLightningModule(same[lightning]extra). Prefer Fabric / native DDP when you need full loss schedules,DistributedWindowSampler, or the shared epoch driver. The module composes aGraphKoopmanModel, accepts batches ofGraphSnapshotSequence/HeteroGraphSnapshotSequence(or a list thereof), and exports format-1 checkpoints withexport_format1_checkpointRank-aware window sampling (
DistributedWindowSampler) and trajectory sharding helpers (including hetero)Optional Ray Train model DDP via
run_ray_train_fit_loop()(requirespip install "koopman-graph[ray]"or[distributed]; wraps Ray TrainTorchTraineraround the same scientific fit loop). Prefer native DDP / Fabric unless you already standardize on Ray Train. Multi-node Ray Train is opt-in (KOOPMAN_GRAPH_MULTINODE=1); default CI stays single-process — see Scope and limitationsOptional Ray parallel ensemble member fits via
fit_ensemble_with_ray()orEnsembleGraphKoopmanModel.fit(..., parallel_backend="ray", member_factory=...)(same[ray]extra). Sequential ensemble fit remains the default. This does not change UQ coverage guarantees — members stay independent fits. Do not confuse ensemble Ray withrun_ray_train_fit_loop()Example script (outside
nbmakeCI):torchrun --standalone --nproc_per_node=2 \\ examples/scripts/ddp_fit_torchrun.py
See
examples/scripts/README.md. Multi-process smoke tests are opt-in (KOOPMAN_GRAPH_DISTRIBUTED_TESTS=1); default PR CI does not require multi-node hardware.
Ray Tune HPO is supported via power-user helpers under
koopman_graph.tuning (fit_history_metrics, run_ray_tune,
optional example_* smoke scaffolds) and the examples-only script
examples/scripts/ray_tune_koopman_example.py. Search spaces remain
user-defined / script-owned; the library is not an AutoML product.
Optuna is examples-only (no library Optuna API). Optional
pip install "koopman-graph[dask]" activates
koopman_graph.distributed.dask_prep helpers
(materialize_sequences, materialize_window_index_list) for offline
prep. The library does not import Dask on the training path; trainers
remain native DDP / Fabric / Ray Train / Ray ensemble (see FAQ and troubleshooting).
Distributed data-parallel training does not reduce dense
\(N\cdot d\) operator ceilings — see Scope and limitations (Scale).
Analysis¶
KoopmanSpectrum/compute_spectrumwith mode decoding helpers and optionalSpectralDiagnostics(\(\kappa(V)\), Wilkinson \(\kappa_i\), departure from normality, discrete Nyquist \(1/(2\Delta t)\) in cycles per unit time, aliasing flags). Not a finite-horizon \(\|K^{k}\|\) bound. See Spectral diagnostics andexamples/51_spectral_diagnostics.ipynbSliding-window spectral-gap monitor (
monitor_critical_transition()) — positive rate means the gap shrank; not a Ghosh-grade certificate (Ghosh2025). See Spectral-gap criticality monitor andexamples/54_criticality_monitor.ipynbNetworked graph / continuous-graph
.spectrumpaths: distributed Arnoldi (discrete / multiplex hetero / Zhou-symmetric hypergraph / continuous-graph generator factors), Kronecker-sum exact reduction when eligible, or dense assembled eigendecomposition — see Scope and limitations (Scale)attribute_mode_energy/ModeEnergyAttribution— interpretive type / relation energy fractions on assembledK_eff(not causal; not a ResDMD residual on relation-attributed modes)explain_representation/RepresentationExplanation— representation-level node / edge / feature masks on a homogeneous snapshot for targetslatent,one_step_forecast, orreconstruction. Default algorithmgnn_explaineruses PyG GNNExplainer (Ying2019GNNExplainer); optionalalgorithm="integrated_gradients"uses Captum via the[explain]extra (Sundararajan2017IntegratedGradients). Masks are interpretive and non-causal; they are notModeEnergyAttributionand not ResDMD residuals. Homogeneous graphs including delay embeddings and additive control; hetero / hypergraph / adaptive remain rejected — see Scope and limitationsspectral_residuals/SpectralResidualReport— held-out data-driven residuals andtrustworthy_mask(); optionalplot_spectrum(..., annotate_untrustworthy=True). Diagnostic in the learned observable space, not a certified ResDMD bound (ColbrookTownsend2023ResDMD,Colbrook2023ResidualDMD)Finite-dictionary ResDMD MVP (
resdmd(),ResDMDReport) optionally attached toevaluate(..., include_resdmd=True)andResDMDFitCallback, plus finite-matrix resolvent-norm grid (resolvent_norm_grid()) — not infinite-dimensional certified pseudospectra; seeexamples/40_resdmd_pseudospectra.ipynbFinite-sample subspace invariance leakage (
subspace_invariance_report(),evaluate(..., include_invariance=True)) — truncated-SVD projection residual on encoded samples; not a Haseli–Cortés certificate (HaseliCortes2023); discrete dense per-node \(K\) onlyResidual-aware dictionary selection (
select_resdmd_gated()) and opt-inResDMDFitCallback(mode="gate")— drop or reject finite-dictionary ResDMD-polluted RMSE-only winners; not a certified residual bound; default callback mode remains"observe"Sparse graph-factor identification (
identify_sparse_graph_factors()) — STLSQ or teaching group-lasso on frozen \(K_{\\mathrm{self}}\) / \(K_{\\mathrm{nbr}}\) with unpenalized refit. Distinct from latent SINDy (identify_sparse_dynamics()) and fromKoopmanSparsityLoss; those tools still ship. Dual random-walk and \(P>1\) polynomial hops are out of scope.Latent-rank selection (
select_latent_rank()) — VAMP-2, ResDMD elbow, or stability-penalized held-out MSE on a truncated-SVD grid of frozen encodings. Not Ray Tune AutoML for encoderlatent_dim;[msm]/ deeptime is an optional VAMP-2 cross-check (deeptime2021).Protocol-locked experiment manifests (
ExperimentManifest) — schemabenchmark_manifest_v1with dataset SHA-256, ≥3 seeds, mandatory controls, and teaching-portdeviations. CLIrun/verifyhash protocol identity; they do not train and are not SOTA. Default CI verifies hashed synthetics underbenchmarks/v0.15/, not full METR-LA.Kronecker dispersion (
graph_dispersion()) and Granger-style causal MVP (granger_latent_influence(); assumption-laden, non-interventional)Labeled synthetic SCM interventions (
teaching_three_node_scm(),recover_synthetic_interventional_edges()). Recovers a known do-edge on the teaching fixture only — not Granger and not field-data discovery0-dimensional persistence (
persistence_diagram_0d(); optional[tda]) — not a TDA libraryLong-horizon statistics via
koopman_graph.statistics(power-user): Welch PSD (Welch1967),spectral_distance,invariant_measure_distance, Rosensteinlargest_lyapunov_exponent(Rosenstein1993Lyapunov; embedding-sensitive; \(O(T^{2})\)), andLongHorizonReportDynamical similarity and anomaly utilities via
koopman_graph.analysisidentify_sparse_dynamics(SINDy / STLSQ on learned latents — not physical governing equations; distinct fromGEDMDBaseline)koopman_spectral_clustering(node communities from Koopman modes)estimate_coupling_from_snapshots(topology / coupling diagnostics)plot_spectrumfor unit-disk / data-zoom views
Control, adaptation, and observation¶
koopman_graph.adaptation.RecursiveKoopmanAdapter/adapt_stepfor online RLS updatesKoopmanObserverfor latent Kalman filtering / imputation underobservation_masksJointStateTopologyObserverfor Kalman filtering plus group-sparse \(K_{\mathrm{self}}\) / \(K_{\mathrm{nbr}}\) write-back on the observed COO (or dense RLS on per-node \(K\)). Homomorphism claims requireSeparableDictionaryEncoderand a one-tap graph operator (Peng2026KoopmanGKFA); default GNN encoders raise whenclaim_homomorphism=True. This is not Koopman-GKFA, does not infer a new edge set, and is not on the root façade.koopman_graph.env.GraphKoopmanEnv/to_latent_envfor Gymnasium closed-loop controlkoopman_graph.mpc.KoopmanMPCfor additive-control receding-horizon QP and bilinear sequential-linearization ([mpc]/ OSQP; local decoder-linearization guarantees; optional conformal output-constraint tightening)koopman_graph.mpc.TubeKoopmanMPCfor additive discrete residual-tube tightening from conformal quantiles or ensemble radii ([mpc]/ OSQP).evaluatereports constraint-violation rate, feasibility rate, and cost — not tracking MSE alone, not recursive feasibility, and not a Lyapunov closed-loop certificate (Zhang2022TubeMPC)Hybrid physics observables: Laplacian, nodewise graph-gradient magnitude, graph curvature (\(L_{\mathrm{sym}}^2 x\)), polynomial dictionaries, or custom lifting callables. Residual losses are soft penalties, not symplectic/Hamiltonian structure guarantees or a PIKE/SPIKE implementation.
Uncertainty quantification (power-user)¶
koopman_graph.uq.EnsembleGraphKoopmanModel— deep ensembles with empiricalpredict_intervalmean / quantile bounds (not on root__all__)koopman_graph.uq.LatentGaussianKoopmanUQ— linear-Gaussian latent forecast with closed-form covariance propagation and optional Kalman refinement (not DPK)koopman_graph.probabilistic— variational encoder weights plus linear latent \(K\) (distinct from Laplace factor UQ)koopman_graph.uq.ConformalKoopmanUQ— split and adaptive (ACI) conformal intervals; marginal coverage under exchangeability (approximate under temporal dependence). Scores:"aggregate", legacy"per_node"(max-pool over nodes), and"node_wise"(per-node marginal widths; optionalneighbor_smoothingfollowing DAPS-style diffusion,Zargarbashi2023ConformalGNN). Calibration payload kindConformalKoopmanUQ.calibration.v2koopman_graph.uq.BayesianKoopmanUQ— diagonal Laplace posterior over linear Koopman factors with seededsample_forecastintervals (not a BNN over encoder weights; not full DPK / \(K^{2}\)VAE)See notebooks
21_uncertainty_quantification.ipynband30_conformal_uncertainty.ipynb
Hierarchical / multi-resolution (power-user)¶
koopman_graph.hierarchical.HierarchicalGraphKoopmanModel— TopK (optional SAG) pool → composedGraphKoopmanModelon the coarse graph → scatter-unpool;predict(..., resolution=...)for coarse vs fineCoarse-level forecasting with unpooling — not P-K-GCN spatiotemporal super-resolution; graph spectra use the pooled topology
See notebook
23_hierarchical_multiresolution.ipynbfor in-sample RMSE, fine-grid snapshots, and a dense-KspectrumAPI demo on a grid
Research tooling¶
Classical baselines via
koopman_graph.baselines:DMDBaseline,EDMDBaseline(polynomial / RBF / kernel dictionaries; kernel path is \(O(T^2)\) — small/mediumT; Nyström / random-feature approximations available),MpEDMDBaseline(measure-preserving EDMD via a Gram-weighted Procrustes polar factor;Colbrook2023mpEDMD; not a Euclidean \(K_{\\mathrm{eff}}\) certificate),GEDMDBaseline(generator EDMD from supplied \(dx/dt\);Klus2020gEDMD; not derivative-mode SINDy; irregular timestamps do not create \(L\)),HankelDMDBaseline(Hankel-DMD on delay-embedded flattened states;Arbabi2017HankelDMD; notDelayEmbeddingEncoder),HAVOKBaseline(teaching HAVOK on the same delay rows;Brunton2017HAVOK; autonomouspredictuses \(u=0\)),DMDcBaseline,FBDMDBaseline,TLSDMDBaseline,OptDMDBaseline,StreamingDMDBaseline,MRDMDBaseline, andUlamTransferOperatorBaseline. Truncated-SVDrankacceptsNone, a positive integer, or"auto"(Gavish–Donoho median threshold,GavishDonoho2014); fittedselected_rankis recordedTopology-blind VAMP-2 precursor helpers (
vamp2_score/vamp2_loss; optional[msm]for deeptime oracle tests)Contact-graph GraphVAMP teaching baseline (
GraphVAMPBaseline) with synthetic molecular oracles underkoopman_graph.datasets.molecularand optional deeptime interop (koopman_graph.interop;[msm]/[md]) — teaching / diagnostic, not GraphVAMPnets production or a PyEMMA replacement. Packaged alanine-dipeptide teaching card viaalanine_dipeptide_card()(not Folding@home; see Scope and limitations)Lightweight STGCN / DCRNN / Graph WaveNet references plus teaching AGCRN / MTGNN / STGODE / GraphCast / STAEformer-class / spatiotemporal SSM ports in
koopman_graph.baselines.gnn(ForecasterProtocoldeviation tables; not dedicated-library SOTA)Protocol-matched LibCity / BasicTS adapters (
LeaderboardProtocol) — not SOTARestricted portable export (
koopman_graph.export; fixed-topology discrete homogeneous MVP) and in-tree FedAvg (koopman_graph.federated; not DP)Graphon-sampled adjacency and a dense teaching estimator (
sample_graphon_adjacency(),estimate_graphon(); Graphon sampling and continuum limits) — constant / product oracle recovery on aligned graphs; not sparse-graph graphon theory and not a transferability certificateBenchmark datasets and Jupyter tutorials under
examples/Model
save/loadcheckpoints (defaultsafetensors_v1directory or.kgckpt/.zipbundle;legacy_ptpickle escape hatch); ≥90% coverage enforced in CI. See the repositorySECURITY.mdfor load trust boundaries.
Experiment tracking (fit callbacks)¶
Observe-only hooks on the functional fit path (single-process
GraphKoopmanModel.fit / run_fit_loop()):
FitCallbackprotocol andNoOpFitCallback(root-exported)In-tree adapters under
koopman_graph.tracking(power-user; not on root__all__):CsvFitLogger(stdlib CSV) andTensorBoardFitLogger(requires peerpip install tensorboard)Callbacks must not mutate model parameters; default
callbacks=Nonepreserves priorFitHistorybehaviorfit(..., strategy="ddp")does not acceptcallbacksyet — use single-process fit or Lightning loggers for distributed runsLightning
Trainerusers should attach Lightning loggers toKoopmanLightningModule; this release does not add a second FitCallback stack on TrainerWeights & Biases / MLflow are intentionally not core dependencies — see FAQ and troubleshooting and
examples/tracking/wandb_mlflow_callback.py
Hyperparameter search helpers¶
Power-user package koopman_graph.tuning (not on root __all__):
fit_history_metrics()— flatten aFitHistoryinto scalar floats for Tune / Optuna reportersrun_ray_tune()— thin Ray Tune façade (lazy import; requirespip install "koopman-graph[ray]")example_lr_loguniform_space()/example_lr_latent_dim_space()— example smoke scaffolds only (not scientific defaults)
This is not an AutoML product. Searchable hyperparameters and ranges
remain caller-owned. Optuna is examples-only (no library Optuna API).
See examples/scripts/ray_tune_koopman_example.py and
examples/scripts/README.md.
Stability mode selection¶
Use dense or odo when you want a soft prior (odo bounds
ρ(K) via the operator 2-norm but lacks a strict ε-interior
certificate; continuous odo needs eigenvalue loss on the true
spectrum). Choose schur, dissipative, or lyapunov when you
need eigenvalues forced inside the unit disk. See
examples/11_long_horizon_stability.ipynb versus
examples/08_loss_stability.ipynb, and the stability section in
Quickstart.
Built-in datasets¶
Benchmark |
Domain |
Description |
|---|---|---|
|
Synthetic |
Laplacian diffusion on path/ring graphs |
|
Synthetic |
Laplacian diffusion on a 4-connected 2D lattice |
|
Synthetic |
Directional advection with asymmetric edge weights |
|
Epidemic |
Networked SIR on ring / small-world / custom graphs |
|
Epidemic (cache) |
SocioPatterns primary-school contacts (fetch-script + SHA256; CC-BY-NC-SA) |
|
Chaotic ODE |
Lorenz-96 on a ring graph |
|
Chaotic PDE |
1D KS on a path/ring discretization |
|
Fluids (cache) |
Hopf/Stuart–Landau cylinder-wake teaching surrogate |
|
Power systems |
IEEE 118-bus topology with simulated voltage/load dynamics;
typed helpers ( |
|
Traffic |
METR-LA sensor graph with cached speed snapshots |
|
Traffic |
PEMS-BAY speeds (325 sensors; fetch-script + SHA256) |
|
Traffic |
PEMS03/04/07/08 flows ( |