1-- Multiplicative monomial values extend canonically to polynomial homomorphisms.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.EvaluationHom8import Evaluation910predicate MonomialCharacter (I A mul one h : Set) :=11 FunctionBetween(h, monomials(I), A) ∧ h(monomialOne(I)) = one ∧12 (∀ m ∈ monomials(I), ∀ n ∈ monomials(I), h(monomialProduct(I, m, n)) = call2(mul, h(m), h(n)))1314predicate EvaluationMultiplies (I A add zero neg mul one h p q : Set) :=15 polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(polynomialProduct(I, A, add, zero, neg, mul, one, p, q)) = call2(mul, polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p), polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q))1617def evaluationProducts (I A add zero neg mul one h p : Set) : Set:=18 {q ∈ polynomials(I, A, zero) | EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, p, q)}1920-- Sending every monomial to one evaluates every variable at one.21theorem MonomialCharacter.at_one (I A add zero neg mul one : Set)22requiresring : IsCommRing(A, add, zero, neg, mul, one)23shows MonomialCharacter(I, A, mul, one, constantFunction(monomials(I), A, one))24proof25have ordinary := IsCommRing.ring withring26have multiplicative := IsRing.multiplicative with ordinary27have oneIn := IsMonoid.unit_in_carrier with multiplicative28have function := constantFunction.function at monomials(I), A, one with*29have unit := monomialOne.member at I30have unitValue := constantFunction.apply at monomials(I), A, monomialOne(I), one with*31unfold MonomialCharacter32refine⟨function, unitValue, ?_⟩33intros m hm n hn34have product := monomialProduct.member with hm, hn35haveleft:= constantFunction.apply at monomials(I), A, monomialProduct(I, m, n), one with*36have first := constantFunction.apply at monomials(I), A, m, one with*37have second := constantFunction.apply at monomials(I), A, n, one with*38have identity := IsMonoid.left_identity with*39cc4041section Evaluation42variable (I A add zero neg mul one h : Set)43hypothesisring : IsCommRing(A, add, zero, neg, mul, one)44hypothesis character : MonomialCharacter(I, A, mul, one, h)45notationring R := (A, add, zero, neg, mul, one)4647theorem EvaluationMultiplies.zero (p : Set)48requires member : p ∈ polynomials(I, A, zero)49shows EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, p, constantFunction(monomials(I), A, zero))50proof51unfold MonomialCharacter at character52have product := polynomialProduct.zero_right with*53have zeroValue := polynomialEvaluate.zero at I, A, add, zero, neg, mul, one, h with*54have valueP := polynomialEvaluate.in_carrier at I, A, add, zero, neg, mul, one, h, p with*55have annihilate : polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * zero = zero byring56unfold EvaluationMultiplies57cc5859theorem EvaluationMultiplies.swap (p q : Set)60requires memberP : p ∈ polynomials(I, A, zero)61requires memberQ : q ∈ polynomials(I, A, zero)62requires equation : EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, p, q)63shows EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, q, p)64proof65unfold MonomialCharacter at character66have comm := polynomialProduct.commutative at I, A, add, zero, neg, mul, one, p, q with*67have valueP := polynomialEvaluate.in_carrier at I, A, add, zero, neg, mul, one, h, p with*68have valueQ := polynomialEvaluate.in_carrier at I, A, add, zero, neg, mul, one, h, q with*69have commute : polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q) = polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q) * polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p)70ring71unfold EvaluationMultiplies at equation72unfold EvaluationMultiplies73cc7475theorem EvaluationMultiplies.add (p q r : Set)76requires memberP : p ∈ polynomials(I, A, zero)77requires memberQ : q ∈ polynomials(I, A, zero)78requires memberR : r ∈ polynomials(I, A, zero)79requires first : EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, p, q)80requires second : EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, p, r)81shows EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, p, coefficientAdd(monomials(I), A, add, zero, neg, mul, one, q, r))82proof83unfold MonomialCharacter at character84have pq := polynomialProduct.member at I, A, add, zero, neg, mul, one, p, q with*85have pr := polynomialProduct.member at I, A, add, zero, neg, mul, one, p, r with*86have distribute := polynomialProduct.add_right at I, A, add, zero, neg, mul, one, p, q, r with*87have evaluateSum := polynomialEvaluate.add at I, A, add, zero, neg, mul, one, h, q, r with*88have evaluateProducts := polynomialEvaluate.add at I, A, add, zero, neg, mul, one, h, polynomialProduct(I, A, add, zero, neg, mul, one, p, q), polynomialProduct(I, A, add, zero, neg, mul, one, p, r) with*89have valueP := polynomialEvaluate.in_carrier at I, A, add, zero, neg, mul, one, h, p with*90have valueQ := polynomialEvaluate.in_carrier at I, A, add, zero, neg, mul, one, h, q with*91have valueR := polynomialEvaluate.in_carrier at I, A, add, zero, neg, mul, one, h, r with*92have distributeValues : polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * (polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q) + polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(r)) = polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q) + polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(r)93ring94unfold EvaluationMultiplies at first95unfold EvaluationMultiplies at second96unfold EvaluationMultiplies97cc9899theorem EvaluationMultiplies.terms (a b m n : Set)100requires coefficientA : a ∈ A101requires coefficientB : b ∈ A102requires monomialM : m ∈ monomials(I)103requires monomialN : n ∈ monomials(I)104shows EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m), polynomialTerm(I, A, zero, b, n))105proof106have data := character107have values := data.left108have multiplication := data.right.right with m, monomialM, n, monomialN109have ordinary := IsCommRing.ring withring110have coefficient := IsRing.mul_closed at A, add, zero, neg, mul, one, a, b with*111have monomial := monomialProduct.member at I, m, n with*112have product := polynomialProduct.terms at I, A, add, zero, neg, mul, one, a, b, m, n with*113haveleft:= polynomialEvaluate.term at I, A, add, zero, neg, mul, one, h, a * b, monomialProduct(I, m, n) with*114have valueA := polynomialEvaluate.term at I, A, add, zero, neg, mul, one, h, a, m with*115have valueB := polynomialEvaluate.term at I, A, add, zero, neg, mul, one, h, b, n with*116have imageM := FunctionBetween.apply_closed at h, monomials(I), A, m with*117have imageN := FunctionBetween.apply_closed at h, monomials(I), A, n with*118have rearrange : (a * b) * (h(m) * h(n)) = (a * h(m)) * (b * h(n)) byring119unfold EvaluationMultiplies120cc121122theorem EvaluationMultiplies.term (a m q : Set)123requires coefficient : a ∈ A124requires monomial : m ∈ monomials(I)125requires memberQ : q ∈ polynomials(I, A, zero)126shows EvaluationMultiplies(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m), q)127proof128have ordinary := IsCommRing.ring withring129have zeroIn := IsRing.zero_in_carrier with ordinary130have zeroPolynomial := polynomials.zero at I, A, add, zero, neg, mul, one with*131have fixed := polynomialTerm.member at I, A, zero, a, m with*132have base : constantFunction(monomials(I), A, zero) ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m))133apply evaluationProducts.membership.backward134constructor135 . exact zeroPolynomial136 . exact EvaluationMultiplies.zero with*137have terms : ∀ b ∈ A, ∀ n ∈ monomials(I), polynomialTerm(I, A, zero, b, n) ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m))138intros b hb n hn139have member := polynomialTerm.member at I, A, zero, b, n with*140apply evaluationProducts.membership.backward141constructor142 . exact member143 . exact EvaluationMultiplies.terms with*144have sums : ∀ f ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m)), ∀ g ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m)), coefficientAdd(monomials(I), A, add, zero, neg, mul, one, f, g) ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m))145intros f hf g hg146have first := evaluationProducts.membership.forward with hf147have second := evaluationProducts.membership.forward with hg148have member := polynomials.add at I, A, add, zero, neg, mul, one, f, g with*149apply evaluationProducts.membership.backward150constructor151 . exact member152 . exact EvaluationMultiplies.add with*153have generated := polynomials.induction at I, A, add, zero, neg, mul, one, evaluationProducts(I, A, add, zero, neg, mul, one, h, polynomialTerm(I, A, zero, a, m)), q with*154have result := evaluationProducts.membership.forward with generated155exact result.right156157theorem polynomialEvaluate.mul (p q : Set)158requires memberP : p ∈ polynomials(I, A, zero)159requires memberQ : q ∈ polynomials(I, A, zero)160shows polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(polynomialProduct(I, A, add, zero, neg, mul, one, p, q)) = polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q)161proof162have ordinary := IsCommRing.ring withring163have zeroIn := IsRing.zero_in_carrier with ordinary164have zeroPolynomial := polynomials.zero at I, A, add, zero, neg, mul, one with*165have base : constantFunction(monomials(I), A, zero) ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, q)166apply evaluationProducts.membership.backward167constructor168 . exact zeroPolynomial169 . exact EvaluationMultiplies.zero with*170have terms : ∀ b ∈ A, ∀ n ∈ monomials(I), polynomialTerm(I, A, zero, b, n) ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, q)171intros b hb n hn172have member := polynomialTerm.member at I, A, zero, b, n with*173apply evaluationProducts.membership.backward174constructor175 . exact member176 . have forward := EvaluationMultiplies.term at I, A, add, zero, neg, mul, one, h, b, n, q with*177exact EvaluationMultiplies.swap with*178have sums : ∀ f ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, q), ∀ g ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, q), coefficientAdd(monomials(I), A, add, zero, neg, mul, one, f, g) ∈ evaluationProducts(I, A, add, zero, neg, mul, one, h, q)179intros f hf g hg180have first := evaluationProducts.membership.forward with hf181have second := evaluationProducts.membership.forward with hg182have member := polynomials.add at I, A, add, zero, neg, mul, one, f, g with*183apply evaluationProducts.membership.backward184constructor185 . exact member186 . exact EvaluationMultiplies.add with*187have generated := polynomials.induction at I, A, add, zero, neg, mul, one, evaluationProducts(I, A, add, zero, neg, mul, one, h, q), p with*188have result := evaluationProducts.membership.forward with generated189exact EvaluationMultiplies.swap at190 I, A, add, zero, neg, mul, one, h, q, p with*191192theorem polynomialEvaluate.constant (a : Set)193requires coefficient : a ∈ A194shows polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(polynomialConstant(I, A, zero, a)) = a195proof196unfold MonomialCharacter at character197have unit := monomialOne.member at I198have term := polynomialEvaluate.term at I, A, add, zero, neg, mul, one, h, a, monomialOne(I) with*199have identity : a * one = a byring200unfold polynomialConstant201cc202203theorem polynomialEvaluate.hom204shows IsRingHom(polynomialEvaluate(I, A, add, zero, neg, mul, one, h), 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)205proof206have data := character207unfold MonomialCharacter at data208have ordinary := IsCommRing.ring withring209have multiplicative := IsRing.multiplicative with ordinary210have oneIn := IsMonoid.unit_in_carrier with multiplicative211have function := polynomialEvaluate.function at I, A, add, zero, neg, mul, one, h with*212have preservesZero := polynomialEvaluate.zero at I, A, add, zero, neg, mul, one, h with*213have preservesOne := polynomialEvaluate.constant with*214have preservesNeg : ∀ p ∈ polynomials(I, A, zero), polynomialEvaluate(I, A, add, zero, neg, mul, one, h)((polynomialNeg(I, A, add, zero, neg, mul, one))(p)) = -polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p)215intros p hp216have operation := polynomialNeg.apply with*217have value := polynomialEvaluate.neg at I, A, add, zero, neg, mul, one, h, p with*218cc219have preservesAdd : ∀ p ∈ polynomials(I, A, zero), ∀ q ∈ polynomials(I, A, zero), polynomialEvaluate(I, A, add, zero, neg, mul, one, h)((polynomialAdd(I, A, add, zero, neg, mul, one))(p, q)) = polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) + polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q)220intros p hp q hq221have operation := polynomialAdd.apply with hp, hq222have value := polynomialEvaluate.add at I, A, add, zero, neg, mul, one, h, p, q with*223cc224have preservesMul : ∀ p ∈ polynomials(I, A, zero), ∀ q ∈ polynomials(I, A, zero), polynomialEvaluate(I, A, add, zero, neg, mul, one, h)((polynomialMul(I, A, add, zero, neg, mul, one))(p, q)) = polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(p) * polynomialEvaluate(I, A, add, zero, neg, mul, one, h)(q)225intros p hp q hq226have operation := polynomialMul.apply with hp, hq227have value := polynomialEvaluate.mul with hp, hq228cc229unfold IsRingHom230refine⟨function, preservesZero, preservesOne, preservesNeg, preservesAdd, preservesMul⟩231232end Evaluation233