pykoopman

repository·master·Indexed 19 days ago

https://github.com/dynamicslab/pykoopman

A Python package for data-driven approximations to the Koopman operator, enabling the linearization of nonlinear dynamical systems. It features a scikit-learn compatible API with the Koopman and KoopmanContinuous classes. The library provides various observables (such as Polynomial, TimeDelay, and RadialBasisFunctions) and system identification regressors including EDMD, DMDc, KDMD, and HAVOK. It also includes a differentiation module for computing time derivatives and support for simulating fitted models.

Tokens
16K
Snippets
48
Records
72
Agent score
66%

What's inside pykoopman

  1. Overview of PyKoopman for Koopman operator approximation

    master

    PyKoopman is a Python package designed for the data-driven approximation of the Koopman operator in dynamical systems. It provides a toolkit for approximating nonlinear dynamics by embedding them into a linear framework.

    Key capabilities include:

    • System Identification: Tools for both unforced and actuated systems.
    • Nonlinear Projection: Unlike standard Dynamic Mode Decomposition (DMD) which acts as a linear projection, PyKoopman provides comprehensive nonlinear projection methods.
    • Observable Design: Tools to design observables (functions of the system state) and infer the finite-dimensional linear operator that governs their evolution.
    • Trajectory Support: Support for data collected from multiple trajectories.
    • Downstream Applications: Once a linear embedding is discovered, the package facilitates leveraging that linearity for interpretability, observer design, and controller design for the original nonlinear system.
  2. How PyKoopman works: Observables and Regressors

    master

    PyKoopman is designed to approximate the Koopman operator by projecting a nonlinear dynamical system into a finite-dimensional subspace. The package architecture centers around two main components:

    1. Observables: A set of functions that span the subspace for projection (lifting the state $x$ into $z = \Phi(x)$).
    2. Regressor: The optimization algorithm used to find the best fit for the projection of the Koopman operator.

    PyKoopman follows a scikit-learn compatible API, meaning you create a Koopman or KoopmanContinuous object and then call .fit() on your data.

  3. How the Koopman model works in PyKoopman

    master

    The pykoopman.Koopman class is the central component of the package. It follows a two-step process to lift nonlinear dynamics into a linear system:

    1. Observables: A lifting function (defined via an observables object) that maps the state $\mathbf{x}$ to a higher-dimensional observable space $\mathbf{z}$, and a reconstruction method to map $\mathbf{z}$ back to $\mathbf{x}$.
    2. Regression: A regression method (defined via a regressor object) used to find the optimal linear operator $\mathbf{A}$ that evolves the observables in time.

    By combining an observable library with a system identification method, you can approximate the Koopman operator for nonlinear systems.

    from pykoopman import Koopman
    from pykoopman.observables import Polynomial
    from pykoopman.regression import EDMD
    
    # Initialize the model with specific observables and a regressor
    model = Koopman(observables=Polynomial(2), regressor=EDMD())
    
    # Fit the model using state transitions (X, Xnext)
    model.fit(X, Xnext)
    from pykoopman import Koopman
    from pykoopman.observables import Polynomial
    from pykoopman.regression import EDMD
    
    model = Koopman(observables=Polynomial(2),regressor=EDMD())
    model.fit(X,Xnext)
  4. Install PyKoopman from source (recommended)

    master

    For development or preferred environment management, installing from source is recommended. Using uv is the suggested method for managing Python 3.11 environments.

    # Using uv (recommended)
    git clone https://github.com/dynamicslab/pykoopman
    cd pykoopman
    uv venv --python 3.11
    uv pip install -e .
    
    # Using traditional venv
    python -m venv .venv
    source ./.venv/bin/activate   # On Windows: .\.venv\Scripts\activate.ps1
    pip install -e .
  5. Typical workflow for approximating a Koopman operator

    master

    To approximate the Koopman operator of a nonlinear system, follow these steps:

    1. Prepare Data: Collect trajectories of the system, typically represented as two matrices X (current states) and Xnext (states at the next time step).
    2. Define Model: Instantiate pykoopman.Koopman by specifying an observable type (e.g., Polynomial) and a regression method (e.g., EDMD).
    3. Fit: Call .fit(X, Xnext) to learn the operator.
    4. Predict: Use .simulate() to project the system forward.
    from pykoopman import Koopman
    from pykoopman.observables import Polynomial
    from pykoopman.regression import EDMD
    
    # 1. & 2. Setup model
    model = Koopman(observables=Polynomial(2), regressor=EDMD())
    
    # 3. Fit to data
    model.fit(X, Xnext)
    
    # 4. Simulate
    predictions = model.simulate(x0, n_steps=100)
    from pykoopman import Koopman
    from pykoopman.observables import Polynomial
    from pykoopman.regression import EDMD
    
    model = Koopman(observables=Polynomial(2),regressor=EDMD())
    model.fit(X,Xnext)
    
    # After fitting, use simulate
    predictions = model.simulate(x0, n_steps=100)
  6. Concatenate multiple observables with ConcatObservables

    master

    The ConcatObservables class allows you to combine multiple BaseObservables instances into a single feature library.

    Key Behaviors:

    • Redundancy Removal: It automatically handles redundant features. If multiple observables include the identity mapping (system state) or a bias term (include_bias=True), ConcatObservables ensures these are only included once to prevent collinearity.
    • Requirement: The first observable in the observables_list_ must have an include_state attribute.
    • Operator Overloading: You can use the + operator to concatenate observables (e.g., obs1 + obs2), which returns a new ConcatObservables instance.

    Attributes:

    • observables_list_: The list of concatenated observables.
    • include_state: Boolean indicating if a linear feature (system state) is included.
    • n_input_features_: Dimensionality of the input.
    • n_output_features_: Total dimensionality of the concatenated output.
    • measurement_matrix_: Matrix used to map transformed features back to the system state via inverse().
    from pykoopman.observables._base import ConcatObservables
    
    # Assuming obs1 and obs2 are already defined instances of BaseObservables
    combined_obs = ConcatObservables([obs1, obs2])
    # OR using the overloaded + operator
    combined_obs = obs1 + obs2
    
    combined_obs.fit(X)
    features = combined_obs.transform(X)
    state = combined_obs.inverse(features)
  7. Configure Koopman operator types in DLKoopmanRegressor

    master

    When initializing DLKoopmanRegressor, you can specify the mathematical structure of the learned Koopman operator via the mode argument:

    • Standard: A general Koopman operator (uses StandardKoopmanOperator).
    • Hamiltonian: An operator with an off-diagonal structure (uses HamiltonianKoopmanOperator).
    • Dissipative: An operator combining off-diagonal and diagonal components (uses DissipativeKoopmanOperator).
  8. Configure differentiation methods in KoopmanContinuous

    master

    The KoopmanContinuous class accepts an optional differentiator parameter to specify how time derivatives are computed.

    Call Signature Requirement: The differentiator must be a callable with the signature differentiator(x, t), where:

    • x: A 2D numpy ndarray where each example occupies a row.
    • t: A 1D numpy ndarray containing the time points corresponding to each row in x.

    You can use the pykoopman.differentiation.Derivative wrapper to access robust methods from the derivative package, or provide a custom function.

  9. Prepare sequential data with SeqDataModule

    master

    The SeqDataModule (a PyTorch Lightning DataModule) handles the preprocessing, normalization, and creation of time-delayed datasets for training Koopman models.

    Initialization Arguments:

    • data_tr: Training data. A list of 2D np.ndarray (trajectories) or a path to a pickle file containing such a list.
    • data_val: Validation data (optional). Same format as data_tr.
    • look_forward: Number of time steps to predict into the future.
    • batch_size: Number of samples per batch.
    • normalize: Whether to normalize data (default True).
    • normalize_mode: "equal" (divides by standard deviation) or "max" (divides by maximum absolute value).
    • normalize_std_factor: Scaling factor for standard deviation (default 2.0).

    Workflow:

    1. Call prepare_data() to compute mean/std and create time-delayed data.
    2. Call setup(stage="fit") to initialize SeqDataDataset instances.
    3. Use train_dataloader() and val_dataloader() for training.
  10. Use the HAVOK regressor for Koopman approximation

    master

    The HAVOK (Hankel Alternative View of Koopman) regressor aims to determine system matrices $A$ and $B$ such that $\frac{d}{dt} v = Av + Bu$, where $v$ represents leading delay coordinates and $u$ represents a low-energy forcing signal. It uses SVD on a Hankel matrix to identify intrinsic observables.

    Initialization

    from pykoopman.regression import HAVOK
    from pykoopman.differentiation import Derivative
    
    # Initialize with a specific SVD rank and differentiation method
    regressor = HAVOK(
        svd_rank=10, 
        differentiator=Derivative(kind="finite_difference", k=1),
        plot_sv=False
    )

    Fitting the model

    Use the .fit() method with your measurement data. Note that HAVOK does not use the y argument typically found in other regressors.

    Required Argument:

    • dt: The discrete time-step (scalar).
    # x is your measurement data (n_samples, n_features)
    regressor.fit(x, dt=0.01)

    Making predictions

    Use the .predict() method to simulate the system output.

    Arguments:

    • x: The measurement data to base the prediction on.
    • u: Time series of external actuation/control sampled at times in t.
    • t: Time vector for which the solution is provided. Note: The time vector must start at 0.
    # t must start at 0
    t = np.linspace(0, 10, 100)
    # u is the control input
    ypred = regressor.predict(x, u, t)
    from pykoopman.regression import HAVOK
    
    regressor = HAVOK(svd_rank=10)
    regressor.fit(x, dt=0.01)
    ypred = regressor.predict(x, u, t)