1-- Polynomial evaluation over a coefficient homomorphism and algebraic independence.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.EvaluationOver8import MapHom9import Universal1011def polynomialAtOver (I A add z neg mul one B plus o minus times unit f v : Set) : Set:=12 compose(polynomialAt(I, B, plus, o, minus, times, unit, v), polynomialMap(I, A, z, B, o, f), polynomials(I, A, z), polynomials(I, B, o), B)1314notationscoped polynomialAtOver(I, R, S, f, v) => polynomialAtOver(I, R.carrier, R.add, R.zero, R.neg, R.mul, R.one, S.carrier, S.add, S.zero, S.neg, S.mul, S.one, f, v)1516predicate AlgebraicallyIndependent (I A add z neg mul one B plus o minus times unit f v : Set) :=17 IsRingHom(f, A, add, z, neg, mul, one, B, plus, o, minus, times, unit) ∧ FunctionBetween(v, I, B) ∧ InjectiveBetween(polynomialAtOver(I, A, add, z, neg, mul, one, B, plus, o, minus, times, unit, f, v), polynomials(I, A, z), B)1819notationscoped AlgebraicallyIndependent(I, R, S, f, v) => AlgebraicallyIndependent(I, R.carrier, R.add, R.zero, R.neg, R.mul, R.one, S.carrier, S.add, S.zero, S.neg, S.mul, S.one, f, v)2021section Rings22variable (I A add z neg mul one B plus o minus times unit f v : Set)23notationring R := (A, add, z, neg, mul, one)24notationring S := (B, plus, o, minus, times, unit)25notationring P := R[I]26notationring Q := S[I]27hypothesis source : IsCommRing(R)28hypothesis target : IsCommRing(S)29hypothesis hom : IsRingHom(f, R, S)30hypothesis assignment : v : I → S3132theorem polynomialAtOver.hom33shows IsRingHom(polynomialAtOver(I, R, S, f, v), P, S)34proof35have mapped : IsRingHom(polynomialMap(I, R, S, f), P, Q)36exact polynomialMap.hom with*37have evaluated := polynomialAt.hom with*38unfold polynomialAtOver39exact IsRingHom.compose with*4041theorem polynomialAtOver.value (p : Set)42requires polynomial : p ∈ P43shows polynomialAtOver(I, R, S, f, v)(p) = polynomialAt(I, S, v)(polynomialMap(I, R, S, f)(p))44proof45have mapHom : IsRingHom(polynomialMap(I, R, S, f), P, Q)46exact polynomialMap.hom with*47have evaluationHom := polynomialAt.hom with*48have map := IsRingHom.function with mapHom49have evaluation := IsRingHom.function with evaluationHom50unfold polynomialAtOver51exact compose.apply with*5253theorem polynomialAtOver.constant (a : Set)54requires coefficient : a ∈ R55shows polynomialAtOver(I, R, S, f, v)(polynomialConstant(I, R, a)) = f(a)56proof57have zeroIn : R[0] ∈ R bytypecheck58have member := polynomialConstant.member at I, A, z, a with*59have image := IsRingHom.closed with hom, coefficient60have mapped := polynomialMap.constant at I, A, add, z, neg, mul, one, B, plus, o, minus, times, unit, f, a with*61have evaluated := polynomialAt.constant with*62 rwa [polynomialAtOver.value, mapped]6364theorem polynomialAtOver.coefficient_image65shows functionImage(f, R, S) ⊆ functionImage(polynomialAtOver(I, R, S, f, v), P, S)66proof67have evaluation : IsRingHom(polynomialAtOver(I, R, S, f, v), P, S)68exact polynomialAtOver.hom with*69have function := IsRingHom.function with evaluation70have zeroIn : R[0] ∈ R bytypecheck71intros x member72obtain⟨inS, a, coefficient, shape⟩:= functionImage.membership.forward with member73have constant := polynomialConstant.member at I, A, z, a with*74have value := polynomialAtOver.constant at I, A, add, z, neg, mul, one, B, plus, o, minus, times, unit, f, v, a with*75have image := functionImage.value at polynomialAtOver(I, R, S, f, v), P, S, polynomialConstant(I, R, a) with*76rw value at image77 rwa shape7879theorem polynomialAtOver.variable (j : Set)80requires index : j ∈ I81shows polynomialAtOver(I, R, S, f, v)(polynomialVariable(I, R, j)) = v(j)82proof83have zeroIn : R[0] ∈ R bytypecheck84have oneIn : R[1] ∈ R bytypecheck85have member := polynomialVariable.member at I, A, z, one, j with*86have mapped := polynomialMap.variable at I, A, add, z, neg, mul, one, B, plus, o, minus, times, unit, f, j with*87have evaluated := polynomialAt.variable with*88 rwa [polynomialAtOver.value, mapped]8990theorem polynomialAtOver.unique (h : Set)91requires morphism : IsRingHom(h, P, S)92requires constants : ∀ a ∈ R, h(polynomialConstant(I, R, a)) = f(a)93requires variables : ∀ j ∈ I, h(polynomialVariable(I, R, j)) = v(j)94shows h = polynomialAtOver(I, R, S, f, v)95proof96have evaluation : IsRingHom(polynomialAtOver(I, R, S, f, v), P, S)97exact polynomialAtOver.hom with*98have sameConstants : ∀ a ∈ R, h(polynomialConstant(I, R, a)) = polynomialAtOver(I, R, S, f, v)(polynomialConstant(I, R, a))99intros a ha100have first := constants with a, ha101have second := polynomialAtOver.constant with*102cc103have sameVariables : ∀ j ∈ I, h(polynomialVariable(I, R, j)) = polynomialAtOver(I, R, S, f, v)(polynomialVariable(I, R, j))104intros j hj105have first := variables with j, hj106have second := polynomialAtOver.variable at I, A, add, z, neg, mul, one, B, plus, o, minus, times, unit, f, v, j with*107cc108exact IsRingHom.polynomial_ext with*109110theorem AlgebraicallyIndependent.relation_iff (p : Set)111requires independent : AlgebraicallyIndependent(I, R, S, f, v)112requires polynomial : p ∈ P113shows polynomialAtOver(I, R, S, f, v)(p) = S[0] ↔ p = P[0]114proof115have evaluation : IsRingHom(polynomialAtOver(I, R, S, f, v), P, S)116exact polynomialAtOver.hom with*117have zero := IsRingHom.zero with evaluation118have zeroMember := polynomials.zero at I, A, add, z, neg, mul, one with*119have injective := independent.right.right120constructor121 . intro vanishes122have equal : polynomialAtOver(I, R, S, f, v)(p) = polynomialAtOver(I, R, S, f, v)(P[0]) bycc123exact Injective.apply_cancel with*124 . intro equal125 rwa equal126127theorem AlgebraicallyIndependent.of_no_relation128requires relations : ∀ p ∈ P, polynomialAtOver(I, R, S, f, v)(p) = S[0] → p = P[0]129shows AlgebraicallyIndependent(I, R, S, f, v)130proof131have evaluation : IsRingHom(polynomialAtOver(I, R, S, f, v), P, S)132exact polynomialAtOver.hom with*133have function := IsRingHom.function with evaluation134have sourceRing := polynomials.comm_ring at I, A, add, z, neg, mul, one with*135have ordinary := IsCommRing.ring with sourceRing136unfold AlgebraicallyIndependent137refine⟨hom, assignment, ?_⟩138unfold InjectiveBetween139refine⟨function, ?_⟩140intros p hp q hq y hy first second141have valueP := FunctionBetween.apply_value at polynomialAtOver(I, R, S, f, v), P, S, p, y with*142have valueQ := FunctionBetween.apply_value at polynomialAtOver(I, R, S, f, v), P, S, q, y with*143have negative := IsRing.neg_closed with ordinary, hq144have difference : P[p - q] ∈ P145exact IsRing.add_closed with*146have mapped := IsRingHom.sub with sourceRing, evaluation, hp, hq147have zero : polynomialAtOver(I, R, S, f, v)(P[p - q]) = S[0]148rw [mapped, valueP, valueQ]149ring150have vanishes := relations with P[p - q], difference, zero151linear_combination vanishes152153end Rings154section Canonical155variable (I A add z neg mul one : Set)156notationring R := (A, add, z, neg, mul, one)157notationring P := R[I]158hypothesisring : IsCommRing(R)159160theorem polynomialAtOver.identity_coefficients (v : Set)161requires assignment : v : I → R162shows polynomialAtOver(I, R, R, identity(R), v) = polynomialAt(I, R, v)163proof164have hom := IsRingHom.identity withring165have evaluation := polynomialAt.hom with*166have constants : ∀ a ∈ R, polynomialAt(I, R, v)(polynomialConstant(I, R, a)) = identity(R)(a)167intros a ha168have value := polynomialAt.constant with*169have same := identity.apply with*170cc171have variables : ∀ j ∈ I, polynomialAt(I, R, v)(polynomialVariable(I, R, j)) = v(j)172intros j hj173exact polynomialAt.variable with*174 symm175exact polynomialAtOver.unique with*176177theorem polynomialAtOver.canonical_variables178shows polynomialAtOver(I, R, P, polynomialCoefficients(I, R), polynomialVariables(I, R)) = identity(P)179proof180have target := polynomials.comm_ring at I, A, add, z, neg, mul, one with*181have hom := polynomialCoefficients.hom at I, A, add, z, neg, mul, one with*182have zeroIn : R[0] ∈ R bytypecheck183have oneIn : R[1] ∈ R bytypecheck184have assignment := polynomialVariables.function at I, A, z, one with*185have identity := IsRingHom.identity with target186have constants : ∀ a ∈ R, identity(P)(polynomialConstant(I, R, a)) = polynomialCoefficients(I, R)(a)187intros a ha188have member := polynomialConstant.member at I, A, z, a with*189have value := polynomialCoefficients.value at I, A, z, a with*190have same := identity.apply with member191cc192have variables : ∀ j ∈ I, identity(P)(polynomialVariable(I, R, j)) = polynomialVariables(I, R)(j)193intros j hj194have member := polynomialVariable.member at I, A, z, one, j with*195have value := polynomialVariables.value at I, A, z, one, j with*196have same := identity.apply with member197cc198 symm199exact polynomialAtOver.unique with*200201theorem polynomialVariables.algebraically_independent202shows AlgebraicallyIndependent(I, R, P, polynomialCoefficients(I, R), polynomialVariables(I, R))203proof204have hom := polynomialCoefficients.hom at I, A, add, z, neg, mul, one with*205have zeroIn : R[0] ∈ R bytypecheck206have oneIn : R[1] ∈ R bytypecheck207have assignment := polynomialVariables.function at I, A, z, one with*208have evaluation := polynomialAtOver.canonical_variables at I, A, add, z, neg, mul, one with*209have injective := identity.injective at P210unfold AlgebraicallyIndependent211refine⟨hom, assignment, ?_⟩212 rwa evaluation213214end Canonical215