.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/chaos/chaos_metrics/plot_lyapunov_spectrum.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_chaos_chaos_metrics_plot_lyapunov_spectrum.py: Full Lyapunov Spectrum (Benettin QR Method) ============================================= While :func:`physicskit.chaos.visualizers.divergence.plot_lyapunov_divergence` estimates only the *largest* Lyapunov exponent from a single pair of trajectories, :func:`physicskit.chaos.utils.metrics.benettin_lyapunov_spectrum` estimates the *full* spectrum by co-evolving an orthonormal frame :math:`Y` under the linearized (variational) dynamics :math:`\dot{Y} = J(x(t)) Y`, where :math:`J` is the system's Jacobian, and periodically re-orthonormalizing it with a QR decomposition, accumulating the log-growth of each axis. It is applied below to the Lorenz and Rossler flows, .. math:: \text{Lorenz:}\quad \dot{x} &= \sigma(y-x), & \dot{y} &= x(\rho-z)-y, & \dot{z} &= xy - \beta z \\ \text{Rossler:}\quad \dot{x} &= -y-z, & \dot{y} &= x + ay, & \dot{z} &= b + z(x-c) For a chaotic, dissipative flow like Lorenz, the spectrum has one positive exponent (chaos), one exponent near zero (the flow direction along the trajectory itself), and one strongly negative exponent (strong contraction), summing to a negative total consistent with a dissipative system. :func:`physicskit.chaos.utils.metrics.map_lyapunov_spectrum` does the same for discrete maps -- demonstrated below on the dissipative Henon map, :math:`x_{n+1}=1-ax_n^2+y_n,\ y_{n+1}=bx_n`, and the area-preserving Chirikov-Taylor standard map, :math:`p_{n+1}=p_n+k\sin\theta_n \pmod{2\pi}`, :math:`\theta_{n+1}=\theta_n+p_{n+1}\pmod{2\pi}`. .. GENERATED FROM PYTHON SOURCE LINES 31-41 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from physicskit.chaos.systems.continuous import Lorenz, Rossler from physicskit.chaos.systems.maps import HenonMap, StandardMap from physicskit.chaos.utils.metrics import benettin_lyapunov_spectrum, map_lyapunov_spectrum systems = {"Lorenz": Lorenz(), "Rossler": Rossler()} .. GENERATED FROM PYTHON SOURCE LINES 42-44 Continuous flows --------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 44-60 .. code-block:: Python spectra = {name: benettin_lyapunov_spectrum(system, system.initial_state(), dt=0.01, n_steps=8000, n_transient=1000) for name, system in systems.items()} for name, spectrum in spectra.items(): print(f"{name} Lyapunov spectrum: {spectrum} (sum = {spectrum.sum():.3f})") fig, ax = plt.subplots(figsize=(7, 5)) width = 0.35 for offset, (name, spectrum) in zip((-width / 2, width / 2), spectra.items()): idx = np.arange(len(spectrum)) + offset ax.bar(idx, spectrum, width=width, label=name) ax.axhline(0.0, color="black", lw=0.8) ax.set_xticks(range(3)) ax.set_xticklabels([r"$\lambda_1$", r"$\lambda_2$", r"$\lambda_3$"]) ax.set_ylabel("Lyapunov exponent") ax.set_title("Lyapunov spectra: Lorenz vs. Rossler") ax.legend() .. image-sg:: /api/gallery/chaos/chaos_metrics/images/sphx_glr_plot_lyapunov_spectrum_001.png :alt: Lyapunov spectra: Lorenz vs. Rossler :srcset: /api/gallery/chaos/chaos_metrics/images/sphx_glr_plot_lyapunov_spectrum_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Lorenz Lyapunov spectrum: [ 0.88601347 0.01735502 -14.56993363] (sum = -13.667) Rossler Lyapunov spectrum: [ 0.07105687 0.00997877 -5.43497703] (sum = -5.354) .. GENERATED FROM PYTHON SOURCE LINES 61-69 Discrete maps ---------------- The same Benettin QR method applies to discrete maps, just without a `dt` to divide by. As a check on the estimate's quality: the Henon map's Jacobian determinant is exactly ``-b`` everywhere, so its spectrum must sum to exactly ``ln|b|``; the standard map is exactly area-preserving, so its spectrum must sum to exactly zero -- both hold regardless of how precisely the *individual* exponents are estimated. .. GENERATED FROM PYTHON SOURCE LINES 69-89 .. code-block:: Python henon = HenonMap(a=1.4, b=0.3) standard = StandardMap(k=2.0) henon_spectrum = map_lyapunov_spectrum(henon, henon.initial_state(), n_iter=10000, n_transient=1000) standard_spectrum = map_lyapunov_spectrum(standard, standard.initial_state(), n_iter=10000, n_transient=1000) print(f"Henon spectrum: {henon_spectrum} (sum = {henon_spectrum.sum():.4f}, ln|b| = {np.log(0.3):.4f})") print(f"Standard map spectrum: {standard_spectrum} (sum = {standard_spectrum.sum():.4f})") fig2, ax2 = plt.subplots(figsize=(6, 5)) width = 0.35 for offset, (name, spectrum) in zip((-width / 2, width / 2), [("Henon", henon_spectrum), ("Standard map", standard_spectrum)]): idx = np.arange(len(spectrum)) + offset ax2.bar(idx, spectrum, width=width, label=name) ax2.axhline(0.0, color="black", lw=0.8) ax2.set_xticks(range(2)) ax2.set_xticklabels([r"$\lambda_1$", r"$\lambda_2$"]) ax2.set_ylabel("Lyapunov exponent (per iteration)") ax2.set_title("Lyapunov spectra: Henon (dissipative) vs. Standard map (conservative)") ax2.legend() plt.show() .. image-sg:: /api/gallery/chaos/chaos_metrics/images/sphx_glr_plot_lyapunov_spectrum_002.png :alt: Lyapunov spectra: Henon (dissipative) vs. Standard map (conservative) :srcset: /api/gallery/chaos/chaos_metrics/images/sphx_glr_plot_lyapunov_spectrum_002.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Henon spectrum: [ 0.42652047 -1.63049328] (sum = -1.2040, ln|b| = -1.2040) Standard map spectrum: [ 0.46525272 -0.46525272] (sum = 0.0000) .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 1.303 seconds) .. _sphx_glr_download_api_gallery_chaos_chaos_metrics_plot_lyapunov_spectrum.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_lyapunov_spectrum.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_lyapunov_spectrum.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_lyapunov_spectrum.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_