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

Lanczos finds the largest eigenvalue three times

Sixty steps of Lanczos on a 200 by 200 symmetric matrix whose eigenvalues are known exactly. Both ends of the spectrum, , come out right to . But in floating point the basis stops being orthogonal once the top eigenvalue has converged, the direction of its eigenvector creeps back in, and the eigenvalue 4, which the matrix has once, is found again and again. Orthogonalizing each new vector against all the old ones stops 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.

Lanczos is for the extreme eigenvalues of a symmetric matrix too big to diagonalize, when all you can do with it is multiply a vector by it. From one starting vector it builds an orthonormal basis of the Krylov space, the span of . In that basis is tridiagonal, and each new vector needs only the two before it:

The eigenvalues of the small tridiagonal matrix (the on its diagonal, the beside it) are the Ritz values, and the largest and smallest of them converge to the largest and smallest eigenvalues of after far fewer steps than has rows.

The three-term formula is where the trouble is. It makes orthogonal to and by construction, and to every earlier vector only because, in exact arithmetic, those overlaps are zero anyway. In floating point they are not zero, and nothing removes them.

The numpy twin of this program, with the same matrix and starting vector, is posts/refs/lanczos-loses-orthogonality.py; its output is beside it.

Printed

-3.87645
-0.121044
top_residual: 3.65312e-16

Tests 1 of 1 pass

  • A is dense now, entry for entry numpy's, and U_TOP is still its eigenvector for 4 (passes)

Sixty steps, twice

The cell runs Lanczos twice from the same . The plain run is the three-term formula above. The other run, after the formula, subtracts from its component along every basis vector so far, for : full reorthogonalization. That costs extra dot products at step , so over steps where plain Lanczos costs beyond the products with , and it needs every vector kept in memory.

At each step the cell records three things: the Ritz values (the eigenvalues of so far, from eig_sym), the largest overlap of the new vector with any earlier one, and how much of the new vector lies along , the eigenvector of for the eigenvalue 4.

Printed

-4
4
-4
4
3
0.779396
6.53665e-16

Tests 4 of 4 pass

  • both runs find the ends of the spectrum, -4 and 4, to 1e-14 (passes)
  • with reorthogonalization the next Ritz value in is 3, the second eigenvalue, to 1e-13 (passes)
  • the plain basis is far from orthogonal: some new vector overlaps an old one by more than 0.5 (passes)
  • the reorthogonalized basis is orthogonal to 1e-15 (passes)

Where the lost orthogonality goes

The figure shows the size of each new basis vector's component along , the eigenvector for 4. In both runs it first falls, geometrically: stretches the direction the most, so the Krylov space captures it early, and once it is in the space the new vectors, orthogonal to the space, have nothing left along it. By step 13 the largest Ritz value equals 4 to rounding, and at step 14 the plain run's component along reaches its lowest value, ( in numpy: from here on the two programs agree on when things happen and how big they get, not on the last digits).

From there the two runs split. With reorthogonalization the component keeps falling to rounding, below , and stays. In the plain run the rounding errors of each step leave a little of in the new vector, nothing subtracts it, and amplifies it at every later step, for the same reason it amplified in the first place. The component grows back to order one by step 24. The basis then contains a second time, the Ritz values converge to 4 a second time, and the component falls again, only to grow back near step 46. The overlap of new vectors with old ones, in the second figure, rises in step with it. (Where the reorthogonalized component comes out exactly 0, the first figure draws it at .)

Printed

first_dip: 14
1.97856e-08
first_return: 24
0.774543
second_return: 46
Plain Lanczos against full reorthogonalization, step by step
Component of the new basis vector along the eigenvector for 4
plain three-term recurrencefull reorthogonalization
10⁻¹⁵10⁻¹⁰10⁻⁵10⁰|qj⋅u|
Largest overlap of the new basis vector with an earlier one
plain three-term recurrencefull reorthogonalization
10⁻¹⁶10⁻¹²10⁻⁸10⁻⁴10⁰01020304050Lanczos step jmax|qj⋅qi|, i<j

Tests 5 of 5 pass

  • the largest Ritz value is 4 to 1e-14 by step 13, as in numpy (passes)
  • the plain run's component along u bottoms out under 1e-7 at step 14, as in numpy (passes)
  • then grows back to order one by step 24, and again by step 46 (passes)
  • with reorthogonalization it stays below 1e-15 from step 25 on, where the plain run has it back (passes)
  • with reorthogonalization the component along u falls to rounding, below 1e-16, and stays there (passes)

Ghosts

Each time comes back, the plain run finds the eigenvalue 4 again. The figure follows the three largest Ritz values step by step. With reorthogonalization they settle at 4, at 3, and just under 1, the top of the bulk: the three largest eigenvalues of . In the plain run the second and then the third also go to 4. After 60 steps the plain run has three Ritz values within of 4, and the matrix has 4 once. The copies are called ghosts. They are not wrong in the sense of pointing at a number that is not an eigenvalue; they are wrong about multiplicity, and meanwhile the steps spent on them are not spent on the 3 and the bulk.

Full reorthogonalization is the fix used here. It is also the most expensive one; selective reorthogonalization (against converged Ritz vectors only) costs less, and restarted Lanczos, as in ARPACK, keeps full reorthogonalization affordable by keeping the basis short.

Printed

ghosts_plain: 3
ghosts_full: 1
The three largest Ritz values
plain, largestplain, 2ndplain, 3rdreorthogonalized, largestreorthogonalized, 2ndreorthogonalized, 3rd
123401020304050Lanczos step jRitz value

Tests 2 of 2 pass

  • after 60 steps the plain run has 4 three times over; reorthogonalized, once (passes)
  • the reorthogonalized third Ritz value is just under 1, the top of the bulk (passes)

Checked when the site was built: 12 of 12 tests passed, in 0.29 s. Download 2026-09-25-lanczos-loses-orthogonality.viv