LeanFun RevOLVER

2.9 Rootfinding with colleague matrices

The roots of a polynomial can be recovered as eigenvalues of a finite multiplication matrix. Choosing the Chebyshev basis gives the colleague matrix.

2.9.1 Multiplication modulo a polynomial

Let \(K\) be a field and let \(P_j\) have degree \(j\). Every polynomial of degree below \(n\) has coordinates in \(P_0,\ldots ,P_{n-1}\). In \(K[x]/(g)\), multiplication by \(x\) is followed by taking the remainder modulo \(g\). The matrix columns are the coordinates of these basis images.

Definition 2.9.1 Comrade matrix in a degree-graded basis
✓ 🤖

For monic \(g\) of degree \(n\), give \(K[x]/(g)\) the basis whose coordinates are the sequence coordinates \([r]_0,\ldots ,[r]_{n-1}\) of the remainder \(r\) modulo \(g\); by Theorem 2.9.3 its vectors are the images of \(P_0,\ldots ,P_{n-1}\). Define \(C_g\) to be the matrix of multiplication by \(x\) in this basis, with basis images as columns.

References: [Bar75]; [ATAP, Chapter 18].

Lean Formalisation
def Polynomial.Sequence.quotientBasis.{u_1} {K : Type u_1} [Field K] (P : Polynomial.Sequence K) {g : Polynomial K}
  (hg : g.Monic) : Module.Basis (Fin g.natDegree) K (AdjoinRoot g)
Lean definition
/-- The first deg(g) members form a basis of K[X]/(g), for monic g. -/
noncomputable def quotientBasis {g : K[X]} (hg : g.Monic) :
    Basis (Fin g.natDegree) K (AdjoinRoot g) :=
  Basis.ofEquivFun
    { toFun := fun x i ↦ (P.basis P.isUnit_leadingCoeff).repr (AdjoinRoot.modByMonicHom hg x) i
      invFun := fun v ↦ AdjoinRoot.mk g (∑ i, v i • P i)
      map_add' := by intro x y; ext i; simp
      map_smul' := by intro a x; ext i; simp
      left_inv := by
        intro x
        dsimp only
        rw [P.sum_fin_repr (by
          rw [← degree_eq_natDegree hg.ne_zero]
          induction x using AdjoinRoot.induction_on with
          | ih p => exact degree_modByMonic_lt p hg)]
        exact AdjoinRoot.mk_leftInverse hg x
      right_inv := by
        intro v
        funext i
        dsimp only
        rw [AdjoinRoot.modByMonicHom_mk,
          (modByMonic_eq_self_iff hg).mpr (by
            rw [degree_eq_natDegree hg.ne_zero]
            exact P.degree_sum_fin_lt _ v)]
        simp only [map_sum, map_smul, Finsupp.finsetSum_apply, Finsupp.smul_apply, smul_eq_mul]
        have hb (j : Fin g.natDegree) :
            (P.basis P.isUnit_leadingCoeff).repr (P j) = Finsupp.single (j : ℕ) 1 := by
          rw [← P.basis_eq_self P.isUnit_leadingCoeff j, Basis.repr_self]
        simp only [hb, Finsupp.single_apply, ← Fin.ext_iff, mul_ite, mul_one, mul_zero]
        simp }
source

The characteristic polynomial of \(C_g\) is \(g\), and its spectrum over \(K\) is the set of roots of \(g\) in \(K\). Write \([q]_i\) for sequence coordinates and \([x^n]q\) for a monomial coefficient. Its entries are

\[ (C_g)_{ij}=[xP_j]_i-([x^n](xP_j))[g]_i,\qquad 0\le i,j{\lt}n. \]

The correction vanishes for \(j+1{\lt}n\), so only the final column changes. This includes arbitrary monic input polynomials, with repeated roots allowed.

References: [Bar75]; [ATAP, Chapter 18].

Lean Formalisation
theorem Polynomial.Sequence.comradeMatrix_apply.{u_1} {K : Type u_1} [Field K] (P : Polynomial.Sequence K) {g : Polynomial K}
  (hg : g.Monic) (i j : Fin g.natDegree) : P.comradeMatrix hg i j = ((P.basis ⋯).repr (Polynomial.X * ↑P ↑j %ₘ g)) ↑i
Lean proof
/-- Entries use the existing polynomial coordinates and the monic remainder. -/
theorem comradeMatrix_apply {g : K[X]} (hg : g.Monic) (i j : Fin g.natDegree) :
    P.comradeMatrix hg i j =
      (P.basis P.isUnit_leadingCoeff).repr ((X * P j) %ₘ g) i := by
  rw [comradeMatrix, Algebra.leftMulMatrix_eq_repr_mul, quotientBasis_apply,
    ← AdjoinRoot.mk_X, ← map_mul, quotientBasis_repr, AdjoinRoot.modByMonicHom_mk]
source
Quotient bases and finite coordinates
Theorem 2.9.3 Comrade basis vectors and coordinates
✓ 🤖

The \(i\)th basis vector of \(K[x]/(g)\) is the image of \(P_i\), and the coordinates of an element are the sequence coordinates of its remainder modulo \(g\).

Lean Formalisation
theorem Polynomial.Sequence.quotientBasis_apply.{u_1} {K : Type u_1} [Field K] (P : Polynomial.Sequence K) {g : Polynomial K}
  (hg : g.Monic) (i : Fin g.natDegree) : (P.quotientBasis hg) i = (AdjoinRoot.mk g) (↑P ↑i)
Lean proof
/-- The quotient basis is the image of the original degree-graded sequence. -/
@[simp] theorem quotientBasis_apply {g : K[X]} (hg : g.Monic) (i : Fin g.natDegree) :
    P.quotientBasis hg i = AdjoinRoot.mk g (P i) := by
  simp only [quotientBasis, Basis.coe_ofEquivFun, LinearEquiv.coe_symm_mk, Pi.single_apply]
  simp only [ite_smul, one_smul, zero_smul, Finset.sum_ite_eq', Finset.mem_univ, ite_true]
source

2.9.2 Chebyshev colleague matrices

In the Chebyshev basis the multiplication recurrence determines all but a correction in the final column. The resulting eigenvalue problem finds the roots of the polynomial.

For every nonzero real polynomial \(p\), define its colleague matrix by applying the comrade construction in the \(T\) basis to \(p/\operatorname {lc}(p)\). Its size is \(\deg p\) and its characteristic polynomial is \(p/\operatorname {lc}(p)\). The entry formula is the final-column correction above, in the full-constant Chebyshev convention. Its real spectrum is the real roots of \(p\); after embedding its entries in \(\mathbb C\), its complex spectrum is all complex roots of \(p\). Repeated roots are allowed.

References: [Goo61]; [ATAP, Theorem 18.1].

Lean Formalisation
theorem Polynomial.Chebyshev.charpoly_colleagueMatrix (p : Polynomial ℝ) (hp : p ≠ 0) :
  (Polynomial.Chebyshev.colleagueMatrix p hp).charpoly = p * Polynomial.C p.leadingCoeff⁻¹
Lean proof
/-- The colleague characteristic polynomial is the input made monic. -/
theorem charpoly_colleagueMatrix (p : ℝ[X]) (hp : p ≠ 0) :
    (colleagueMatrix p hp).charpoly = p * Polynomial.C p.leadingCoeff⁻¹ :=
  (chebyshevTsequence ℝ).charpoly_comradeMatrix (monic_mul_leadingCoeff_inv hp)
source

Example (Julia).

For degree \(n\ge 2\), the final-column correction in the full-constant convention is \(c_i/(2c_n)\). The example forms that matrix and checks the polynomial residual at its computed eigenvalues. The recurrence starts with \(xT_0=T_1\).


using LinearAlgebra
function colleague(c)               # p = sum c[k+1] T_k of degree n >= 2
    n = length(c) - 1
    @assert n >= 2 && !iszero(c[end])
    C = zeros(n, n)
    C[2, 1] = 1                     # x T_0 = T_1
    for j in 1:n-1, i in (j, j+2)   # x T_j = (T_{j-1} + T_{j+1})/2
        i <= n && (C[i, j+1] = 1/2)
    end
    C[:, n] .-= c[1:n] ./ (2c[n+1]) # final-column correction
    C
end
function T(k, z)                    # T_k(z) by the recurrence
    a, b = one(z), z
    for _ in 1:k; a, b = b, 2z*b - a; end
    a
end
c = [0.2, -1.0, 0.5, 0.3, 0.0, 1.0] # T_5 + 0.3 T_3 + ... + 0.2
r = eigvals(colleague(c))
maximum(abs(sum(c[k+1]*T(k, z) for k in 0:5)) for z in r)  # polynomial residual at the computed eigenvalues
count(z -> abs(imag(z)) < 1e-12 && abs(real(z)) <= 1, r)   # number of computed real roots in the interval
Characteristic-polynomial and coordinate proofs

For a monic polynomial \(g\) over a field, \(K[x]/(g)\) has the power basis \(1,x,\ldots ,x^{\deg g-1}\). Multiplication by its generating root has characteristic polynomial \(g\). Characteristic polynomials are invariant under choice of basis, and their roots in the base field are exactly the matrix spectrum.

Lean Formalisation
theorem AdjoinRoot.minpoly_powerBasis_gen_of_monic.{u_5} {K : Type u_5} [Field K] {f : Polynomial K} (hf : f.Monic)
  (hf' : f ≠ 0 := ⋯) : minpoly K (AdjoinRoot.powerBasis hf').gen = f
Mathlib source
Theorem 2.9.6 Finite coordinates of a polynomial sequence
✓ 🤖

Let \(P_j\) have degree \(j\) over a field. A polynomial of degree below \(n\) has zero coordinates at every index \(j\ge n\) and reconstructs from its first \(n\) coordinates. Conversely, a combination of those \(n\) basis members has degree below \(n\). No orthogonality hypothesis is required.

Reference: elementary linear algebra used in the comrade construction [Bar75].

Lean Formalisation
theorem Polynomial.Sequence.basis_repr_eq_zero_of_degree_lt.{u_1} {K : Type u_1} [Field K] (P : Polynomial.Sequence K)
  {p : Polynomial K} {n j : ℕ} (hp : p.degree < ↑n) (hj : n ≤ j) : ((P.basis ⋯).repr p) j = 0
Lean proof
/-- A degree-graded basis has no coordinates above the polynomial's degree. -/
theorem basis_repr_eq_zero_of_degree_lt {p : K[X]} {n j : ℕ}
    (hp : p.degree < n) (hj : n ≤ j) :
    (P.basis P.isUnit_leadingCoeff).repr p j = 0 := by
  have hs : p ∈ Submodule.span K (P '' Set.Iio n) := by
    rw [P.span_degreeLT (fun i _ ↦ P.isUnit_leadingCoeff i)]
    exact mem_degreeLT.mpr hp
  clear hp
  induction hs using Submodule.span_induction with
  | mem q hq =>
    obtain ⟨i, hi, rfl⟩ := hq
    rw [← P.basis_eq_self P.isUnit_leadingCoeff i, Basis.repr_self]
    simp [show i ≠ j by exact ne_of_lt (lt_of_lt_of_le hi hj)]
  | zero => simp
  | add q r _ _ hq hr => simp [hq, hr]
  | smul a q _ hq => simp [hq]
source