This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

vp.control.lyapunov

The X with A X + X A^T = Q, as scipy.linalg.solve_continuous_lyapunov(A, Q). lib/lyap solves A'^T X + X A' + C = 0, so A' = A^T and C = -Q.

Part of the distribution vipyr; it runs from a checkout of the repository. Planned on PyPI as pip install vipyr.

Signature

vp.control.lyapunov(A, Q)

Parameters

A : ndarray[float64], required
Range: rank 2, square.
Q : ndarray[float64], required
Range: rank 2, square.

Returns

A frozen LyapunovResult. Iterating it gives the fields below in order; it also has params, tests, log and check().

X : ndarray[float64]

Raises

vipyr.ParameterError
A ValueError: an argument outside its range, choices, rank or shape, or one of a group given without the rest; its .param names the argument.
TypeError
An argument of the wrong type, or an unknown keyword.
vipyr.VivBuildError
An ImportError: no C compiler, or the program's C does not build.

Examples

import numpy as np
import vipyr as vp
A = np.array([[-1.0, 0.5], [0.0, -2.0]])
r = vp.control.lyapunov(A=A, Q=np.eye(2))
print(np.abs(A @ r.X + r.X @ A.T - np.eye(2)).max() < 1e-14)
assert r.check()
True

Each example ran as written when these pages were generated, and the output shown is what it printed.

Checked against

Reference
scipy.linalg.solve_continuous_lyapunov(A, Q), which solves A X + X A^T = Q
Compared by
relative residual of A X + X A^T - Q, scaled by 2|A||X| + |Q|; the difference from SciPy's X against a looser tolerance
Tolerance
residual 10−13, vs_reference 10−9
Why that tolerance
Bartels-Stewart is backward stable in the residual; X's agreement depends on the separation of A's spectrum from -A's

Credits

  • The Schur, Riccati and Lyapunov solvers use algorithms after SLICOT; no SLICOT code is copied.

Source