1-- Constant coefficients and the evaluation homomorphism at the origin (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.Origin8import Constants910theorem monomialProduct.one_factors (I m n : Set)11requires memberM : m ∈ monomials(I)12requires memberN : n ∈ monomials(I)13requires productOne : monomialProduct(I, m, n) = monomialOne(I)14shows m = monomialOne(I) ∧ n = monomialOne(I)15proof16have unit := monomialOne.member at I17have first : m = monomialOne(I)18apply monomials.ext with memberM, unit19intros i hi20have mNat := monomials.exponent at I, m, i with*21have nNat := monomials.exponent at I, n, i with*22have value := monomialProduct.value at I, m, n, i with*23have zeroValue := monomialOne.value with hi24have sumZero : m(i) + n(i) =0bycc25have zeroRule := add.eq_zero_left at n(i), m(i) with*26have vanishes := zeroRule with sumZero27cc28have second : n = monomialOne(I)29have comm := monomialProduct.commutative at I, m, n with*30have rightUnit := monomialProduct.one at I, n with*31cc32refine⟨first, second⟩3334defgraph polynomialAtOrigin (I A zero : Set) (p ∈ polynomials(I, A, zero)) : A := p(monomialOne(I))35proof36have unit := monomialOne.member at I37exact polynomials.coefficient with*3839theorem polynomialProduct.constant_coefficient (I A add zero neg mul one p q : Set)40requiresring : IsCommRing(A, add, zero, neg, mul, one)41requires memberP : p ∈ polynomials(I, A, zero)42requires memberQ : q ∈ polynomials(I, A, zero)43shows polynomialProduct(I, A, add, zero, neg, mul, one, p, q)(monomialOne(I)) = call2(mul, p(monomialOne(I)), q(monomialOne(I)))44proof45have unit := monomialOne.member at I46have pair := product.pair at monomialOne(I), monomialOne(I), monomials(I), monomials(I) with*47have singletonSubset : {(monomialOne(I), monomialOne(I))} ⊆ monomials(I) × monomials(I) bysimp48have supportDomain := convolutionPairs.subset at I, zero, p, q49have domain : convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))} ⊆ monomials(I) × monomials(I)50simp51have finitePairs := convolutionPairs.finite with memberP, memberQ52have finiteSingleton := Finite.singleton at (monomialOne(I), monomialOne(I))53have finite := Finite.union with finitePairs, finiteSingleton54have covers : convolutionPairs(I, zero, p, q) ⊆ convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}55simp56have singleton := singleton.self at (monomialOne(I), monomialOne(I))57have source : (monomialOne(I), monomialOne(I)) ∈ convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}58simp59have weights := boundedConvolutionWeights.function at I, convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}, A, add, zero, neg, mul, one, p, q with*60have imageValue := monomialMul.apply at I, monomialOne(I), monomialOne(I) with*61unfold call2 at imageValue62have unitLaw := monomialProduct.one at I, monomialOne(I) with*63have image : monomialMul(I)((monomialOne(I), monomialOne(I))) = monomialOne(I) bycc64have unique : ∀ t ∈ convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}, monomialMul(I)(t) = monomialOne(I) → t = (monomialOne(I), monomialOne(I))65intros t ht equality66have included := domain67have pairMember := included with t, ht68obtain⟨bound, m, hm, n, hn, shape⟩:= product.membership.forward with pairMember69have value := monomialMul.apply at I, m, n with*70unfold call2 at value71have productOne : monomialProduct(I, m, n) = monomialOne(I) bycc72have factors := monomialProduct.one_factors at I, m, n with*73cc74have isolated := finitePushforward.unique_fiber at convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}, monomials(I), A, add, zero, neg, mul, one, monomialMul(I), boundedConvolutionWeights(I, convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}, A, add, zero, neg, mul, one, p, q), (monomialOne(I), monomialOne(I)), monomialOne(I) with*75have bounded := polynomialProduct.on_domain withring, memberP, memberQ, domain, finite, covers76have coefficient := boundedConvolutionWeights.pair at I, convolutionPairs(I, zero, p, q) ∪ {(monomialOne(I), monomialOne(I))}, A, add, zero, neg, mul, one, p, q, monomialOne(I), monomialOne(I) with*77cc7879theorem polynomialAtOrigin.constant (I A zero a : Set)80requires zeroIn : zero ∈ A81requires coefficient : a ∈ A82shows polynomialAtOrigin(I, A, zero)(polynomialConstant(I, A, zero, a)) = a83proof84have member := polynomialConstant.member at I, A, zero, a with*85have value := polynomialAtOrigin.value at I, A, zero, polynomialConstant(I, A, zero, a) with*86have coefficientValue := polynomialConstant.coefficient at I, A, zero, a with*87cc8889theorem polynomialAtOrigin.coefficients (I A zero a : Set)90requires zeroIn : zero ∈ A91requires coefficient : a ∈ A92shows polynomialAtOrigin(I, A, zero)(polynomialCoefficients(I, A, zero)(a)) = a93proof94have value := polynomialCoefficients.value at I, A, zero, a with*95rw value96exact polynomialAtOrigin.constant with*9798theorem polynomialAtOrigin.variable (I A zero one j : Set)99requires zeroIn : zero ∈ A100requires oneIn : one ∈ A101requires index : j ∈ I102shows polynomialAtOrigin(I, A, zero)(polynomialVariable(I, A, zero, one, j)) = zero103proof104have member := polynomialVariable.member at I, A, zero, one, j with*105have unit := monomialOne.member at I106have different : monomialOne(I) ≠ monomialVariable(I, j)107intro equal108have unitValue := monomialOne.value at I, j with*109have variableValue := monomialVariable.same at I, j with*110have impossible : (0:Nat) = (1:Nat) bycc111exact Naturals.disjoint.zero.succ at0with impossible112have coefficient : polynomialVariable(I, A, zero, one, j)(monomialOne(I)) = zero113unfold polynomialVariable114exact polynomialTerm.other with*115have value := polynomialAtOrigin.value at I, A, zero, polynomialVariable(I, A, zero, one, j) with*116cc117118section Rings119variable (I A add zero neg mul one : Set)120hypothesisring : IsCommRing(A, add, zero, neg, mul, one)121notationring R := (A, add, zero, neg, mul, one)122123theorem polynomialAtOrigin.hom124shows IsRingHom(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), constantFunction(monomials(I), A, zero), polynomialNeg(I, A, add, zero, neg, mul, one), polynomialMul(I, A, add, zero, neg, mul, one), polynomialConstant(I, A, zero, one), A, add, zero, neg, mul, one)125proof126have ordinary := IsCommRing.ring withring127have zeroIn := IsRing.zero_in_carrier with ordinary128have multiplicative := IsRing.multiplicative with ordinary129have oneIn := IsMonoid.unit_in_carrier with multiplicative130have unit := monomialOne.member at I131have function := polynomialAtOrigin.function at I, A, zero132have zeroPolynomial := polynomials.zero at I, A, add, zero, neg, mul, one with*133have zeroValue := polynomialAtOrigin.value at I, A, zero, constantFunction(monomials(I), A, zero) with*134have zeroCoefficient := constantFunction.apply at monomials(I), A, monomialOne(I), zero with*135have preservesZero : polynomialAtOrigin(I, A, zero)(constantFunction(monomials(I), A, zero)) = zero bycc136have preservesOne := polynomialAtOrigin.constant at I, A, zero, one with*137have preservesNeg : ∀ p ∈ polynomials(I, A, zero), polynomialAtOrigin(I, A, zero)((polynomialNeg(I, A, add, zero, neg, mul, one))(p)) = -polynomialAtOrigin(I, A, zero)(p)138intros p hp139have functionP := polynomials.function with hp140have negative := polynomials.neg with hp141have operation := polynomialNeg.apply with hp142have source := polynomialAtOrigin.value at I, A, zero, coefficientNeg(monomials(I), A, add, zero, neg, mul, one, p) with*143have coefficient := coefficientNeg.value at monomials(I), A, add, zero, neg, mul, one, p, monomialOne(I) with*144have value := polynomialAtOrigin.value at I, A, zero, p with*145cc146have preservesAdd : ∀ p ∈ polynomials(I, A, zero), ∀ q ∈ polynomials(I, A, zero), polynomialAtOrigin(I, A, zero)((polynomialAdd(I, A, add, zero, neg, mul, one))(p, q)) = polynomialAtOrigin(I, A, zero)(p) + polynomialAtOrigin(I, A, zero)(q)147intros p hp q hq148have functionP := polynomials.function with hp149have functionQ := polynomials.function with hq150have member := polynomials.add with hp, hq151have operation := polynomialAdd.apply with hp, hq152have source := polynomialAtOrigin.value at I, A, zero, coefficientAdd(monomials(I), A, add, zero, neg, mul, one, p, q) with*153have coefficient := coefficientAdd.value at monomials(I), A, add, zero, neg, mul, one, p, q, monomialOne(I) with*154have valueP := polynomialAtOrigin.value at I, A, zero, p with*155have valueQ := polynomialAtOrigin.value at I, A, zero, q with*156cc157have preservesMul : ∀ p ∈ polynomials(I, A, zero), ∀ q ∈ polynomials(I, A, zero), polynomialAtOrigin(I, A, zero)((polynomialMul(I, A, add, zero, neg, mul, one))(p, q)) = polynomialAtOrigin(I, A, zero)(p) * polynomialAtOrigin(I, A, zero)(q)158intros p hp q hq159have functionP := polynomials.function with hp160have functionQ := polynomials.function with hq161have member := polynomialProduct.member with hp, hq162have operation := polynomialMul.apply with hp, hq163have source := polynomialAtOrigin.value at I, A, zero, polynomialProduct(I, A, add, zero, neg, mul, one, p, q) with*164have coefficient := polynomialProduct.constant_coefficient with hp, hq165have valueP := polynomialAtOrigin.value at I, A, zero, p with*166have valueQ := polynomialAtOrigin.value at I, A, zero, q with*167cc168unfold IsRingHom169refine⟨function, preservesZero, preservesOne, preservesNeg, preservesAdd, preservesMul⟩170171theorem polynomialAtOrigin.kernel_ideal172shows IsIdeal(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), constantFunction(monomials(I), A, zero), polynomialNeg(I, A, add, zero, neg, mul, one), polynomialMul(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero))173proof174have source := polynomials.comm_ring at I, A, add, zero, neg, mul, one with*175have hom := polynomialAtOrigin.hom at I, A, add, zero, neg, mul, one with*176exact IsRingHom.kernel_ideal with source, ring, hom177178end Rings179180theorem polynomialAtOrigin.surjective (I A zero : Set)181requires zeroIn : zero ∈ A182shows SurjectiveBetween(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), A)183proof184have function := polynomialAtOrigin.function at I, A, zero185constructor186 . exact function187 . intros a ha188have member := polynomialConstant.member at I, A, zero, a with*189have value := polynomialAtOrigin.constant at I, A, zero, a with*190have edge := FunctionBetween.relates_apply with*191refine⟨polynomialConstant(I, A, zero, a), member, _⟩192 rwa value at edge193194theorem polynomialAtOrigin.kernel_membership (I A zero p : Set)195shows p ∈ ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero) ↔ p ∈ polynomials(I, A, zero) ∧ p(monomialOne(I)) = zero196proof197constructor198 . intro member199have data := ringKernel.membership.forward with member200have value := polynomialAtOrigin.value at I, A, zero, p with*201constructor202 . exact data.left203 . cc204 . intro data205have value := polynomialAtOrigin.value at I, A, zero, p with*206apply ringKernel.membership.backward207constructor208 . exact data.left209 . cc210211section Quotient212variable (I A add zero neg mul one : Set)213hypothesisring : IsCommRing(A, add, zero, neg, mul, one)214215theorem polynomialAtOrigin.quotient_iso216shows IsRingIso(quotientMap(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), A, idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero))),217 (polynomials(I, A, zero) ⧸ idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero))),218 quotientBinary(polynomials(I, A, zero), idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero)), polynomialAdd(I, A, add, zero, neg, mul, one)), ⟦constantFunction(monomials(I), A, zero)⟧[polynomials(I, A, zero), idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero))],219 quotientUnary(polynomials(I, A, zero), idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero)), polynomialNeg(I, A, add, zero, neg, mul, one)), quotientBinary(polynomials(I, A, zero), idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero)), polynomialMul(I, A, add, zero, neg, mul, one)), ⟦polynomialConstant(I, A, zero, one)⟧[polynomials(I, A, zero), idealRelation(polynomials(I, A, zero), polynomialAdd(I, A, add, zero, neg, mul, one), polynomialNeg(I, A, add, zero, neg, mul, one), ringKernel(polynomialAtOrigin(I, A, zero), polynomials(I, A, zero), zero))],220 A, add, zero, neg, mul, one)221proof222have ordinary := IsCommRing.ring withring223have zeroIn := IsRing.zero_in_carrier with ordinary224have source := polynomials.comm_ring at I, A, add, zero, neg, mul, one with*225have hom := polynomialAtOrigin.hom at I, A, add, zero, neg, mul, one with*226have onto := polynomialAtOrigin.surjective at I, A, zero with*227exact idealQuotient.first_isomorphism with source, ring, hom, onto228229end Quotient230