API Reference¶
Public classes and functions are re-exported from koopman_graph. Detailed
documentation is organized by module below.
Package¶
KoopmanGraph: topology-aware Koopman dynamics on graphs.
Public API¶
GraphKoopmanModelEnd-to-end encode → Koopman advance → decode model.
GNNEncoder,GATEncoderGNN encoders for latent lifting.
GNNDecoderGNN decoder for physical reconstruction.
KoopmanOperatorLearnable finite-dimensional Koopman matrix.
KoopmanSpectrumEigendecomposition and continuous-time mode characteristics.
compute_spectrum,decode_mode_shapesSpectral analysis and latent-to-spatial mode decoding helpers.
DMDBaseline,EDMDBaseline,DMDcBaselineClassical topology-agnostic Koopman baselines.
GraphSnapshotSequence,WindowSamplerContainer and fixed-length mini-batch sampler for graph snapshots.
TemporalSplit,temporal_splitTemporal train/validation/test splitting utilities.
EvaluationResult,evaluate_forecast,mae,rmse,mapeMulti-horizon forecast evaluation metrics.
ForwardConsistencyLossLatent-space linear evolution consistency loss.
BackwardConsistencyLossLatent-space inverse linear evolution consistency loss.
EigenvalueRegularizationLossUnit-circle eigenvalue hinge penalty for operator stability.
FitHistoryTraining history returned by
fit().LossWeightsWeights for reconstruction and consistency loss terms.
__version__Package version string.
- class koopman_graph.BackwardConsistencyLoss(*args, **kwargs)[source]
Bases:
ModulePenalize deviation from inverse linear latent evolution under K.
For latent encodings
z_tandz_{t+1}with forward dynamicsz_{t+1} = z_t @ K.T, the backward (adjoint) consistency term is the mean squared error betweenz_tand the inverse propagation ofz_{t+1}:\[\mathcal{L}_{\mathrm{bc}} = \| z_t - z_{t+1} K^{\dagger} \|^2\]where
K^{\dagger}denotes an inverse or pseudo-inverse ofK.Trade-offs¶
Benefits: Enforces bidirectional linear consistency, which can improve Koopman operator identifiability and training stability when paired with the forward consistency term (see Lusch et al., 2018; Mezić, 2021).
Costs: Dense unconstrained
Krequires a matrix inverse or pseudo-inverse. The ODO parameterization (parameterization"odo") provides a cheap exact factorized inverse and bounds the spectral radius. For denseK, sequence-level training precomputes the inverse once per step rather than per snapshot pair.Notes
This module is stateless. Call
forward()with consecutive latent encodings and aKoopmanOperator.- forward(z_t, z_t1, koopman, *, control=None, inverse_matrix=None)[source]
Compute backward consistency loss between consecutive latent states.
- Parameters:
z_t (Tensor) – Latent encoding at time
t, shape(..., latent_dim).z_t1 (Tensor) – Latent encoding at time
t+1, same shape asz_t.koopman (
KoopmanOperator) – Learnable linear propagator whose inverse step is applied toz_t1.control (Tensor or None, optional) – Control input that drove the forward transition from
ttot+1.inverse_matrix (Tensor or None, optional) – Precomputed dense inverse matrix reused across pair evaluations.
- Returns:
Scalar mean-squared error between
z_tand the inverse propagation ofz_t1.- Return type:
Tensor
- class koopman_graph.EigenvalueRegularizationLoss(*args, **kwargs)[source]
Bases:
ModulePenalize Koopman eigenvalues outside the unit circle.
Implements a hinge-style eigenloss that activates only when eigenvalue magnitudes exceed one:
\[\mathcal{L}_{\mathrm{eig}} = \mathrm{mean}\big(\max(|\lambda_i| - 1, 0)^2\big)\]For the ODO parameterization, eigenvalues are read directly from the bounded diagonal factor, avoiding an explicit eigendecomposition.
Trade-offs¶
Benefits: Encourages discrete-time stability without hard-constraining the operator parameterization. Complements spectrally constrained ODO initialization (DeepKoopFormer-style factorization; eigeninit/eigenloss literature).
Costs: Dense
Krequirestorch.linalg.eigvalseach evaluation. Use the ODO parameterization when a hard spectral-radius bound is preferred.Notes
This module is stateless. Call
forward()with aKoopmanOperator.- forward(koopman)[source]
Compute the unit-circle eigenvalue hinge penalty.
- Parameters:
koopman (
KoopmanOperator) – Operator whose eigenvalue magnitudes are penalized.- Returns:
Scalar hinge penalty (zero when all magnitudes are <= 1).
- Return type:
Tensor
- class koopman_graph.EvaluationResult(horizons, aggregate_mae, aggregate_rmse, aggregate_mape, num_origins)[source]
Bases:
objectMulti-horizon forecast evaluation summary.
- horizons
Per-horizon metrics in ascending horizon order.
- Type:
- aggregate_mae
Mean of per-horizon MAE values.
- Type:
- aggregate_rmse
Mean of per-horizon RMSE values.
- Type:
- aggregate_mape
Mean of per-horizon MAPE values.
- Type:
- num_origins
Number of forecast origins averaged over.
- Type:
- class koopman_graph.DMDBaseline(*, time_step=1.0, rank=None)[source]
Bases:
objectDynamic Mode Decomposition baseline on flattened node states.
DMDBaselineignores graph message passing: each graph snapshot is reshaped into one vector and a linear map is fit by least squares. The learned operator follows the package conventionx_next = x @ K.T.- Parameters:
- fit(sequence)[source]
Fit the DMD operator from consecutive graph snapshots.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Training snapshots with shared topology.
- Returns:
The fitted baseline.
- Return type:
- Raises:
ValueError – If fewer than two snapshots are provided or rank is invalid.
- predict(initial_graph, steps)[source]
Autoregressively predict future graph snapshots.
- spectrum()[source]
Return the DMD operator spectrum.
- Returns:
Eigendecomposition and continuous-time mode characteristics of the fitted DMD operator.
- Return type:
- class koopman_graph.DMDcBaseline(*, time_step=1.0, rank=None)[source]
Bases:
objectDynamic Mode Decomposition with control on flattened node states.
DMDcBaselineextendsDMDBaselinewith exogenous inputs, fittingx_{t+1} = x_t @ K.T + u_t @ Bby least squares on flattened graph snapshots. Global controls use shape(control_dim,); per-node controls are flattened during fitting and prediction.- Parameters:
- fit(sequence)[source]
Fit controlled DMD operators from consecutive graph snapshots.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Training snapshots with shared topology and control inputs.
- Returns:
The fitted baseline.
- Return type:
- Raises:
ValueError – If fewer than two snapshots are provided, controls are missing, or rank is invalid.
- predict(initial_graph, steps, controls)[source]
Autoregressively predict future graph snapshots with future controls.
- Parameters:
initial_graph (Data) – Initial graph snapshot. Its topology is copied to every prediction.
steps (int) – Number of future snapshots to predict.
controls (sequence of Tensor) – Future control inputs, one per rollout step. Global controls use shape
(control_dim,); per-node controls use(num_nodes, control_dim).
- Returns:
Predicted graph snapshots with the same node/feature shape as the fitted training data.
- Return type:
list of Data
- spectrum()[source]
Return the autonomous DMD operator spectrum.
- Returns:
Eigendecomposition of the fitted state-transition operator
K.- Return type:
- class koopman_graph.EDMDBaseline(*, time_step=1.0, rank=None, polynomial_degree=2)[source]
Bases:
objectExtended DMD baseline with polynomial observables.
EDMD lifts flattened graph states into a fixed observable space, fits a linear Koopman operator there, and learns a least-squares decoder back to physical node features.
polynomial_degree=1is an identity observable;polynomial_degree=2appends elementwise squared terms.- Parameters:
time_step (float, optional) – Physical duration represented by one snapshot transition. Used by
spectrum(). Default is1.0.rank (int or None, optional) – Optional truncated-SVD rank for the observable data matrix.
Noneuses the full least-squares solution. Default isNone.polynomial_degree ({1, 2}, optional) – Polynomial observable degree. Default is
2.
- fit(sequence)[source]
Fit EDMD operator and linear reconstruction decoder.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Training snapshots with shared topology.
- Returns:
The fitted baseline.
- Return type:
- Raises:
ValueError – If fewer than two snapshots are provided or rank is invalid.
- predict(initial_graph, steps)[source]
Autoregressively predict future graph snapshots.
- Parameters:
initial_graph (Data) – Initial graph snapshot. Its topology is copied to every prediction.
steps (int) – Number of future snapshots to predict.
- Returns:
Predicted graph snapshots with the same node/feature shape as the fitted training data.
- Return type:
list of Data
- Raises:
RuntimeError – If the baseline has not been fit.
ValueError – If
steps < 1or graph metadata does not match the fit data.
- spectrum()[source]
Return the EDMD observable-space operator spectrum.
- Returns:
Eigendecomposition and continuous-time mode characteristics of the fitted observable-space operator.
- Return type:
- class koopman_graph.FitHistory(loss, epochs, reconstruction_loss=<factory>, forward_loss=<factory>, backward_loss=<factory>, rollout_loss=<factory>, eigenvalue_loss=<factory>, val_loss=None, val_reconstruction_loss=None, val_forward_loss=None, val_backward_loss=None, val_rollout_loss=None, val_eigenvalue_loss=None, stopped_early=False, best_epoch=None, best_loss=None)[source]
Bases:
objectTraining history returned by
GraphKoopmanModel.fit().- epochs
Number of training epochs completed (may be less than requested when early stopping triggers).
- Type:
- val_loss
Per-epoch validation loss when a validation sequence is provided.
- val_reconstruction_loss
Per-epoch unweighted validation reconstruction loss.
- val_forward_loss
Per-epoch unweighted validation forward consistency loss.
- val_backward_loss
Per-epoch unweighted validation backward consistency loss.
- stopped_early
Whether training stopped before the requested epoch count.
- Type:
- best_epoch
Zero-based index of the lowest-loss epoch when best-epoch tracking is enabled in
fit().- Type:
int or None
- best_loss
Lowest monitored loss observed when best-epoch tracking is enabled.
- Type:
float or None
- class koopman_graph.ForwardConsistencyLoss(*args, **kwargs)[source]
Bases:
ModulePenalize deviation from linear latent evolution under the Koopman operator.
For latent encodings
z_tandz_{t+1}, the loss is the mean squared error betweenK @ z_t(implemented asz_t @ K.T) andz_{t+1}:\[\mathcal{L}_{\mathrm{fc}} = \| K z_t - z_{t+1} \|^2\]Notes
This module is stateless. Call
forward()with consecutive latent encodings and aKoopmanOperator.- forward(z_t, z_t1, koopman, *, control=None)[source]
Compute forward consistency loss between consecutive latent states.
- Parameters:
z_t (Tensor) – Latent encoding at time
t, shape(..., latent_dim).z_t1 (Tensor) – Latent encoding at time
t+1, same shape asz_t.koopman (
KoopmanOperator) – Learnable linear propagator applied toz_t.control (Tensor or None, optional) – Control input driving the transition from
ttot+1.
- Returns:
Scalar mean-squared error between
koopman(z_t, control)andz_t1.- Return type:
Tensor
- class koopman_graph.GATEncoder(in_channels, hidden_channels, latent_dim, *, num_layers=2, activation='relu', heads=1, dropout=0.0)[source]
Bases:
BaseGNNModuleGAT encoder that lifts node features into a latent space.
Applies stacked Graph Attention Network layers with configurable hidden activation. The final layer maps directly to
latent_dimwithout an activation, producing per-node latent vectors suitable for Koopman propagation.Scalar
edge_weightarguments are accepted for API symmetry withGNNEncoderbut are ignored becauseGATConvdoes not consume scalar edge weights.- in_channels
Input node feature dimension.
- Type:
- hidden_channels
Hidden GAT channel width.
- Type:
- latent_dim
Output latent dimension per node.
- Type:
- heads
Number of attention heads per GAT layer.
- Type:
- dropout
Dropout probability inside GAT attention.
- Type:
- class koopman_graph.GNNDecoder(latent_dim, hidden_channels, out_channels, *, num_layers=2, activation='relu')[source]
Bases:
BaseGNNModuleGCN decoder that maps latent node features back to physical space.
Applies stacked Graph Convolutional Network layers with configurable hidden activation. The final layer maps directly to
out_channelswithout an activation, producing per-node physical feature predictions.- latent_dim
Input latent dimension per node.
- Type:
- hidden_channels
Hidden GCN channel width.
- Type:
- out_channels
Output physical feature dimension per node.
- Type:
- class koopman_graph.GNNEncoder(in_channels, hidden_channels, latent_dim, *, num_layers=2, activation='relu')[source]
Bases:
BaseGNNModuleGCN encoder that lifts node features into a latent space.
Applies stacked Graph Convolutional Network layers with configurable hidden activation. The final layer maps directly to
latent_dimwithout an activation, producing per-node latent vectors suitable for Koopman propagation.- in_channels
Input node feature dimension.
- Type:
- hidden_channels
Hidden GCN channel width.
- Type:
- latent_dim
Output latent dimension per node.
- Type:
- class koopman_graph.GraphKoopmanModel(encoder, decoder, latent_dim, time_step, *, koopman_init_mode='identity_noise', koopman_init_scale=0.01, koopman_parameterization='dense', koopman_max_spectral_radius=1.0, control_dim=0)[source]
Bases:
ModuleTopology-aware Koopman dynamics model for graph snapshots.
Composes a GNN encoder (lifting), a finite-dimensional Koopman operator (linear latent evolution), and a symmetric GNN decoder (reconstruction).
- encoder
Topology-aware encoder for latent lifting.
- Type:
- decoder
Symmetric GNN decoder for physical reconstruction.
- Type:
- latent_dim
Latent space dimension shared by encoder, operator, and decoder.
- Type:
- time_step
Physical time increment associated with one model step. Used by
spectrum()to convert discrete eigenvalues into continuous-time growth rates and frequencies.- Type:
- koopman
Learnable linear propagator in latent space.
- Type:
- spectrum()[source]
Analyze the learned Koopman operator spectrum.
Uses
time_stepto convert discrete eigenvalues into continuous-time growth rates and frequencies.- Returns:
Magnitude-sorted eigenvalues, eigenvectors, and continuous-time mode characteristics.
- Return type:
- save(path)[source]
Persist model weights and architecture configuration to disk.
- Parameters:
path (str or Path) – Destination checkpoint file (
.pt). Parent directories are created when missing.
- classmethod load(path, *, map_location=None)[source]
Load a trained model from a checkpoint file.
Reconstructs encoder, decoder, and Koopman operator architecture from the saved configuration and restores learned weights.
- Parameters:
path (str or Path) – Checkpoint file produced by
save().map_location (str, torch.device, or None, optional) – Device mapping forwarded to
torch.load().
- Returns:
Ready-to-use model in evaluation mode.
- Return type:
- forward(x_or_data, edge_index=None, edge_weight=None, control=None)[source]
Predict the next graph snapshot from the current one.
Performs encode → linear Koopman advance → decode for a single step.
- Parameters:
x_or_data (Tensor or Data) – Either a PyG
Dataobject or node featuresxof shape(num_nodes, in_channels).edge_index (Tensor, optional) – Edge index with shape
(2, num_edges). Required whenx_or_datais a tensor; ignored forDatainput.edge_weight (Tensor, optional) – Scalar edge weights with shape
(num_edges,). Required whenx_or_datais a tensor and weights are used; ignored forDatainput.control (Tensor or None, optional) – Exogenous control input for this step. Required when
control_dimis positive.
- Returns:
Predicted node features of shape
(num_nodes, out_channels).- Return type:
Tensor
- predict(initial_graph, steps, edge_index=None, edge_weight=None, controls=None, future_topologies=None)[source]
Autoregressively predict future graph snapshots.
Encodes the initial graph once, advances the latent state with the Koopman operator for
stepsiterations, and decodes after each step. Runs in evaluation mode without gradient tracking.When
future_topologiesis omitted, each rollout step decodes with the hold-last-known topology: the initial graph topology is used for step 0, and each subsequent step reuses the most recently provided topology. Pass oneDataobject per rollout step (topology only; node features are ignored) to supply a known future rewiring schedule.- Parameters:
initial_graph (Tensor or Data) – Either a PyG
Dataobject or node featuresxof shape(num_nodes, in_channels).steps (int) – Number of future snapshots to predict (must be >= 1).
edge_index (Tensor, optional) – Edge index with shape
(2, num_edges). Required wheninitial_graphis a tensor; ignored forDatainput.edge_weight (Tensor, optional) – Scalar edge weights with shape
(num_edges,). Required wheninitial_graphis a tensor and weights are used; ignored forDatainput.controls (sequence of Tensor or None, optional) – Future control inputs for each rollout step. Required with length
stepswhencontrol_dimis positive.future_topologies (sequence of Data or None, optional) – Known topologies for rollout decode steps. Shorter sequences hold the last provided topology for remaining steps.
- Returns:
stepspredicted graph snapshots. EachData.xhas shape(num_nodes, out_channels)and carries theedge_index(and optionaledge_weight) used for that step’s decode.- Return type:
list of Data
- Raises:
ValueError – If
steps < 1or controls are missing/invalid for a controlled model.
- evaluate(sequence, *, horizons=(3, 6, 12), start_indices=None)[source]
Evaluate multi-horizon forecast accuracy on a snapshot sequence.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Evaluation snapshots with shared topology.
horizons (sequence of int, optional) – Forecast horizons to report. Default is
(3, 6, 12).start_indices (sequence of int or None, optional) – Forecast-origin indices. When
None, uses every valid origin insequence.
- Returns:
Per-horizon and aggregate MAE, RMSE, and MAPE.
- Return type:
- fit(data_sequence, *, epochs=100, lr=0.001, optimizer=<class 'torch.optim.adam.Adam'>, device=None, loss_weights=None, loss_weight_schedule=None, rollout_horizon=None, rollout_start_indices=None, rollout_starts_per_epoch=None, rollout_start_seed=None, lr_scheduler=None, window_length=None, batch_size=8, windows_per_epoch=None, window_seed=None, max_grad_norm=None, early_stopping_patience=None, early_stopping_min_delta=0.0, early_stopping_monitor='auto', validation_sequence=None, restore_best_weights=False, checkpoint_path=None, **optimizer_kwargs)[source]
Train encoder, Koopman operator, and decoder end-to-end.
Minimizes a weighted sum of one-step MSE and optional forward and backward consistency terms:
loss = w_r * recon_loss + w_f * ||K z_t - z_{t+1}||^2 + w_b * ||z_t - z_{t+1} K^{\dagger}||^2
where
z_tandz_{t+1}are encoder outputs for consecutive snapshots and weights(w_r, w_f, w_b)come from aLossWeightsobject or an optional per-epoch schedule.When
data_sequenceis a list ofGraphSnapshotSequenceobjects, losses are averaged across trajectories before each optimizer step.- Parameters:
data_sequence (GraphSnapshotSequence, sequence of Data, or sequence of GraphSnapshotSequence) – One training trajectory or multiple trajectories of the same system. A plain list of
Datasnapshots is treated as a single trajectory; a list whose first element is aGraphSnapshotSequenceis treated as multiple trajectories.epochs (int, optional) – Number of training epochs. Default is
100.lr (float, optional) – Learning rate passed to the optimizer. Default is
1e-3.optimizer (callable, optional) – Optimizer class. Default is
torch.optim.Adam.device (str, torch.device, or None, optional) – Device for training. Defaults to the model’s current device, or CPU if the model has no parameters.
loss_weights (LossWeights or None, optional) – Static loss weights for all epochs. When
Noneand no schedule is provided, defaults to reconstruction-only training.loss_weight_schedule (callable or None, optional) – Callable
epoch -> LossWeightsapplied each epoch. Overridesloss_weightswhen set.rollout_horizon (int or None, optional) – Number of autoregressive rollout steps used when
loss_weights.rolloutis non-zero. Defaults tonum_timesteps - 1.rollout_start_indices (sequence of int,
"all", or None, optional) – Rollout-loss origin indices.Noneuses[0];"all"uses every valid origin for the rollout horizon.rollout_starts_per_epoch (int or None, optional) – When set, randomly sample this many rollout origins each epoch.
rollout_start_seed (int or None, optional) – Base seed for random rollout-origin sampling. The effective seed is
rollout_start_seed + epoch.lr_scheduler (LRScheduler or callable, optional) – Learning-rate scheduler instance or factory
optimizer -> scheduler. Stepped once per epoch after the optimizer update.window_length (int or None, optional) – Fixed number of snapshots per training window. When set, enables mini-batch training with multiple optimizer steps per epoch.
Nonepreserves full-sequence single-step training.batch_size (int, optional) – Number of temporal windows averaged per optimizer step. Used only when
window_lengthis set. Default is8.windows_per_epoch (int or None, optional) – Maximum sampled windows per epoch.
Noneuses every valid window across all trajectories.window_seed (int or None, optional) – Base seed for reproducible epoch-specific window shuffling.
max_grad_norm (float or None, optional) – When set, clip the global gradient norm before each optimizer step.
early_stopping_patience (int or None, optional) – Stop training when training loss fails to improve for this many consecutive epochs. Disabled when
None.early_stopping_min_delta (float, optional) – Minimum decrease in the monitored loss to count as improvement. Default is
0.0.early_stopping_monitor ({"auto", "train", "val"}, optional) – Loss used for early stopping and best-epoch tracking.
"auto"monitors validation loss whenvalidation_sequenceis provided, otherwise training loss. Default is"auto".validation_sequence (GraphSnapshotSequence, sequence of Data, sequence of GraphSnapshotSequence, or None, optional) – Optional held-out snapshots for per-epoch validation loss. A single validation sequence is reused for all training trajectories; a list of validation sequences must match the training trajectory count.
restore_best_weights (bool, optional) – When
True, reload in-memory weights from the lowest-loss epoch after training completes. Default isFalse.checkpoint_path (str, Path, or None, optional) – When set, write a checkpoint at the lowest-loss epoch using
save(). Default isNone.**optimizer_kwargs (Any) – Additional keyword arguments forwarded to the optimizer constructor.
- Returns:
Per-epoch training and validation losses and early-stop metadata.
- Return type:
- Raises:
ValueError – If
epochs < 1,early_stopping_patience < 1when set,early_stopping_monitor="val"withoutvalidation_sequence, validation list length mismatches training trajectories, or fewer than two snapshots are provided for training or validation.
- class koopman_graph.GraphSnapshotSequence(snapshots, *, allow_dynamic_topology=False, control_inputs=None)[source]
Bases:
objectContainer for a time-ordered sequence of PyG
Datagraph snapshots.By default all snapshots must share the same
edge_index, optionaledge_weight, node count, and feature dimension. Setallow_dynamic_topology=Trueto permit per-snapshotedge_indexwhile still requiring a fixed node count and feature dimension. Optionalcontrol_inputsstore exogenous inputsu_tapplied when advancing from snapshotttot+1. Downstream training APIs should require at least two snapshots; construction here allows a single snapshot for inspection or prediction-only workflows.Notes
Read-only views of sequence metadata are exposed as
snapshots,edge_index,edge_weight,is_dynamic_topology,control_inputs,has_controls,control_dim,num_nodes,num_timesteps, andin_channels. Theedge_indexandedge_weightproperties are only defined for static-topology sequences; usesequence[t].edge_indexwhenis_dynamic_topologyisTrue.- classmethod from_arrays(node_features, edge_index, *, edge_weight=None, control_inputs=None, dtype=torch.float32)[source]
Build a sequence from node feature arrays and a shared topology.
- Parameters:
node_features (array-like) – Array with shape
(num_timesteps, num_nodes, in_channels).edge_index (array-like) – Shared edge index with shape
(2, num_edges).edge_weight (array-like, optional) – Shared scalar edge weights with shape
(num_edges,). When provided, attached to every snapshot.control_inputs (array-like, optional) – Per-timestep control inputs with shape
(num_timesteps, control_dim)or(num_timesteps, num_nodes, control_dim).dtype (torch.dtype, optional) – Floating dtype used when converting numpy inputs to torch tensors. Default is
torch.float32.
- Returns:
Validated snapshot sequence.
- Return type:
- Raises:
ValueError – If
node_features,edge_index, oredge_weighthave invalid shape.
- classmethod from_dynamic_arrays(node_features, edge_indices, *, edge_weights=None, control_inputs=None, dtype=torch.float32)[source]
Build a dynamic-topology sequence from per-timestep edge indices.
- Parameters:
node_features (array-like) – Array with shape
(num_timesteps, num_nodes, in_channels).edge_indices (sequence of array-like) – One edge index per timestep, each with shape
(2, num_edges_t).edge_weights (sequence of array-like or None, optional) – Optional per-timestep scalar edge weights aligned with
edge_indices. When provided, must have the same length asedge_indices.control_inputs (array-like, optional) – Per-timestep control inputs with shape
(num_timesteps, control_dim)or(num_timesteps, num_nodes, control_dim).dtype (torch.dtype, optional) – Floating dtype used when converting numpy inputs to torch tensors. Default is
torch.float32.
- Returns:
Validated snapshot sequence with
allow_dynamic_topology=True.- Return type:
- Raises:
ValueError – If shapes are inconsistent or
edge_indiceslength mismatchesnum_timesteps.
- property is_dynamic_topology: bool
Return whether snapshots use time-varying
edge_index.- Returns:
Truewhen the sequence was constructed withallow_dynamic_topology=Trueand at least one snapshot differs inedge_indexfrom the first snapshot.- Return type:
- property allow_dynamic_topology: bool
Return whether dynamic topology mode was enabled at construction.
- Returns:
Truewhen per-snapshotedge_indexvalues are permitted.- Return type:
- property control_inputs: Tensor | None
Return per-timestep control inputs when present.
- Returns:
Control tensor with shape
(num_timesteps, control_dim)or(num_timesteps, num_nodes, control_dim).- Return type:
Tensor or None
- property has_controls: bool
Return whether the sequence carries control inputs.
- Returns:
Truewhencontrol_inputsis notNone.- Return type:
- property control_dim: int
Return the control feature dimension.
- Returns:
Control dimension when controls are present, otherwise
0.- Return type:
- control_at(index)[source]
Return the control input driving transition from snapshot
index.- Parameters:
index (int) – Timestep index in
[0, num_timesteps - 1].- Returns:
Control vector for the transition
index -> index + 1.- Return type:
Tensor
- Raises:
ValueError – If controls are absent or
indexis out of range.
- rollout_controls(start, steps)[source]
Return controls for an autoregressive rollout from a start snapshot.
- Parameters:
- Returns:
Control inputs for each rollout step. Empty when the sequence has no controls.
- Return type:
list of Tensor
- Raises:
ValueError – If
startorstepsare invalid or controls are unavailable for the requested horizon.
- property snapshots: list[Data]
Return the underlying list of graph snapshots.
- Returns:
Time-ordered PyG graph snapshots.
- Return type:
list of Data
- property edge_index: Tensor
Return the shared edge index for static-topology sequences.
- Returns:
Edge index with shape
(2, num_edges).- Return type:
Tensor
- Raises:
ValueError – If
is_dynamic_topologyisTrue.
- property edge_weight: Tensor | None
Return the shared scalar edge weights for static-topology sequences.
- Returns:
Edge weights with shape
(num_edges,), orNonewhen the sequence is unweighted.- Return type:
Tensor or None
- Raises:
ValueError – If
is_dynamic_topologyisTrue.
- property num_nodes: int
Return the number of nodes in the graph topology.
- Returns:
Node count shared across all snapshots.
- Return type:
- property num_timesteps: int
Return the number of timesteps in the sequence.
- Returns:
Length of the temporal sequence.
- Return type:
- property in_channels: int
Return the node feature dimension.
- Returns:
Feature dimension shared across all snapshots.
- Return type:
- slice(start, stop)[source]
Return a contiguous temporal sub-sequence.
- Parameters:
- Returns:
Snapshots in
[start, stop)with matching controls and topology policy.- Return type:
- Raises:
ValueError – If the bounds are negative, empty, reversed, or exceed the sequence length.
- class koopman_graph.HorizonMetrics(horizon, mae, rmse, mape)[source]
Bases:
objectForecast metrics at a single prediction horizon.
- horizon
Forecast horizon in steps.
- Type:
- mae
Mean absolute error averaged over evaluation origins.
- Type:
- rmse
Root mean squared error averaged over evaluation origins.
- Type:
- mape
Mean absolute percentage error averaged over evaluation origins.
- Type:
- class koopman_graph.KoopmanOperator(latent_dim, *, init_mode='identity_noise', init_scale=0.01, parameterization='dense', max_spectral_radius=1.0, control_dim=0)[source]
Bases:
ModuleLearnable finite-dimensional Koopman operator matrix K.
Applies the same linear map to each node’s latent vector. For input
zwith trailing dimensionlatent_dim, the uncontrolled forward pass computes:z_next = z @ K.T
When
control_dimis positive, exogenous inputs drive the transition:z_next = z @ K.T + u @ B
where
Khas shape(latent_dim, latent_dim)andBhas shape(control_dim, latent_dim). Global controlsuwith shape(control_dim,)are broadcast to every node; per-node controls use shape(num_nodes, control_dim). Arbitrary leading dimensions are supported (e.g.(num_nodes, latent_dim)or(batch, num_nodes, latent_dim)).- latent_dim
Dimension of the latent space.
- Type:
- control_dim
Dimension of exogenous control inputs. Zero disables control.
- Type:
- init_mode
Weight initialization strategy for
K.- Type:
- init_scale
Noise scale used when
init_mode="identity_noise".- Type:
- parameterization
Parameterization used for
K("dense"or"odo").- Type:
- max_spectral_radius
Upper bound on the spectral radius when
parameterization="odo".- Type:
- reset_control_parameters()[source]
Reinitialize the control input matrix
B.- Return type:
None
- control_term(u, *, num_nodes=None)[source]
Map control inputs to a latent-space offset
u @ B.- Parameters:
u (Tensor) – Global control with shape
(control_dim,)or per-node control with shape(num_nodes, control_dim).num_nodes (int or None, optional) – Expected node count when
uis per-node. Used for validation only.
- Returns:
Latent offset with shape
(latent_dim,)for global control or(num_nodes, latent_dim)for per-node control.- Return type:
Tensor
- Raises:
ValueError – If
control_dimis zero,uhas invalid shape, or per-nodeudoes not matchnum_nodes.
- property K: Tensor
Assembled Koopman matrix with shape
(latent_dim, latent_dim).For
parameterization="dense"this is the learnable parameter. Forparameterization="odo"it is assembled from orthogonal factors and a bounded diagonal matrix.- Returns:
Current operator matrix
K.- Return type:
Tensor
- reset_parameters()[source]
Reinitialize operator parameters according to
init_mode.- Return type:
None
- spectral_radius()[source]
Return the spectral radius of the assembled operator matrix.
- Returns:
Scalar tensor with the maximum eigenvalue magnitude.
- Return type:
Tensor
- forward(z, control=None)[source]
Advance latent states by one linear Koopman step.
When
control_dimis positive, the controlled update is:z_next = z @ K.T + control_effect
where
control_effectisu @ Bbroadcast for global controluwith shape(control_dim,)or applied per node whenuhas shape(num_nodes, control_dim).- Parameters:
z (Tensor) – Latent states with shape
(..., latent_dim).control (Tensor or None, optional) – Exogenous control input applied during this step. Required when
control_dimis positive.
- Returns:
Advanced latent states with the same shape as
z.- Return type:
Tensor
- Raises:
ValueError – If the trailing dimension of
zdoes not matchlatent_dim, controls are missing for a controlled operator, orcontrolhas an invalid shape.
- inverse_step(z, *, control=None, inverse_matrix=None)[source]
Apply one inverse Koopman step to recover the previous latent state.
For forward dynamics
z_{t+1} = z_t @ K.T + u_t @ B, this returns an estimate ofz_tfromz_{t+1}and the controlu_tthat drove the transition.- Parameters:
z (Tensor) – Latent states at time
t+1with shape(..., latent_dim).control (Tensor or None, optional) – Control input that drove the forward transition. Required when
control_dimis positive.inverse_matrix (Tensor or None, optional) – Precomputed
K^{-1}for dense parameterization. When omitted, the inverse is computed on demand.
- Returns:
Recovered latent states at time
t, same shape asz.- Return type:
Tensor
- dense_inverse_matrix()[source]
Return the inverse (or pseudo-inverse) of the assembled dense matrix.
Intended for reuse across multiple backward-consistency pair evaluations within one training step.
- Returns:
Matrix
K^{-1}(orK^{\dagger}) with shape(latent_dim, latent_dim).- Return type:
Tensor
- Raises:
ValueError – If
parameterizationis not"dense".
- class koopman_graph.KoopmanSpectrum(eigenvalues, eigenvectors, magnitudes, growth_rates, frequencies, time_step)[source]
Bases:
objectEigendecomposition and time scales of a discrete Koopman operator.
Eigenpairs are sorted by descending eigenvalue magnitude. Frequencies are reported in cycles per unit time; multiply by
2 * pifor angular frequency.- eigenvalues
Complex eigenvalues with shape
(latent_dim,).- Type:
Tensor
- eigenvectors
Complex right eigenvectors stored as columns, with shape
(latent_dim, latent_dim).- Type:
Tensor
- magnitudes
Eigenvalue magnitudes with shape
(latent_dim,).- Type:
Tensor
- growth_rates
Continuous-time exponential growth rates
log(|lambda|) / time_step.- Type:
Tensor
- frequencies
Signed continuous-time frequencies
angle(lambda) / (2 * pi * time_step)in cycles per unit time.- Type:
Tensor
- time_step
Physical duration represented by one discrete Koopman step.
- Type:
- mode_amplitudes(latent_states)[source]
Project latent states onto the Koopman eigenvector basis.
For a latent row vector
z, the returned amplitudesasatisfyz.T = eigenvectors @ a. Any leading dimensions are preserved.- Parameters:
latent_states (Tensor) – Latent states with shape
(..., latent_dim).- Returns:
Complex mode amplitudes with the same shape as
latent_states.- Return type:
Tensor
- Raises:
ValueError – If the trailing latent dimension does not match the spectrum.
RuntimeError – If the eigenvector matrix is singular.
- class koopman_graph.LossWeights(reconstruction=1.0, forward=0.0, backward=0.0, rollout=0.0, eigenvalue=0.0)[source]
Bases:
objectWeights for reconstruction and consistency loss terms.
- reconstruction
Weight on the one-step reconstruction (MSE) loss.
- Type:
- forward
Weight on the forward consistency loss.
- Type:
- backward
Weight on the backward consistency loss.
- Type:
- rollout
Weight on the autoregressive rollout reconstruction loss.
- Type:
- eigenvalue
Weight on the unit-circle eigenvalue hinge penalty.
- Type:
- class koopman_graph.TemporalSplit(train, val, test)[source]
Bases:
objectTrain, validation, and test snapshot sequences from a temporal split.
- train
Earliest contiguous snapshots used for training.
- Type:
- val
Middle contiguous snapshots used for validation.
- Type:
- test
Latest contiguous snapshots held out for evaluation.
- Type:
- class koopman_graph.WindowSampler(sequences, *, window_length, batch_size=8, windows_per_epoch=None, shuffle=True, seed=None)[source]
Bases:
objectSample fixed-length temporal windows from one or more trajectories.
- Parameters:
sequences (GraphSnapshotSequence or sequence of GraphSnapshotSequence) – Source trajectories. Each must contain at least
window_lengthsnapshots.window_length (int) – Number of snapshots per sampled window. Must be at least
2.batch_size (int, optional) – Number of windows yielded together. Default is
8.windows_per_epoch (int or None, optional) – Maximum number of windows sampled per epoch.
Noneuses every valid window. Values larger than the available window count are capped.shuffle (bool, optional) – Randomize window order each epoch. Default is
True.seed (int or None, optional) – Base seed for reproducible epoch-specific shuffling.
- property num_windows: int
Return the total number of valid windows.
- Returns:
Number of valid windows across every source trajectory.
- Return type:
- koopman_graph.compute_spectrum(operator, time_step)[source]
Compute the sorted spectrum and continuous-time mode characteristics.
- Parameters:
operator (Tensor) – Square discrete-time Koopman matrix with shape
(latent_dim, latent_dim).time_step (float) – Positive physical duration represented by one operator step.
- Returns:
Eigenpairs sorted by descending magnitude, plus growth rates and frequencies converted using
time_step.- Return type:
- Raises:
ValueError – If
operatoris not a non-empty square matrix ortime_stepis not positive.TypeError – If
operatoris not floating-point or complex.
- koopman_graph.decode_mode_shapes(model, x_or_data, mode_indices=None, *, edge_index=None, perturbation=0.001)[source]
Decode latent Koopman directions into spatial node-feature mode shapes.
The decoder is generally nonlinear, so mode shapes are estimated with a centered finite-difference directional derivative around the encoded graph. Real and imaginary parts of complex eigenvectors are probed separately and combined into a complex-valued mode shape.
- Parameters:
model (GraphKoopmanModel) – Model whose operator spectrum and decoder are analyzed.
x_or_data (Tensor or Data) – Reference graph used as the decoder linearization point.
mode_indices (sequence of int or None, optional) – Indices into the magnitude-sorted spectrum. Defaults to every mode.
edge_index (Tensor or None, optional) – Graph edges, required when
x_or_datais a feature tensor.perturbation (float, optional) – Positive centered finite-difference step. Default is
1e-3.
- Returns:
Complex mode shapes with shape
(num_modes, num_nodes, out_channels).- Return type:
Tensor
- Raises:
ValueError – If
perturbationis not positive or a mode index is out of range.
- koopman_graph.evaluate_forecast(model, sequence, *, horizons=(3, 6, 12), start_indices=None)[source]
Evaluate autoregressive multi-horizon forecasts on a snapshot sequence.
For each forecast origin, the model predicts up to
max(horizons)steps ahead and metrics are averaged across origins at each requested horizon.- Parameters:
model (nn.Module) – Model implementing
predict().sequence (GraphSnapshotSequence) – Evaluation snapshots with shared topology.
horizons (sequence of int, optional) – Forecast horizons to report. Default is
(3, 6, 12).start_indices (sequence of int or None, optional) – Forecast-origin indices. When
None, uses every valid origin insequence.
- Returns:
Per-horizon and aggregate MAE, RMSE, and MAPE.
- Return type:
- Raises:
ValueError – If
horizonsis empty, any horizon is invalid, or the sequence is too short.
- koopman_graph.mae(prediction, target)[source]
Compute mean absolute error.
- Parameters:
prediction (Tensor) – Predicted values.
target (Tensor) – Ground-truth values with the same shape as
prediction.
- Returns:
Scalar mean absolute error.
- Return type:
Tensor
- koopman_graph.mape(prediction, target, *, eps=1e-08)[source]
Compute mean absolute percentage error.
- Parameters:
prediction (Tensor) – Predicted values.
target (Tensor) – Ground-truth values with the same shape as
prediction.eps (float, optional) – Small constant added to the denominator for numerical stability. Default is
1e-8.
- Returns:
Scalar mean absolute percentage error (not scaled to 0–100).
- Return type:
Tensor
- koopman_graph.rmse(prediction, target)[source]
Compute root mean squared error.
- Parameters:
prediction (Tensor) – Predicted values.
target (Tensor) – Ground-truth values with the same shape as
prediction.
- Returns:
Scalar root mean squared error.
- Return type:
Tensor
- koopman_graph.temporal_split(sequence, *, train_ratio=0.7, val_ratio=0.1, test_ratio=0.2, min_train_timesteps=2, min_val_timesteps=2, min_test_timesteps=1)[source]
Split a snapshot sequence into contiguous train, validation, and test sets.
Earlier snapshots are assigned to training, later snapshots to validation and test. Ratios must sum to
1.0.- Parameters:
sequence (GraphSnapshotSequence) – Full time-ordered snapshot sequence to split.
train_ratio (float, optional) – Fraction of timesteps assigned to training. Default is
0.7.val_ratio (float, optional) – Fraction assigned to validation. Default is
0.1.test_ratio (float, optional) – Fraction assigned to test. Default is
0.2.min_train_timesteps (int, optional) – Minimum training snapshots required. Default is
2.min_val_timesteps (int, optional) – Minimum validation snapshots required. Default is
2.min_test_timesteps (int, optional) – Minimum test snapshots required. Default is
1.
- Returns:
Contiguous train, validation, and test sequences sharing topology.
- Return type:
- Raises:
ValueError – If ratios do not sum to
1.0, any minimum is violated, or the sequence is too short for the requested split.
Model¶
GraphKoopmanModel: encoder, Koopman operator, and decoder composition.
- class koopman_graph.model.GraphKoopmanModel(encoder, decoder, latent_dim, time_step, *, koopman_init_mode='identity_noise', koopman_init_scale=0.01, koopman_parameterization='dense', koopman_max_spectral_radius=1.0, control_dim=0)[source]¶
Bases:
ModuleTopology-aware Koopman dynamics model for graph snapshots.
Composes a GNN encoder (lifting), a finite-dimensional Koopman operator (linear latent evolution), and a symmetric GNN decoder (reconstruction).
- encoder¶
Topology-aware encoder for latent lifting.
- Type:
- decoder¶
Symmetric GNN decoder for physical reconstruction.
- Type:
- time_step¶
Physical time increment associated with one model step. Used by
spectrum()to convert discrete eigenvalues into continuous-time growth rates and frequencies.- Type:
- koopman¶
Learnable linear propagator in latent space.
- Type:
- spectrum()[source]¶
Analyze the learned Koopman operator spectrum.
Uses
time_stepto convert discrete eigenvalues into continuous-time growth rates and frequencies.- Returns:
Magnitude-sorted eigenvalues, eigenvectors, and continuous-time mode characteristics.
- Return type:
- save(path)[source]¶
Persist model weights and architecture configuration to disk.
- Parameters:
path (str or Path) – Destination checkpoint file (
.pt). Parent directories are created when missing.
- classmethod load(path, *, map_location=None)[source]¶
Load a trained model from a checkpoint file.
Reconstructs encoder, decoder, and Koopman operator architecture from the saved configuration and restores learned weights.
- Parameters:
map_location (str, torch.device, or None, optional) – Device mapping forwarded to
torch.load().
- Returns:
Ready-to-use model in evaluation mode.
- Return type:
- forward(x_or_data, edge_index=None, edge_weight=None, control=None)[source]¶
Predict the next graph snapshot from the current one.
Performs encode → linear Koopman advance → decode for a single step.
- Parameters:
x_or_data (Tensor or Data) – Either a PyG
Dataobject or node featuresxof shape(num_nodes, in_channels).edge_index (Tensor, optional) – Edge index with shape
(2, num_edges). Required whenx_or_datais a tensor; ignored forDatainput.edge_weight (Tensor, optional) – Scalar edge weights with shape
(num_edges,). Required whenx_or_datais a tensor and weights are used; ignored forDatainput.control (Tensor or None, optional) – Exogenous control input for this step. Required when
control_dimis positive.
- Returns:
Predicted node features of shape
(num_nodes, out_channels).- Return type:
Tensor
- predict(initial_graph, steps, edge_index=None, edge_weight=None, controls=None, future_topologies=None)[source]¶
Autoregressively predict future graph snapshots.
Encodes the initial graph once, advances the latent state with the Koopman operator for
stepsiterations, and decodes after each step. Runs in evaluation mode without gradient tracking.When
future_topologiesis omitted, each rollout step decodes with the hold-last-known topology: the initial graph topology is used for step 0, and each subsequent step reuses the most recently provided topology. Pass oneDataobject per rollout step (topology only; node features are ignored) to supply a known future rewiring schedule.- Parameters:
initial_graph (Tensor or Data) – Either a PyG
Dataobject or node featuresxof shape(num_nodes, in_channels).steps (int) – Number of future snapshots to predict (must be >= 1).
edge_index (Tensor, optional) – Edge index with shape
(2, num_edges). Required wheninitial_graphis a tensor; ignored forDatainput.edge_weight (Tensor, optional) – Scalar edge weights with shape
(num_edges,). Required wheninitial_graphis a tensor and weights are used; ignored forDatainput.controls (sequence of Tensor or None, optional) – Future control inputs for each rollout step. Required with length
stepswhencontrol_dimis positive.future_topologies (sequence of Data or None, optional) – Known topologies for rollout decode steps. Shorter sequences hold the last provided topology for remaining steps.
- Returns:
stepspredicted graph snapshots. EachData.xhas shape(num_nodes, out_channels)and carries theedge_index(and optionaledge_weight) used for that step’s decode.- Return type:
list of Data
- Raises:
ValueError – If
steps < 1or controls are missing/invalid for a controlled model.
- evaluate(sequence, *, horizons=(3, 6, 12), start_indices=None)[source]¶
Evaluate multi-horizon forecast accuracy on a snapshot sequence.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Evaluation snapshots with shared topology.
horizons (sequence of int, optional) – Forecast horizons to report. Default is
(3, 6, 12).start_indices (sequence of int or None, optional) – Forecast-origin indices. When
None, uses every valid origin insequence.
- Returns:
Per-horizon and aggregate MAE, RMSE, and MAPE.
- Return type:
- fit(data_sequence, *, epochs=100, lr=0.001, optimizer=<class 'torch.optim.adam.Adam'>, device=None, loss_weights=None, loss_weight_schedule=None, rollout_horizon=None, rollout_start_indices=None, rollout_starts_per_epoch=None, rollout_start_seed=None, lr_scheduler=None, window_length=None, batch_size=8, windows_per_epoch=None, window_seed=None, max_grad_norm=None, early_stopping_patience=None, early_stopping_min_delta=0.0, early_stopping_monitor='auto', validation_sequence=None, restore_best_weights=False, checkpoint_path=None, **optimizer_kwargs)[source]¶
Train encoder, Koopman operator, and decoder end-to-end.
Minimizes a weighted sum of one-step MSE and optional forward and backward consistency terms:
loss = w_r * recon_loss + w_f * ||K z_t - z_{t+1}||^2 + w_b * ||z_t - z_{t+1} K^{\dagger}||^2
where
z_tandz_{t+1}are encoder outputs for consecutive snapshots and weights(w_r, w_f, w_b)come from aLossWeightsobject or an optional per-epoch schedule.When
data_sequenceis a list ofGraphSnapshotSequenceobjects, losses are averaged across trajectories before each optimizer step.- Parameters:
data_sequence (GraphSnapshotSequence, sequence of Data, or sequence of GraphSnapshotSequence) – One training trajectory or multiple trajectories of the same system. A plain list of
Datasnapshots is treated as a single trajectory; a list whose first element is aGraphSnapshotSequenceis treated as multiple trajectories.epochs (int, optional) – Number of training epochs. Default is
100.lr (float, optional) – Learning rate passed to the optimizer. Default is
1e-3.optimizer (callable, optional) – Optimizer class. Default is
torch.optim.Adam.device (str, torch.device, or None, optional) – Device for training. Defaults to the model’s current device, or CPU if the model has no parameters.
loss_weights (LossWeights or None, optional) – Static loss weights for all epochs. When
Noneand no schedule is provided, defaults to reconstruction-only training.loss_weight_schedule (callable or None, optional) – Callable
epoch -> LossWeightsapplied each epoch. Overridesloss_weightswhen set.rollout_horizon (int or None, optional) – Number of autoregressive rollout steps used when
loss_weights.rolloutis non-zero. Defaults tonum_timesteps - 1.rollout_start_indices (sequence of int,
"all", or None, optional) – Rollout-loss origin indices.Noneuses[0];"all"uses every valid origin for the rollout horizon.rollout_starts_per_epoch (int or None, optional) – When set, randomly sample this many rollout origins each epoch.
rollout_start_seed (int or None, optional) – Base seed for random rollout-origin sampling. The effective seed is
rollout_start_seed + epoch.lr_scheduler (LRScheduler or callable, optional) – Learning-rate scheduler instance or factory
optimizer -> scheduler. Stepped once per epoch after the optimizer update.window_length (int or None, optional) – Fixed number of snapshots per training window. When set, enables mini-batch training with multiple optimizer steps per epoch.
Nonepreserves full-sequence single-step training.batch_size (int, optional) – Number of temporal windows averaged per optimizer step. Used only when
window_lengthis set. Default is8.windows_per_epoch (int or None, optional) – Maximum sampled windows per epoch.
Noneuses every valid window across all trajectories.window_seed (int or None, optional) – Base seed for reproducible epoch-specific window shuffling.
max_grad_norm (float or None, optional) – When set, clip the global gradient norm before each optimizer step.
early_stopping_patience (int or None, optional) – Stop training when training loss fails to improve for this many consecutive epochs. Disabled when
None.early_stopping_min_delta (float, optional) – Minimum decrease in the monitored loss to count as improvement. Default is
0.0.early_stopping_monitor ({"auto", "train", "val"}, optional) – Loss used for early stopping and best-epoch tracking.
"auto"monitors validation loss whenvalidation_sequenceis provided, otherwise training loss. Default is"auto".validation_sequence (GraphSnapshotSequence, sequence of Data, sequence of GraphSnapshotSequence, or None, optional) – Optional held-out snapshots for per-epoch validation loss. A single validation sequence is reused for all training trajectories; a list of validation sequences must match the training trajectory count.
restore_best_weights (bool, optional) – When
True, reload in-memory weights from the lowest-loss epoch after training completes. Default isFalse.checkpoint_path (str, Path, or None, optional) – When set, write a checkpoint at the lowest-loss epoch using
save(). Default isNone.**optimizer_kwargs (Any) – Additional keyword arguments forwarded to the optimizer constructor.
- Returns:
Per-epoch training and validation losses and early-stop metadata.
- Return type:
- Raises:
ValueError – If
epochs < 1,early_stopping_patience < 1when set,early_stopping_monitor="val"withoutvalidation_sequence, validation list length mismatches training trajectories, or fewer than two snapshots are provided for training or validation.
Encoders¶
Graph Neural Network encoders for topology-aware latent lifting.
- class koopman_graph.encoder.BaseGNNModule(*, input_channels, input_dim_name, num_layers, activation, convs)[source]¶
Bases:
ModuleShared message-passing stack for GNN encoders and decoders.
- activation¶
Instantiated hidden-layer activation.
- Type:
nn.Module
- convs¶
Ordered graph convolution layers.
- Type:
nn.ModuleList
- forward(x_or_data, edge_index=None, edge_weight=None)[source]¶
Run the stacked message-passing layers on graph node features.
- Parameters:
x_or_data (Tensor or Data) – Either a PyG
Dataobject or node featuresx.edge_index (Tensor or None, optional) – Edge index required when
x_or_datais a tensor.edge_weight (Tensor or None, optional) – Scalar edge weights with shape
(num_edges,). Passed toGCNConvwhen present. Ignored by GAT layers.
- Returns:
Transformed node features with shape
(num_nodes, out_channels).- Return type:
Tensor
- class koopman_graph.encoder.GNNEncoder(in_channels, hidden_channels, latent_dim, *, num_layers=2, activation='relu')[source]¶
Bases:
BaseGNNModuleGCN encoder that lifts node features into a latent space.
Applies stacked Graph Convolutional Network layers with configurable hidden activation. The final layer maps directly to
latent_dimwithout an activation, producing per-node latent vectors suitable for Koopman propagation.Hidden GCN channel width.
- Type:
- class koopman_graph.encoder.GATEncoder(in_channels, hidden_channels, latent_dim, *, num_layers=2, activation='relu', heads=1, dropout=0.0)[source]¶
Bases:
BaseGNNModuleGAT encoder that lifts node features into a latent space.
Applies stacked Graph Attention Network layers with configurable hidden activation. The final layer maps directly to
latent_dimwithout an activation, producing per-node latent vectors suitable for Koopman propagation.Scalar
edge_weightarguments are accepted for API symmetry withGNNEncoderbut are ignored becauseGATConvdoes not consume scalar edge weights.Hidden GAT channel width.
- Type:
Decoder¶
Graph Neural Network decoders for latent-to-physical reconstruction.
- class koopman_graph.decoder.GNNDecoder(latent_dim, hidden_channels, out_channels, *, num_layers=2, activation='relu')[source]¶
Bases:
BaseGNNModuleGCN decoder that maps latent node features back to physical space.
Applies stacked Graph Convolutional Network layers with configurable hidden activation. The final layer maps directly to
out_channelswithout an activation, producing per-node physical feature predictions.Hidden GCN channel width.
- Type:
Koopman Operator¶
Finite-dimensional Koopman operator for latent-state linear propagation.
- class koopman_graph.operator.KoopmanOperator(latent_dim, *, init_mode='identity_noise', init_scale=0.01, parameterization='dense', max_spectral_radius=1.0, control_dim=0)[source]¶
Bases:
ModuleLearnable finite-dimensional Koopman operator matrix K.
Applies the same linear map to each node’s latent vector. For input
zwith trailing dimensionlatent_dim, the uncontrolled forward pass computes:z_next = z @ K.T
When
control_dimis positive, exogenous inputs drive the transition:z_next = z @ K.T + u @ B
where
Khas shape(latent_dim, latent_dim)andBhas shape(control_dim, latent_dim). Global controlsuwith shape(control_dim,)are broadcast to every node; per-node controls use shape(num_nodes, control_dim). Arbitrary leading dimensions are supported (e.g.(num_nodes, latent_dim)or(batch, num_nodes, latent_dim)).- control_term(u, *, num_nodes=None)[source]¶
Map control inputs to a latent-space offset
u @ B.- Parameters:
u (Tensor) – Global control with shape
(control_dim,)or per-node control with shape(num_nodes, control_dim).num_nodes (int or None, optional) – Expected node count when
uis per-node. Used for validation only.
- Returns:
Latent offset with shape
(latent_dim,)for global control or(num_nodes, latent_dim)for per-node control.- Return type:
Tensor
- Raises:
ValueError – If
control_dimis zero,uhas invalid shape, or per-nodeudoes not matchnum_nodes.
- property K: Tensor¶
Assembled Koopman matrix with shape
(latent_dim, latent_dim).For
parameterization="dense"this is the learnable parameter. Forparameterization="odo"it is assembled from orthogonal factors and a bounded diagonal matrix.- Returns:
Current operator matrix
K.- Return type:
Tensor
- reset_parameters()[source]¶
Reinitialize operator parameters according to
init_mode.- Return type:
None
- spectral_radius()[source]¶
Return the spectral radius of the assembled operator matrix.
- Returns:
Scalar tensor with the maximum eigenvalue magnitude.
- Return type:
Tensor
- forward(z, control=None)[source]¶
Advance latent states by one linear Koopman step.
When
control_dimis positive, the controlled update is:z_next = z @ K.T + control_effect
where
control_effectisu @ Bbroadcast for global controluwith shape(control_dim,)or applied per node whenuhas shape(num_nodes, control_dim).- Parameters:
z (Tensor) – Latent states with shape
(..., latent_dim).control (Tensor or None, optional) – Exogenous control input applied during this step. Required when
control_dimis positive.
- Returns:
Advanced latent states with the same shape as
z.- Return type:
Tensor
- Raises:
ValueError – If the trailing dimension of
zdoes not matchlatent_dim, controls are missing for a controlled operator, orcontrolhas an invalid shape.
- inverse_step(z, *, control=None, inverse_matrix=None)[source]¶
Apply one inverse Koopman step to recover the previous latent state.
For forward dynamics
z_{t+1} = z_t @ K.T + u_t @ B, this returns an estimate ofz_tfromz_{t+1}and the controlu_tthat drove the transition.- Parameters:
z (Tensor) – Latent states at time
t+1with shape(..., latent_dim).control (Tensor or None, optional) – Control input that drove the forward transition. Required when
control_dimis positive.inverse_matrix (Tensor or None, optional) – Precomputed
K^{-1}for dense parameterization. When omitted, the inverse is computed on demand.
- Returns:
Recovered latent states at time
t, same shape asz.- Return type:
Tensor
- dense_inverse_matrix()[source]¶
Return the inverse (or pseudo-inverse) of the assembled dense matrix.
Intended for reuse across multiple backward-consistency pair evaluations within one training step.
- Returns:
Matrix
K^{-1}(orK^{\dagger}) with shape(latent_dim, latent_dim).- Return type:
Tensor
- Raises:
ValueError – If
parameterizationis not"dense".
Spectral Analysis¶
Spectral analysis utilities for finite-dimensional Koopman operators.
- class koopman_graph.analysis.KoopmanSpectrum(eigenvalues, eigenvectors, magnitudes, growth_rates, frequencies, time_step)[source]¶
Bases:
objectEigendecomposition and time scales of a discrete Koopman operator.
Eigenpairs are sorted by descending eigenvalue magnitude. Frequencies are reported in cycles per unit time; multiply by
2 * pifor angular frequency.- eigenvalues¶
Complex eigenvalues with shape
(latent_dim,).- Type:
Tensor
- eigenvectors¶
Complex right eigenvectors stored as columns, with shape
(latent_dim, latent_dim).- Type:
Tensor
- magnitudes¶
Eigenvalue magnitudes with shape
(latent_dim,).- Type:
Tensor
- growth_rates¶
Continuous-time exponential growth rates
log(|lambda|) / time_step.- Type:
Tensor
- frequencies¶
Signed continuous-time frequencies
angle(lambda) / (2 * pi * time_step)in cycles per unit time.- Type:
Tensor
- mode_amplitudes(latent_states)[source]¶
Project latent states onto the Koopman eigenvector basis.
For a latent row vector
z, the returned amplitudesasatisfyz.T = eigenvectors @ a. Any leading dimensions are preserved.- Parameters:
latent_states (Tensor) – Latent states with shape
(..., latent_dim).- Returns:
Complex mode amplitudes with the same shape as
latent_states.- Return type:
Tensor
- Raises:
ValueError – If the trailing latent dimension does not match the spectrum.
RuntimeError – If the eigenvector matrix is singular.
- koopman_graph.analysis.compute_spectrum(operator, time_step)[source]¶
Compute the sorted spectrum and continuous-time mode characteristics.
- Parameters:
operator (Tensor) – Square discrete-time Koopman matrix with shape
(latent_dim, latent_dim).time_step (float) – Positive physical duration represented by one operator step.
- Returns:
Eigenpairs sorted by descending magnitude, plus growth rates and frequencies converted using
time_step.- Return type:
- Raises:
ValueError – If
operatoris not a non-empty square matrix ortime_stepis not positive.TypeError – If
operatoris not floating-point or complex.
- koopman_graph.analysis.decode_mode_shapes(model, x_or_data, mode_indices=None, *, edge_index=None, perturbation=0.001)[source]¶
Decode latent Koopman directions into spatial node-feature mode shapes.
The decoder is generally nonlinear, so mode shapes are estimated with a centered finite-difference directional derivative around the encoded graph. Real and imaginary parts of complex eigenvectors are probed separately and combined into a complex-valued mode shape.
- Parameters:
model (GraphKoopmanModel) – Model whose operator spectrum and decoder are analyzed.
x_or_data (Tensor or Data) – Reference graph used as the decoder linearization point.
mode_indices (sequence of int or None, optional) – Indices into the magnitude-sorted spectrum. Defaults to every mode.
edge_index (Tensor or None, optional) – Graph edges, required when
x_or_datais a feature tensor.perturbation (float, optional) – Positive centered finite-difference step. Default is
1e-3.
- Returns:
Complex mode shapes with shape
(num_modes, num_nodes, out_channels).- Return type:
Tensor
- Raises:
ValueError – If
perturbationis not positive or a mode index is out of range.
Baselines¶
Classical topology-agnostic Koopman baselines.
- class koopman_graph.baselines.DMDBaseline(*, time_step=1.0, rank=None)[source]¶
Bases:
objectDynamic Mode Decomposition baseline on flattened node states.
DMDBaselineignores graph message passing: each graph snapshot is reshaped into one vector and a linear map is fit by least squares. The learned operator follows the package conventionx_next = x @ K.T.- Parameters:
time_step (float, optional) – Physical duration represented by one snapshot transition. Used by
spectrum(). Default is1.0.rank (int or None, optional) – Optional truncated-SVD rank for the data matrix.
Noneuses the full least-squares solution. Default isNone.
- fit(sequence)[source]¶
Fit the DMD operator from consecutive graph snapshots.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Training snapshots with shared topology.
- Returns:
The fitted baseline.
- Return type:
- Raises:
ValueError – If fewer than two snapshots are provided or rank is invalid.
- class koopman_graph.baselines.DMDcBaseline(*, time_step=1.0, rank=None)[source]¶
Bases:
objectDynamic Mode Decomposition with control on flattened node states.
DMDcBaselineextendsDMDBaselinewith exogenous inputs, fittingx_{t+1} = x_t @ K.T + u_t @ Bby least squares on flattened graph snapshots. Global controls use shape(control_dim,); per-node controls are flattened during fitting and prediction.- Parameters:
time_step (float, optional) – Physical duration represented by one snapshot transition. Used by
spectrum(). Default is1.0.rank (int or None, optional) – Optional truncated-SVD rank for the augmented regression.
Noneuses the full least-squares solution. Default isNone.
- fit(sequence)[source]¶
Fit controlled DMD operators from consecutive graph snapshots.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Training snapshots with shared topology and control inputs.
- Returns:
The fitted baseline.
- Return type:
- Raises:
ValueError – If fewer than two snapshots are provided, controls are missing, or rank is invalid.
- predict(initial_graph, steps, controls)[source]¶
Autoregressively predict future graph snapshots with future controls.
- Parameters:
initial_graph (Data) – Initial graph snapshot. Its topology is copied to every prediction.
steps (int) – Number of future snapshots to predict.
controls (sequence of Tensor) – Future control inputs, one per rollout step. Global controls use shape
(control_dim,); per-node controls use(num_nodes, control_dim).
- Returns:
Predicted graph snapshots with the same node/feature shape as the fitted training data.
- Return type:
list of Data
- class koopman_graph.baselines.EDMDBaseline(*, time_step=1.0, rank=None, polynomial_degree=2)[source]¶
Bases:
objectExtended DMD baseline with polynomial observables.
EDMD lifts flattened graph states into a fixed observable space, fits a linear Koopman operator there, and learns a least-squares decoder back to physical node features.
polynomial_degree=1is an identity observable;polynomial_degree=2appends elementwise squared terms.- Parameters:
time_step (float, optional) – Physical duration represented by one snapshot transition. Used by
spectrum(). Default is1.0.rank (int or None, optional) – Optional truncated-SVD rank for the observable data matrix.
Noneuses the full least-squares solution. Default isNone.polynomial_degree ({1, 2}, optional) – Polynomial observable degree. Default is
2.
- fit(sequence)[source]¶
Fit EDMD operator and linear reconstruction decoder.
- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Training snapshots with shared topology.
- Returns:
The fitted baseline.
- Return type:
- Raises:
ValueError – If fewer than two snapshots are provided or rank is invalid.
- predict(initial_graph, steps)[source]¶
Autoregressively predict future graph snapshots.
- Parameters:
initial_graph (Data) – Initial graph snapshot. Its topology is copied to every prediction.
steps (int) – Number of future snapshots to predict.
- Returns:
Predicted graph snapshots with the same node/feature shape as the fitted training data.
- Return type:
list of Data
- Raises:
RuntimeError – If the baseline has not been fit.
ValueError – If
steps < 1or graph metadata does not match the fit data.
Data Utilities¶
Utilities for spatiotemporal graph snapshot sequences.
- class koopman_graph.data.WindowSampler(sequences, *, window_length, batch_size=8, windows_per_epoch=None, shuffle=True, seed=None)[source]¶
Bases:
objectSample fixed-length temporal windows from one or more trajectories.
- Parameters:
sequences (GraphSnapshotSequence or sequence of GraphSnapshotSequence) – Source trajectories. Each must contain at least
window_lengthsnapshots.window_length (int) – Number of snapshots per sampled window. Must be at least
2.batch_size (int, optional) – Number of windows yielded together. Default is
8.windows_per_epoch (int or None, optional) – Maximum number of windows sampled per epoch.
Noneuses every valid window. Values larger than the available window count are capped.shuffle (bool, optional) – Randomize window order each epoch. Default is
True.seed (int or None, optional) – Base seed for reproducible epoch-specific shuffling.
- property num_windows: int¶
Return the total number of valid windows.
- Returns:
Number of valid windows across every source trajectory.
- Return type:
- class koopman_graph.data.TemporalSplit(train, val, test)[source]¶
Bases:
objectTrain, validation, and test snapshot sequences from a temporal split.
- train¶
Earliest contiguous snapshots used for training.
- Type:
- val¶
Middle contiguous snapshots used for validation.
- Type:
- test¶
Latest contiguous snapshots held out for evaluation.
- Type:
- koopman_graph.data.temporal_split(sequence, *, train_ratio=0.7, val_ratio=0.1, test_ratio=0.2, min_train_timesteps=2, min_val_timesteps=2, min_test_timesteps=1)[source]¶
Split a snapshot sequence into contiguous train, validation, and test sets.
Earlier snapshots are assigned to training, later snapshots to validation and test. Ratios must sum to
1.0.- Parameters:
sequence (GraphSnapshotSequence) – Full time-ordered snapshot sequence to split.
train_ratio (float, optional) – Fraction of timesteps assigned to training. Default is
0.7.val_ratio (float, optional) – Fraction assigned to validation. Default is
0.1.test_ratio (float, optional) – Fraction assigned to test. Default is
0.2.min_train_timesteps (int, optional) – Minimum training snapshots required. Default is
2.min_val_timesteps (int, optional) – Minimum validation snapshots required. Default is
2.min_test_timesteps (int, optional) – Minimum test snapshots required. Default is
1.
- Returns:
Contiguous train, validation, and test sequences sharing topology.
- Return type:
- Raises:
ValueError – If ratios do not sum to
1.0, any minimum is violated, or the sequence is too short for the requested split.
- class koopman_graph.data.GraphSnapshotSequence(snapshots, *, allow_dynamic_topology=False, control_inputs=None)[source]¶
Bases:
objectContainer for a time-ordered sequence of PyG
Datagraph snapshots.By default all snapshots must share the same
edge_index, optionaledge_weight, node count, and feature dimension. Setallow_dynamic_topology=Trueto permit per-snapshotedge_indexwhile still requiring a fixed node count and feature dimension. Optionalcontrol_inputsstore exogenous inputsu_tapplied when advancing from snapshotttot+1. Downstream training APIs should require at least two snapshots; construction here allows a single snapshot for inspection or prediction-only workflows.Notes
Read-only views of sequence metadata are exposed as
snapshots,edge_index,edge_weight,is_dynamic_topology,control_inputs,has_controls,control_dim,num_nodes,num_timesteps, andin_channels. Theedge_indexandedge_weightproperties are only defined for static-topology sequences; usesequence[t].edge_indexwhenis_dynamic_topologyisTrue.- classmethod from_arrays(node_features, edge_index, *, edge_weight=None, control_inputs=None, dtype=torch.float32)[source]¶
Build a sequence from node feature arrays and a shared topology.
- Parameters:
node_features (array-like) – Array with shape
(num_timesteps, num_nodes, in_channels).edge_index (array-like) – Shared edge index with shape
(2, num_edges).edge_weight (array-like, optional) – Shared scalar edge weights with shape
(num_edges,). When provided, attached to every snapshot.control_inputs (array-like, optional) – Per-timestep control inputs with shape
(num_timesteps, control_dim)or(num_timesteps, num_nodes, control_dim).dtype (torch.dtype, optional) – Floating dtype used when converting numpy inputs to torch tensors. Default is
torch.float32.
- Returns:
Validated snapshot sequence.
- Return type:
- Raises:
ValueError – If
node_features,edge_index, oredge_weighthave invalid shape.
- classmethod from_dynamic_arrays(node_features, edge_indices, *, edge_weights=None, control_inputs=None, dtype=torch.float32)[source]¶
Build a dynamic-topology sequence from per-timestep edge indices.
- Parameters:
node_features (array-like) – Array with shape
(num_timesteps, num_nodes, in_channels).edge_indices (sequence of array-like) – One edge index per timestep, each with shape
(2, num_edges_t).edge_weights (sequence of array-like or None, optional) – Optional per-timestep scalar edge weights aligned with
edge_indices. When provided, must have the same length asedge_indices.control_inputs (array-like, optional) – Per-timestep control inputs with shape
(num_timesteps, control_dim)or(num_timesteps, num_nodes, control_dim).dtype (torch.dtype, optional) – Floating dtype used when converting numpy inputs to torch tensors. Default is
torch.float32.
- Returns:
Validated snapshot sequence with
allow_dynamic_topology=True.- Return type:
- Raises:
ValueError – If shapes are inconsistent or
edge_indiceslength mismatchesnum_timesteps.
- property is_dynamic_topology: bool¶
Return whether snapshots use time-varying
edge_index.- Returns:
Truewhen the sequence was constructed withallow_dynamic_topology=Trueand at least one snapshot differs inedge_indexfrom the first snapshot.- Return type:
- property allow_dynamic_topology: bool¶
Return whether dynamic topology mode was enabled at construction.
- Returns:
Truewhen per-snapshotedge_indexvalues are permitted.- Return type:
- property control_inputs: Tensor | None¶
Return per-timestep control inputs when present.
- Returns:
Control tensor with shape
(num_timesteps, control_dim)or(num_timesteps, num_nodes, control_dim).- Return type:
Tensor or None
- property has_controls: bool¶
Return whether the sequence carries control inputs.
- Returns:
Truewhencontrol_inputsis notNone.- Return type:
- property control_dim: int¶
Return the control feature dimension.
- Returns:
Control dimension when controls are present, otherwise
0.- Return type:
- control_at(index)[source]¶
Return the control input driving transition from snapshot
index.- Parameters:
index (int) – Timestep index in
[0, num_timesteps - 1].- Returns:
Control vector for the transition
index -> index + 1.- Return type:
Tensor
- Raises:
ValueError – If controls are absent or
indexis out of range.
- rollout_controls(start, steps)[source]¶
Return controls for an autoregressive rollout from a start snapshot.
- Parameters:
- Returns:
Control inputs for each rollout step. Empty when the sequence has no controls.
- Return type:
list of Tensor
- Raises:
ValueError – If
startorstepsare invalid or controls are unavailable for the requested horizon.
- property snapshots: list[Data]¶
Return the underlying list of graph snapshots.
- Returns:
Time-ordered PyG graph snapshots.
- Return type:
list of Data
- property edge_index: Tensor¶
Return the shared edge index for static-topology sequences.
- Returns:
Edge index with shape
(2, num_edges).- Return type:
Tensor
- Raises:
ValueError – If
is_dynamic_topologyisTrue.
- property edge_weight: Tensor | None¶
Return the shared scalar edge weights for static-topology sequences.
- Returns:
Edge weights with shape
(num_edges,), orNonewhen the sequence is unweighted.- Return type:
Tensor or None
- Raises:
ValueError – If
is_dynamic_topologyisTrue.
- property num_nodes: int¶
Return the number of nodes in the graph topology.
- Returns:
Node count shared across all snapshots.
- Return type:
- property num_timesteps: int¶
Return the number of timesteps in the sequence.
- Returns:
Length of the temporal sequence.
- Return type:
- property in_channels: int¶
Return the node feature dimension.
- Returns:
Feature dimension shared across all snapshots.
- Return type:
- slice(start, stop)[source]¶
Return a contiguous temporal sub-sequence.
- Parameters:
- Returns:
Snapshots in
[start, stop)with matching controls and topology policy.- Return type:
- Raises:
ValueError – If the bounds are negative, empty, reversed, or exceed the sequence length.
- koopman_graph.data.resolve_sequence(sequence)[source]¶
Normalize input into a validated snapshot sequence.
Wraps a plain sequence of
Datasnapshots inGraphSnapshotSequence; existing sequences are returned unchanged.- Parameters:
sequence (GraphSnapshotSequence or sequence of Data) – Raw snapshot input from a training, baseline, or inference API.
- Returns:
Validated sequence container.
- Return type:
Losses¶
Loss functions for Koopman graph dynamics training.
- class koopman_graph.losses.ForwardConsistencyLoss(*args, **kwargs)[source]¶
Bases:
ModulePenalize deviation from linear latent evolution under the Koopman operator.
For latent encodings
z_tandz_{t+1}, the loss is the mean squared error betweenK @ z_t(implemented asz_t @ K.T) andz_{t+1}:\[\mathcal{L}_{\mathrm{fc}} = \| K z_t - z_{t+1} \|^2\]Notes
This module is stateless. Call
forward()with consecutive latent encodings and aKoopmanOperator.- forward(z_t, z_t1, koopman, *, control=None)[source]¶
Compute forward consistency loss between consecutive latent states.
- Parameters:
z_t (Tensor) – Latent encoding at time
t, shape(..., latent_dim).z_t1 (Tensor) – Latent encoding at time
t+1, same shape asz_t.koopman (
KoopmanOperator) – Learnable linear propagator applied toz_t.control (Tensor or None, optional) – Control input driving the transition from
ttot+1.
- Returns:
Scalar mean-squared error between
koopman(z_t, control)andz_t1.- Return type:
Tensor
- class koopman_graph.losses.BackwardConsistencyLoss(*args, **kwargs)[source]¶
Bases:
ModulePenalize deviation from inverse linear latent evolution under K.
For latent encodings
z_tandz_{t+1}with forward dynamicsz_{t+1} = z_t @ K.T, the backward (adjoint) consistency term is the mean squared error betweenz_tand the inverse propagation ofz_{t+1}:\[\mathcal{L}_{\mathrm{bc}} = \| z_t - z_{t+1} K^{\dagger} \|^2\]where
K^{\dagger}denotes an inverse or pseudo-inverse ofK.Trade-offs¶
Benefits: Enforces bidirectional linear consistency, which can improve Koopman operator identifiability and training stability when paired with the forward consistency term (see Lusch et al., 2018; Mezić, 2021).
Costs: Dense unconstrained
Krequires a matrix inverse or pseudo-inverse. The ODO parameterization (parameterization"odo") provides a cheap exact factorized inverse and bounds the spectral radius. For denseK, sequence-level training precomputes the inverse once per step rather than per snapshot pair.Notes
This module is stateless. Call
forward()with consecutive latent encodings and aKoopmanOperator.- forward(z_t, z_t1, koopman, *, control=None, inverse_matrix=None)[source]¶
Compute backward consistency loss between consecutive latent states.
- Parameters:
z_t (Tensor) – Latent encoding at time
t, shape(..., latent_dim).z_t1 (Tensor) – Latent encoding at time
t+1, same shape asz_t.koopman (
KoopmanOperator) – Learnable linear propagator whose inverse step is applied toz_t1.control (Tensor or None, optional) – Control input that drove the forward transition from
ttot+1.inverse_matrix (Tensor or None, optional) – Precomputed dense inverse matrix reused across pair evaluations.
- Returns:
Scalar mean-squared error between
z_tand the inverse propagation ofz_t1.- Return type:
Tensor
- class koopman_graph.losses.EigenvalueRegularizationLoss(*args, **kwargs)[source]¶
Bases:
ModulePenalize Koopman eigenvalues outside the unit circle.
Implements a hinge-style eigenloss that activates only when eigenvalue magnitudes exceed one:
\[\mathcal{L}_{\mathrm{eig}} = \mathrm{mean}\big(\max(|\lambda_i| - 1, 0)^2\big)\]For the ODO parameterization, eigenvalues are read directly from the bounded diagonal factor, avoiding an explicit eigendecomposition.
Trade-offs¶
Benefits: Encourages discrete-time stability without hard-constraining the operator parameterization. Complements spectrally constrained ODO initialization (DeepKoopFormer-style factorization; eigeninit/eigenloss literature).
Costs: Dense
Krequirestorch.linalg.eigvalseach evaluation. Use the ODO parameterization when a hard spectral-radius bound is preferred.Notes
This module is stateless. Call
forward()with aKoopmanOperator.- forward(koopman)[source]¶
Compute the unit-circle eigenvalue hinge penalty.
- Parameters:
koopman (
KoopmanOperator) – Operator whose eigenvalue magnitudes are penalized.- Returns:
Scalar hinge penalty (zero when all magnitudes are <= 1).
- Return type:
Tensor
- koopman_graph.losses.rollout_sequence_loss(model, sequence, *, horizon, start=0)[source]¶
Compute autoregressive rollout reconstruction loss from one start snapshot.
Encodes
sequence[start]once, advances the latent state with the Koopman operator forhorizonsteps, and compares decoded predictions to the observed snapshotssequence[start + 1 : start + horizon + 1]. This term aligns training withpredict().- Parameters:
model (nn.Module) – Model with
encoder,koopman, anddecoderattributes.sequence (
GraphSnapshotSequence) – Time-ordered snapshots. For dynamic-topology sequences, each decode step uses the target snapshot’sedge_index.horizon (int) – Number of rollout steps (must be >= 1).
start (int, optional) – Index of the initial snapshot. Default is
0.
- Returns:
Scalar mean rollout reconstruction loss over
horizonsteps.- Return type:
Tensor
- Raises:
ValueError – If
horizon < 1,start < 0, or the sequence is too short.
- koopman_graph.losses.rollout_multi_start_loss(model, sequence, *, horizon, start_indices)[source]¶
Average rollout reconstruction loss over multiple start snapshots.
- Parameters:
model (nn.Module) – Model with
encoder,koopman, anddecoderattributes.sequence (GraphSnapshotSequence) – Time-ordered snapshots.
horizon (int) – Number of rollout steps (must be >= 1).
start_indices (sequence of int) – Zero-based origin indices for each rollout.
- Returns:
Scalar mean rollout loss across origins.
- Return type:
Tensor
- Raises:
ValueError – If
start_indicesis empty or any origin is invalid.
Training¶
Training utilities for GraphKoopmanModel.
- class koopman_graph.training.LossWeights(reconstruction=1.0, forward=0.0, backward=0.0, rollout=0.0, eigenvalue=0.0)[source]¶
Bases:
objectWeights for reconstruction and consistency loss terms.
- class koopman_graph.training.TrainingLossBreakdown(reconstruction, forward, backward, rollout, eigenvalue, total)[source]¶
Bases:
objectUnweighted and weighted training loss terms for one batch or epoch.
- reconstruction¶
Mean one-step reconstruction loss.
- Type:
Tensor
- forward¶
Mean forward consistency loss.
- Type:
Tensor
- backward¶
Mean backward consistency loss.
- Type:
Tensor
- rollout¶
Mean rollout reconstruction loss.
- Type:
Tensor
- eigenvalue¶
Eigenvalue hinge regularization loss.
- Type:
Tensor
- total¶
Weighted sum of all active loss terms.
- Type:
Tensor
- classmethod zeros(device)[source]¶
Return a zero breakdown on
device.- Parameters:
device (torch.device) – Device for the zero tensors.
- Returns:
Breakdown with all scalar terms set to zero.
- Return type:
- koopman_graph.training.mean_training_loss_breakdown(breakdowns)[source]¶
Average loss breakdowns across multiple trajectories.
- Parameters:
breakdowns (sequence of TrainingLossBreakdown) – Per-trajectory breakdowns to average.
- Returns:
Element-wise mean across
breakdowns.- Return type:
- Raises:
ValueError – If
breakdownsis empty.
- class koopman_graph.training.FitHistory(loss, epochs, reconstruction_loss=<factory>, forward_loss=<factory>, backward_loss=<factory>, rollout_loss=<factory>, eigenvalue_loss=<factory>, val_loss=None, val_reconstruction_loss=None, val_forward_loss=None, val_backward_loss=None, val_rollout_loss=None, val_eigenvalue_loss=None, stopped_early=False, best_epoch=None, best_loss=None)[source]¶
Bases:
objectTraining history returned by
GraphKoopmanModel.fit().- epochs¶
Number of training epochs completed (may be less than requested when early stopping triggers).
- Type:
- val_loss¶
Per-epoch validation loss when a validation sequence is provided.
- val_reconstruction_loss¶
Per-epoch unweighted validation reconstruction loss.
- val_forward_loss¶
Per-epoch unweighted validation forward consistency loss.
- val_backward_loss¶
Per-epoch unweighted validation backward consistency loss.
- koopman_graph.training.constant_loss_weights(*, reconstruction=1.0, forward=0.0, backward=0.0, rollout=0.0, eigenvalue=0.0)[source]¶
Build static loss weights for all training epochs.
- Parameters:
reconstruction (float, optional) – Weight on the reconstruction loss. Default is
1.0.forward (float, optional) – Weight on the forward consistency loss. Default is
0.0.backward (float, optional) – Weight on the backward consistency loss. Default is
0.0.rollout (float, optional) – Weight on the rollout reconstruction loss. Default is
0.0.eigenvalue (float, optional) – Weight on the eigenvalue hinge penalty. Default is
0.0.
- Returns:
Fixed weights applied uniformly across epochs.
- Return type:
- koopman_graph.training.linear_ramp_loss_weights(start, end, ramp_epochs)[source]¶
Linearly interpolate loss weights over the first
ramp_epochs.- Parameters:
start (
LossWeights) – Weights at epoch0.end (
LossWeights) – Weights reached at epochramp_epochs - 1and held thereafter.ramp_epochs (int) – Number of epochs over which to interpolate. Must be >= 1.
- Returns:
Schedule mapping epoch index to
LossWeights.- Return type:
callable
- Raises:
ValueError – If
ramp_epochs < 1.
- koopman_graph.training.one_step_loss(model, snapshot_t, snapshot_t1, *, control=None)[source]¶
Compute one-step MSE between model prediction and the next snapshot.
- Parameters:
model (nn.Module) – Model implementing a single-step forward pass (e.g.
GraphKoopmanModel).snapshot_t (Data) – Graph snapshot at time
t.snapshot_t1 (Data) – Graph snapshot at time
t+1(prediction target).control (Tensor or None, optional) – Control input driving the transition from
ttot+1.
- Returns:
Scalar mean-squared error loss.
- Return type:
Tensor
- koopman_graph.training.compute_sequence_loss(model, sequence)[source]¶
Average one-step prediction loss over consecutive snapshot pairs.
- Parameters:
model (nn.Module) – Model implementing a single-step forward pass.
sequence (
GraphSnapshotSequence) – Time-ordered snapshots with at least two timesteps.
- Returns:
Scalar average loss over all consecutive pairs.
- Return type:
Tensor
- Raises:
ValueError – If
sequencecontains fewer than two snapshots.
- koopman_graph.training.compute_forward_consistency_sequence_loss(model, sequence)[source]¶
Average forward consistency loss over consecutive snapshot pairs.
- Parameters:
model (nn.Module) – Model with
encoderandkoopmanattributes.sequence (
GraphSnapshotSequence) – Time-ordered snapshots with at least two timesteps.
- Returns:
Scalar average forward consistency loss.
- Return type:
Tensor
- Raises:
ValueError – If
sequencecontains fewer than two snapshots.
- koopman_graph.training.compute_backward_consistency_sequence_loss(model, sequence)[source]¶
Average backward consistency loss over consecutive snapshot pairs.
- Parameters:
model (nn.Module) – Model with
encoderandkoopmanattributes.sequence (
GraphSnapshotSequence) – Time-ordered snapshots with at least two timesteps.
- Returns:
Scalar average backward consistency loss.
- Return type:
Tensor
- Raises:
ValueError – If
sequencecontains fewer than two snapshots.
- koopman_graph.training.compute_eigenvalue_regularization_loss(model)[source]¶
Compute the eigenvalue hinge penalty for the model Koopman operator.
- Parameters:
model (nn.Module) – Model with a
koopmanattribute.- Returns:
Scalar eigenvalue regularization loss.
- Return type:
Tensor
- koopman_graph.training.resolve_rollout_start_indices(sequence, *, horizon, rollout_start_indices=None, rollout_starts_per_epoch=None, rollout_start_seed=None, epoch=0)[source]¶
Resolve rollout-loss origin indices for one training epoch.
- Parameters:
sequence (GraphSnapshotSequence) – Training snapshots.
horizon (int) – Rollout horizon in steps.
rollout_start_indices (sequence of int,
"all", or None, optional) – Explicit origins, all valid origins, orNonefor the default[0].rollout_starts_per_epoch (int or None, optional) – When set, randomly sample this many valid origins each epoch. Overrides
rollout_start_indicesexcept when that argument is an explicit non-empty index list.rollout_start_seed (int or None, optional) – Base seed for random origin sampling. The effective seed is
rollout_start_seed + epochwhen provided.epoch (int, optional) – Zero-based epoch index mixed into the random seed. Default is
0.
- Returns:
Valid zero-based rollout origin indices.
- Return type:
- Raises:
ValueError – If
horizonis invalid, no origins are available, or an origin is out of range.
- koopman_graph.training.compute_rollout_loss(model, sequence, *, horizon, start_indices)[source]¶
Compute rollout reconstruction loss averaged over start origins.
- Parameters:
model (nn.Module) – Model with encoder, Koopman operator, and decoder.
sequence (GraphSnapshotSequence) – Training snapshots.
horizon (int) – Number of rollout steps.
start_indices (sequence of int) – Rollout origin indices.
- Returns:
Scalar mean rollout loss across origins.
- Return type:
Tensor
- koopman_graph.training.compute_training_loss(model, sequence, loss_weights, *, rollout_horizon=None, rollout_start_indices=None)[source]¶
Compute reconstruction, consistency, and rollout losses.
- Parameters:
model (nn.Module) – Model implementing a single-step forward pass with encoder and Koopman operator.
sequence (
GraphSnapshotSequence) – Time-ordered snapshots with at least two timesteps.loss_weights (
LossWeights) – Weights for reconstruction, forward, backward, and rollout terms.rollout_horizon (int or None, optional) – Number of rollout steps when
loss_weights.rolloutis non-zero. Defaults tosequence.num_timesteps - 1.rollout_start_indices (sequence of int or None, optional) – Rollout origin indices. Defaults to
[0]whenNone.
- Returns:
Unweighted per-term losses and the weighted total.
- Return type:
- koopman_graph.training.train_one_epoch(model, sequences, optimizer, loss_weights, *, max_grad_norm=None, rollout_horizon=None, rollout_start_indices=None)[source]¶
Run one training epoch and return the averaged loss breakdown.
- Parameters:
model (nn.Module) – Model to train.
sequences (GraphSnapshotSequence or sequence of GraphSnapshotSequence) – One or more training trajectories.
optimizer (Optimizer) – PyTorch optimizer used for the parameter update.
loss_weights (
LossWeights) – Weights for reconstruction and consistency terms this epoch.max_grad_norm (float or None, optional) – When set, clip the global gradient norm to this value before
optimizer.step().rollout_horizon (int or None, optional) – Number of rollout steps when
loss_weights.rolloutis non-zero.rollout_start_indices (sequence of int or None, optional) – Rollout origin indices for this epoch.
- Returns:
Mean loss breakdown across trajectories.
- Return type:
- koopman_graph.training.train_windowed_epoch(model, sampler, optimizer, loss_weights, *, epoch=0, max_grad_norm=None, rollout_horizon=None, rollout_start_indices=None, rollout_starts_per_epoch=None, rollout_start_seed=None)[source]¶
Train on mini-batches of fixed-length temporal windows.
Each batch averages its window losses before one optimizer step. The returned breakdown is weighted by the number of windows in each batch, so a smaller final batch does not receive disproportionate weight.
- Parameters:
model (nn.Module) – Model to train.
sampler (WindowSampler) – Window sampler defining trajectories, window size, and batch schedule.
optimizer (Optimizer) – Optimizer updated once per yielded batch.
loss_weights (LossWeights) – Active loss weights for the epoch.
epoch (int, optional) – Zero-based epoch index used for sampler shuffling. Default is
0.max_grad_norm (float or None, optional) – Optional global gradient clipping threshold.
rollout_horizon (int or None, optional) – Rollout horizon. Defaults to
window_length - 1.rollout_start_indices (sequence of int,
"all", or None, optional) – Rollout origins relative to each sampled window.rollout_starts_per_epoch (int or None, optional) – Number of randomly sampled rollout origins.
rollout_start_seed (int or None, optional) – Base seed for rollout-origin sampling.
- Returns:
Window-weighted mean loss breakdown for the epoch.
- Return type:
- koopman_graph.training.eval_one_epoch(model, sequences, loss_weights, *, rollout_horizon=None, rollout_start_indices=None)[source]¶
Compute validation loss for one epoch without parameter updates.
- Parameters:
model (nn.Module) – Model to evaluate.
sequences (GraphSnapshotSequence or sequence of GraphSnapshotSequence) – One or more validation trajectories.
loss_weights (LossWeights) – Weights for reconstruction and consistency terms.
rollout_horizon (int or None, optional) – Number of rollout steps when
loss_weights.rolloutis non-zero.rollout_start_indices (sequence of int or None, optional) – Rollout origin indices for this epoch.
- Returns:
Mean loss breakdown across trajectories.
- Return type:
- koopman_graph.training.resolve_early_stopping_monitor(monitor, *, has_validation)[source]¶
Resolve which loss early stopping should monitor.
- Parameters:
monitor ({"auto", "train", "val"}) – Requested monitor mode.
has_validation (bool) – Whether a validation sequence was provided to
fit().
- Returns:
Resolved monitor target.
- Return type:
{“train”, “val”}
- Raises:
ValueError – If
monitor="val"but no validation sequence was provided.
- koopman_graph.training.is_sequence_of_sequences(data)[source]¶
Return whether
datais a list of snapshot sequences.- Parameters:
data (TrainingInput or ValidationInput) – Training or validation input passed to
fit().- Returns:
Truewhen the first element is aGraphSnapshotSequence.- Return type:
- koopman_graph.training.resolve_training_sequences(data_sequence)[source]¶
Normalize training input into one or more snapshot sequences.
- Parameters:
data_sequence (TrainingInput) – Single sequence, list of
Datasnapshots, or list of sequences.- Returns:
One or more validated training trajectories.
- Return type:
- Raises:
ValueError – If a multi-sequence input is empty.
- koopman_graph.training.resolve_validation_sequences(validation_sequence, *, num_training_sequences)[source]¶
Normalize validation input for
fit().A single validation sequence is reused for all training trajectories. A list of validation sequences must match the training trajectory count.
- Parameters:
validation_sequence (ValidationInput) – Optional validation data.
num_training_sequences (int) – Number of training trajectories supplied to
fit().
- Returns:
Validation trajectories aligned with training input.
- Return type:
list of GraphSnapshotSequence or None
- Raises:
ValueError – If a validation list length does not match
num_training_sequences.
- koopman_graph.training.resolve_lr_scheduler(lr_scheduler, optimizer)[source]¶
Instantiate an optional learning-rate scheduler.
- Parameters:
lr_scheduler (LRScheduler, callable, or None) – Scheduler instance or factory
optimizer -> scheduler.optimizer (Optimizer) – Optimizer passed to a scheduler factory.
- Returns:
Resolved scheduler, if any.
- Return type:
LRScheduler or None
- koopman_graph.training.resolve_device(model, device)[source]¶
Resolve the training device from an explicit argument or model parameters.
- Parameters:
model (nn.Module) – Model whose parameter device is used as fallback.
device (str, torch.device, or None) – Explicit device. When
None, uses the device of the first model parameter, or CPU if the model has no parameters.
- Returns:
Resolved device for training or inference.
- Return type:
- koopman_graph.training.resolve_loss_weights_for_epoch(epoch, *, loss_weights, loss_weight_schedule)[source]¶
Resolve per-epoch loss weights from static weights or a schedule.
- Parameters:
epoch (int) – Zero-based epoch index.
loss_weights (
LossWeightsor None) – Explicit static weights. WhenNoneand no schedule is provided, defaults to reconstruction-only weights.loss_weight_schedule (callable or None) – Optional per-epoch schedule. Takes precedence over
loss_weights.
- Returns:
Weights to use for the given epoch.
- Return type:
- koopman_graph.training.should_stop_early(*, epoch_loss, best_loss, epochs_without_improvement, patience, min_delta)[source]¶
Update early-stopping state after an epoch.
- Parameters:
epoch_loss (float) – Training loss for the completed epoch.
best_loss (float) – Best loss seen so far.
epochs_without_improvement (int) – Consecutive epochs without sufficient improvement.
patience (int) – Stop after this many non-improving epochs.
min_delta (float) – Minimum decrease in loss to count as improvement.
- Returns:
Whether to stop, updated best loss, and updated non-improvement count.
- Return type:
Metrics¶
Forecast evaluation metrics for graph snapshot sequences.
- koopman_graph.metrics.mae(prediction, target)[source]¶
Compute mean absolute error.
- Parameters:
prediction (Tensor) – Predicted values.
target (Tensor) – Ground-truth values with the same shape as
prediction.
- Returns:
Scalar mean absolute error.
- Return type:
Tensor
- koopman_graph.metrics.rmse(prediction, target)[source]¶
Compute root mean squared error.
- Parameters:
prediction (Tensor) – Predicted values.
target (Tensor) – Ground-truth values with the same shape as
prediction.
- Returns:
Scalar root mean squared error.
- Return type:
Tensor
- koopman_graph.metrics.mape(prediction, target, *, eps=1e-08)[source]¶
Compute mean absolute percentage error.
- Parameters:
prediction (Tensor) – Predicted values.
target (Tensor) – Ground-truth values with the same shape as
prediction.eps (float, optional) – Small constant added to the denominator for numerical stability. Default is
1e-8.
- Returns:
Scalar mean absolute percentage error (not scaled to 0–100).
- Return type:
Tensor
- class koopman_graph.metrics.HorizonMetrics(horizon, mae, rmse, mape)[source]¶
Bases:
objectForecast metrics at a single prediction horizon.
- class koopman_graph.metrics.EvaluationResult(horizons, aggregate_mae, aggregate_rmse, aggregate_mape, num_origins)[source]¶
Bases:
objectMulti-horizon forecast evaluation summary.
- horizons¶
Per-horizon metrics in ascending horizon order.
- Type:
- koopman_graph.metrics.evaluate_forecast(model, sequence, *, horizons=(3, 6, 12), start_indices=None)[source]¶
Evaluate autoregressive multi-horizon forecasts on a snapshot sequence.
For each forecast origin, the model predicts up to
max(horizons)steps ahead and metrics are averaged across origins at each requested horizon.- Parameters:
model (nn.Module) – Model implementing
predict().sequence (GraphSnapshotSequence) – Evaluation snapshots with shared topology.
horizons (sequence of int, optional) – Forecast horizons to report. Default is
(3, 6, 12).start_indices (sequence of int or None, optional) – Forecast-origin indices. When
None, uses every valid origin insequence.
- Returns:
Per-horizon and aggregate MAE, RMSE, and MAPE.
- Return type:
- Raises:
ValueError – If
horizonsis empty, any horizon is invalid, or the sequence is too short.
Serialization¶
Checkpoint serialization for GraphKoopmanModel.
- koopman_graph.serialization.build_model_config(model)[source]¶
Extract architecture configuration from a
GraphKoopmanModel.- Parameters:
model (GraphKoopmanModel) – Model whose encoder, decoder, and Koopman settings will be serialized.
- Returns:
JSON-serializable architecture configuration.
- Return type:
- koopman_graph.serialization.reconstruct_model(config)[source]¶
Reconstruct a
GraphKoopmanModelfrom a checkpoint configuration.- Parameters:
config (dict) – Architecture configuration produced by
build_model_config().- Returns:
Uninitialized-weight model matching the saved architecture.
- Return type:
- koopman_graph.serialization.build_checkpoint(model)[source]¶
Build a versioned checkpoint dictionary for a model.
- Parameters:
model (GraphKoopmanModel) – Model whose weights and architecture will be serialized.
- Returns:
Checkpoint payload suitable for
torch.save().- Return type:
- koopman_graph.serialization.save_checkpoint(model, path)[source]¶
Persist a trained model checkpoint to disk.
- Parameters:
model (GraphKoopmanModel) – Model to serialize.
path (str or Path) – Destination
.ptfile path.
- koopman_graph.serialization.load_checkpoint(path, *, map_location=None)[source]¶
Load a trained model from a checkpoint file.
- Parameters:
path (str or Path) – Checkpoint
.ptfile produced bysave_checkpoint().map_location (str, torch.device, or None, optional) – Device mapping forwarded to
torch.load().
- Returns:
Reconstructed model with restored weights in evaluation mode.
- Return type:
- Raises:
ValueError – If the checkpoint format version is unsupported or the payload is invalid.
FileNotFoundError – If
pathdoes not exist.
Datasets¶
Dataset utilities for KoopmanGraph benchmarks and examples.
Public benchmarks¶
- SyntheticDynamicGraphBenchmark
Reproducible Laplacian-diffusion dynamics on path/ring topologies.
- GridDynamicGraphBenchmark
Laplacian diffusion on a 4-connected 2D lattice graph.
- AnisotropicAdvectionGridBenchmark
Directional advection on a grid with asymmetric neighbor weights.
- IEEE118DynamicBenchmark
IEEE 118-bus MATPOWER topology with simulated voltage/load dynamics.
- MetrLaTrafficBenchmark
METR-LA traffic-speed sensor graph with cached speed snapshots.
- class koopman_graph.datasets.AnisotropicAdvectionGridBenchmark[source]¶
Bases:
objectDirectional advection on a 2D lattice with asymmetric neighbor weights.
Each node updates from a weighted mixture of neighbors where the west and north directions dominate. This breaks the symmetry that GCN layers assume when they aggregate neighbors uniformly, making graph attention a better fit than plain convolution for rollout forecasting.
The one-step update is
\[x_{t+1} = \text{decay\_rate} \cdot x_t + (1 - \text{decay\_rate}) \cdot \frac{\sum_{j \in \mathcal{N}(i)} w_{ij} x_{j,t}} {\sum_{j \in \mathcal{N}(i)} w_{ij}}\]with
w_{i,\text{west}} = west_weight,w_{i,\text{north}} = north_weight, and remaining neighbors sharing the leftover mass equally.- Parameters:
num_rows (int, optional) – Grid height. Default is
8.num_cols (int, optional) – Grid width. Default is
8.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.decay_rate (float, optional) – Self-retention factor in
(0, 1). Default is0.85.west_weight (float, optional) – Relative influence of the western neighbor. Default is
0.7.north_weight (float, optional) – Relative influence of the northern neighbor. Default is
0.2.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.005.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- classmethod generate(*, num_rows=8, num_cols=8, num_timesteps=40, in_channels=3, decay_rate=0.85, west_weight=0.7, north_weight=0.2, noise_std=0.005, seed=42, initial_state='ones', dtype=torch.float32)[source]¶
Generate a directional advection snapshot sequence on a grid.
- Parameters:
num_rows (int, optional) – Grid height. Default is
8.num_cols (int, optional) – Grid width. Default is
8.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.decay_rate (float, optional) – Self-retention factor in
(0, 1). Default is0.85.west_weight (float, optional) – Relative influence of the western neighbor. Default is
0.7.north_weight (float, optional) – Relative influence of the northern neighbor. Default is
0.2.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.005.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots on the grid graph.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
- class koopman_graph.datasets.GridDynamicGraphBenchmark[source]¶
Bases:
objectReproducible Laplacian diffusion on a 2D lattice graph.
Node features evolve via the same graph diffusion dynamics as
SyntheticDynamicGraphBenchmark, but on a 4-connected grid. Corner, edge, and interior nodes have different degrees, which makes graph attention encoders a natural fit.- Parameters:
num_rows (int, optional) – Grid height. Default is
10.num_cols (int, optional) – Grid width. Default is
10.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.1.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.99.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.01.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- classmethod generate(*, num_rows=10, num_cols=10, num_timesteps=40, in_channels=3, diffusion_rate=0.1, decay_rate=0.99, noise_std=0.01, seed=42, initial_state='ones', dtype=torch.float32)[source]¶
Generate a dynamic 2D grid snapshot sequence.
- Parameters:
num_rows (int, optional) – Grid height. Default is
10.num_cols (int, optional) – Grid width. Default is
10.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.1.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.99.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.01.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots on the grid graph.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
- class koopman_graph.datasets.IEEE118DynamicBenchmark[source]¶
Bases:
objectIEEE 118-bus spatiotemporal benchmark built from MATPOWER topology.
Node features are bus quantities
[Vm, Va, Pd, Qd](per-unit loads). Voltages and angles evolve via graph Laplacian diffusion on the real IEEE 118 transmission topology; loads follow a slow sinusoidal ramp to emulate changing grid conditions over time.For large-scale optimal power flow snapshots, see the PowerGraph dataset (
https://arxiv.org/abs/2402.02827).- classmethod load_topology(cache_dir=None, *, dtype=torch.float32)[source]¶
Load the cached IEEE 118 topology tables.
- Parameters:
cache_dir (Path, optional) – Directory containing cached topology artifacts. Defaults to the package
data/ieee118directory.dtype (torch.dtype, optional) – Floating dtype for node features. Default is
torch.float32.
- Returns:
Topology payload with keys
base_mva,bus_ids,edge_index,initial_features,num_nodes, andsource_url.- Return type:
- classmethod generate(*, num_timesteps=40, diffusion_rate=0.35, decay_rate=0.98, noise_std=0.002, load_ramp_amplitude=0.15, load_ramp_period=20.0, expose_load_ramp_control=False, seed=42, cache_dir=None, dtype=torch.float32)[source]¶
Generate a dynamic IEEE 118-bus snapshot sequence.
- Parameters:
num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.diffusion_rate (float, optional) – Laplacian diffusion strength for
VmandVa. Default is0.35.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.98.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.002.load_ramp_amplitude (float, optional) – Peak fractional change applied to
PdandQd. Default is0.15.load_ramp_period (float, optional) – Sinusoidal load ramp period in timesteps. Default is
20.0.expose_load_ramp_control (bool, optional) – When
True, attach the sinusoidal load-ramp multiplier as global control inputs with shape(num_timesteps, 1). Default isFalse.seed (int, optional) – Random seed for noise. Default is
42.cache_dir (Path, optional) – Directory containing cached topology artifacts.
dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots on the IEEE 118-bus graph.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
- class koopman_graph.datasets.MetrLaTrafficBenchmark[source]¶
Bases:
objectMETR-LA traffic-speed benchmark built from the DCRNN sensor graph.
Node features are per-sensor traffic speeds (mph), z-score normalized over the cached time window. The road-network adjacency follows the standard DCRNN Gaussian kernel on pairwise distances.
Full speed history is distributed with the DCRNN release (Google Drive / Baidu Yun). A public mirror is documented in
scripts/download_metr_la.py.- classmethod load_topology(cache_dir=None, *, dtype=torch.float32)[source]¶
Load cached METR-LA graph topology and metadata.
- Parameters:
cache_dir (Path, optional) – Directory containing cached traffic artifacts. Defaults to the package
data/metr_ladirectory.dtype (torch.dtype, optional) – Floating dtype for returned tensors. Default is
torch.float32.
- Returns:
Metadata with keys
sensor_ids,edge_index,edge_weight,num_nodes,source_h5_url, andnormalized_k.- Return type:
- classmethod load_sequence(cache_dir=None, *, dtype=torch.float32)[source]¶
Load the cached METR-LA speed snapshot sequence.
- Parameters:
cache_dir (Path, optional) – Directory containing cached traffic artifacts. Defaults to the package
data/metr_ladirectory.dtype (torch.dtype, optional) – Floating dtype for speed features. Default is
torch.float32.
- Returns:
Time-ordered graph snapshots with one speed feature per sensor.
- Return type:
- class koopman_graph.datasets.SyntheticDynamicGraphBenchmark[source]¶
Bases:
objectReproducible synthetic graph dynamics for benchmarks and tutorials.
Node features evolve via graph Laplacian diffusion with optional global decay and additive Gaussian noise:
\[x_{t+1} = \text{decay\_rate} \cdot S x_t + \mathcal{N}(0, \sigma^2)\]where
S = (1 - diffusion_rate) * I + diffusion_rate * D^{-1/2} A D^{-1/2}.- Parameters:
num_nodes (int, optional) – Number of nodes in the graph. Default is
20.num_timesteps (int, optional) – Number of temporal snapshots. Default is
50.in_channels (int, optional) – Node feature dimension. Default is
3.topology ({"path", "ring"}, optional) – Static graph topology shared across timesteps. Default is
"path".diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.5.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.95.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.0.seed (int, optional) – Random seed for the initial state and noise.
Noneuses unseeded randomness.initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"random".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- classmethod generate(*, num_nodes=20, num_timesteps=50, in_channels=3, topology='path', diffusion_rate=0.5, decay_rate=0.95, noise_std=0.0, seed=None, initial_state='random', dtype=torch.float32)[source]¶
Generate a synthetic dynamic graph snapshot sequence.
- Parameters:
num_nodes (int, optional) – Number of nodes in the graph. Default is
20.num_timesteps (int, optional) – Number of temporal snapshots. Default is
50.in_channels (int, optional) – Node feature dimension. Default is
3.topology ({"path", "ring"}, optional) – Static graph topology shared across timesteps. Default is
"path".diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.5.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.95.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.0.seed (int, optional) – Random seed for the initial state and noise.
Noneuses unseeded randomness.initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"random".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots with shared topology and documented dynamics.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
Synthetic spatiotemporal graph benchmarks for tests and tutorials.
- class koopman_graph.datasets.synthetic.SyntheticDynamicGraphBenchmark[source]¶
Bases:
objectReproducible synthetic graph dynamics for benchmarks and tutorials.
Node features evolve via graph Laplacian diffusion with optional global decay and additive Gaussian noise:
\[x_{t+1} = \text{decay\_rate} \cdot S x_t + \mathcal{N}(0, \sigma^2)\]where
S = (1 - diffusion_rate) * I + diffusion_rate * D^{-1/2} A D^{-1/2}.- Parameters:
num_nodes (int, optional) – Number of nodes in the graph. Default is
20.num_timesteps (int, optional) – Number of temporal snapshots. Default is
50.in_channels (int, optional) – Node feature dimension. Default is
3.topology ({"path", "ring"}, optional) – Static graph topology shared across timesteps. Default is
"path".diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.5.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.95.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.0.seed (int, optional) – Random seed for the initial state and noise.
Noneuses unseeded randomness.initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"random".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- classmethod generate(*, num_nodes=20, num_timesteps=50, in_channels=3, topology='path', diffusion_rate=0.5, decay_rate=0.95, noise_std=0.0, seed=None, initial_state='random', dtype=torch.float32)[source]¶
Generate a synthetic dynamic graph snapshot sequence.
- Parameters:
num_nodes (int, optional) – Number of nodes in the graph. Default is
20.num_timesteps (int, optional) – Number of temporal snapshots. Default is
50.in_channels (int, optional) – Node feature dimension. Default is
3.topology ({"path", "ring"}, optional) – Static graph topology shared across timesteps. Default is
"path".diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.5.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.95.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.0.seed (int, optional) – Random seed for the initial state and noise.
Noneuses unseeded randomness.initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"random".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots with shared topology and documented dynamics.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
2D grid spatiotemporal graph benchmarks for tests and tutorials.
- koopman_graph.datasets.grid.grid_node_index(row, col, *, num_cols)[source]¶
Return the flattened node index for a grid coordinate.
- class koopman_graph.datasets.grid.GridDynamicGraphBenchmark[source]¶
Bases:
objectReproducible Laplacian diffusion on a 2D lattice graph.
Node features evolve via the same graph diffusion dynamics as
SyntheticDynamicGraphBenchmark, but on a 4-connected grid. Corner, edge, and interior nodes have different degrees, which makes graph attention encoders a natural fit.- Parameters:
num_rows (int, optional) – Grid height. Default is
10.num_cols (int, optional) – Grid width. Default is
10.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.1.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.99.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.01.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- classmethod generate(*, num_rows=10, num_cols=10, num_timesteps=40, in_channels=3, diffusion_rate=0.1, decay_rate=0.99, noise_std=0.01, seed=42, initial_state='ones', dtype=torch.float32)[source]¶
Generate a dynamic 2D grid snapshot sequence.
- Parameters:
num_rows (int, optional) – Grid height. Default is
10.num_cols (int, optional) – Grid width. Default is
10.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.diffusion_rate (float, optional) – Laplacian diffusion strength in
[0, 1]. Default is0.1.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.99.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.01.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots on the grid graph.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
- class koopman_graph.datasets.grid.AnisotropicAdvectionGridBenchmark[source]¶
Bases:
objectDirectional advection on a 2D lattice with asymmetric neighbor weights.
Each node updates from a weighted mixture of neighbors where the west and north directions dominate. This breaks the symmetry that GCN layers assume when they aggregate neighbors uniformly, making graph attention a better fit than plain convolution for rollout forecasting.
The one-step update is
\[x_{t+1} = \text{decay\_rate} \cdot x_t + (1 - \text{decay\_rate}) \cdot \frac{\sum_{j \in \mathcal{N}(i)} w_{ij} x_{j,t}} {\sum_{j \in \mathcal{N}(i)} w_{ij}}\]with
w_{i,\text{west}} = west_weight,w_{i,\text{north}} = north_weight, and remaining neighbors sharing the leftover mass equally.- Parameters:
num_rows (int, optional) – Grid height. Default is
8.num_cols (int, optional) – Grid width. Default is
8.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.decay_rate (float, optional) – Self-retention factor in
(0, 1). Default is0.85.west_weight (float, optional) – Relative influence of the western neighbor. Default is
0.7.north_weight (float, optional) – Relative influence of the northern neighbor. Default is
0.2.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.005.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- classmethod generate(*, num_rows=8, num_cols=8, num_timesteps=40, in_channels=3, decay_rate=0.85, west_weight=0.7, north_weight=0.2, noise_std=0.005, seed=42, initial_state='ones', dtype=torch.float32)[source]¶
Generate a directional advection snapshot sequence on a grid.
- Parameters:
num_rows (int, optional) – Grid height. Default is
8.num_cols (int, optional) – Grid width. Default is
8.num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.in_channels (int, optional) – Node feature dimension. Default is
3.decay_rate (float, optional) – Self-retention factor in
(0, 1). Default is0.85.west_weight (float, optional) – Relative influence of the western neighbor. Default is
0.7.north_weight (float, optional) – Relative influence of the northern neighbor. Default is
0.2.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.005.seed (int, optional) – Random seed for the initial state and noise.
initial_state ({"random", "ones"}, optional) – Initial node feature pattern. Default is
"ones".dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots on the grid graph.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
IEEE 118-bus MATPOWER benchmark for tutorials and tests.
- koopman_graph.datasets.ieee118.parse_matpower_case(text)[source]¶
Parse bus and branch tables from a MATPOWER version-2 case file.
- koopman_graph.datasets.ieee118.topology_from_matpower_text(text, *, dtype=torch.float32)[source]¶
Convert MATPOWER case text into tensors used by the benchmark.
- Parameters:
text (str) – Contents of a MATPOWER version-2
.mcase file.dtype (torch.dtype, optional) – Floating dtype for node features. Default is
torch.float32.
- Returns:
Topology payload with keys
base_mva,bus_ids,edge_index,initial_features,num_nodes, andsource_url.- Return type:
- koopman_graph.datasets.ieee118.download_matpower_case118()[source]¶
Download the MATPOWER IEEE 118-bus case file text.
- Returns:
Raw
case118.mfile contents.- Return type:
- koopman_graph.datasets.ieee118.ensure_topology_cache(cache_dir=None, *, force=False, dtype=torch.float32)[source]¶
Download, parse, and cache IEEE 118 topology if needed.
- Parameters:
cache_dir (Path, optional) – Directory used for cached topology artifacts. Defaults to
data/ieee118at the repository root.force (bool, optional) – Rebuild the cache even when it already exists.
dtype (torch.dtype, optional) – Floating dtype stored in the cache. Default is
torch.float32.
- Returns:
Path to the cached
topology.ptfile.- Return type:
Path
- koopman_graph.datasets.ieee118.load_topology(cache_dir=None, *, dtype=torch.float32)[source]¶
Load cached IEEE 118 topology, creating the cache on first use.
- Parameters:
cache_dir (Path, optional) – Directory containing
topology.pt.dtype (torch.dtype, optional) – Floating dtype for returned tensors. Default is
torch.float32.
- Returns:
Topology payload with
edge_indexandinitial_features.- Return type:
- class koopman_graph.datasets.ieee118.IEEE118DynamicBenchmark[source]¶
Bases:
objectIEEE 118-bus spatiotemporal benchmark built from MATPOWER topology.
Node features are bus quantities
[Vm, Va, Pd, Qd](per-unit loads). Voltages and angles evolve via graph Laplacian diffusion on the real IEEE 118 transmission topology; loads follow a slow sinusoidal ramp to emulate changing grid conditions over time.For large-scale optimal power flow snapshots, see the PowerGraph dataset (
https://arxiv.org/abs/2402.02827).- classmethod load_topology(cache_dir=None, *, dtype=torch.float32)[source]¶
Load the cached IEEE 118 topology tables.
- Parameters:
cache_dir (Path, optional) – Directory containing cached topology artifacts. Defaults to the package
data/ieee118directory.dtype (torch.dtype, optional) – Floating dtype for node features. Default is
torch.float32.
- Returns:
Topology payload with keys
base_mva,bus_ids,edge_index,initial_features,num_nodes, andsource_url.- Return type:
- classmethod generate(*, num_timesteps=40, diffusion_rate=0.35, decay_rate=0.98, noise_std=0.002, load_ramp_amplitude=0.15, load_ramp_period=20.0, expose_load_ramp_control=False, seed=42, cache_dir=None, dtype=torch.float32)[source]¶
Generate a dynamic IEEE 118-bus snapshot sequence.
- Parameters:
num_timesteps (int, optional) – Number of temporal snapshots. Default is
40.diffusion_rate (float, optional) – Laplacian diffusion strength for
VmandVa. Default is0.35.decay_rate (float, optional) – Global amplitude decay applied each step. Default is
0.98.noise_std (float, optional) – Standard deviation of additive Gaussian noise. Default is
0.002.load_ramp_amplitude (float, optional) – Peak fractional change applied to
PdandQd. Default is0.15.load_ramp_period (float, optional) – Sinusoidal load ramp period in timesteps. Default is
20.0.expose_load_ramp_control (bool, optional) – When
True, attach the sinusoidal load-ramp multiplier as global control inputs with shape(num_timesteps, 1). Default isFalse.seed (int, optional) – Random seed for noise. Default is
42.cache_dir (Path, optional) – Directory containing cached topology artifacts.
dtype (torch.dtype, optional) – Floating dtype for generated features. Default is
torch.float32.
- Returns:
Time-ordered snapshots on the IEEE 118-bus graph.
- Return type:
- Raises:
ValueError – If any generation parameter is invalid.
METR-LA traffic benchmark for tutorials and tests.
- koopman_graph.datasets.metr_la.download_sensor_ids()[source]¶
Download the ordered METR-LA sensor ID list from the DCRNN repository.
- koopman_graph.datasets.metr_la.download_distances_csv()[source]¶
Download the METR-LA pairwise road-distance CSV from DCRNN.
- Returns:
Raw CSV text with columns
from,to, andcost.- Return type:
- koopman_graph.datasets.metr_la.build_adjacency_matrix(distance_csv, sensor_ids, *, normalized_k=0.1)[source]¶
Build a Gaussian-kernel adjacency matrix from DCRNN distance CSV data.
Follows the preprocessing in the DCRNN gen_adj_mx script.
- Parameters:
- Returns:
Adjacency matrix with shape
(len(sensor_ids), len(sensor_ids)).- Return type:
ndarray
- koopman_graph.datasets.metr_la.adjacency_to_edge_index(adj_mx)[source]¶
Convert an adjacency matrix to a bidirectional PyG
edge_index.- Parameters:
adj_mx (ndarray) – Weighted adjacency matrix.
- Returns:
Long tensor with shape
(2, num_edges).- Return type:
Tensor
- koopman_graph.datasets.metr_la.adjacency_to_edge_weight(adj_mx)[source]¶
Extract scalar edge weights aligned with
adjacency_to_edge_index().- Parameters:
adj_mx (ndarray) – Weighted adjacency matrix.
- Returns:
Float tensor with shape
(num_edges,).- Return type:
Tensor
- koopman_graph.datasets.metr_la.read_h5_speed_window(h5_path, *, num_timesteps, offset=0)[source]¶
Read a window of METR-LA speed values from an HDF5 file.
- Parameters:
- Returns:
Speed array with shape
(num_timesteps, num_sensors).- Return type:
ndarray
- Raises:
ImportError – If
h5pyis not installed.ValueError – If the requested window exceeds the available rows.
- koopman_graph.datasets.metr_la.preprocess_speeds(speeds)[source]¶
Impute missing METR-LA readings before normalization.
The DCRNN HDF5 release encodes missing loop-detector samples as
0. Non-positive values are treated as missing and filled along time per sensor using forward fill followed by backward fill.- Parameters:
speeds (ndarray) – Raw speed array with shape
(num_timesteps, num_sensors).- Returns:
Imputed speeds with the same shape.
- Return type:
ndarray
- Raises:
ValueError – If
speedsis not two-dimensional.
- koopman_graph.datasets.metr_la.normalize_speeds(speeds)[source]¶
Per-sensor z-score normalization along the time axis.
- Parameters:
speeds (ndarray) – Speed array with shape
(num_timesteps, num_sensors).- Returns:
Normalized speeds with the same shape.
- Return type:
ndarray
- koopman_graph.datasets.metr_la.build_traffic_cache_payload(speeds, sensor_ids, *, normalized_k=0.1, source_h5_url='https://huggingface.co/datasets/MintBruce/SkyTraffic/resolve/main/metr-la.h5', timestep_offset=0)[source]¶
Assemble a cache payload from speed readings and DCRNN graph metadata.
- Parameters:
speeds (ndarray) – Raw speed readings with shape
(num_timesteps, num_sensors).normalized_k (float, optional) – Adjacency sparsity threshold. Default is
0.1.source_h5_url (str, optional) – Provenance URL for the speed source file.
timestep_offset (int, optional) – Row offset used when extracting
speedsfrom the HDF5 table.
- Returns:
Serializable cache payload for
traffic.pt.- Return type:
- koopman_graph.datasets.metr_la.ensure_traffic_cache(cache_dir=None, *, force=False, h5_path=None, num_timesteps=60, offset=0, normalized_k=0.1)[source]¶
Download graph metadata and build the METR-LA traffic cache if needed.
- Parameters:
cache_dir (Path, optional) – Directory used for
traffic.pt. Defaults todata/metr_la.force (bool, optional) – Rebuild the cache even when it already exists.
h5_path (Path, optional) – Local
metr-la.h5file used to refresh speed readings. When omitted andforce=True, an existing cache is reused without fetching HDF5.num_timesteps (int, optional) – Number of timesteps stored in the cache. Default is
60.offset (int, optional) – Starting row in the HDF5 speed table. Default is
0.normalized_k (float, optional) – Adjacency sparsity threshold. Default is
0.1.
- Returns:
Path to
traffic.pt.- Return type:
Path
- koopman_graph.datasets.metr_la.load_traffic_cache(cache_dir=None, *, dtype=torch.float32)[source]¶
Load cached METR-LA topology and speed readings.
- Parameters:
cache_dir (Path, optional) – Directory containing
traffic.pt.dtype (torch.dtype, optional) – Floating dtype for returned speed tensors. Default is
torch.float32.
- Returns:
Cache payload with
edge_indexandspeedstensors.- Return type:
- class koopman_graph.datasets.metr_la.MetrLaTrafficBenchmark[source]¶
Bases:
objectMETR-LA traffic-speed benchmark built from the DCRNN sensor graph.
Node features are per-sensor traffic speeds (mph), z-score normalized over the cached time window. The road-network adjacency follows the standard DCRNN Gaussian kernel on pairwise distances.
Full speed history is distributed with the DCRNN release (Google Drive / Baidu Yun). A public mirror is documented in
scripts/download_metr_la.py.- classmethod load_topology(cache_dir=None, *, dtype=torch.float32)[source]¶
Load cached METR-LA graph topology and metadata.
- Parameters:
cache_dir (Path, optional) – Directory containing cached traffic artifacts. Defaults to the package
data/metr_ladirectory.dtype (torch.dtype, optional) – Floating dtype for returned tensors. Default is
torch.float32.
- Returns:
Metadata with keys
sensor_ids,edge_index,edge_weight,num_nodes,source_h5_url, andnormalized_k.- Return type:
- classmethod load_sequence(cache_dir=None, *, dtype=torch.float32)[source]¶
Load the cached METR-LA speed snapshot sequence.
- Parameters:
cache_dir (Path, optional) – Directory containing cached traffic artifacts. Defaults to the package
data/metr_ladirectory.dtype (torch.dtype, optional) – Floating dtype for speed features. Default is
torch.float32.
- Returns:
Time-ordered graph snapshots with one speed feature per sensor.
- Return type: