1-- A sparse polynomial has only finitely many nonzero coefficients in any one variable.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.VariableExpansion8import VariableCoefficients910defgraph monomialExponent (I j : Set) (m ∈ monomials(I)) : ℕ := m(j)11requires index : j ∈ I12proof13have natural := monomials.exponent at I, m, j with*14exact nat.omega.forward at m(j) with*1516defgraph polynomialCoefficientFamily (I A z p j : Set) (n ∈ ℕ) : polynomials(I, A, z) := polynomialVariableCoefficient(I, A, z, p, j, n)17requires zeroIn : z ∈ A18requires polynomial : p ∈ polynomials(I, A, z)19proof20have natural := nat.omega.backward at n with*21exact polynomialVariableCoefficient.member with*2223notationscoped polynomialCoefficientFamily(I, R, p, j) => polynomialCoefficientFamily(I, R.carrier, R.zero, p, j)2425section Expansion26variable (I A z p j : Set)27hypothesis zeroIn : z ∈ A28hypothesis polynomial : p ∈ polynomials(I, A, z)29hypothesis index : j ∈ I3031theorem polynomialVariableCoefficient.outside (n : Nat)32requires absent : ¬(n ∈ functionImage(monomialExponent(I, j), functionSupport(p, monomials(I), z), ℕ))33shows polynomialVariableCoefficient(I, A, z, p, j, n) = constantFunction(monomials(I), A, z)34proof35have function := polynomialVariableCoefficient.function at I, A, z, p, j, n with*36have zeroFunction := constantFunction.function at monomials(I), A, z with*37apply FunctionBetween.ext with function, zeroFunction38intros m hm39have zeroValue := constantFunction.apply at monomials(I), A, m, z with*40rw zeroValue41have alternatives : m(j) =0∨ m(j) ≠0bytauto42cases alternatives with missing | present43 . have value := polynomialVariableCoefficient.at_zero with*44rw value45by_contra nonzero46have naturalZero := nat.omega.forward with Naturals.constructor.zero47have nIn := nat.omega.forward at n with*48have single := monomialSingle.member at I, j, n with*49have product := monomialProduct.member at I, coefficientSingle(I, ℕ, 0, n, j), m with*50have exponent := monomialProduct.value at I, coefficientSingle(I, ℕ, 0, n, j), m, j with*51have singleValue := coefficientSingle.same at I, ℕ, 0, n, j with*52have identity := add.right_unit with*53have equal : monomialProduct(I, coefficientSingle(I, ℕ, 0, n, j), m)(j) = n bycc54have imageValue := monomialExponent.value at I, j, monomialProduct(I, coefficientSingle(I, ℕ, 0, n, j), m) with*55have supported : monomialProduct(I, coefficientSingle(I, ℕ, 0, n, j), m) ∈ functionSupport(p, monomials(I), z)56exact functionSupport.membership.backward with⟨product, nonzero⟩57apply absent58apply functionImage.membership.backward59refine⟨nIn, monomialProduct(I, coefficientSingle(I, ℕ, 0, n, j), m), supported, ?_⟩60cc61 . exact polynomialVariableCoefficient.at_nonzero with*6263theorem polynomialCoefficientFamily.support64shows functionSupport(polynomialCoefficientFamily(I, A, z, p, j), ℕ, constantFunction(monomials(I), A, z)) ⊆ functionImage(monomialExponent(I, j), functionSupport(p, monomials(I), z), ℕ)65proof66intros n hn67have data := functionSupport.membership.forward with hn68have natural := nat.omega.backward with data.left69have value := polynomialCoefficientFamily.value at I, A, z, p, j, n with*70by_contra absent71have vanishes := polynomialVariableCoefficient.outside with*72apply data.right73cc7475theorem polynomialCoefficientFamily.finite_support76shows Finite(functionSupport(polynomialCoefficientFamily(I, A, z, p, j), ℕ, constantFunction(monomials(I), A, z)))77proof78have finite := polynomials.finite_support with polynomial79have domain := functionSupport.subset at p, monomials(I), z80have exponents := monomialExponent.function at I, j with*81have imageFinite := Finite.function_image with exponents, finite, domain82have bound := polynomialCoefficientFamily.support with*83exact Finite.subset with imageFinite, bound8485theorem polynomialCoefficientFamily.map86shows CoefficientMap(polynomialCoefficientFamily(I, A, z, p, j), ℕ, polynomials(I, A, z), constantFunction(monomials(I), A, z))87proof88have function := polynomialCoefficientFamily.function at I, A, z, p, j with*89have finite := polynomialCoefficientFamily.finite_support with*90unfold CoefficientMap91refine⟨function, finite⟩9293end Expansion94theorem polynomialVariableCoefficient.agree_away (I A add z neg mul one p j v w : Set, n : Nat)95requiresring : IsCommRing(A, add, z, neg, mul, one)96requires polynomial : p ∈ polynomials(I, A, z)97requires first : v : I → A98requires second : w : I → A99requires agreement : ∀ i ∈ I, i ≠ j → v(i) = w(i)100shows polynomialAt(I, A, add, z, neg, mul, one, v)(polynomialVariableCoefficient(I, A, z, p, j, n)) = polynomialAt(I, A, add, z, neg, mul, one, w)(polynomialVariableCoefficient(I, A, z, p, j, n))101proof102have ordinary := IsCommRing.ring withring103have zeroIn := IsRing.zero_in_carrier with ordinary104have coefficient := polynomialVariableCoefficient.member at I, A, z, p, j, n with*105have bound := polynomialVariableCoefficient.variables at I, A, z, p, j, n with*106have domain := polynomialVariablesUsed.subset at I, A, z, p107have same : ∀ i ∈ polynomialVariablesUsed(I, A, z, polynomialVariableCoefficient(I, A, z, p, j, n)), v(i) = w(i)108intros i hi109have data := bound with i, hi110have difference := difference.membership.forward with data111have inI := domain with i, difference.left112have different : i ≠ j113intro equal114have singleton := singleton.membership.backward with equal115exact difference.right with singleton116exact agreement with i, inI, different117exact polynomialAt.agree_on_variables with*118