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

Notebooks · posts/solving-the-riccati-equation-without-integrating-it

Solving the Riccati equation without integrating it

Every LQR controller comes from a quadratic matrix equation, and the tempting way to solve it is to integrate the differential version backwards until it stops moving. On a one-state system that method returns 73.783 where the answer is 414.214, with no warning. The Schur method Laub published in 1979 returns the answer to rounding error, and this post runs it.

The gains of a linear-quadratic regulator come out of

quadratic in the matrix . There is an obvious way to solve it: run backwards from zero until it stops changing. Each step is one matrix multiply and one matrix add, it converges on most problems, and the earlier LQR post on this site uses it.

Take , , , , one state. The quadratic formula gives exactly. The closed loop it produces decays like , so the Riccati flow settles over roughly seven hundred seconds, and eighty seconds of backward integration gets nowhere near. It returns 73.783, and nothing in its output signals the error.

The fix is to solve a linear eigenvalue problem instead. Stack and the two weights into the Hamiltonian

whose spectrum is symmetric about the imaginary axis: every eigenvalue is matched by , so exactly of the are stable. Take an orthonormal basis for the invariant subspace of those , and . No quadratic equation is solved.

Computing that basis is the main work. It is done by reducing to real Schur form (block upper triangular) and moving the stable blocks to the top left. The animation below shows that reduction: the eleven subdiagonal entries of the Hessenberg matrix, driven to zero by Francis's implicit double-shift QR iteration, one turn of its outer loop at a time. Entry 9 (counting from 0) goes first, and fast. Its size over four successive turns is , , , : the exponent doubles each time, which is the quadratic convergence a good shift gives. When an entry reaches rounding level, the matrix splits there into two smaller problems and the iteration moves on to the block above. After thirty turns nothing is left to do, and the four entries still nonzero, at , belong to the 2 by 2 blocks holding the Hamiltonian's four complex-conjugate pairs of eigenvalues.

The last figure compares residuals on ten systems. The Schur method's relative residual stays below on all of them, including those where the largest entry of runs to five figures and the absolute residual is . The matrix sign function, another way to get from , is more than thirty times worse on at least one.

Look inside this program

  • Atlas

    The program’s map: every function and which calls which.

  • There’s no recorded run of this program yet.

Shift+Enter in a cell runs it and moves to the next. Running a cell runs every cell above it too, as one program.

[1]lines 56–394