vp.control.schur
The real Schur decomposition A = Z T Z^T: T quasi-triangular, Z orthogonal. As scipy.linalg.schur(A, output="real"). T is not unique, so compare through the residual and the eigenvalues, not entry by entry.
Part of the distribution vipyr; it runs from a checkout of the
repository. Planned on PyPI as pip install vipyr.
Signature
vp.control.schur(A) Parameters
- A : ndarray[float64], required
- Range: rank 2, square.
Returns
A frozen SchurResult. Iterating it gives the fields below in order; it also has
params, tests, log and check().
- T : ndarray[float64]
- Z : 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, B = vp.control.cartpole_model(h=1e-5)
r = vp.control.schur(A=A)
T, Z = r # the open-loop modes are on T's diagonal
print(np.round(np.sort(np.diag(T)), 4)) # one positive: the pole falls
assert r.check() [-3.9739 0. 0. 3.9739]Each example ran as written when these pages were generated, and the output shown is what it printed.
Checked against
- Reference
- scipy.linalg.schur(A, output='real') and scipy.linalg.eigvals(A)
- Compared by
- residuals: max|A - Z T Z^T| / max|A|, max|Z^T Z - I|, T quasi-triangular; eigenvalues of T's blocks against eigvals, relative to max|A|. Never T entry by entry: it is not unique
- Tolerance
- residual 2 × 10−13, orthogonality 2 × 10−13, eigenvalues 10−10
- Why that tolerance
- backward stable: residuals of a modest multiple of n u (n <= 12 here); eigenvalues of a nonnormal matrix move by the residual times their condition number
Credits
- The Schur, Riccati and Lyapunov solvers use algorithms after SLICOT; no SLICOT code is copied.
Source
- Manifest: kernels/k1/k1.export.toml
- Viv: kernels/k1/control.viv
- Viv: lib/schur.viv
- The defs it reaches and the calls between them: map of the code