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

← Posts

demoAINumerics

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.

Look inside this program

  • Atlas

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

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

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.

Printed

exact_slow: 414.214
schur_slow: [[414.214]]
naive_slow: [[73.783]]
worst_open: 2.0668
dim_stable: 6
0.00496361
8.03144e-16
-0.335031
ham_trace: 0
pmax: [5.7319, 3003.78, 150.669, 50.9556, 8122.15, 63.5384, 56.0792, 2228.53, 4011.09, 22253.8]
The Hamiltonian's twelve eigenvalues-0.500.5-2-1012real partimaginary part
the six stable ones, which P is built fromthe six unstable ones, discarded
Each subdiagonal entry shrinking to zero
entry 9, the first to goentry 7, which goes nextentry 3, higher up
10⁻²⁸10⁻²¹10⁻¹⁴10⁻⁷10⁰051015202530turns of the outer loopthe entry's size
The subdiagonal being driven to zero
−15−10−500246810which subdiagonal entrylog10 of its size

 

0.0 / 9.9 s
Relative residual, ten systems, two methods
the Schur methodthe matrix sign function
−16−14−1202468systemlog10 of the relative residual

Tests 10 of 10 pass

  • the backward integration is wrong by four fifths on the slow system (passes)
  • the demo system starts unstable and the gains put every mode in the left half plane (passes)
  • the Hamiltonian has exactly six stable eigenvalues and zero trace (passes)
  • every eigenvalue of the Hamiltonian is matched by minus itself (passes)
  • the largest P, five figures, still has a relative residual below 1e-14 (passes)
  • P solves the Riccati equation with a relative residual below 1e-14 (passes)
  • thirty turns leaves four subdiagonal entries, one per complex pair (passes)
  • entry 9 converges quadratically: the exponent doubles each turn (passes)
  • the Schur method beats the sign function on every one of the ten systems (passes)
  • some of these systems are nearly uncontrollable, which is the hard case (passes)

Checked when the site was built: 10 of 10 tests passed, in 0.25 s. Download 2026-09-23-solving-the-riccati-equation-without-integrating-it.viv