Type at least 2 letters. Enter opens the first result, Esc closes.

    ML for Science · Lesson 5 · Chaos, data and uncertainty

    Chaos, predictability, Koopman, DMD and SINDy

    Intermediate 100 min 5 interactive figures 5 videos Colab notebook

    Before this lesson: linear algebra 05 (eigenvalues, complex pairs), linear algebra 08 (the SVD and the pseudoinverse) and linear algebra 12 (least squares); lesson 02 (RK4, stability) and lesson 03 (the tangent-linear model). Helpful: optimization 09 (sparse regression). Time: about 100 minutes, plus the notebook.


    Why this matters #

    Weather is chaotic. Lorenz found sensitive dependence on initial conditions in 1963 with the three-variable model of this lesson, a truncated model of convection. Today, skilful forecasts of day-to-day midlatitude weather reach about 10 days. Zhang et al. (2019) estimate that a 10 times smaller initial-condition error would add at most about 5 days. Lyapunov exponents explain why the gain is so small: they set how fast errors grow. They also explain three things you meet in this track:

    • gradients through long rollouts explode (lesson 03);
    • 4D-Var assimilation windows must be short (lesson 06);
    • ML weather models are judged by ensembles and statistics at long lead times, not by one trajectory (lesson 16).

    The second half is about learning dynamics from data. The Koopman operator turns nonlinear dynamics into linear dynamics on functions of the state. DMD is the best-fit linear model of snapshot data, and it approximates the Koopman operator. SINDy finds sparse, readable equations. These are standard tools in fluid dynamics and climate data analysis. They are also the ideas behind Koopman autoencoders and the linear latent dynamics of state-space models in ML.

    1. Predict first #

    2. The picture #

    Errors that double: the simplest chaotic map #

    Iterate a map xk+1=f(xk)x_{k+1} = f(x_k) from two nearby starting points. Their distance δk\delta_k obeys δk+1≈∣f′(xk)∣ δk\delta_{k+1} \approx |f'(x_k)|\,\delta_k (a first-order Taylor step). After kk steps,

    δk≈δ0∏j=0k−1∣f′(xj)∣=δ0 ekλ,λ=lim⁡k→∞1k∑j=0k−1ln⁡∣f′(xj)∣.\delta_k \approx \delta_0\prod_{j=0}^{k-1}|f'(x_j)| = \delta_0\,e^{k\lambda}, \qquad \lambda = \lim_{k\to\infty}\frac1k\sum_{j=0}^{k-1}\ln|f'(x_j)| .

    The number λ\lambda is the Lyapunov exponent (per step): the average logarithmic stretching along the orbit. It is an average, not the local rate at one point.

    Example. The doubling map x↦2x mod 1x \mapsto 2x \bmod 1 has f′=2f' = 2 everywhere, so λ=ln⁡2\lambda = \ln 2. Every step doubles the error. In binary, one step shifts all digits of xx one place to the left, so each step reveals one more binary digit of x0x_0. In float64, the orbit of x0=0.1x_0 = 0.1 becomes exactly 0 after 55 steps: all the information in the starting value has been used up. The logistic map x↦4x(1−x)x \mapsto 4x(1 - x) also has λ=ln⁡2\lambda = \ln 2 (the notebook checks it).

    The predictability time. An error δ0\delta_0 reaches a tolerance Δ\Delta when δ0eλk=Δ\delta_0 e^{\lambda k} = \Delta, that is, after

    k=1λln⁡Δδ0 steps.k = \frac{1}{\lambda}\ln\frac{\Delta}{\delta_0}\ \text{steps}.

    The starting error enters only through a logarithm. A better initial condition helps, but only a little.

    Fixed points and their type #

    Now a flow u˙=f(u)\dot u = f(u), with u∈Rnu \in \R^n (we use uu for the state, as in lessons 02 and 03). A fixed point u∗u^* has f(u∗)=0f(u^*) = 0: a state that does not move. Near it, write u=u∗+δu = u^* + \delta. A Taylor step gives δ˙≈J(u∗) δ\dot\delta \approx J(u^*)\,\delta, with the Jacobian J=∂f/∂uJ = \partial f/\partial u. This is a linear ODE, and its solutions are combinations of eλitvie^{\lambda_i t}v_i for the eigenpairs (λi,vi)(\lambda_i, v_i) of J(u∗)J(u^*) (linear algebra 05). So:

    • the real part of an eigenvalue decides growth (>0> 0) or decay (<0< 0) along its direction;
    • the imaginary part decides rotation: a complex pair a±bia \pm bi gives a spiral with angular frequency bb.

    In the plane, the two eigenvalues are fixed by the trace T=tr⁡JT = \operatorname{tr} J and the determinant D=det⁡JD = \det J: λ1,2=T/2±T2/4−D\lambda_{1,2} = T/2 \pm \sqrt{T^2/4 - D}. So one picture classifies every case.

    Interactive figure: loading…

    Drag the orange point in the trace–determinant plane (left), or use the presets. The right side shows the phase portrait of a matrix with this trace and determinant: blue trajectories with arrows, and the eigenvector lines in yellow when the eigenvalues are real. Below the dashed parabola D=T2/4D = T^2/4 the eigenvalues are real; above it they are a complex pair. Notice that the sign of TT alone decides stability when D>0D > 0.

    Eigenvalues of J(u∗)J(u^*) Type In the (T,D)(T, D) plane
    real, both negative stable node D>0D > 0, T<0T < 0, below the parabola
    real, opposite signs saddle D<0D < 0
    complex pair, negative real part stable spiral D>0D > 0, T<0T < 0, above the parabola
    complex pair, positive real part unstable spiral D>0D > 0, T>0T > 0, above the parabola
    purely imaginary pair centre (for the linear system) T=0T = 0, D>0D > 0

    In three dimensions there are three eigenvalues, and the same rules apply direction by direction. A real negative eigenvalue together with a complex pair of positive real part is a saddle-focus: trajectories come in along one direction and spiral out in a plane.

    Quick check

    At a fixed point of a 3D system, the Jacobian has the eigenvalues −13.86-13.86 and 0.094±10.19i0.094 \pm 10.19i. What type of fixed point is it?

    Two runs of a chaotic flow #

    Lorenz-63 is the classic chaotic flow:

    x˙=σ(y−x),y˙=x(ρ−z)−y,z˙=xy−βz,σ=10, ρ=28, β=8/3.\dot x = \sigma(y - x), \qquad \dot y = x(\rho - z) - y, \qquad \dot z = xy - \beta z, \qquad \sigma = 10,\ \rho = 28,\ \beta = 8/3 .

    Every fixed point of it is unstable (section 3), yet trajectories stay bounded. They wander around two "wings", the Lorenz attractor, and never repeat. Start two trajectories very close together and watch.

    Interactive figure: loading…

    Press Play, or move the time slider. Two Lorenz-63 trajectories start δ0\delta_0 apart (blue and orange, shown in the (x,z)(x, z) plane). For a long time they look like one curve. The magenta curve below is their distance on a log axis. It wiggles, but on average it follows the dashed line of slope λ1=0.906\lambda_1 = 0.906, until it saturates at the size of the attractor. Change δ0\delta_0 by a factor 1000: the time to reach distance 1 moves by only about ln⁡(1000)/0.906≈7.6\ln(1000)/0.906 \approx 7.6.

    Chaos is stretching and folding at the same time. Stretching: some directions grow, so nearby states separate. Folding: the attractor is bounded, so the stretched set must fold back onto itself. Together they mix states: after a while, the state could be anywhere on the attractor.

    Quick check

    For Lorenz-63, λ1=0.906\lambda_1 = 0.906 per time unit. About how long does it take for a small error to double?

    Three ways to look at dynamics #

    • States and nearby trajectories: fixed points, linearisation, Lyapunov exponents. This is the first half of the lesson.
    • Observables: instead of moving the state, move functions g(u)g(u) of the state, for example the temperature at one place. The rule that moves them, the Koopman operator, is linear even when ff is not. The price: it acts on a space of functions, which is infinite-dimensional.
    • Data: DMD fits the best linear map between snapshots of chosen observables. SINDy fits a sparse combination of candidate terms to the vector field ff.

    The next figure shows the observable view on a nonlinear system with a known answer. In the state (x1,x2)(x_1, x_2) the trajectory bends, so no matrix can follow it. With one extra observable, x12x_1^2, the same motion is exactly linear.

    Interactive figure: loading…

    Drag the yellow start point, then switch the observables. The system is x˙1=−0.05 x1\dot x_1 = -0.05\,x_1, x˙2=−(x2−x12)\dot x_2 = -(x_2 - x_1^2). The blue curve is the true trajectory; it falls fast onto the grey parabola (the slow manifold) and then slides slowly along it. DMD uses the aqua snapshots (t≤10t \le 10) and its linear model is the orange dashed curve. With the state (x1,x2)(x_1, x_2) the model misses the bend and one rate is wrong. With (x1,x2,x12)(x_1, x_2, x_1^2) the error drops to rounding level and the rates are exactly −0.05-0.05, −1-1 and −0.1-0.1. The chart shows why: along the trajectory, the logarithms of the three Koopman eigenfunctions are straight lines.

    3. Definitions and main results #

    Fixed points and Lorenz-63 #

    A fixed point u∗u^* is hyperbolic if no eigenvalue of J(u∗)J(u^*) has zero real part. Near a hyperbolic fixed point, the nonlinear flow looks like the linear flow δ˙=J(u∗)δ\dot\delta = J(u^*)\delta (the Hartman–Grobman theorem): stable if all real parts are negative, a saddle if the signs are mixed, with spiralling where there are complex pairs. A centre is not hyperbolic, and there the linearisation can mislead: small nonlinear terms decide.

    The Jacobian of Lorenz-63 is

    J(x,y,z)=(−σσ0ρ−z−1−xyx−β).J(x, y, z) = \begin{pmatrix} -\sigma & \sigma & 0 \\ \rho - z & -1 & -x \\ y & x & -\beta \end{pmatrix}.

    Fixed points. x˙=0\dot x = 0 gives y=xy = x. Then z˙=0\dot z = 0 gives z=x2/βz = x^2/\beta, and y˙=0\dot y = 0 gives x(ρ−1−z)=0x(\rho - 1 - z) = 0. So either x=0x = 0 (the origin), or z=ρ−1z = \rho - 1 and x2=β(ρ−1)x^2 = \beta(\rho - 1):

    C±=(±β(ρ−1), ±β(ρ−1), ρ−1)=(±8.485, ±8.485, 27).C_\pm = \big(\pm\sqrt{\beta(\rho - 1)},\ \pm\sqrt{\beta(\rho - 1)},\ \rho - 1\big) = (\pm 8.485,\ \pm 8.485,\ 27).
    • At the origin, the eigenvalues are 11.82811.828, −22.828-22.828 and −8/3-8/3: a saddle.
    • At C±C_\pm, they are −13.855-13.855 and 0.094±10.195i0.094 \pm 10.195i: a saddle-focus (unstable spiral), because ρ=28\rho = 28 is above the Hopf value ρH=σ(σ+β+3)/(σ−β−1)=24.74\rho_H = \sigma(\sigma + \beta + 3)/(\sigma - \beta - 1) = 24.74.

    Every fixed point is unstable, yet trajectories stay bounded: they wander around C+C_+ and C−C_- on the attractor. The trace of the Jacobian is −(σ+1+β)=−13.667-(\sigma + 1 + \beta) = -13.667 at every point. So volumes in state space shrink by the factor e−13.667e^{-13.667} per time unit (this follows from Liouville's formula, step 2 of the proof of Theorem 1 below).

    Lyapunov exponents #

    A small perturbation δ\delta of a trajectory u(t)u(t) obeys the tangent-linear model δ˙=J(u(t)) δ\dot\delta = J(u(t))\,\delta (lesson 03). Collect all directions at once in the tangent propagator M(t)=∂u(t)/∂u(0)M(t) = \partial u(t)/\partial u(0):

    M˙=J(u(t)) M,M(0)=I,δ(t)=M(t) δ(0).\dot M = J(u(t))\,M, \qquad M(0) = I, \qquad \delta(t) = M(t)\,\delta(0).

    Definition. The Lyapunov exponents λ1≥⋯≥λn\lambda_1 \ge \dots \ge \lambda_n are

    λi=lim⁡t→∞1tln⁡si(M(t)),\lambda_i = \lim_{t\to\infty}\frac1t\ln s_i\big(M(t)\big),

    where s1≥⋯≥sns_1 \ge \dots \ge s_n are the singular values of M(t)M(t) (linear algebra 08). M(t)M(t) maps a small ball to an ellipsoid, and sis_i are its semi-axes, so λi\lambda_i is the average exponential growth rate of the ii-th axis.

    Oseledets' theorem says that these limits exist and are the same for almost every starting point on the attractor (with respect to an ergodic invariant measure, here the natural measure of the attractor). For almost every δ(0)\delta(0), 1tln⁡(∥δ(t)∥/∥δ(0)∥)→λ1\tfrac1t\ln\big(\|\delta(t)\|/\|\delta(0)\|\big) \to \lambda_1: a random perturbation turns towards the fastest-growing direction. A bounded system with λ1>0\lambda_1 > 0 is chaotic. For Lorenz-63 the exponents are (0.906, 0, −14.572)(0.906,\ 0,\ -14.572) (Sprott, 2003).

    Theorem 1 (sum of the exponents). ∑iλi=lim⁡t→∞1t∫0ttr⁡J(u(s)) ds\displaystyle\sum_i\lambda_i = \lim_{t\to\infty}\frac1t\int_0^t \operatorname{tr}J(u(s))\,ds.

    Why this is true, in one sentence: tr⁡J\operatorname{tr}J is the rate at which small volumes grow, and the volume of the ellipsoid is the product of its axes, ∏isi\prod_i s_i, which grows at the rate ∑iλi\sum_i\lambda_i.

    Proof.

    1. Jacobi's formula: ddtdet⁡M=det⁡M⋅tr⁡(M−1M˙)\frac{d}{dt}\det M = \det M\cdot\operatorname{tr}(M^{-1}\dot M).
    2. M−1M˙=M−1JMM^{-1}\dot M = M^{-1}JM has the same trace as JJ (similar matrices). So ddtdet⁡M=tr⁡(J)det⁡M\frac{d}{dt}\det M = \operatorname{tr}(J)\det M, and det⁡M(t)=exp⁡∫0ttr⁡J(u(s)) ds\det M(t) = \exp\int_0^t\operatorname{tr}J(u(s))\,ds (Liouville's formula).
    3. ∣det⁡M∣=∏isi(M)|\det M| = \prod_i s_i(M). Take the logarithm and divide by tt: ∑i1tln⁡si(M(t))=1t∫0ttr⁡J ds\sum_i\frac1t\ln s_i(M(t)) = \frac1t\int_0^t\operatorname{tr}J\,ds.
    4. Let t→∞t \to \infty. ■\blacksquare

    For Lorenz-63, tr⁡J\operatorname{tr}J is constant, so 0.906+0−14.572=−13.6670.906 + 0 - 14.572 = -13.667 exactly. The strongly negative λ3\lambda_3 squeezes volumes, so the attractor has zero volume. Its Kaplan–Yorke dimension 2+λ1/∣λ3∣=2.062 + \lambda_1/|\lambda_3| = 2.06 says that it is a thin set, a little more than two-dimensional.

    Theorem 2 (a flow has a zero exponent). Let u(t)u(t) be a bounded trajectory of u˙=f(u)\dot u = f(u) that does not converge to a fixed point, and assume that ∥f(u(t))∥\|f(u(t))\| does not decay to zero exponentially fast. Then one Lyapunov exponent is 00. The reason: pushing the state along the trajectory only shifts it in time, and a time shift neither grows nor shrinks on average.

    Proof of Theorem 2

    The assumption means 1tln⁡∥f(u(t))∥→0\frac1t\ln\|f(u(t))\| \to 0. It holds when the trajectory keeps coming back to a region where ∥f∥≥c>0\|f\| \ge c > 0, away from the fixed points.

    1. Differentiate f(u(t))f(u(t)) along the trajectory: ddtf(u(t))=J(u(t)) u˙(t)=J(u(t)) f(u(t))\frac{d}{dt}f(u(t)) = J(u(t))\,\dot u(t) = J(u(t))\,f(u(t)).
    2. So δ(t)=f(u(t))\delta(t) = f(u(t)) solves the tangent-linear model, with δ(0)=f(u(0))\delta(0) = f(u(0)). It is the perturbation that shifts the trajectory in time: u(t+ε)≈u(t)+εf(u(t))u(t + \varepsilon) \approx u(t) + \varepsilon f(u(t)).
    3. ∥f(u(t))∥\|f(u(t))\| is bounded above (continuous ff on a bounded set), and by the assumption it does not go to zero exponentially. So 1tln⁡∥f(u(t))∥→0\frac1t\ln\|f(u(t))\| \to 0: the growth rate in this direction is 00.
    4. By Oseledets' theorem, every direction grows at the rate of one of the exponents. So one λi\lambda_i equals 00. ■\blacksquare

    Computing λ1\lambda_1 (Benettin's method). Integrate the state together with one tangent vector δ\delta (the tangent-linear model, not a second trajectory). Every τ\tau time units:

    1. add ln⁡∥δ∥\ln\|\delta\| to a running sum;
    2. rescale δ\delta to norm 1 (keep its direction).

    After KK intervals, λ1≈1Kτ∑kln⁡∥δk∥\lambda_1 \approx \frac{1}{K\tau}\sum_k\ln\|\delta_k\|. The rescaling is needed: δ\delta grows like e0.906te^{0.906t} and would overflow float64 near t≈780t \approx 780.

    All exponents, and why two trajectories need care

    To get all nn exponents, carry nn tangent vectors as the columns of QQ. Every step, propagate them and re-orthonormalise with a QR factorisation QnewR=MτQQ_{\text{new}}R = M_\tau Q (linear algebra 12). Then λi≈1Kτ∑kln⁡∣Rii(k)∣\lambda_i \approx \frac{1}{K\tau}\sum_k\ln|R_{ii}^{(k)}|. Without QR, every vector would turn towards the fastest-growing direction and all estimates would approach λ1\lambda_1.

    The two-trajectory version (as in the figure) must also rescale the separation before it stops being small; otherwise the estimate saturates at the size of the attractor. A single pair also gives a noisy slope, because the local growth rate changes along the attractor.

    Predictability. An error grows like δ0eλ1t\delta_0 e^{\lambda_1 t}. For Lorenz-63:

    • the Lyapunov time is 1/λ1=1.101/\lambda_1 = 1.10 time units (growth by the factor ee);
    • the doubling time is ln⁡2/λ1=0.77\ln 2/\lambda_1 = 0.77 time units;
    • the time to reach a tolerance Δ\Delta is the predictability time Tp=1λ1ln⁡(Δ/δ0)T_p = \frac{1}{\lambda_1}\ln(\Delta/\delta_0).

    Three consequences for this track:

    • Training through rollouts. The gradient of a loss at time TT with respect to u(0)u(0) contains M(T)⊤M(T)^\top, so it grows like eλ1Te^{\lambda_1 T} (lesson 03).
    • Data assimilation. The 4D-Var cost function gets many local minima when the window is long, so windows are short (lesson 06).
    • Forecasts depend on the day. The finite-time growth rate varies along the attractor, so predictability depends on the state of the flow. This is why ensemble forecasts show more spread on some days than on others.

    The Koopman operator #

    Take a discrete-time system uk+1=F(uk)u_{k+1} = F(u_k). For a flow, FF is the flow map over a time step Δt\Delta t. An observable is a function gg of the state, for example the temperature at one point.

    Definition. The Koopman operator K\mathcal K acts on observables by composition with FF:

    (Kg)(u)=g(F(u)),so(Kg)(uk)=g(uk+1).(\mathcal K g)(u) = g(F(u)), \qquad\text{so}\qquad (\mathcal K g)(u_k) = g(u_{k+1}).

    In words: Kg\mathcal K g is the observable "gg, one step later".

    Proposition (linearity and eigenfunctions).

    1. K\mathcal K is linear: K(ag+bh)=a Kg+b Kh\mathcal K(ag + bh) = a\,\mathcal Kg + b\,\mathcal Kh for any FF, linear or not.
    2. If Kφ=μφ\mathcal K\varphi = \mu\varphi (a Koopman eigenfunction with eigenvalue μ\mu), then φ(uk)=μkφ(u0)\varphi(u_k) = \mu^k\varphi(u_0): along every trajectory, φ\varphi evolves exactly linearly.
    3. If φ1,φ2\varphi_1, \varphi_2 are eigenfunctions with eigenvalues μ1,μ2\mu_1, \mu_2, then φ1φ2\varphi_1\varphi_2 is an eigenfunction with eigenvalue μ1μ2\mu_1\mu_2.
    Proof of the proposition
    1. (ag+bh)(F(u))=a g(F(u))+b h(F(u))(ag + bh)(F(u)) = a\,g(F(u)) + b\,h(F(u)). Nothing here uses linearity of FF: we only evaluate functions at the point F(u)F(u).
    2. φ(uk)=(Kφ)(uk−1)=μ φ(uk−1)\varphi(u_k) = (\mathcal K\varphi)(u_{k-1}) = \mu\,\varphi(u_{k-1}). Repeat kk times.
    3. K(φ1φ2)(u)=φ1(F(u)) φ2(F(u))=μ1φ1(u) μ2φ2(u)\mathcal K(\varphi_1\varphi_2)(u) = \varphi_1(F(u))\,\varphi_2(F(u)) = \mu_1\varphi_1(u)\,\mu_2\varphi_2(u). ■\blacksquare

    The price: K\mathcal K acts on a space of functions, which is infinite-dimensional. In continuous time, an eigenfunction with f⋅∇φ=ωφf\cdot\nabla\varphi = \omega\varphi satisfies φ(u(t))=eωtφ(u(0))\varphi(u(t)) = e^{\omega t}\varphi(u(0)), and the flow map over Δt\Delta t has the eigenvalue μ=eωΔt\mu = e^{\omega\Delta t}.

    Linear systems. For F(u)=AuF(u) = Au and a left eigenvector ww of AA (w⊤A=μw⊤w^\top A = \mu w^\top), the observable φ(u)=w⊤u\varphi(u) = w^\top u is an eigenfunction: φ(Au)=w⊤Au=μ w⊤u\varphi(Au) = w^\top Au = \mu\,w^\top u.

    A finite invariant subspace for a nonlinear system (Brunton and Kutz, §7.4). This is the system of the figure in section 2. With continuous-time rates μ\mu and λ\lambda (here λ\lambda is a rate of the model, not a Lyapunov exponent):

    x˙1=μx1,x˙2=λ(x2−x12),λ<μ<0,  λ≠2μ.\dot x_1 = \mu x_1, \qquad \dot x_2 = \lambda(x_2 - x_1^2), \qquad \lambda < \mu < 0,\ \ \lambda \ne 2\mu .

    Take the observables y=(x1,x2,x12)y = (x_1, x_2, x_1^2). Step by step:

    • y˙1=x˙1=μy1\dot y_1 = \dot x_1 = \mu y_1;
    • y˙2=λx2−λx12=λy2−λy3\dot y_2 = \lambda x_2 - \lambda x_1^2 = \lambda y_2 - \lambda y_3;
    • y˙3=2x1x˙1=2μx12=2μy3\dot y_3 = 2x_1\dot x_1 = 2\mu x_1^2 = 2\mu y_3 (chain rule).

    So

    y˙=Ky,K=(μ000λ−λ002μ),\dot y = K y, \qquad K = \begin{pmatrix}\mu & 0 & 0\\ 0 & \lambda & -\lambda\\ 0 & 0 & 2\mu\end{pmatrix},

    a linear system, exactly, and y(t+Δt)=eKΔty(t)y(t + \Delta t) = e^{K\Delta t}y(t). The nonlinear term x12x_1^2 is now a coordinate. The eigenvalues of KK are μ\mu, λ\lambda and 2μ2\mu, with the eigenfunctions x1x_1, x2−b x12x_2 - b\,x_1^2 with b=λ/(λ−2μ)b = \lambda/(\lambda - 2\mu), and x12x_1^2.

    Check of the middle one: ddt(x2−bx12)=λx2−λx12−2bμx12=λx2−(λ+2bμ)x12\frac{d}{dt}(x_2 - bx_1^2) = \lambda x_2 - \lambda x_1^2 - 2b\mu x_1^2 = \lambda x_2 - (\lambda + 2b\mu)x_1^2. This equals λ(x2−bx12)\lambda(x_2 - bx_1^2) exactly when λ+2bμ=λb\lambda + 2b\mu = \lambda b, that is, b(λ−2μ)=λb(\lambda - 2\mu) = \lambda. The curve x2=bx12x_2 = b x_1^2, where this eigenfunction is 0, is the slow manifold of the figure: the fast rate λ\lambda pulls every trajectory onto it.

    Quick check

    For the logistic map F(x)=4x(1−x)F(x) = 4x(1 - x), which statement about its Koopman operator is true?

    When no finite subspace exists. The quiz shows the first obstacle: for the logistic map the degree of the polynomials doubles at each step. For chaos the obstacle is deeper.

    Mixing and the continuous Koopman spectrum

    The Lorenz attractor is mixing (Luzzatto, Melbourne and Paccaut, 2005): any two regions of the attractor become, after a long time, statistically independent. On a mixing attractor the only eigenfunctions of K\mathcal K in L2L^2 of the invariant measure are the constants, and the rest of the spectrum is continuous. A finite linear model of chaos can therefore only be approximate, and only over short horizons. Practical methods (extended DMD with many observables, delay coordinates, Koopman autoencoders) give good short-term predictions and useful coherent patterns, not an exact finite linear system.

    Koopman modes. Suppose each state component is a combination of eigenfunctions, u=∑jvjφj(u)u = \sum_j v_j\varphi_j(u). Then uk=∑jvj μjk φj(u0)u_k = \sum_j v_j\,\mu_j^k\,\varphi_j(u_0): the state is a sum of fixed spatial patterns vjv_j (the Koopman modes), each with one growth rate and one frequency. DMD estimates the pairs (vj,μj)(v_j, \mu_j) from data, with the state coordinates as observables.

    Dynamic mode decomposition (DMD) #

    Data. Snapshot pairs (xk,xk′)(x_k, x_k') with xk′=F(xk)x_k' = F(x_k), usually xk′=xk+1x_k' = x_{k+1} at spacing Δt\Delta t. (From here on we write xx for a data vector, as in the DMD literature.) Arrange them as columns:

    X=[x1⋯xm],X′=[x1′⋯xm′],both n×m,X = [x_1 \cdots x_m], \qquad X' = [x_1' \cdots x_m'], \qquad \text{both } n \times m,

    with nn the number of measured values per snapshot (for example grid points) and mm the number of snapshots.

    The best-fit linear map. A=argmin⁡A∥X′−AX∥F=X′X+A = \operatorname*{argmin}_A\|X' - AX\|_F = X'X^+, with X+X^+ the pseudoinverse (linear algebra 08). Each row of AA is a least-squares problem, and X+X^+ gives the minimum-norm solution. For a field with n=106n = 10^6 grid points, AA has 101210^{12} entries. Exact DMD never forms it.

    Exact DMD (Tu et al., 2014, Algorithm 2):

    1. Reduced SVD X=UΣV∗X = U\Sigma V^*, truncated to rank rr: UrU_r (n×rn \times r), Σr\Sigma_r, VrV_r (m×rm \times r).
    2. Projected operator A~=Ur∗X′VrΣr−1\tilde A = U_r^*X'V_r\Sigma_r^{-1} (r×rr \times r). It equals Ur∗AUrU_r^*AU_r for A=X′VrΣr−1Ur∗A = X'V_r\Sigma_r^{-1}U_r^*: the map AA seen in the coordinates of the top rr singular vectors.
    3. Eigendecomposition A~W=WΛ\tilde AW = W\Lambda. The diagonal of Λ\Lambda holds the DMD eigenvalues μj\mu_j.
    4. Exact DMD modes Φ=X′VrΣr−1W\Phi = X'V_r\Sigma_r^{-1}W (n×rn \times r). A mode is defined only up to a scale factor (Tu et al. divide column jj by μj\mu_j; Brunton and Kutz do not).
    5. Continuous-time rates ωj=ln⁡(μj)/Δt\omega_j = \ln(\mu_j)/\Delta t: growth rate Re⁡ωj\operatorname{Re}\omega_j and angular frequency Im⁡ωj\operatorname{Im}\omega_j. Amplitudes b=Φ+x1b = \Phi^+x_1, and the model x(t)≈∑jϕj eωjt bjx(t) \approx \sum_j\phi_j\,e^{\omega_j t}\,b_j, where ϕj\phi_j is column jj of Φ\Phi.

    The cost is one thin SVD, O(nm2)O(nm^2), plus small r×rr \times r problems.

    Reading a DMD eigenvalue. Write μ=∣μ∣eiθ\mu = |\mu|e^{i\theta}. Then ω=(ln⁡∣μ∣+iθ)/Δt\omega = (\ln|\mu| + i\theta)/\Delta t:

    • ∣μ∣<1|\mu| < 1: the mode decays; ∣μ∣=1|\mu| = 1: it neither grows nor decays; ∣μ∣>1|\mu| > 1: it grows;
    • the angle θ\theta is the rotation per step, so the angular frequency is θ/Δt\theta/\Delta t.
    Interactive figure: loading…

    Move the rank rr, then add noise. The data (left map) are two travelling waves, one neutral and one decaying, plus sensor noise; violet is negative, yellow positive. The right map is the rank-rr DMD model, rolled out from the first snapshot. In the complex plane, the orange dots are the DMD eigenvalues and the blue rings the true ones. With r=4r = 4 they match: two on the unit circle, two just inside. With r<4r < 4 a wave is missing. With noise and r>4r > 4, extra eigenvalues appear deep inside the circle: they fit noise. The singular values (top right) show the gap after 4.

    Theorem 3 (exact DMD modes are eigenvectors of AA; Tu et al., Theorem 1). Let A=X′VrΣr−1Ur∗A = X'V_r\Sigma_r^{-1}U_r^*. If A~w=μw\tilde Aw = \mu w with μ≠0\mu \ne 0, then ϕ=X′VrΣr−1w\phi = X'V_r\Sigma_r^{-1}w is nonzero and Aϕ=μϕA\phi = \mu\phi. Conversely, every nonzero eigenvalue of AA is an eigenvalue of A~\tilde A.

    Proof of Theorem 3

    Write B=X′VrΣr−1B = X'V_r\Sigma_r^{-1}, so that A=BUr∗A = BU_r^* and A~=Ur∗B\tilde A = U_r^*B. (The two products of the same two matrices in the two orders: this is the whole trick.)

    1. Aϕ=BUr∗Bw=BA~w=μBw=μϕA\phi = BU_r^*Bw = B\tilde Aw = \mu Bw = \mu\phi.
    2. If ϕ=Bw=0\phi = Bw = 0, then A~w=Ur∗Bw=0\tilde Aw = U_r^*Bw = 0, so μ=0\mu = 0, a contradiction. So ϕ≠0\phi \ne 0.
    3. Conversely, let Aϕ=μϕA\phi = \mu\phi with μ≠0\mu \ne 0, and w=Ur∗ϕw = U_r^*\phi. Then A~w=Ur∗BUr∗ϕ=Ur∗Aϕ=μw\tilde Aw = U_r^*BU_r^*\phi = U_r^*A\phi = \mu w.
    4. w≠0w \ne 0: if Ur∗ϕ=0U_r^*\phi = 0, then Aϕ=BUr∗ϕ=0A\phi = BU_r^*\phi = 0, so μ=0\mu = 0. ■\blacksquare

    The older projected modes UrWU_rW are the projections of the exact modes onto the column space of XX. They are not eigenvectors of AA in general.

    Theorem 4 (DMD recovers a linear system). If xk′=Atruexkx_k' = A_{\text{true}}x_k for all kk and XX has rank nn, then X′X+=AtrueX'X^+ = A_{\text{true}}, and exact DMD with r=nr = n returns the eigenvalues of AtrueA_{\text{true}}.

    Proof.

    1. X′=AtrueXX' = A_{\text{true}}X, so X′X+=AtrueXX+X'X^+ = A_{\text{true}}XX^+.
    2. XX+XX^+ is the orthogonal projector onto the column space of XX, which is all of Rn\R^n when rank⁡X=n\operatorname{rank}X = n. So XX+=IXX^+ = I and X′X+=AtrueX'X^+ = A_{\text{true}}.
    3. With r=nr = n, Theorem 3 gives all nonzero eigenvalues of AA. (AtrueA_{\text{true}} is invertible when it comes from a flow map, so no eigenvalue is 0.) ■\blacksquare

    If the data span only a subspace SS (for example one trajectory inside an invariant subspace), then X′X+=AtruePSX'X^+ = A_{\text{true}}P_S, with PSP_S the projector onto SS: DMD sees only the modes that the data excite.

    Quick check

    DMD with Δt=0.1\Delta t = 0.1 returns the eigenvalue μ=0.9 e0.1i\mu = 0.9\,e^{0.1i}. What does this mode do?

    DMD in practice.

    • Rank rr. Too large with noisy data gives spurious eigenvalues; too small misses dynamics. Look for a gap in the singular values. Gavish–Donoho hard thresholding is a principled choice.
    • Noise. Least squares treats XX as exact, so sensor noise biases the eigenvalues towards the origin (too much damping; in the figure, try σ=0.3\sigma = 0.3). Forward–backward and total-least-squares DMD reduce this bias (Dawson et al., 2016).
    • Few observables. A scalar signal cos⁡(ωkΔt)\cos(\omega k\Delta t) needs the two eigenvalues e±iωΔte^{\pm i\omega\Delta t}, but a 1×11 \times 1 matrix has one. Stack time-delayed copies (a Hankel matrix) to get enough rows: this is time-delay embedding.
    • Sampling. ω=ln⁡μ/Δt\omega = \ln\mu/\Delta t is unique only for ∣Im⁡ω∣<π/Δt|\operatorname{Im}\omega| < \pi/\Delta t; faster oscillations alias (they look like slower ones).
    • DMD or POD (PCA)? Proper orthogonal decomposition (POD), also called PCA or EOF analysis, ranks spatial patterns by variance and ignores the time order of the snapshots (linear algebra 09). A DMD mode is a pattern with one frequency and one growth rate. So DMD can separate, for example, an annual cycle from a slower oscillation that has a similar variance, where POD would mix them.

    SINDy: sparse identification of nonlinear dynamics #

    Model. Assume that each component of ff is a sparse combination of known candidate functions: u˙≈Θ(u) Ξ\dot u \approx \Theta(u)\,\Xi. Here Θ(u)\Theta(u) is a row of pp library functions of the state (for the Lorenz state (x,y,z)(x, y, z): 1,x,y,z,x2,xy,…1, x, y, z, x^2, xy, \dots), and Ξ∈Rp×n\Xi \in \R^{p \times n} is sparse: most entries are 0. With mm samples, stack the states as rows of XX (m×nm \times n), the time derivatives as rows of X˙\dot X, and the library as Θ(X)\Theta(X) (m×pm \times p):

    X˙≈Θ(X) Ξ.\dot X \approx \Theta(X)\,\Xi .

    Column kk of Ξ\Xi is a regression problem for u˙k\dot u_k. We want few nonzero coefficients, so that the result is a short equation. This is like the lasso, min⁡∥X˙k−Θξ∥2+α∥ξ∥1\min\|\dot X_k - \Theta\xi\|^2 + \alpha\|\xi\|_1 (optimization 09), but SINDy usually uses a simpler method.

    Sequentially thresholded least squares (STLSQ) (Brunton, Proctor and Kutz, 2016):

    1. Ξ←\Xi \leftarrow the least-squares solution of Θ(X)Ξ=X˙\Theta(X)\Xi = \dot X (dense: every term is used).
    2. Set every entry with ∣ξjk∣<η|\xi_{jk}| < \eta to zero. The threshold η\eta is called λ\lambda in the book.
    3. For each column kk, refit by least squares using only the library terms that are still active.
    4. Repeat steps 2–3 until the set of active terms no longer changes.

    Proposition (STLSQ stops). The active set of each column never grows, so STLSQ reaches a fixed point after at most pp changes per column.

    Proof. An entry set to zero in step 2 is excluded from the refit in step 3, so it stays zero: entries can leave the active set but never return. Each change removes at least one of the pp terms. When no entry falls below η\eta, steps 2–3 change nothing. ■\blacksquare

    For Lorenz-63 with all monomials up to degree 2 (p=10p = 10), Ξ\Xi has 30 entries and 7 of them are nonzero: −10,10-10, 10 (for x˙\dot x: xx, yy); 28,−1,−128, -1, -1 (for y˙\dot y: xx, yy, xzxz); −8/3,1-8/3, 1 (for z˙\dot z: zz, xyxy).

    Interactive figure: loading…

    Move the threshold, then add noise. The bars are the 30 coefficients of the first, dense least-squares fit, on a log axis: blue for the 7 true terms, magenta for the 23 terms that should be 0. The yellow line is the threshold η\eta. Below it, the equations that STLSQ returns; wrong extra terms appear in magenta. STLSQ succeeds when the line separates the blue bars from the magenta bars. Notice that the smallest true coefficient is 1, so no threshold above 1 can work.

    Choices that decide success:

    • The library must contain the true terms, in good coordinates. SINDy cannot invent a term that is not in the list.
    • The threshold must lie between the largest spurious coefficient and the smallest true one (here ∣−1∣=1|-1| = 1). Normalise the library columns, or the threshold means different things for xx and x2x^2.
    • Derivatives. Finite differences amplify noise by about 1/Δt1/\Delta t. Use smoothed or total-variation-regularised derivatives, or the weak (integral) form of SINDy.
    • Relation to DMD: with a linear library, a discrete-time target xk+1x_{k+1} and no threshold, SINDy is DMD.
    Quick check

    You run STLSQ on clean Lorenz-63 data with the threshold η=2\eta = 2. What happens?

    Answers to section 1. (1) The separation grows like 10−8e0.906t10^{-8}e^{0.906t}. It reaches order 1 after ln⁡(108)/0.906≈20\ln(10^8)/0.906 \approx 20 time units, and the size of the attractor (about 20) about 3 time units later. A 1000 times smaller error gains only ln⁡(1000)/0.906≈7.6\ln(1000)/0.906 \approx 7.6 time units. (2) Not in the state coordinates: the fixed points of x↦Axx \mapsto Ax form a linear subspace (the null space of A−IA - I), so a linear model cannot have the three isolated fixed points of Lorenz-63. With observables it can work exactly for some systems (the slow-manifold example), but never for a chaotic one, whose Koopman spectrum is continuous.

    4. Worked example #

    (a) DMD by hand. Data from Atrue=(0.50.200.8)A_{\text{true}} = \begin{pmatrix} 0.5 & 0.2\\ 0 & 0.8\end{pmatrix} with x0=(1,1)x_0 = (1, 1) and Δt=0.1\Delta t = 0.1.

    Step 1, the snapshots: x1=Atruex0=(0.5+0.2, 0.8)=(0.7,0.8)x_1 = A_{\text{true}}x_0 = (0.5 + 0.2,\ 0.8) = (0.7, 0.8) and x2=Atruex1=(0.35+0.16, 0.64)=(0.51,0.64)x_2 = A_{\text{true}}x_1 = (0.35 + 0.16,\ 0.64) = (0.51, 0.64).

    Step 2, the data matrices (the snapshots x0,x1x_0, x_1 and their successors x1,x2x_1, x_2):

    X=(10.710.8),X′=(0.70.510.80.64).X = \begin{pmatrix} 1 & 0.7\\ 1 & 0.8\end{pmatrix},\qquad X' = \begin{pmatrix} 0.7 & 0.51\\ 0.8 & 0.64\end{pmatrix}.

    Step 3, the pseudoinverse. XX is square with det⁡X=0.8−0.7=0.1≠0\det X = 0.8 - 0.7 = 0.1 \ne 0, so X+=X−1X^+ = X^{-1}:

    X−1=10.1(0.8−0.7−11)=(8−7−1010).X^{-1} = \frac{1}{0.1}\begin{pmatrix} 0.8 & -0.7\\ -1 & 1\end{pmatrix} = \begin{pmatrix} 8 & -7\\ -10 & 10\end{pmatrix}.

    Step 4, the product X′X−1X'X^{-1}, row by row:

    row 1:(0.7⋅8−0.51⋅10, −0.7⋅7+0.51⋅10)=(5.6−5.1, −4.9+5.1)=(0.5, 0.2),row 2:(0.8⋅8−0.64⋅10, −0.8⋅7+0.64⋅10)=(6.4−6.4, −5.6+6.4)=(0, 0.8).\begin{aligned} \text{row 1:}\quad &(0.7\cdot8 - 0.51\cdot10,\ -0.7\cdot7 + 0.51\cdot10)\\ &= (5.6 - 5.1,\ -4.9 + 5.1) = (0.5,\ 0.2),\\ \text{row 2:}\quad &(0.8\cdot8 - 0.64\cdot10,\ -0.8\cdot7 + 0.64\cdot10)\\ &= (6.4 - 6.4,\ -5.6 + 6.4) = (0,\ 0.8). \end{aligned}

    This is AtrueA_{\text{true}} (Theorem 4). Step 5, the eigenvalues: the matrix is triangular, so μ1=0.5\mu_1 = 0.5 and μ2=0.8\mu_2 = 0.8, with the eigenvectors (modes) (1,0)(1, 0) and (2,3)(2, 3). The continuous-time rates are ln⁡0.5/0.1=−6.93\ln 0.5/0.1 = -6.93 and ln⁡0.8/0.1=−2.23\ln 0.8/0.1 = -2.23. Both modes decay; the second one more slowly.

    (b) Lifting makes DMD exact. In the slow-manifold system take μ=−0.05\mu = -0.05, λ=−1\lambda = -1 and Δt=0.1\Delta t = 0.1.

    • The Koopman eigenvalues of the flow map are eμΔt=0.99501e^{\mu\Delta t} = 0.99501, eλΔt=0.90484e^{\lambda\Delta t} = 0.90484 and e2μΔt=0.99005e^{2\mu\Delta t} = 0.99005.
    • b=λ/(λ−2μ)=−1/(−0.9)=1.111b = \lambda/(\lambda - 2\mu) = -1/(-0.9) = 1.111.
    • On a trajectory from (1.5,−1)(1.5, -1) over 0≤t≤100 \le t \le 10, DMD on the state (x1,x2)(x_1, x_2) returns the rates −0.05-0.05 and −1.22-1.22. The rate μ\mu is right, because the x1x_1 equation is linear. The rate −1.22-1.22 is wrong: it is neither λ=−1\lambda = -1 nor 2μ=−0.12\mu = -0.1. A 2×22 \times 2 matrix has room for only two rates, so the least-squares fit mixes the effects of λ\lambda and 2μ2\mu.
    • DMD on (x1,x2,x12)(x_1, x_2, x_1^2) returns −0.05-0.05, −1-1 and −0.1-0.1, and the fitted matrix equals eKΔte^{K\Delta t} to about 10−1410^{-14} (section 5).

    (c) Lorenz numbers without simulation.

    • Sum of the exponents: ∑iλi=tr⁡J=−(10+1+8/3)=−13.667\sum_i\lambda_i = \operatorname{tr}J = -(10 + 1 + 8/3) = -13.667.
    • With λ1=0.906\lambda_1 = 0.906 and λ2=0\lambda_2 = 0: λ3=−13.667−0.906=−14.573\lambda_3 = -13.667 - 0.906 = -14.573 (Sprott: −14.5723-14.5723).
    • Kaplan–Yorke dimension: 2+0.906/14.572=2.0622 + 0.906/14.572 = 2.062.
    • Doubling time: 0.693/0.906=0.770.693/0.906 = 0.77 time units.

    (d) One STLSQ step by hand. The first, dense least-squares fit in section 5 (the array dense) gives, for y˙\dot y, the coefficients 27.99127.991 (xx), −0.998-0.998 (yy), −1.000-1.000 (xzxz), and every other coefficient below 0.0050.005 in absolute value.

    • With η=0.1\eta = 0.1, step 2 keeps {x,y,xz}\{x, y, xz\} and deletes the other 7 terms.
    • Step 3 refits y˙\dot y on these three columns only.
    • The next step 2 deletes nothing, so STLSQ stops.

    Any η\eta between about 0.0050.005 and 11 gives the right active set here; η=2\eta = 2 deletes the true terms −y-y and −xz-xz (and xyxy in z˙\dot z).

    5. In code #

    The first block finds the Lorenz fixed points and estimates λ1\lambda_1 with Benettin's method:

    import numpy as np
    
    sigma, rho, beta = 10.0, 28.0, 8 / 3
    
    def f(u):                                   # Lorenz-63
        x, y, z = u
        return np.array([sigma * (y - x), x * (rho - z) - y, x * y - beta * z])
    
    def jac(u):                                 # its Jacobian J = df/du
        x, y, z = u
        return np.array([[-sigma, sigma, 0.0], [rho - z, -1.0, -x], [y, x, -beta]])
    
    c = np.sqrt(beta * (rho - 1))               # C± = (±c, ±c, ρ - 1)
    for p in [(0, 0, 0), (c, c, rho - 1)]:
        print(np.round(np.sort_complex(np.linalg.eigvals(jac(np.array(p)))), 3))
    # [-22.828+0.j  -2.667+0.j  11.828+0.j]             saddle at the origin
    # [-13.855 +0.j  0.094-10.195j  0.094+10.195j]      saddle-focus at C+
    print(np.trace(jac(np.zeros(3))))           # -13.666666666666666 = -(σ + 1 + β)
    
    def rk4(F, u, h):
        k1 = F(u); k2 = F(u + h / 2 * k1); k3 = F(u + h / 2 * k2); k4 = F(u + h * k3)
        return u + h / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
    
    # Benettin: state + one tangent vector d (d' = J(u) d), renormalised every step
    G = lambda w: np.concatenate([f(w[:3]), jac(w[:3]) @ w[3:]])
    h, u = 0.01, np.array([1.0, 1.0, 1.0])
    for _ in range(2000):                       # 20 time units of transient
        u = rk4(f, u, h)
    w, total, n = np.concatenate([u, [1.0, 0.0, 0.0]]), 0.0, 50_000
    for _ in range(n):
        w = rk4(G, w, h)
        g = np.linalg.norm(w[3:]); total += np.log(g); w[3:] /= g
    lam1 = total / (n * h)
    print(f"{lam1:.3f}  doubling time {np.log(2) / lam1:.2f}")   # 0.908  doubling time 0.76
    

    Over 500 time units the estimate is 0.9080.908; longer runs converge to 0.9060.906. The second block is exact DMD from the SVD, on the worked examples (a) and (b):

    import numpy as np
    from scipy.linalg import expm
    
    def exact_dmd(X, Xp, r):
        """Exact DMD (Tu et al. 2014): eigenvalues mu and modes Phi of A = X' X^+, rank r."""
        U, s, Vh = np.linalg.svd(X, full_matrices=False)
        U, s, V = U[:, :r], s[:r], Vh[:r].conj().T
        At = U.conj().T @ Xp @ V / s            # r x r projected operator
        mu, W = np.linalg.eig(At)
        Phi = Xp @ V / s @ W                    # exact DMD modes
        return mu, Phi
    
    # (a) the 2x2 worked example: DMD returns the matrix that made the data
    A_true = np.array([[0.5, 0.2], [0.0, 0.8]])
    snaps = [np.array([1.0, 1.0])]
    for _ in range(2):
        snaps.append(A_true @ snaps[-1])
    S = np.column_stack(snaps)
    mu, Phi = exact_dmd(S[:, :-1], S[:, 1:], r=2)
    print(np.sort(mu.real), np.sort(np.log(mu.real) / 0.1).round(3))   # [0.5 0.8] [-6.931 -2.231]
    print(np.abs(A_true @ Phi - Phi * mu).max() < 1e-12)              # True: A φ = μ φ
    
    # (b) the slow-manifold system, sampled exactly: state vs lifted observables
    mu_, lam, dt = -0.05, -1.0, 0.1
    t = np.arange(0, 10 + 1e-9, dt)
    x1 = 1.5 * np.exp(mu_ * t)
    b = lam / (lam - 2 * mu_)
    x2 = (-1.0 - b * 1.5**2) * np.exp(lam * t) + b * x1**2   # exact solution from (1.5, -1)
    rates = lambda Z, r: np.sort(np.log(exact_dmd(Z[:, :-1], Z[:, 1:], r)[0]).real / dt)
    print(rates(np.vstack([x1, x2]), 2).round(3))            # [-1.222 -0.05 ]: one rate is wrong
    lifted = np.vstack([x1, x2, x1**2])
    print(rates(lifted, 3).round(3))                         # [-1.   -0.1  -0.05]: λ, 2μ, μ
    K = np.array([[mu_, 0, 0], [0, lam, -lam], [0, 0, 2 * mu_]])
    A_fit = lifted[:, 1:] @ np.linalg.pinv(lifted[:, :-1])
    print(f"{np.abs(A_fit - expm(K * dt)).max():.0e}")       # 3e-15
    

    The third block is SINDy on Lorenz-63, with derivatives estimated from the data:

    import numpy as np
    from scipy.integrate import solve_ivp
    
    rhs = lambda t, u: [10 * (u[1] - u[0]), u[0] * (28 - u[2]) - u[1], u[0] * u[1] - 8 / 3 * u[2]]
    dt = 0.002
    t = np.arange(0, 20, dt)
    X = solve_ivp(rhs, (0, t[-1]), [-8.0, 8.0, 27.0], t_eval=t, method="DOP853",
                  rtol=1e-12, atol=1e-12).y.T               # 10,000 states, shape (10000, 3)
    dX = np.gradient(X, dt, axis=0, edge_order=2)           # derivatives from the data
    
    x, y, z = X.T
    names = ["1", "x", "y", "z", "x^2", "xy", "xz", "y^2", "yz", "z^2"]
    Theta = np.column_stack([np.ones_like(x), x, y, z, x*x, x*y, x*z, y*y, y*z, z*z])
    
    def stlsq(Theta, dX, eta, iters=10):
        Xi = np.linalg.lstsq(Theta, dX, rcond=None)[0]      # step 1: dense least squares
        for _ in range(iters):
            small = np.abs(Xi) < eta                         # step 2: threshold
            Xi[small] = 0
            for k in range(dX.shape[1]):                     # step 3: refit the active terms
                big = ~small[:, k]
                Xi[big, k] = np.linalg.lstsq(Theta[:, big], dX[:, k], rcond=None)[0]
        return Xi
    
    dense = np.linalg.lstsq(Theta, dX, rcond=None)[0]
    true = np.zeros((10, 3))
    true[[1, 2], 0] = [-10, 10]; true[[1, 2, 6], 1] = [28, -1, -1]; true[[3, 5], 2] = [-8 / 3, 1]
    print(f"largest spurious |xi| in the dense fit: {np.abs(dense[true == 0]).max():.4f}")  # 0.0040
    Xi = stlsq(Theta, dX, eta=0.1)
    for name, row in zip(names, Xi):
        if np.any(row):
            print(f"{name:>4}", "  ".join(f"{v:9.4f}" for v in row))
    #    x    -9.9992    27.9924     0.0000
    #    y     9.9992    -0.9986     0.0000
    #    z     0.0000     0.0000    -2.6664
    #   xy     0.0000     0.0000     0.9999
    #   xz     0.0000    -0.9998     0.0000
    rel = np.abs(Xi[true != 0] - true[true != 0]) / np.abs(true[true != 0])
    print(f"same terms: {np.array_equal(Xi != 0, true != 0)}, largest relative error {rel.max():.2%}")
    # same terms: True, largest relative error 0.14%
    

    The dense fit already has the seven true coefficients within 0.25% (the error comes from the second-order differences), and every spurious one is below 0.005. STLSQ removes the spurious terms, and the refit brings the largest relative error to 0.14%. PyDMD and PySINDy are the standard libraries for these methods; the notebook builds them from scratch.

    6. Where it shows up #

    • Weather and climate. Lorenz-63 and Lorenz-96 are the test beds of data assimilation (lesson 06). Lyapunov exponents explain the predictability limit, the need for ensembles, and why a perfect emulator still diverges from the truth. So long rollouts are evaluated by statistics, spectra and probabilistic scores (CRPS, lesson 07), not by pointwise error at long lead times.
    • Climate patterns. DMD-type methods extract oscillating modes from geophysical fields: multi-resolution DMD on sea-surface temperature data from 1990–2010 isolates the 1997 El Niño as its own mode (Kutz, Fu and Brunton, 2016).
    • Seismology. Simple spring–slider models of a fault with friction are chaotic (Huang and Turcotte, 1990). This is one argument for why the exact timing of earthquakes is hard to predict, and why seismic hazard is stated as a probability.
    • Training through dynamics. Backpropagation through a rollout of length TT of a chaotic model multiplies gradients by about eλ1Te^{\lambda_1 T} (lesson 03). Short rollouts keep these gradients and the memory cost under control: GraphCast trains with rollouts of at most 12 six-hour steps (Lam et al., 2023).
    • Machine learning. Koopman autoencoders learn coordinates in which the dynamics are linear (Lusch, Kutz and Brunton, 2018); SINDy autoencoders learn coordinates in which the dynamics are sparse (Champion et al., 2019). State-space layers (S4, Mamba) also evolve a latent state by a linear recurrence and read it out nonlinearly (deep learning 16).
    • Equation discovery and closures. SINDy and its PDE version identify reduced models of fluid and plasma flows and subgrid closure terms.

    7. Common mistakes #

    • Estimating λ1\lambda_1 from two trajectories without rescaling, or over a too short time. The separation saturates at the attractor size, and finite-time rates fluctuate along the attractor.
    • Mixing units. An exponent per sampling step equals λΔt\lambda\Delta t, where λ\lambda is the exponent per unit time. In the same way, a DMD eigenvalue μ\mu is per step and ω=ln⁡μ/Δt\omega = \ln\mu/\Delta t is per unit time.
    • Reading Re⁡μ\operatorname{Re}\mu as growth. Growth or decay is decided by ∣μ∣|\mu| compared with 1 (or by Re⁡ω\operatorname{Re}\omega), not by the sign of Re⁡μ\operatorname{Re}\mu.
    • Too coarse sampling for DMD. Frequencies above π/Δt\pi/\Delta t alias.
    • Calling the projected modes UrWU_rW exact DMD modes, or choosing the rank rr by eye on noisy data.
    • Believing that a finite linear model can be exact for chaos. Truncated Koopman models of chaotic systems are short-horizon approximations.
    • SINDy: a library without the true terms; a threshold above the smallest true coefficient; unnormalised columns; raw finite differences of noisy data.
    • Reading a DMD eigenvalue near 1 as dynamics when it is just the mean of the data (a constant observable has μ=1\mu = 1). Subtract the mean first, or keep this in mind.

    8. Check yourself #

    1. For Lorenz-63, λ1=0.906\lambda_1 = 0.906 and λ2=0\lambda_2 = 0. Find λ3\lambda_3 without any simulation.
      AnswerTheorem 1 with the constant trace: λ1+λ2+λ3=−(σ+1+β)=−13.667\lambda_1 + \lambda_2 + \lambda_3 = -(\sigma + 1 + \beta) = -13.667, so λ3=−14.573\lambda_3 = -14.573.
    2. Suppose a single exponent λ\lambda described weather error growth. What λ\lambda makes a 10 times smaller initial error add 5 days of skill (the estimate of Zhang et al.)? What is the doubling time?
      AnswerTp=1λln⁡(Δ/δ0)T_p = \frac1\lambda\ln(\Delta/\delta_0), so dividing δ0\delta_0 by 10 adds ln⁡(10)/λ=5\ln(10)/\lambda = 5 days: λ=0.46\lambda = 0.46 per day, and the doubling time is ln⁡2/0.46=1.5\ln 2/0.46 = 1.5 days. (Real error growth is faster at small scales and saturates there, so one exponent is a simplification.)
    3. Data come from xk+1=Axkx_{k+1} = Ax_k with A=diag⁡(0.9,0.5)A = \operatorname{diag}(0.9, 0.5) and x0=(1,0)x_0 = (1, 0). What does DMD return, and why?
      AnswerEvery snapshot is a multiple of e1e_1, so rank⁡X=1\operatorname{rank}X = 1 and X′X+=0.9 XX+=diag⁡(0.9,0)X'X^+ = 0.9\,XX^+ = \operatorname{diag}(0.9, 0). DMD finds only μ=0.9\mu = 0.9. The mode with 0.50.5 is never excited, so the data cannot reveal it (Theorem 4 needs rank⁡X=n\operatorname{rank}X = n).
    4. Show that x12x_1^2 is a Koopman eigenfunction of the slow-manifold system, and give its eigenvalue in continuous time and for the flow map over Δt\Delta t.
      Answerddtx12=2x1x˙1=2μx12\frac{d}{dt}x_1^2 = 2x_1\dot x_1 = 2\mu x_1^2, so x12(t)=e2μtx12(0)x_1^2(t) = e^{2\mu t}x_1^2(0): the continuous-time eigenvalue is 2μ2\mu, and the flow-map eigenvalue is e2μΔte^{2\mu\Delta t}. It is the product of the eigenfunction x1x_1 with itself, so its eigenvalue is the square of eμΔte^{\mu\Delta t}.
    5. Why does DMD on the scalar signal xk=cos⁡(ωkΔt)x_k = \cos(\omega k\Delta t) fail, and how do time delays fix it?
      AnswerA 1×11 \times 1 fit has one real eigenvalue, but cos⁡\cos needs the pair e±iωΔte^{\pm i\omega\Delta t}. The signal satisfies xk+2=2cos⁡(ωΔt) xk+1−xkx_{k+2} = 2\cos(\omega\Delta t)\,x_{k+1} - x_k, so the delay vector (xk,xk+1)(x_k, x_{k+1}) evolves by an exact 2×22 \times 2 linear map with eigenvalues e±iωΔte^{\pm i\omega\Delta t}. DMD on the Hankel matrix recovers them.
    6. You run STLSQ on noisy Lorenz data and get extra terms such as 0.03 z20.03\,z^2 in x˙\dot x. Name two fixes.
      AnswerBetter derivatives (smoothing, total-variation regularisation, or the weak/integral form); a larger threshold (still below the smallest true coefficient, 1) after normalising the library columns; more data; or a shorter library. Then check the fitted model by simulating it and comparing statistics with the data.
    Recall cardsAnswer in your head first, then reveal. Add the cards to your review deck to see them again just before you would forget.
    1. Define the largest Lyapunov exponent λ1\lambda_1 of a trajectory.

    2. What is λ1\lambda_1 for Lorenz-63 (σ=10\sigma = 10, ρ=28\rho = 28, β=8/3\beta = 8/3), and what is the doubling time of an error?

    3. What is the sum of all Lyapunov exponents, and why?

    4. Give the predictability time for an error δ0\delta_0 and a tolerance Δ\Delta.

    5. Why must Benettin's method renormalise the tangent vector?

    6. Define the Koopman operator, and say why it is linear.

    7. Give the exact DMD formula for the projected operator and the modes.

    8. A DMD eigenvalue is μ\mu with time step Δt\Delta t. What are its growth rate and angular frequency?

    9. What problem does SINDy solve?

    10. DMD or POD: what is the difference in what a mode means?

    Open the review →

    9. Interview angle #

    Typical questions and short model answers:

    • "What is a Lyapunov exponent, and what does it mean for forecasting?" — The average exponential rate at which nearby trajectories separate. The predictability time grows only like ln⁡(1/δ0)/λ1\ln(1/\delta_0)/\lambda_1, so better observations help little; hence ensembles and probabilistic scores.
    • "What is the Koopman operator? What is the catch?" — Composition with the dynamics; it is linear on observables. It is infinite-dimensional, and for chaos its spectrum is continuous, so finite models are approximate.
    • "DMD or PCA/POD?" — POD ranks patterns by variance; DMD gives patterns with one frequency and one growth rate each, from the best-fit linear map. Exact DMD never forms AA.
    • "How would you discover equations from data, and what breaks it?" — SINDy: a library plus sparse regression. It breaks with noisy derivatives, a library without the right terms, or bad coordinates.
    • "Your emulator matches the truth for 5 days and then drifts, although its one-step error is tiny. Is it broken?" — Not necessarily. With λ1>0\lambda_1 > 0 any small error grows. Evaluate statistics, spectra and ensemble scores instead of pointwise error at long lead times.

    10. Practice #

    The notebook for this lesson runs in Colab or in the browser. It has five exercises, each with a check cell and a folded solution:

    1. Find the fixed points of Lorenz-63 and classify them with the eigenvalues of the Jacobian.
    2. Estimate the largest Lyapunov exponent with the tangent-linear model and renormalisation (≈ 0.906).
    3. Write exact DMD from the SVD and check that it recovers the eigenvalues of a known linear system.
    4. Compare DMD on the state and on the lifted observables of the slow-manifold system.
    5. Write STLSQ and recover the Lorenz-63 coefficients from data within 1%.

    11. Watch and read #

    Lorenz-63, sensitive dependence and why chaos limits prediction.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    How the exponents are defined and computed, as in section 3.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The SVD-based DMD algorithm and how to read the eigenvalues and modes.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    Observables, Koopman eigenfunctions and the slow-manifold example.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play
    The library, the sparse regression and the Lorenz-63 example.
    Open on YouTube · the player loads from youtube-nocookie.com when you press play