Gradient computations come from Kao and Hennequin (2020), https://arxiv.org/pdf/2011.11430.pdf
# Gradient computations come from Kao and Hennequin (2020), https://arxiv.org/pdf/2011.11430.pdf
"""
A,B,Q,R=inputs
A,B,Q,R=inputs
(dX,)=output_grads
(dX,)=output_grads
X=self(A,B,Q,R)
X=solve_discrete_are(A,B,Q,R)
K_inner=R+matrix_dot(B.T,X,B)
K_inner=R+matrix_dot(B.T,X,B)
...
@@ -317,12 +290,20 @@ class SolveDiscreteARE(Op):
...
@@ -317,12 +290,20 @@ class SolveDiscreteARE(Op):
return[A_bar,B_bar,Q_bar,R_bar]
return[A_bar,B_bar,Q_bar,R_bar]
classSolveDiscreteARE(OpFromGraph):
"""
Wrapper Op for solving the discrete Algebraic Riccati equation
:math:`A^TXA - X - (A^TXB)(R + B^TXB)^{-1}(B^TXA) + Q = 0` for :math:`X`.
"""
gufunc_signature="(m,m),(m,n),(m,m),(n,n)->(m,m)"
defsolve_discrete_are(
defsolve_discrete_are(
A:TensorLike,
A:TensorLike,
B:TensorLike,
B:TensorLike,
Q:TensorLike,
Q:TensorLike,
R:TensorLike,
R:TensorLike,
enforce_Q_symmetric:bool=False,
)->TensorVariable:
)->TensorVariable:
"""
"""
Solve the discrete Algebraic Riccati equation :math:`A^TXA - X - (A^TXB)(R + B^TXB)^{-1}(B^TXA) + Q = 0`.
Solve the discrete Algebraic Riccati equation :math:`A^TXA - X - (A^TXB)(R + B^TXB)^{-1}(B^TXA) + Q = 0`.
...
@@ -344,18 +325,128 @@ def solve_discrete_are(
...
@@ -344,18 +325,128 @@ def solve_discrete_are(
Symmetric square matrix of shape M x M
Symmetric square matrix of shape M x M
R: TensorLike
R: TensorLike
Square matrix of shape N x N
Square matrix of shape N x N
enforce_Q_symmetric: bool
If True, the provided Q matrix is transformed to 0.5 * (Q + Q.T) to ensure symmetry
Returns
Returns
-------
-------
X: TensorVariable
X: TensorVariable
Square matrix of shape M x M, representing the solution to the DARE
Square matrix of shape M x M, representing the solution to the DARE
Notes
-----
This function is copied from the scipy implementation, found here: https://github.com/scipy/scipy/blob/892baa06054c31bed734423c0f53eaed52b1914b/scipy/linalg/_solvers.py#L687
Notes are also adapted from the scipy documentation.
The equation is solved by forming the extended symplectic matrix pencil as described in [1]_,
:math: `H - \\lambda J`, given by the block matrices:
.. math::
H = \begin{bmatrix} A & 0 & B \\\\
-Q & I & 0 \\\\
0 & 0 & R \\end{bmatrix}
, \\quad
J = \begin{bmatrix} I & 0 & 0 \\\\
0 & A^H & 0 \\\\
0 & -B^H & 0 \\end{bmatrix}
The stable invariant subspace of the pencil is then computed via the QZ decomposition. Failure conditions are
linked to the symmetry of the solution matrix :math:`U_2 U_1^{-1}`, as described in [1]_ and [2]_. When the
solution is not symmetric, NaNs are returned.
[3]_ describes a balancing procedure for Hamiltonian matrices that can improve numerical stability. This procedure
is not yet implemented in this function.
References
----------
.. [1] P. van Dooren , "A Generalized Eigenvalue Approach For Solving
Riccati Equations.", SIAM Journal on Scientific and Statistical
Computing, Vol.2(2), :doi:`10.1137/0902010`
.. [2] A.J. Laub, "A Schur Method for Solving Algebraic Riccati
Equations.", Massachusetts Institute of Technology. Laboratory for
Information and Decision Systems. LIDS-R ; 859. Available online :
http://hdl.handle.net/1721.1/1301
.. [3] P. Benner, "Symplectic Balancing of Hamiltonian Matrices", 2001,
SIAM J. Sci. Comput., 2001, Vol.22(5), :doi:`10.1137/S1064827500367993`