1-- Finite coefficient lists and Horner evaluation with polynomial coefficients (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.CoefficientHorner8import VariableExpansion9import HornerHom1011theorem polynomialCoefficientFamily.list_representation (I A z p j : Set)12requires zeroIn : z ∈ A13requires polynomial : p ∈ polynomials(I, A, z)14requires index : j ∈ I15shows∃ cs, List(polynomials(I, A, z), cs) ∧ (∀ n, Nat(n) → listCoefficient{polynomials(I, A, z)}(constantFunction(monomials(I), A, z), cs, n) = polynomialVariableCoefficient(I, A, z, p, j, n))16proof17have map := polynomialCoefficientFamily.map with*18obtain⟨cs, list, values⟩:= CoefficientMap.list_representation with map19refine⟨cs, list, ?_⟩20intros n nNat21have value := values with n, nNat22have family := polynomialCoefficientFamily.value at I, A, z, p, j, n with*23cc2425theorem polynomialVariableCoefficient.list_recover (I A z p j : Set)26requires zeroIn : z ∈ A27requires polynomial : p ∈ polynomials(I, A, z)28requires index : j ∈ I29shows∃ cs, List(polynomials(I, A, z), cs) ∧ (∀ m ∈ monomials(I), listCoefficient{polynomials(I, A, z)}(constantFunction(monomials(I), A, z), cs, m(j))(coefficientErase(I, ℕ, 0, m, j)) = p(m))30proof31obtain⟨cs, list, values⟩:= polynomialCoefficientFamily.list_representation at I, A, z, p, j with*32refine⟨cs, list, ?_⟩33intros m hm34have natural := monomials.exponent with*35have value := values with m(j), natural36have recovery := polynomialVariableCoefficient.recover with*37cc3839-- All coefficients, including the top one, occur in cs; the terminal value is zero.40def polynomialFromCoefficients (I A add z neg mul one j : Set) (cs : List(polynomials(I, A, z))) : Set:=41 hornerAt{polynomials(I, A, z)}(polynomialAdd(I, A, add, z, neg, mul, one), polynomialMul(I, A, add, z, neg, mul, one), constantFunction(monomials(I), A, z), polynomialVariable(I, A, z, one, j), cs)4243notationscoped polynomialFromCoefficients(I, R, j, cs) => polynomialFromCoefficients(I, R.carrier, R.add, R.zero, R.neg, R.mul, R.one, j, cs)4445section Rings46variable (I A add z neg mul one j : Set)47notationring R := (A, add, z, neg, mul, one)48notationring P := R[I]49hypothesisring : IsCommRing(R)5051theorem polynomialFromCoefficients.member (cs : List(polynomials(I, A, z)))52shows polynomialFromCoefficients(I, A, add, z, neg, mul, one, j, cs) ∈ P53proof54have target : IsCommRing(P)55exact polynomials.comm_ring with*56have zeroIn : R[0] ∈ R bytypecheck57have oneIn : R[1] ∈ R bytypecheck58have initial : P[0] ∈ P bytypecheck59havevariable:= polynomialVariable.member at I, A, z, one, j with*60unfold polynomialFromCoefficients61exact hornerAt.closed with*6263theorem polynomialFromCoefficients.nil64shows polynomialFromCoefficients(I, A, add, z, neg, mul, one, j, []) = P[0]65proof66unfold polynomialFromCoefficients67exact hornerAt.nil with*6869theorem polynomialFromCoefficients.cons (c : Set) (cs : List(polynomials(I, A, z)))70requires coefficient : c ∈ P71shows polynomialFromCoefficients(I, A, add, z, neg, mul, one, j, c :: cs) = P[c + polynomialVariable(I, R, j) * polynomialFromCoefficients(I, A, add, z, neg, mul, one, j, cs)]72proof73unfold polynomialFromCoefficients74exact hornerAt.cons with*7576theorem polynomialAt.coefficient_horner (v : Set) (cs : List(polynomials(I, A, z)))77requires assignment : v : I → R78requires index : j ∈ I79shows polynomialAt(I, R, v)(polynomialFromCoefficients(I, A, add, z, neg, mul, one, j, cs)) = hornerAt{A}(add, mul, z, v(j), listMap{polynomials(I, A, z)}(polynomialAt(I, R, v), cs))80proof81have source : IsCommRing(P)82exact polynomials.comm_ring with*83have hom : IsRingHom(polynomialAt(I, R, v), P, R)84exact polynomialAt.hom with*85have zeroIn : R[0] ∈ R bytypecheck86have oneIn : R[1] ∈ R bytypecheck87have initial : P[0] ∈ P bytypecheck88havevariable:= polynomialVariable.member at I, A, z, one, j with*89have mapped := hornerAt.map at polynomials(I, A, z), polynomialAdd(I, A, add, z, neg, mul, one), constantFunction(monomials(I), A, z), polynomialNeg(I, A, add, z, neg, mul, one), polynomialMul(I, A, add, z, neg, mul, one), polynomialConstant(I, A, z, one), A, add, z, neg, mul, one, polynomialAt(I, R, v), constantFunction(monomials(I), A, z), polynomialVariable(I, R, j), cs with*90have zeroValue := IsRingHom.zero with hom91have variableValue := polynomialAt.variable with*92unfold polynomialFromCoefficients93rw [zeroValue, variableValue] at mapped94cc9596end Rings97