solve_discrete_are(a, b, q, r, e=None, s=None, balanced=True)
The DARE is defined as
$$A^HXA - X - (A^HXB) (R + B^HXB)^{-1} (B^HXA) + Q = 0$$The limitations for a solution to exist are :
All eigenvalues of $A$ outside the unit disc, should be controllable.
The associated symplectic pencil (See Notes), should have eigenvalues sufficiently away from the unit circle.
Moreover, if e
and s
are not both precisely None
, then the generalized version of DARE
is solved. When omitted, e
is assumed to be the identity and s
is assumed to be the zero matrix.
The equation is solved by forming the extended symplectic matrix pencil, as described in , $H - \lambda J$ given by the block matrices :
[ A 0 B ] [ E 0 B ] [ -Q E^H -S ] - \lambda * [ 0 A^H 0 ] [ S^H 0 R ] [ 0 -B^H 0 ]
and using a QZ decomposition method.
In this algorithm, the fail conditions are linked to the symmetry of the product $U_2 U_1^{-1}$ and condition number of $U_1$ . Here, $U$ is the 2m-by-m matrix that holds the eigenvectors spanning the stable subspace with 2-m rows and partitioned into two m-row matrices. See and for more details.
In order to improve the QZ decomposition accuracy, the pencil goes through a balancing step where the sum of absolute values of $H$ and $J$ rows/cols (after removing the diagonal entries) is balanced following the recipe given in . If the data has small numerical noise, balancing may amplify their effects and some clean up is required.
Square matrix
Input
Input
Square matrix
Nonsingular square matrix
Input
The boolean that indicates whether a balancing step is performed on the data. The default is set to True.
For cases where the stable subspace of the pencil could not be isolated. See Notes section and the references for details.
Solution to the discrete algebraic Riccati equation.
Solves the discrete-time algebraic Riccati equation (DARE).
solve_continuous_are
Solves the continuous algebraic Riccati equation
Given a
, b
, q
, and r
solve for x
:
>>> from scipy import linalg as la
... a = np.array([[0, 1], [0, -1]])
... b = np.array([[1, 0], [2, 1]])
... q = np.array([[-4, -4], [-4, 7]])
... r = np.array([[9, 3], [3, 1]])
... x = la.solve_discrete_are(a, b, q, r)
... x array([[-4., -4.], [-4., 7.]])
>>> R = la.solve(r + b.T.dot(x).dot(b), b.T.dot(x).dot(a))See :
... np.allclose(a.T.dot(x).dot(a) - x - a.T.dot(x).dot(b).dot(R), -q) True
The following pages refer to to this document either explicitly or contain code examples using this.
scipy.linalg._solvers.solve_continuous_are
scipy.linalg._solvers.solve_discrete_are
Hover to see nodes names; edges to Self not shown, Caped at 50 nodes.
Using a canvas is more power efficient and can get hundred of nodes ; but does not allow hyperlinks; , arrows or text (beyond on hover)
SVG is more flexible but power hungry; and does not scale well to 50 + nodes.
All aboves nodes referred to, (or are referred from) current nodes; Edges from Self to other have been omitted (or all nodes would be connected to the central node "self" which is not useful). Nodes are colored by the library they belong to, and scaled with the number of references pointing them