Skip to main content

LYAPAX logo

lyapax

CI Documentation Status

JAX-native Lyapunov exponent computation for ODEs and DDEs, via the Benettin/QR method with jax.jvp/jax.vmap tangent propagation.

📚 Documentation

Looking for the documentation?

➡️ https://lyapax.readthedocs.io/en/latest/

It includes:

  • Installation guide
  • Quick start tutorial
  • API reference
  • Examples and gallery
  • Validation, benchmarks, and implementation details

Install

pip install lyapax

Development installation

If you plan to contribute, run the test suite, or build the documentation, clone the repository and install the appropriate extras:

pip install -e ".[dev]"       # testing
pip install -e ".[examples]"  # example scripts
pip install -e ".[docs]"      # documentation
pip install -e ".[adaptive]"  # Diffrax backend

Requires jax>=0.10, Python >=3.11.

Enable float64 before anything else. Lyapunov exponents are averages of log-growth rates accumulated over many steps; JAX's default float32 silently degrades long-horizon estimates. Do this first, before creating any jax.numpy arrays:

import jax
jax.config.update("jax_enable_x64", True)

lyapunov_spectrum/lyapunov_spectrum_dde warn if called with a float32 state0 and x64 is off.

Minimal example

import jax
jax.config.update("jax_enable_x64", True)
import jax.numpy as jnp

from lyapax import lyapunov_spectrum, ode_problem

sigma, rho, beta = 10.0, 28.0, 8.0 / 3.0

def rhs(state):
    x, y, z = state
    return jnp.array([sigma * (y - x), x * (rho - z) - y, x * y - beta * z])

problem = ode_problem(rhs, state0=jnp.array([1.0, 1.0, 1.0]), dt=1e-2)

result = lyapunov_spectrum(
    problem, n_steps=50_000, renorm_every=10, t_transient=100.0,
)
print(result.exponents)  # ~ [0.906, 0.0, -14.57]

result.history gives the running per-column estimate at each renormalization point, for checking convergence.

rhs is just a plain state -> jnp.ndarray function - write your own for any system. lyapax.systems has this Lorenz system and other standard test systems (Rössler, Kuramoto, ...) prebuilt, if you'd rather not retype them.

Method and scope

lyapunov_spectrum propagates a (d, k) matrix of tangent vectors alongside the trajectory via jax.jvp (one forward-mode pass per tracked column, batched with jax.vmap), QR-decomposes it every renorm_every steps, accumulates log|diag(R)|, and divides by elapsed time (Benettin's method). k defaults to the full spectrum (k = d); cost scales with k, not d, so partial spectra of high-dimensional systems are cheap.

lyapunov_spectrum_dde generalizes this to fixed-delay DDEs by differentiating through an augmented (state, ring_buffer) carry.

What this does not do:

  • No stiff (implicit) ODE solvers. step_fn is whatever integrator you hand it - a fixed-step map (ode_problem(..., integrator="rk4") by default, direct rk4_step/euler_step step functions, or Euler/Heun/RK6 via lyapax.simulator), or an adaptive-step explicit one via the optional adaptive extra (lyapax.adaptive.diffrax_adaptive_step, backed by diffrax; ode_problem only - not network_problem or DDEs). Exponents are for the numerical time-dt map (or accepted-step sequence, for the adaptive integrator), not an exact flow - check dt/tolerance convergence for anything you report. The adaptive integrator is for tolerance-driven accuracy control, not speed - measured 2-4x slower than rk4/rk6 at matched accuracy, not faster; see docs/background/capabilities.md.
  • DDE delays must be known and fixed, resolved one of two ways. By default (grid-snapped), a physical delay tau is rounded to the nearest multiple of dt (lyapax.dde.resolve_tau_steps); use lyapax.dde.tau_eff to see the delay actually used, and shrink dt to converge it toward tau. Passing interpolate=True instead reconstructs the delayed history with a cubic-Hermite interpolant, removing that rounding on the uniform-delay path at some extra cost - see 13_dde_history_interpolation.py and docs/background/lyapax_implementation.md.
  • history columns are ordered once, by the final row. Near- degenerate exponents can swap order over the run - see LyapunovResult.history's docstring.

Examples

Runnable, sphinx-gallery-formatted demos in examples/ (pip install -e ".[examples]", then python examples/01_linear_ode.py):

File Task
00_time_series_sanity_check.py Inspecting the raw simulated time series before computing exponents
01_linear_ode.py Exact-eigenvalue sanity check for the QR engine
01b_custom_system.py Writing your own rhs from scratch, no lyapax.systems
02_chaotic_maps.py 1D/2D maps with closed-form exponents
03_chaotic_flows.py Lorenz/Rössler, the standard chaotic-ODE benchmarks
04_linear_network.py Coupled network vs. exact Jacobian eigenvalues
05_kuramoto_sync.py Kuramoto network synchronization transition
06_custom_coupling.py Writing a custom coupling function
07_speed_and_accuracy.py Cost/accuracy tradeoffs across settings
08_delayed_coupling.py Two-node linear DDE network vs. delay
09_kuramoto_delayed_network.py Effect of transmission delay on a Kuramoto network
10_matrix_free_scaling.py Dense jacfwd vs. jvp/vmap, and why it matters for partial spectra
11_vmap_parameter_sweep.py Batched parameter sweeps via jax.vmap
12_public_api_overview.py Problem-object API for ODEs, networks, and DDEs
13_dde_history_interpolation.py Grid-snapped vs. Hermite-interpolated DDE history reads
14_gpu_acceleration.py When GPU execution pays off for larger Lyapunov workloads
15_adaptive_ode.py Adaptive-step ODE integration via the optional diffrax backend
16_convergence_drift.py Chunked run-inspect-resume loop with convergence_drift
17_dde_resume.py Resuming a checkpointed DDE run
18_differentiate_lyapunov_exponent.py Differentiating an exponent w.r.t. a system parameter, and where that breaks down
19_kaplan_yorke_dimension.py Kaplan-Yorke dimension from a Lyapunov spectrum

Building the docs

pip install -e ".[docs,adaptive]"
sphinx-build -b html docs docs/_build/html

This re-runs every numbered examples/*.py file to render it into a sphinx-gallery gallery (code, output, and plots), including 15_adaptive_ode.py (hence the adaptive extra above), alongside the API reference; open docs/_build/html/index.html when it's done.

Further reading

  • docs/background/validation.md - the correctness tests this package is held to (exact values, structural invariants, literature figures).
  • docs/background/benchmarks.md - comparison against jitcode/jitcdde and ChaosTools.jl.
  • docs/background/capabilities.md - a candid summary of what lyapax does and does not do, including measured performance characteristics.

Download files

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

Source Distribution

lyapax-0.3.0.tar.gz (84.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lyapax-0.3.0-py3-none-any.whl (61.3 kB view details)

Uploaded Python 3

File details

Details for the file lyapax-0.3.0.tar.gz.

File metadata

  • Download URL: lyapax-0.3.0.tar.gz
  • Upload date:
  • Size: 84.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lyapax-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f62f2f825464b49647b9ae895adb68570d6c9132b9d20fbe64fe6e95dd5b9f74
MD5 2a8de2753e6235ba1f642ed1065e2c27
BLAKE2b-256 07c8c3d88f1a09472dd812c22d8164443afa7a323482cf3da9a1c7fe080244e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for lyapax-0.3.0.tar.gz:

Publisher: publish.yml on Ziaeemehr/lyapax

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lyapax-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: lyapax-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 61.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lyapax-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6093dede63ccef85a337b23fe1ec9fb51dfb75b696bf8454a0d5dfc0c9c3c82e
MD5 5745ac4700c34865df88a868aa219c37
BLAKE2b-256 df376660f6c034e9ef2a687d72df05e3f61305004bd6c44729bf0b68061fb92a

See more details on using hashes here.

Provenance

The following attestation bundles were made for lyapax-0.3.0-py3-none-any.whl:

Publisher: publish.yml on Ziaeemehr/lyapax

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page