1-- Mapping sparse polynomial coefficients through a ring homomorphism (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.CoefficientMap8import Constants9import Terms1011theorem polynomials.compose (I A z B o f p : Set)12requires function : f : A → B13requires zero : f(z) = o14requires polynomial : p ∈ polynomials(I, A, z)15shows compose(f, p, monomials(I), A, B) ∈ polynomials(I, B, o)16proof17have values := polynomials.function with polynomial18have mapped := compose.function with values, function19have finite := polynomials.finite_support with polynomial20have subset : functionSupport(compose(f, p, monomials(I), A, B), monomials(I), o) ⊆ functionSupport(p, monomials(I), z)21intros m member22obtain⟨monomial, nonzero⟩:= functionSupport.membership.forward with member23have value := compose.apply at f, p, monomials(I), A, B, m with*24apply functionSupport.membership.backward25refine⟨monomial, ?_⟩26intro vanishes27apply nonzero28cc29have support := Finite.subset with finite, subset30have map : CoefficientMap(compose(f, p, monomials(I), A, B), monomials(I), B, o)31unfold CoefficientMap32refine⟨mapped, support⟩33exact polynomials.contains with*3435defgraph polynomialMap (I A z B o f : Set) (p ∈ polynomials(I, A, z)) : polynomials(I, B, o) := compose(f, p, monomials(I), A, B)36requires function : f : A → B37requires zero : f(z) = o38proof39exact polynomials.compose with*4041notationscoped polynomialMap(I, R, S, f) => polynomialMap(I, R.carrier, R.zero, S.carrier, S.zero, f)4243theorem polynomialMap.coefficient (I A z B o f p m : Set)44requires function : f : A → B45requires zero : f(z) = o46requires polynomial : p ∈ polynomials(I, A, z)47requires monomial : m ∈ monomials(I)48shows polynomialMap(I, A, z, B, o, f)(p)(m) = f(p(m))49proof50have values := polynomials.function with polynomial51have mapped := polynomialMap.value at I, A, z, B, o, f, p with*52have value := compose.apply at f, p, monomials(I), A, B, m with*53cc5455theorem polynomialMap.member (I A z B o f p : Set)56requires function : f : A → B57requires zero : f(z) = o58requires polynomial : p ∈ polynomials(I, A, z)59shows polynomialMap(I, A, z, B, o, f)(p) ∈ polynomials(I, B, o)60proof61have map := polynomialMap.function at I, A, z, B, o, f with*62exact FunctionBetween.apply_closed with*6364section Rings65variable (I A add z neg mul one B plus o minus times unit f : Set)66notationring R := (A, add, z, neg, mul, one)67notationring S := (B, plus, o, minus, times, unit)68notationring P := R[I]69notationring Q := S[I]70hypothesis source : IsCommRing(R)71hypothesis target : IsCommRing(S)72hypothesis hom : IsRingHom(f, R, S)7374theorem polynomialMap.add (p q : Set)75requiresleft : p ∈ P76requiresright : q ∈ P77shows polynomialMap(I, A, z, B, o, f)(P[p + q]) = Q[polynomialMap(I, A, z, B, o, f)(p) + polynomialMap(I, A, z, B, o, f)(q)]78proof79have function := IsRingHom.function with hom80have zero := IsRingHom.zero with hom81have sourceRing := polynomials.comm_ring at I, A, add, z, neg, mul, one with*82have targetRing := polynomials.comm_ring at I, B, plus, o, minus, times, unit with*83have sourceOrdinary := IsCommRing.ring with sourceRing84have targetOrdinary := IsCommRing.ring with targetRing85have sum := IsRing.add_closed with sourceOrdinary, left, right86have mappedSum := polynomialMap.member at I, A, z, B, o, f, P[p + q] with*87have mappedLeft := polynomialMap.member at I, A, z, B, o, f, p with*88have mappedRight := polynomialMap.member at I, A, z, B, o, f, q with*89have targetSum := IsRing.add_closed with targetOrdinary, mappedLeft,90 mappedRight91have sourceValue := polynomialAdd.apply at I, A, add, z, neg, mul, one, p, q with*92have targetValue := polynomialAdd.apply at I, B, plus, o, minus, times, unit, polynomialMap(I, A, z, B, o, f)(p), polynomialMap(I, A, z, B, o, f)(q) with*93have pFunction := polynomials.function withleft94have qFunction := polynomials.function withright95have fpFunction := polynomials.function with mappedLeft96have fqFunction := polynomials.function with mappedRight97apply polynomials.ext with mappedSum, targetSum98intros m monomial99have pIn := polynomials.coefficient at I, A, z, p, m with*100have qIn := polynomials.coefficient at I, A, z, q, m with*101have sumCoefficient := polynomialMap.coefficient at I, A, z, B, o, f, P[p + q], m with*102have pCoefficient := polynomialMap.coefficient at I, A, z, B, o, f, p, m with*103have qCoefficient := polynomialMap.coefficient at I, A, z, B, o, f, q, m with*104have sourceCoefficient := coefficientAdd.value at monomials(I), A, add, z, neg, mul, one, p, q, m with*105have targetCoefficient := coefficientAdd.value at monomials(I), B, plus, o, minus, times, unit, polynomialMap(I, A, z, B, o, f)(p), polynomialMap(I, A, z, B, o, f)(q), m with*106have preserved := IsRingHom.add with hom, pIn, qIn107cc108109theorem polynomialMap.coefficient_add (p q : Set)110requiresleft : p ∈ P111requiresright : q ∈ P112shows polynomialMap(I, R, S, f)(coefficientAdd(monomials(I), A, add, z, neg, mul, one, p, q)) = coefficientAdd(monomials(I), B, plus, o, minus, times, unit, polynomialMap(I, R, S, f)(p), polynomialMap(I, R, S, f)(q))113proof114have function := IsRingHom.function with hom115have zero := IsRingHom.zero with hom116have mappedLeft := polynomialMap.member at I, A, z, B, o, f, p with*117have mappedRight := polynomialMap.member at I, A, z, B, o, f, q with*118have first := polynomialAdd.apply at I, A, add, z, neg, mul, one, p, q with*119have second := polynomialAdd.apply at I, B, plus, o, minus, times, unit, polynomialMap(I, R, S, f)(p), polynomialMap(I, R, S, f)(q) with*120have value := polynomialMap.add at I, A, add, z, neg, mul, one, B, plus, o, minus, times, unit, f, p, q with*121cc122123theorem polynomialMap.zero124shows polynomialMap(I, A, z, B, o, f)(P[0]) = Q[0]125proof126have function := IsRingHom.function with hom127have zero := IsRingHom.zero with hom128have sourceMember := polynomials.zero at I, A, add, z, neg, mul, one with*129have targetMember := polynomials.zero at I, B, plus, o, minus, times, unit with*130have mapped := polynomialMap.member with*131have zeroIn : R[0] ∈ R bytypecheck132have targetZero : S[0] ∈ S bytypecheck133apply polynomials.ext with mapped, targetMember134intros m monomial135have coefficient := polynomialMap.coefficient with*136haveleft:= constantFunction.apply at monomials(I), A, m, z with*137haveright:= constantFunction.apply at monomials(I), B, m, o with*138cc139140theorem polynomialMap.term (a m : Set)141requires coefficient : a ∈ R142requires monomial : m ∈ monomials(I)143shows polynomialMap(I, A, z, B, o, f)(polynomialTerm(I, A, z, a, m)) = polynomialTerm(I, B, o, f(a), m)144proof145have function := IsRingHom.function with hom146have zero := IsRingHom.zero with hom147have zeroIn : R[0] ∈ R bytypecheck148have targetZero : S[0] ∈ S bytypecheck149have image := IsRingHom.closed with hom, coefficient150have term := polynomialTerm.member at I, A, z, a, m with*151have targetTerm := polynomialTerm.member at I, B, o, f(a), m with*152have mapped := polynomialMap.member at I, A, z, B, o, f, polynomialTerm(I, A, z, a, m) with*153apply polynomials.ext with mapped, targetTerm154intros n hn155have value := polynomialMap.coefficient at I, A, z, B, o, f, polynomialTerm(I, A, z, a, m), n with*156have alternatives : n = m ∨ n ≠ m bytauto157cases alternatives with same | different158 . rw same159haveleft:= polynomialTerm.same at I, A, z, a, m with*160haveright:= polynomialTerm.same at I, B, o, f(a), m with*161rw same at value162cc163 . haveleft:= polynomialTerm.other at I, A, z, a, m, n with*164haveright:= polynomialTerm.other at I, B, o, f(a), m, n with*165cc166167theorem polynomialMap.constant (a : Set)168requires coefficient : a ∈ R169shows polynomialMap(I, A, z, B, o, f)(polynomialConstant(I, A, z, a)) = polynomialConstant(I, B, o, f(a))170proof171have monomial := monomialOne.member at I172have value := polynomialMap.term with*173unfold polynomialConstant174cc175176theorem polynomialMap.variable (j : Set)177shows polynomialMap(I, A, z, B, o, f)(polynomialVariable(I, A, z, one, j)) = polynomialVariable(I, B, o, unit, j)178proof179have coefficient : R[1] ∈ R bytypecheck180have monomial := monomialVariable.member at I, j181have value := polynomialMap.term with*182have oneValue := IsRingHom.one with hom183unfold polynomialVariable184cc185186end Rings187