Repository navigation
v0.15.0
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
Adamfitunchanged; 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.bibmethod keys for the post-0.14 catalog:
Guo2025ModularEDMD,LibCity2021,BasicTS2024,kooplearn2026,
PyKoopman2024(same work asPan2024), andPyDMD2018. 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_VERSIONstay 1. No telemetry download. - Examples 48 and 51–54: identification report plus residual-aware
reject of a polluted RMSE-only dictionary; non-normal / Nyquist
SpectralDiagnosticstoys; 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
SpectralDiagnosticsonKoopmanSpectrum(κ(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, andsign(Re λ)). Populated bycompute_spectrum/
compute_generator_spectrum(nyquist_frequencyisNoneon
generators). Discretecompute_spectrumemits oneUserWarningwhen
any mode is Nyquist-adjacent.implied_timescalescarries 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_amplitudeswarns whenκ(V)exceedsCONDITION_WARN
(1e6) and raisesDefectiveSpectrumError(aLinAlgError) when
Vis 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 SciPylogm(CPU; Al-Mohy–Higham).
Neither path claims that defectivity marks every critical regime.
monitor_critical_transitionscores 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"acceptskoopman_filter_degree(default
1, the one-tapI⊗K_self + Â⊗K_nbrmap).P=0is self only;
P>1is an opt-in monomialsum_k Â^k ⊗ K_kwith globally shared
extra hops. Dual random-walk remains an extra direction, not an extra
hop.P=1checkpoints and forwards stay bit-identical. Block-diagonal
inverse and distributed inverse / Arnoldi requireP=1; dense inverse
uses the assembled polynomial. Eligible discrete spectrum uses
Kroneckereig(B(λ_i))withB(λ)=Σ_k λ^k K_kfor anyP>=0
(not a sum of independent factor eigenvalues). Dual / orbit stay
dense; continuous-graph Kronecker remains one-tap. The helper raises
ValueErrorfor dual adjacency; operator.spectrumstill
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.fitwarns
(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 countsnum_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 PyGBatchso shared
Kapplies to the disconnected union with per-graph shifts.
Reconstruction (and forward consistency when weighted) match the mean
of the existing per-sequenceMultiTrajectoryloop 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-
Parm (Pin{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 denseK_eff
on a tinyP=2path 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.identificationclosed-form ridge / TLS / constrained
least-squares solvers and opt-in
GraphKoopmanModel.fit(..., identification=IdentificationConfig(...))
(off the root façade). Defaultidentification=Nonekeeps the Adam
path and does not import the package. Alternating fit freezes the
encoder, writes dense per-nodeK, then takes encoder/decoder Adam
steps. Discrete denseKoopmanOperatoronly; graph / hetero /
continuous / controlled / delay / windowed / DDP layouts raise.
solver="varpro"raisesNotImplementedError. After an
identification fit,model.identification_reportholds 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-inevaluate(..., 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-nodeKonly; graph / hetero / continuous / delay /
controlled layouts raise. Closed-formfitstill does not fill
IdentificationReport.invariance. - Residual-aware dictionary selection
(koopman_graph.identification.select_resdmd_gated, off the root
façade) and opt-inResDMDFitCallback(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 asresdmd).
IdentificationConfig.gate_resdmd=Truefills
IdentificationReport.spectralon the final identificationfit;
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-onlypredictsurface asEDMDBaseline. Unitarity is in the
Gram inner product; this does not obsolete Euclidean conditioning on
a general directedK_eff. -
GEDMDBaseline(off the root façade): generator EDMD from supplied
dictionary derivatives (Klus2020gEDMD,
doi:10.1016/j.physd.2020.132416).Data.dx_dtor
fit(..., derivatives=); polynomial dictionaries only.Kstores
the generatorL. Irregular timestamps do not createL. Distinct
fromidentify_sparse_dynamics(..., mode="derivative"). -
HankelDMDBaselineandHAVOKBaseline(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. Optionalhistory=supplies older delays
(oldest → newest); omitted slots are zeros. HAVOKpredictuses
forcingu=0. Defaultn_delays=2; HAVOKhavok_rank=3must fit
insidemin(num_windows, n_delays * state_dim)at fit. -
identify_sparse_graph_factors(off the root façade): STLSQ or
teaching group-lasso on frozenK_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 fromidentify_sparse_dynamics
andKoopmanSparsityLoss, which still ship. Dual random-walk and
polynomialP>1maps 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.tuningHPO for encoderlatent_dim.
Does not train a model per candidate and does not fill
IdentificationReport.selected_rankonfit. -
ExperimentManifest(off the root façade): frozen
benchmark_manifest_v1records with dataset SHA-256, ≥3 seeds,
track-mandatory controls, and non-emptydeviationsfor teaching GNN
methods. JSON always; YAML needs PyYAML ([cli]). Distinct from
LibCity / BasicTS leaderboard hosting. The[benchmark]extra is
empty. -
koopman-graph benchmark run/verify(off the root façade):
identity-boundsummary.json(benchmark_summary_v1) with a
canonical SHA-256.runrequires--dataand checks the dataset
payload digest.verifyfails on a tampered summary hash. This
increment does not train models or invent RMSE. The CLI lazy-imports
koopman_graph.benchmarkinside handlers only. - Tracked smoke fixtures under
benchmarks/v0.15/(telemetry-like,
multiphysics, topology transfer): hashed UTF-8 stand-ins, FAIR
cards, and identity-bound summaries. CI jobbenchmark-smokeruns
koopman-graph benchmark verifyon those stubs. Not METR-LA
training and not invented MAE / RMSE. - Example 47 (
examples/47_benchmark_manifest.ipynb): CLI walkthrough
of identity-boundbenchmark run/verifyon tracked
benchmarks/v0.15/smoke fixtures. Does not download METR-LA and
does not invent MAE / RMSE. - Opt-in
GraphDynamicsConfig/GraphStateSnapshot(packagedata,
off the root façade). Defaultgraph_dynamics=Nonekeeps 0.14 encode
/ decode / advance. When a config is passed,topology_headdefaults
tosparse_candidate(candidate_k=8) via
SparseCandidateTopologyHead(logits on at mostN kcandidate
pairs, not denseN×N).dense_mlpkeepsPredictedTopologyHead
with anNceiling of 64. Distinct from
learn_topology="self_adaptive"/AdaptiveAdjacency. Additive
format-1 keygraph_dynamics(absent ⇒None);FORMAT_VERSION
stays 1. When a head is attached andrecursive_trainingis true,
fit/predict/evaluate/ UQ use predicted
Â_{t+1}=g_φ(z_t)as sigmoid weights on the candidate COO unless
future_topologiesortopology_policy="hold_last"is set. Evaluate
on dynamic sequences injects oracle futures only when that recursive
path is off. Presence BCE uses a linear per-node head when masks
exist. Topology / presence terms onTrainingLossBreakdowndefault
to zero whengraph_dynamicsis unset (LossWeightsis unchanged).
learn_topology="self_adaptive"cannot be combined with a non-none
topology head.GraphStateSnapshotis a supervision record, not a
replacement forGraphSnapshotSequence. -
JointStateTopologyObserver(packageadaptation, off the root
façade): Kalman filter plus group-sparseK_self/K_nbron the
observed COO, or dense RLS on per-nodeK.
claim_homomorphism=Trueraises unless the encoder is
SeparableDictionaryEncoder(encoder_kind="separable") and the
operator is a one-tap graph Koopman operator (Peng, Shen & Zhu,
arXiv:2606.17797,Peng2026KoopmanGKFA). Default GNN encoders mix
neighbors and are not separable. The observer does not infer a new
edge set, does not run ADMM onA, and does not certify a three-term
MSE bound. Dual random-walk andfilter_degree != 1graph maps raise. Class-only
encoder (no factoryencoder="separable"). No checkpoint key;
FORMAT_VERSIONstays 1. ImportingRecursiveKoopmanAdapter/
KoopmanObserverdoes not loadidentification. -
EntityRemap(packagedata, off the root façade): injective
placement of source nodes into a caller-chosen finiteN_max.
entity_idsnames union rows;indexmaps source rows onto that
union.apply_snapshotremapsxandedge_index.
GraphSnapshotSequencestill refuses a changing node count;
the error namesEntityRemapand unbounded growth. This is not
automatic entity resolution. HomogeneousDataonly. No checkpoint
key;FORMAT_VERSIONstays 1. -
estimate_graphon/GraphonEstimate(packageoperators, off the
root façade): dense teaching fit of constant, product, or low-rank
kernels on aligned homogeneous graphs with a sharedN(ceiling
256). Constant recovery is the mean off-diagonal edge probability
(dimensionless). Product recovery uses degree scores
û_i = 2 d_i / (N-1). Low-rank is a truncated SVD sketch without an
oracle-quality claim. Sparse-graph graphon theory is refused.
Recovering a teaching kernel is not a transferability certificate on
arbitrary sparse sensor graphs (Ruiz2023Transferability). Optional
positions=onsample_graphon_adjacencyholds latents for the
product oracle. No checkpoint key;FORMAT_VERSIONstays 1. - Example 50 (
examples/50_graph_state_closure.ipynb): opt-in
predicted topology versus hold-last on a seeded six-node directed
$G(n,p)$ event.
A dense stub that scores the post-event graph beats hold-last when
the target is the model's own oracle one-step forecast. That is a
wiring check, not a learned-forecast claim. Dense logits permute
with node order; changingNstill needsEntityRemap. - Homogeneous
parameter_trajectoryand frozenConditioningContext
(packagedata, off the root façade): per-snapshot
(μ, t, u)records with caller-defined regime coordinates
(dimensionless if unspecified) and timestamps in the caller time
unit.koopman="switched"/"mixture"remain latent-gated or
piecewise LTI maps, notK(μ)(Macesic2018Nonautonomous).
Carrying parameters does not change the defaultkoopman=None
operator.FORMAT_VERSIONstays 1. - Discrete
koopman="parametric"interpolantK(μ)=Σ_j α_j(μ) K_j
with RBF or simplex weights (ParametricKoopmanOperator, off the
root façade). Distinct from latent-gated switched / mixture. Convex
combinations preserve dense / row-stochastic / doubly-stochastic
factors; symplectic / ODO / Schur / dissipative / Lyapunov /
auxiliary-spectral mixes raise. Export refuses the interpolant.
Additive checkpoint type string;FORMAT_VERSIONstays 1.
leave_one_regime_outcompares the interpolant to pooled LTI on
latent pairs. - Time-of-day recipes
diurnal_control_featuresand
diurnal_phase_index(packagedata, off the root façade): Fourier
sine/cosine columns for existing additive / bilinear control, and
integer phase bins for a per-step switchedphase_indexthat does
not mutatemode_index. Not a calendar serializer and not a
checkpoint key. Discretefit/predict_atstill reject
non-uniformΔt; usedynamics_mode="continuous"or supply gEDMD
derivatives (Klus2020gEDMD). Irregular timestamps do not create
L. - Opt-in
DriftDiffusionKoopman(packageoperators, off the root
façade): Euler–Maruyama or Yosida step fordz = Lz dt + F dW.
forwardis the conditional-expectation semigroup;advance
samples a path. Not a factory kind.
dynamics_mode="stochastic"stays diagonal process noise after
discreteK. Not certified SDE theory and not SDMD
(Xu2025StochasticSemigroup,Zhou2025Yosida). No checkpoint key;
FORMAT_VERSIONstays 1. -
JointCoverageSpec(packageuq, off the root façade) names the
conformal estimand. Defaulttarget="per_node_marginal".
Simultaneous / event targets andblock!="none"raise.
ConformalKoopmanUQ.coveragealways names the target. Proper
scoresgaussian_crps,gaussian_nll, andenergy_scoreevaluate
forecasts and do not certify coverage (Schlembach2025Conformal). -
CochainStateandCochainKoopmanOperator(packageoperators,
off the root façade): degree-specifick<=1maps on a static
signedB_1. Not a factory kind; defaultkoopman=Nonestays
"pernode". Distinct fromkoopman="hodge". Face latents are
stored, not evolved.boundary_nilpotencyflagsB_1 B_2 ≈ 0at
atol1e-6(Lim2020Hodge,TopoX2024). Feature-axis
intertwining is a loss. No checkpoint key;FORMAT_VERSIONstays 1. -
markov_closure_reportandFiniteMemoryKoopman(package
analysis, off the root façade): Ljung–Box-style residual-energy
whiteness (lags in timesteps) and a convolution
z[t+1] = z[t] @ Omega.T + sum_s z[t-s] @ K_s.T. Not a factory
kind, not delay embedding, and not HAVOK (Brunton2017HAVOK). Not
Mori–Zwanzig identification (Lin2021MoriZwanzig,Ljung1978Box).
Memory-order selection is not implemented. No checkpoint key;
FORMAT_VERSIONstays 1. -
hodge_decompose_modesandHodgeModeComponents(package
analysis, off the root façade): combinatorial Hodge split of
stored eigenvector columns into gradient / curl / harmonic parts
on a static signedB_1(kin{0, 1}). Analysis-only — not a
factory kind, not physical circulation, notkoopman="hodge", and
not TopologicX / sheaf parity (Lim2020Hodge,TopoX2024). Face
curl is not shipped.FORMAT_VERSIONstays 1. -
order2_cochain_teachingandbind_cochain_operator(packagenn,
off the root façade): order-2 filled triangle bound to
CochainKoopmanOperator.k=2stored, not evolved. Cell-complex
teaching ceiling remainsMAX_CELL_COMPLEX_DEGREE(3). Sheaf
restriction maps stay learned-optional (default diagonal). Not
TopologicX / TDA ecosystem parity (TopoX2024).
FORMAT_VERSIONstays 1. -
EquivariantKoopmanOperatoradds onel=2irrep (n_tensors;
scale * I_5) beside the existingscale * I_3vector blocks.
Not a factory kind. DefaultE3EquivariantEncoderstill projects
to invariant scalars. The operator leaf does not importe3nn;
the rotation test uses[equivariance]. Not a molecular MD
production stack (Thomas2018TFN,Geiger2022e3nn).
FORMAT_VERSIONstays 1. -
MassConservingDecoder,PositivityDecoder, and
LinearConservingDecoder(packagenn, off the root façade):
opt-in decoded-space softmax / affine mass, positivity, and
min-normC x = c_0heads on named channels. Not a factory
kind and not a checkpoint type string. Latent symplecticK
alone does not conserve decoded mass (Greydanus2019HNN).
IEEE-118generate/generate_typedremain Laplacian
diffusion plus a load ramp — not AC power flow.
FORMAT_VERSIONstays 1. -
LinearOperatorProtocolwith
PolynomialGraphLinearOperatorand
MatrixFreeGraphLinearOperator(packageoperators, off the
root façade): commonmatvec/rmatvec/solve/
expm_action/ leading eigpairs / residual norms wrapping a
degree-P>=2graph polynomial and the existing one-tap
matrix_freepath. Dense assembly is refused whenN·d
exceedsMAX_DENSE_LINEAR_OPERATOR_SIZE(4096). Trainer DDP
does not shrink that representation. Kronecker exact spectrum
remains a special case. Not a factory kind.
FORMAT_VERSIONstays 1. -
TubeKoopmanMPCandTubeMPCReport(packagempc, off the
root façade): residual-tube tightening from conformal quantiles
or ensemble residual radii on additive discrete plants.
Closed-loopevaluatereports constraint-violation rate,
feasibility rate, and quadratic stage cost against the nominal
output boxes — not tracking MSE alone. Local decoder
linearization is unchanged. Not a chance-constraint solver,
not a recursive-feasibility or Lyapunov closed-loop
certificate, and not Zhang et al. r-KMPC with an offline
ancillary law (Zhang2022TubeMPC). Bilinear / networked /
continuous plants raise. Not a factory kind.
FORMAT_VERSIONstays 1. - Labeled synthetic SCM interventions (package
analysis, off the
root façade):teaching_three_node_scmand
recover_synthetic_interventional_edgesrecover a known
do-edge0 → 1on a three-node linear Gaussian fixture.
granger_latent_influenceremains non-interventional.
Not a factory kind and not field-data causal discovery.
FORMAT_VERSIONstays 1.
Changed
- Example 22 discussion, gallery caption, and
limitations.rstcite the
saved GraphKoopman-leading aggregate RMSE (0.6551 vs 0.7076 / 1.0754 /
0.9036 for STGCN / DCRNN / Graph WaveNet) with unequal-budget and
teaching-baseline caveats. Examples 37/38 keep negative transfer and
the one-tap versus joint-LS gap as allowed outcomes, not SOTA. limitations.rstre-homes the post-0.14 honesty ceilings on one
page: one-hop default versus polynomial opt-in; Nyquist and
non-normal diagnostics; node versus cochain; uniform discrete
Δt; identification versus Adam; graph-state fixed-union;
mpEDMD versusSpectralDiagnostics; decoded constraint heads;
matrix-free eligibility; criticality as a non-certificate;
example 22 ranking; and the example-38 joint-LS gap not
attributed to hop order. Neighbor-factor isotypic tying remains
shipped. Negative transfer and null ablations stay allowed.- CI and release workflows pin
astral-sh/setup-uv10.0.1 (v10
disables the default cache onreleaseevents).
Security
- Locked
aiohttp3.14.2 → 3.14.3 (indirect extra;
GHSA-cq5v-8q36-5273, out-of-bounds heap read on a malformed
chunked HTTP response).
Fixed
markov_closure_reportimports SciPy inside the χ² evaluation so
import koopman_graphno longer requires the[dev]/[mpc]
extra. That unblocks the CLI-only benchmark-smoke job and the
docs extra Sphinx build.LinearConservingDecoderprojects ontoCx = c_0through the
Gram systemC C^Tinstead of a fatlstsq. On Linux CPU GELS
the old path could leave an O(1) residual on later rows while
the first equation looked exact.- Example 48 compares rotation leakage to 1 within
1e-8rather
than requiring a bitwise1.0.
Notes
- Factory defaults are unchanged vs 0.14.0 (
koopman=None→
"pernode";sparsity="dense"; AMP off).FORMAT_VERSIONstays 1. - The Zenodo DOI remains
10.5281/zenodo.21926723until a new version
DOI is minted at the 0.15 tag.
Full changelog: see CHANGELOG.md ([0.15.0] - 2026-08-19).