1-- Horner representations evaluated through arbitrary coefficient extensions (ZF).2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Algebra.Polynomial.HornerExtension8import HornerDegree9import Characteristic1011section Extensions12variable (I A add zero neg mul one B plus z minus times unit f v j : Set)13notationring R := (A, add, zero, neg, mul, one)14notationring S := (B, plus, z, minus, times, unit)15notationring P := R[I]16hypothesis source : IsCommRing(R)17hypothesis target : IsCommRing(S)18hypothesis hom : IsRingHom(f, R, S)19hypothesis assignment : v : I → S20hypothesis index : j ∈ I2122theorem polynomialAtOver.from_horner (leading : Set) (cs : List(A))23requires initial : leading ∈ R24shows polynomialAtOver(I, R, S, f, v)(polynomialFromHorner(I, R, j, leading, cs)) =25 monicValue{A}(f, plus, times, f(leading), v(j), cs)26proof27induction cs28| List.nil =>29rw [polynomialFromHorner.nil, monicValue]30exact polynomialAtOver.constant with*31| List.cons(c, tail) using ih =>32have coefficient : c ∈ R byassumption33have previous := ih34have zeroIn : R[0] ∈ R bytypecheck35have oneIn : R[1] ∈ R bytypecheck36have polynomialRing := polynomials.comm_ring at I, A, add, zero, neg, mul, one with*37have ordinary := IsCommRing.ring with polynomialRing38have constant := polynomialConstant.member at I, A, zero, c with*39havevariable:= polynomialVariable.member at I, A, zero, one, j with*40have rest := polynomialFromHorner.member at I, A, add, zero, neg, mul, one, j, leading, tail with*41have product := IsRing.mul_closed with ordinary, variable, rest42have evaluation := polynomialAtOver.hom with*43have sumValue := IsRingHom.add with evaluation, constant, product44have productValue := IsRingHom.mul with evaluation, variable, rest45have constantValue := polynomialAtOver.constant with coefficient46have variableValue := polynomialAtOver.variable at I, A, add, zero, neg, mul, one, B, plus, z, minus, times, unit, f, v, j with*47have expression := polynomialFromHorner.cons at I, A, add, zero, neg, mul, one, j, leading, c, tail with*48have evaluated := hornerValue.cons at A, f, plus, times, f(leading), v(j), c, tail with*49cc5051theorem polynomialAtOver.from_monic_horner (cs : List(A))52shows polynomialAtOver(I, R, S, f, v)(polynomialFromHorner(I, R, j, R[1], cs)) =53 monicValue(R, f, S, v(j), cs)54proof55have initial : R[1] ∈ R bytypecheck56have mappedOne := IsRingHom.one with hom57have evaluated := polynomialAtOver.from_horner with*58cc5960-- This consumes a proved monic representation; it does not assume one exists.61theorem characteristicPolynomial.horner_annihilates (n : Nat) (M N w k : Set) (cs : List(A))62requires matrixM : RingMatrix(n, R, M)63requires matrixN : RingMatrix(n, S, N)64requires entries : ∀ a ∈ n, ∀ b ∈ n, N[a, b] = f(M[a, b])65requires eigenvector : LeftEigenvector(n, S, N, v(j), w)66requires coordinate : k ∈ n67requires representation : characteristicPolynomial(n, I, R, M, j) = polynomialFromHorner(I, R, j, R[1], cs)68shows S[monicValue(R, f, S, v(j), cs) * w(k)] = S[0]69proof70have evaluated := polynomialAtOver.from_monic_horner with*71have annihilated := characteristicPolynomial.annihilates with*72cc7374end Extensions75