Skip to main content

Sparse Identification of Nonlinear Dynamics

Project description

BuildCI Documentation Status PyPI Codecov JOSS

PySINDy is a sparse regression package with several implementations for the Sparse Identification of Nonlinear Dynamical systems (SINDy) method introduced in Brunton et al. (2016), including the unified optimization approach of Champion et al. (2019).

System identification

System identification refers to the process of leveraging measurement data to infer governing equations, in the form of dynamical systems, describing the data. Once discovered, these equations can make predictions about future states, can inform control inputs, or can enable the theoretical study using analytical techniques. Dynamical systems are a flexible, well-studied class of mathematical objects for modeling systems evolving in time. SINDy is a model discovery method which uses sparse regression to infer nonlinear dynamical systems from measurement data. The resulting models are inherently interpretable and generalizable.

How it works

Suppose, for some physical system of interest, we have measurements of state variables x(t) (a vector of length n) at different points in time. Examples of state variables include the position, velocity, or acceleration of objects; lift, drag, or angle of attack of aerodynamic objects; and concentrations of different chemical species. If we suspect that the system could be well-modeled by a dynamical system of the form:

x'(t) = f(x(t)),

then we can use SINDy to learn f(x) from the data (x'(t) denotes the time derivative of x(t)). Note that both f(x) and x(t) are typically vectors. The fundamental assumption SINDy employs is that each component of f(x), f_i(x) can be represented as a sparse linear combination of basis functions theta_j(x):

f_i(x) = theta_1(x) * xi_{1,i} + theta_2(x) * xi_{2,i} + ... + theta_l * xi{l,i}

Concatenating all the objects into matrices (denoted with capitalized names) helps to simplify things. To this end we place all measurements of the state variables into a data matrix X (with a row per time measurement and a column per variable), the derivatives of the state variables into a matrix X', all basis functions evaluated at all points in time into a matrix Theta(X) (each basis function gets a column), and all coefficients into a third matrix Xi (one column per state variable). The approximation problem to be solved can then be compactly written as:

X' = Theta(X) * Xi.

Each row of this matrix equation corresponds to one coordinate function of f(x). SINDy employs sparse regression techniques to find a solution Xi with sparse column vectors. For a more in-depth look at the mathematical foundations of SINDy, please see our introduction to SINDy.

Relation to PySINDy

The PySINDy class revolves around the SINDy class which consists of three primary components; one for each term in the above matrix approximation problem.

  • differentiation_method: computes X', though if derivatives are known or measured directly, they can be used instead

  • feature_library: specifies the candidate basis functions to be used to construct Theta(X)

  • optimizer: implements a sparse regression method for solving for Xi

Once a SINDy object has been created it must be fit to measurement data, similar to a scikit-learn model. It can then be used to predict derivatives given new measurements, evolve novel initial conditions forward in time, and more. PySINDy has been written to be as compatible with scikit-learn objects and methods as possible.

Example

Suppose we have measurements of the position of a particle obeying the following dynamical system at different points in time:

x' = -2x
y' = y

Note that this system of differential equations decouples into two differential equations whose solutions are simply x(t) = x_0 * exp(-2 * t) and y(t) = y_0 * exp(t), where x_0 = x(0) and y_0 = y(0) are the initial conditions.

Using the initial conditions x_0 = 3 and y_0 = 0.5, we construct the data matrix X.

import numpy as np
import pysindy as ps

t = np.linspace(0, 1, 100)
x = 3 * np.exp(-2 * t)
y = 0.5 * np.exp(t)
X = np.stack((x, y), axis=-1)  # First column is x, second is y

To instantiate a SINDy object with the default differentiation method, feature library, and optimizer and then fit it to the data, we invoke

model = ps.SINDy(feature_names=["x", "y"])
model.fit(X, t=t)

We use the feature_names argument so that the model prints out the correct labels for x and y. We can inspect the governing equations discovered by the model and check whether they seem reasonable with the print function.

model.print()

which prints the following:

x' = -2.000 x
y' = 1.000 y

PySINDy provides numerous other features not shown here. We recommend the feature overview section of the documentation for a more exhaustive summary of additional features.

Installation

Installing with pip

If you are using Linux or macOS you can install PySINDy with pip:

pip install pysindy

Installing from source

First clone this repository:

git clone https://github.com/dynamicslab/pysindy

Then, to install the package, run

pip install .

If you do not have pip you can instead use

python setup.py install

If you do not have root access, you should add the --user option to the above lines.

Documentation

The documentation site for PySINDy can be found here. There are numerous examples of PySINDy in action to help you get started. Examples are also available as Jupyter notebooks.

Community guidelines

Contributing code

We welcome contributions to PySINDy. To contribute a new feature please submit a pull request. To be accepted your code should conform to PEP8 (you may choose to use flake8 to test this before submitting your pull request). Your contributed code should pass all unit tests. Upon submission of a pull request, your code will be linted and tested automatically, but you may also choose to lint it yourself invoking

pre-commit -a -v

as well as test it yourself by running

pytest

Reporting issues or bugs

If you find a bug in the code or want to request a new feature, please open an issue.

Getting help

For help using PySINDy please consult the documentation and/or our examples, or create an issue.

References

  • Brunton, Steven L., Joshua L. Proctor, and J. Nathan Kutz. Discovering governing equations from data by sparse identification of nonlinear dynamical systems. Proceedings of the National Academy of Sciences 113.15 (2016): 3932-3937. [DOI]

  • Champion, Kathleen, Peng Zheng, Aleksandr Y. Aravkin, Steven L. Brunton, and J. Nathan Kutz. A unified sparse optimization framework to learn parsimonious physics-informed models from data. arXiv preprint arXiv:1906.10612 (2019). [arXiv]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysindy-0.14.1.tar.gz (2.8 MB view details)

Uploaded Source

Built Distribution

pysindy-0.14.1-py3-none-any.whl (33.1 kB view details)

Uploaded Python 3

File details

Details for the file pysindy-0.14.1.tar.gz.

File metadata

  • Download URL: pysindy-0.14.1.tar.gz
  • Upload date:
  • Size: 2.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.7

File hashes

Hashes for pysindy-0.14.1.tar.gz
Algorithm Hash digest
SHA256 7034526d106e3908837dcaf9456951207f35f2ed37b000f61d60572b540df9a4
MD5 1d12923aa72b57ef2762d1f02f9fd360
BLAKE2b-256 63381cf5583a17b1c4767295f915ac5c9050f90ef31fca3536d80da9d13d7175

See more details on using hashes here.

File details

Details for the file pysindy-0.14.1-py3-none-any.whl.

File metadata

  • Download URL: pysindy-0.14.1-py3-none-any.whl
  • Upload date:
  • Size: 33.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.7.7

File hashes

Hashes for pysindy-0.14.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3343956a8e4f7ed84aad307aa83b206763f36295355c2a75a6e9d9e5d0ddb3e5
MD5 1efa50233b7dc74022a37072ae116341
BLAKE2b-256 3779dfb38cdb2d0991b563cd43e2cc573db464ec99ef3086a28e4d5997c1afd9

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page