“Know how to solve every problem that has been solved.” “What I cannot create, I do not understand.” — Richard Feynman

Lanczos ↔ continued fractions (cycling reader)

Cycling

A document in the cycling-rephrasings format: each paragraph below has multiple framings of the same claim. The default view shows one framing per paragraph; click any paragraph to cycle to another framing of its claim. The outline view (top button) hides all bodies and shows the argument's skeleton — the overview sequence — for fast skimming. Each card has a copy button (top-right) that grabs the framing you're currently looking at.

Click a paragraph to cycle through its alternative framings.
There are three facts at work. First, the inverse of a tridiagonal matrix has a closed-form expression that happens to look like a continued fraction. Second, Lanczos — given any symmetric operator and a starting vector — builds an orthonormal basis in which that operator IS tridiagonal. Third, matrix elements of the resolvent in that basis project onto matrix elements of the tridiagonal's inverse. Stack the three and the "correspondence" falls out. No individual step is doing anything magical; each is a routine result on its own.
Take a tridiagonal matrix with diagonal and off-diagonal . Cramer's rule on gives the top-left entry as a ratio of two determinants. The cofactor expansion of those determinants produces a two-term recursion in dimension, and the recursion telescopes into The coefficients of the continued fraction are exactly the entries of . No new information was added; the structure of the matrix forced this expression.
Here is the essential formula, with everything else stripped away. Write for with its first row and column deleted. The resolvent's top-left entry is a ratio of two characteristic polynomials, and both determinants are produced by the SAME three-term recurrence — because expanding a tridiagonal determinant along its last row leaves only two surviving terms: The continued fraction is nothing more than this ratio written out level by level; the nested tower you see is exactly that recurrence unrolled. Every other paragraph on this page is commentary on this one identity.
Given a symmetric operator and a starting vector , Lanczos builds an orthonormal basis of the Krylov subspace such that the matrix elements are tridiagonal. The diagonal entries of that matrix are the Lanczos coefficients ; the off-diagonals are . That's the defining property — the whole point of the algorithm is to tridiagonalize in the basis it constructs.
Take symmetric. Run Lanczos from a starting vector for steps to get a tridiagonal . The resolvent matrix element projects, in the Krylov basis, onto the top-left entry of . That entry, by the tridiagonal-inverse identity, is a continued fraction in 's entries — which are 's Lanczos coefficients . The chain you ran is the rational-function approximation. No extra step.
Lanczos coefficients are, by construction, the three-term recurrence coefficients of the orthogonal polynomials with respect to the spectral measure of under . Continued fractions of the form Lanczos produces are, by classical analysis going back to Stieltjes in 1894, the Stieltjes transforms of those measures. The Heine-Markov theorem says the rational function whose continued-fraction coefficients match the first recurrence coefficients of a positive measure agrees with the measure's Stieltjes transform on the first moments. That's the Padé approximant. The Lanczos-CF correspondence is the spectral moment problem in disguise — the same theorem Gauss quadrature is built on.

Worked out: from a matrix you can check to the Padé connection

The framings above state the identity in general. General is where the one fact that makes this useful goes to hide, so here it is on real numbers — first an invented matrix small enough to check by hand, then a bigger one where the truncated chain becomes a Padé approximant, which is the entire reason anyone runs Lanczos in the first place. Every number below is from actually running the algorithm.

1. An invented 3×3, full chain — the mechanics, and the trap

Take a dense symmetric matrix (dense, so it is genuinely not tridiagonal — Lanczos has to do real work) and the starting vector :

import numpy as np

def lanczos(A, v0, m):                 # symmetric A, start vector v0, m steps
    n = len(v0); V = np.zeros((n, m)); a = np.zeros(m); b = np.zeros(m)
    V[:, 0] = v0 / np.linalg.norm(v0); bprev = 0.0; vprev = np.zeros(n)
    for j in range(m):
        w = A @ V[:, j]; a[j] = V[:, j] @ w            # alpha_j = <v_j|A|v_j>
        w = w - a[j]*V[:, j] - bprev*vprev             # three-term recurrence
        for k in range(j): w -= (V[:, k] @ w) * V[:, k]   # reorthogonalize
        b[j] = np.linalg.norm(w)                       # beta_j = <v_{j+1}|A|v_j>
        if b[j] < 1e-12 or j == m-1: break
        vprev = V[:, j]; bprev = b[j]; V[:, j+1] = w / b[j]
    return a, b

def cf(a, b, z, n):                    # n-level continued fraction, bottom-up
    f = z - a[n-1]
    for j in range(n-2, -1, -1):
        f = (z - a[j]) - b[j]**2 / f
    return 1.0 / f
A  = np.array([[2., 1, 1], [1, 3, 1], [1, 1, 4]])   # dense, NOT tridiagonal
v0 = np.array([1., 0, 0])
a, b = lanczos(A, v0, 3)
print("alpha =", a)           # [2.    4.5   2.5 ]   <- real Lanczos output
print("beta  =", b[:2])       # [1.4142  0.5 ]       = (sqrt 2, 1/2)
print("CF_3(6) =", cf(a, b, 6, 3))                        # 0.3846153846
print("exact   =", v0 @ np.linalg.solve(6*np.eye(3)-A, v0))  # 0.3846153846

Lanczos hands back and — these are computed, not chosen. Feed them into the three-level continued fraction (, ):

Evaluate at , bottom up: ; then ; then ; so . The direct resolvent is also . They agree exactly.

And that exactness is the trap. The chain ran to , so of course the continued fraction equals the resolvent — at full length it's just Cramer's rule written sideways. A full-dimension Lanczos run reproduces the resolvent identically and approximates nothing. Nothing here is worth the trouble. The trouble only pays off when .

2. A bigger matrix, truncated chain — the [n−1/n] Padé approximant

Let's apply this to something concrete, an 8×8 random symmetric matrix with a random unit starting vector . The resolvent at gives us the exact answer to check against — — and Lanczos now lets us evaluate the truncated continued fraction at each chain length:

rng = np.random.default_rng(3); N = 8
M = rng.standard_normal((N, N)); A = (M + M.T) / 2     # random symmetric 8x8
v0 = rng.standard_normal(N); v0 /= np.linalg.norm(v0)
a, b = lanczos(A, v0, N)
exact = v0 @ np.linalg.solve(6*np.eye(N) - A, v0)      # 0.173892043148
for n in range(1, N+1):
    print(n, cf(a, b, 6, n), abs(cf(a, b, 6, n) - exact))
n   CF_n(6)            |CF_n - exact|
1   0.148050615223     2.58e-02
2   0.167297739854     6.59e-03
3   0.170822791951     3.07e-03     <- [2/3] Pade from 3 Lanczos steps
4   0.173469327962     4.23e-04
5   0.173885545845     6.50e-06
6   0.173891769274     2.74e-07
7   0.173892043101     4.65e-11
8   0.173892043148     2.78e-17     <- n = dim: exact, machine precision
Semilog plot of the error between the n-level continued fraction and the exact resolvent versus Lanczos chain length n, for an 8x8 matrix at z=6. The error falls roughly geometrically from about 0.026 at n=1 to machine precision (1e-17) at n=8.

This is the content. Each truncated continued fraction is a rational function of degree over degree — the Padé approximant of the resolvent. Three Lanczos steps give a approximant already good to three digits; at it collapses onto the exact value at machine precision. Short chain, cheap approximation; full chain, exact. That is why you run a handful of Lanczos steps on a million-dimensional operator and read off a rational function instead of inverting anything — the 3×3-run-to-completion never shows you this, because it has no "short chain" to truncate.

3. Why Lanczos steps are the Padé approximant

The connection is the part that's genuinely hard to find stated plainly, so here it is in one chain of equalities. The resolvent is the moment-generating function of 's spectral measure (the measure that puts weight at each eigenvalue of ):

The are the moments of . Now three facts line up:

Put them together: the -level Lanczos continued fraction is a degree- rational function matching the first moments of — which is exactly the Padé approximant. Lanczos coefficients = Gauss-quadrature rule = Padé approximant. Three names for one object, and the reason a 1950s numerical algorithm reproduces a 1890s moment-problem theorem.

Checked on the 8×8: at the continued fraction reproduces the first moments and first diverges from the truth at — the difference between and the six-moment sum shrinks like as grows ( at , at ), precisely the "first unmatched moment is the 7th" signature of a six-moment match. The Padé is matching six moments, on the nose.

It's not a coincidence: the classical orthogonal polynomials are Lanczos

Everything above secretly lives in one classical theory — orthogonal polynomials on the real line. Recall the spectral measure of (weight at each eigenvalue). That measure has its own family of orthogonal polynomials , the ones obeying . Every such family satisfies a three-term recurrence,

and the coefficients of that recurrence are exactly the entries of the Jacobi (tridiagonal) matrix — which is to say, exactly what Lanczos hands back. So Lanczos is the algorithm that generates the orthogonal polynomials of 's spectral measure. The continued fraction is their Stieltjes transform, the Gauss quadrature is their roots-and-weights rule, the Padé approximant is their moment match. One structure, four names.

Which means the famous orthogonal polynomial families aren't separate objects to memorize — each is just Lanczos run on a classical weight. Take the multiplication-by- operator with weight , start from , and the 's and 's that come out are the textbook recurrence coefficients:

# Run Lanczos on "multiply by x" with a classical weight w(x); out come the
# recurrence coefficients of THAT weight's orthogonal polynomials. The starting
# vector v0 = sqrt(weights) makes v0's spectral measure equal the weighted measure.
def recover(nodes, weights, m=6):
    return lanczos(nodes, np.sqrt(weights), m)

# Legendre: weight 1 on [-1,1]
x = np.linspace(-1, 1, 20000); a, b = recover(x, np.full(20000, 2/20000))
print("Legendre  beta:", b[:5], " vs  n/sqrt(4n^2-1)")
# Chebyshev (1st): weight 1/sqrt(1-x^2)
xc = np.cos((np.arange(4000)+0.5)*np.pi/4000); a, b = recover(xc, np.full(4000, np.pi/4000))
print("Chebyshev beta:", b[:5], " vs  1/sqrt2 then 1/2, 1/2, ...")
# Hermite: weight e^{-x^2}
xh, wh = np.polynomial.hermite.hermgauss(60); a, b = recover(xh, wh)
print("Hermite   beta:", b[:5], " vs  sqrt(n/2)")
# Laguerre: weight e^{-x} on [0, inf)
xl, wl = np.polynomial.laguerre.laggauss(60); a, b = recover(xl, wl)
print("Laguerre  alpha:", a[:5], " beta:", b[:5], " vs  2n+1  and  n")
Legendre  beta: [0.5774 0.5164 0.5071 0.5040 0.5025]   vs  n/sqrt(4n^2-1)
Chebyshev beta: [0.7071 0.5    0.5    0.5    0.5   ]   vs  1/sqrt2 then 1/2, 1/2, ...
Hermite   beta: [0.7071 1.     1.2247 1.4142 1.5811]   vs  sqrt(n/2)
Laguerre  alpha: [1. 3. 5. 7. 9.]  beta: [1. 2. 3. 4. 5.]   vs  2n+1  and  n

Every one matches its textbook formula — Legendre's , Chebyshev's , Hermite's , Laguerre's diagonal and off-diagonal — recovered by running the same Lanczos routine from the top of this page on the right measure. The classical families are the special cases where the measure happens to be a classical weight; the named Gauss quadratures are the same Jacobi-matrix eigenproblem (Golub-Welsch):

familyweight intervalJacobi off-diagonals quadrature
LegendreGauss-Legendre
Chebyshev (1st)Gauss-Chebyshev
HermiteGauss-Hermite
Laguerre (diag )Gauss-Laguerre
Jacobi(closed form in )Gauss-Jacobi

Watch the matrix collapse to tridiagonal

The recovery above runs Lanczos and reads off the 's. But you can see why the matrix is tridiagonal in the first place without running Lanczos at all. Build the orthonormal polynomials of a weight by plain Gram-Schmidt, then fill in the multiplication-by- matrix by quadrature — using none of the recurrence coefficients, so the structure is an output. Every entry more than one step off the diagonal comes back as machine zero. Pick a column to see what multiplication by does to a single basis polynomial: it can only reach one degree up, and self-adjointness kills everything more than one degree down.

Build the orthonormal polynomials of the Legendre weight by Gram–Schmidt, then fill the matrix M[i][j] = ⟨P̃ᵢ, x·P̃ⱼ⟩ by quadrature — no recurrence coefficients used. Click a column to see what multiplying by x does to that basis polynomial.

columns j → ; rows i ↓  (basis index 0…6)
x · P̃2  =  (decomposition onto the basis)
0
≈0
1
0.516
2
≈0
3
0.507
4
≈0
5
≈0
6
≈0

Only 1, 2 and 3 survive. Multiplying by x raises the degree to 3 (so nothing above P̃3), and orthogonality kills everything below P̃1: ⟨x·P̃2, P̃m⟩ = ⟨P̃2, x·P̃m⟩, and x·P̃m has degree m+1 < 2 whenever m < 1. Three terms, forced.

Everything more than one step off the diagonal came out ≈0 (≤ 10⁻¹³, the quadrature floor) — computed, not assumed. The off-diagonal band you do see is the Lanczos β sequence: for Legendre that's the textbook recurrence coefficient. Symmetric, because multiplication by the real variable x is self-adjoint; tridiagonal, because x raises degree by exactly one. Run Lanczos on this measure and these same numbers fall out.

Two facts are doing all the work. Multiplication by is self-adjoint, because is real and slides across the integral with no conjugate — so is symmetric. And has degree , so it is orthogonal to every with ; symmetry then forces the mirror zeros below . A symmetric matrix that vanishes outside the first off-diagonal is exactly a tridiagonal one — a three-term recurrence. The Jacobi matrix isn't a lucky shape; it's the only shape these two facts allow.

The converse closes the loop. Favard's theorem (1935): any sequence obeying that three-term recurrence with real is the orthogonal-polynomial family of some positive measure. So the correspondence is a clean bijection,

and Lanczos is the constructive direction: hand it an operator and a vector, it builds the Jacobi matrix, which is a measure's orthogonal polynomials. Run it on a textbook weight and you get Legendre or Hermite; run it on a quantum Hamiltonian and a state, you get the bespoke orthogonal polynomials of that system's spectral density — and their continued fraction is the resolvent, their Gauss rule is the spectral-density approximation, their Padé is the moment match. Stieltjes (1894), Favard (1935), Gauss quadrature, Lanczos (1950), and the continued fraction at the top of this page are all the same theorem about the same object. Not a coincidence — just the moment problem, seen from five directions.

Related on this site