1-- Removing zero summands from finite ring sums, without Choice.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.Ring.SumSupport8import SumExtension910section Rings11variable (A add zero neg mul one w : Set)12hypothesisring : IsCommRing(A, add, zero, neg, mul, one)13notationring R := (A, add, zero, neg, mul, one)1415theorem matchingRingRow.zero (f x : Set, n : Nat)16requires vanishes : w(x) = zero17shows matchingRingRow(A, zero, add, w, f, x, n) = zero18proof19induction n20| zero =>21rw matchingRingRow22rfl23| succ(k) using ih =>24have ordinary := IsCommRing.ring withring25have zeroIn := IsRing.zero_in_carrier with ordinary26have value : w(x) ∈ A27 rwa vanishes28have alternatives : f(k) = x ∨ f(k) ≠ x bytauto29have entry : singleValue(A, zero, w(x), x, f(k)) = zero30cases alternatives with same | different31 . have selected := singleValue.same at A, zero, w(x), x, f(k) with*32cc33 . exact singleValue.other at A, zero, w(x), x, f(k) with*34rw [matchingRingRow, ih, entry]35ring3637theorem matchingRingRow.covered_or_zero (f x : Set, n : Nat)38requires value : w(x) ∈ A39requires distinct : DistinctValues(f, n)40requires covered : Occurs(f, n, x) ∨ w(x) = zero41shows matchingRingRow(A, zero, add, w, f, x, n) = w(x)42proof43cases covered with occurs | vanishes44 . have unique := matchingRingRow.unique at A, add, zero, neg, mul, one, w, f, x, n with*45exact unique with distinct, occurs46 . have empty := matchingRingRow.zero at A, add, zero, neg, mul, one, w, f, x, n with*47cc4849theorem matchingRingTotal.support_sum (f g : Set, n m : Nat)50requires distinct : DistinctValues(f, n)51shows WeightedValues(w, g, A, m) → (∀ j ∈ m, Occurs(f, n, g(j)) ∨ w(g(j)) = zero) →52 matchingRingTotal(A, zero, add, w, f, g, n, m) = indexedRingSum(w, g, add, zero, m)53proof54induction m55| zero =>56intros values covered57simp [matchingRingTotal, indexedRingSum]58| succ(k) using ih =>59intros values covered60haveprefix : ∀ j ∈ k, Occurs(f, n, g(j)) ∨ w(g(j)) = zero61intros j before62have included := membership.into_successor at j, k with*63exact covered with j, included64have last := covered with k, membership.self_successor at k with*65have valuePrefix := WeightedValues.prefix at w, g, A, k with*66have valueLast := WeightedValues.last at w, g, A, k with*67have row := matchingRingRow.covered_or_zero at A, add, zero, neg, mul, one, w, f, g(k), n with*68have previous := ih with valuePrefix, prefix69rw [matchingRingTotal, indexedRingSum, previous, row]70rfl7172theorem indexedRingSum.same_nonzero_entries (f g : Set, n m : Nat)73requires valuesF : WeightedValues(w, f, A, n)74requires valuesG : WeightedValues(w, g, A, m)75requires distinctF : DistinctValues(f, n)76requires distinctG : DistinctValues(g, m)77requires coveredF : ∀ i ∈ n, Occurs(g, m, f(i)) ∨ w(f(i)) = zero78requires coveredG : ∀ j ∈ m, Occurs(f, n, g(j)) ∨ w(g(j)) = zero79shows indexedRingSum(w, f, add, zero, n) = indexedRingSum(w, g, add, zero, m)80proof81haveleft:= matchingRingTotal.support_sum at A, add, zero, neg, mul, one, w, g, f, m, n with*, valuesF, coveredF82haveright:= matchingRingTotal.support_sum at A, add, zero, neg, mul, one, w, f, g, n, m with*, valuesG, coveredG83have transpose := matchingRingTotal.transpose at A, add, zero, neg, mul, one, w, f, g, m, n with*84rw [←left, ←right]85 symm86exact transpose with valuesF8788end Rings8990theorem finiteRingSum.restrict (V S A add zero neg mul one w : Set)91requiresring : IsCommRing(A, add, zero, neg, mul, one)92requires finite : Finite(V)93requires weights : w : V → A94requires subset : S ⊆ V95requires vanishes : ∀ x ∈ V, ¬(x ∈ S) → w(x) = zero96shows finiteRingSum(V, A, add, zero, neg, mul, one, w) =97 finiteRingSum(S, A, add, zero, neg, mul, one, restrict(w, S))98proof99have finiteS := Finite.subset with finite, subset100have closed : ∀ x ∈ S, w(x) ∈ A101intros x hx102have included := subset103have member := included with x, hx104exact FunctionBetween.apply_closed with*105have restricted := restrict.function with*106have selectedV := finiteRingSum.selected at V, A, add, zero, neg, mul, one, w with*107have selectedS := finiteRingSum.selected at S, A, add, zero, neg, mul, one, restrict(w, S) with*108obtain⟨n, naturalN, f, enumerationF, equationV⟩:= selectedV.right109obtain⟨m, naturalM, g, enumerationG, equationS⟩:= selectedS.right110have injF := Bijective.injective with enumerationF111have injG := Bijective.injective with enumerationG112have surjF := Bijective.surjective with enumerationF113have surjG := Bijective.surjective with enumerationG114have functionF := Injective.function with injF115have functionG := Injective.function with injG116have distinctF := Injective.distinct_values with injF117have distinctG := Injective.distinct_values with injG118have valuesF := WeightedValues.of_functions with weights, functionF119have valuesG : WeightedValues(w, g, A, m)120intros i hi121have member := FunctionBetween.apply_closed with*122exact closed with g(i), member123have coveredF : ∀ i ∈ n, Occurs(g, m, f(i)) ∨ w(f(i)) = zero124intros i hi125have member := FunctionBetween.apply_closed with*126have alternatives : f(i) ∈ S ∨¬(f(i) ∈ S) bytauto127cases alternatives with inside | outside128 . left129exact Surjective.occurs with*130 . right131exact vanishes with f(i), member, outside132have coveredG : ∀ i ∈ m, Occurs(f, n, g(i)) ∨ w(g(i)) = zero133intros i hi134have inS := FunctionBetween.apply_closed with*135have included := subset136have inV := included with g(i), inS137left138exact Surjective.occurs with*139have same := indexedRingSum.same_nonzero_entries with valuesF, valuesG, distinctF, distinctG, coveredF, coveredG140have pointwise : ∀ i ∈ m, w(g(i)) = restrict(w, S)(g(i))141intros i hi142have inS := FunctionBetween.apply_closed with*143 symm144exact restrict.apply with*145have congr := indexedRingSum.congr at w, restrict(w, S), g, g, add, zero, m with naturalM146have equal := congr with pointwise147cc148149theorem finiteRingSum.reindex (D E A add zero neg mul one w v f : Set)150requiresring : IsCommRing(A, add, zero, neg, mul, one)151requires finite : Finite(D)152requires weightsW : w : D → A153requires weightsV : v : E → A154requires bijective : BijectiveBetween(f, D, E)155requires values : ∀ d ∈ D, w(d) = v(f(d))156shows finiteRingSum(D, A, add, zero, neg, mul, one, w) = finiteRingSum(E, A, add, zero, neg, mul, one, v)157proof158have selected := finiteRingSum.selected at D, A, add, zero, neg, mul, one, w with*159obtain⟨n, natural, g, enumeration, equation⟩:= selected.right160have composed := compose.bijective at f, g, n, D, E with*161have injF := Bijective.injective with bijective162have injG := Bijective.injective with enumeration163have functionF := Injective.function with injF164have functionG := Injective.function with injG165have equationV := finiteRingSum.enumeration at E, A, add, zero, neg, mul, one, v, compose(f, g, n, D, E), n with*166have pointwise : ∀ i ∈ n, w(g(i)) = v(compose(f, g, n, D, E)(i))167intros i hi168have member := FunctionBetween.apply_closed at g, n, D, i with*169have value := values with g(i), member170have composite := compose.apply at f, g, n, D, E, i with*171cc172have congr := indexedRingSum.congr at w, v, g, compose(f, g, n, D, E), add, zero, n with natural173have same := congr with pointwise174cc175176-- The smaller-domain weights may be represented by any agreeing graph.177theorem finiteRingSum.zero_extension (D S A add zero neg mul one w v : Set)178requiresring : IsCommRing(A, add, zero, neg, mul, one)179requires finite : Finite(D)180requires weightsW : w : D → A181requires weightsV : v : S → A182requires subset : S ⊆ D183requires agreement : ∀ s ∈ S, w(s) = v(s)184requires vanishes : ∀ d ∈ D, ¬(d ∈ S) → w(d) = zero185shows finiteRingSum(D, A, add, zero, neg, mul, one, w) = finiteRingSum(S, A, add, zero, neg, mul, one, v)186proof187have closed : ∀ s ∈ S, w(s) ∈ A188intros s hs189have value := FunctionBetween.apply_closed with*190have equal := agreement with s, hs191 rwa equal192have restricted := restrict.function with*193have same : restrict(w, S) = v194apply FunctionBetween.ext with restricted, weightsV195intros s hs196have value := restrict.apply with*197have equal := agreement with s, hs198cc199have sum := finiteRingSum.restrict with*200 rwa same at sum201202theorem finiteRingSum.singleton (A add zero neg mul one w x : Set)203requiresring : IsCommRing(A, add, zero, neg, mul, one)204requires weights : w : {x} → A205shows finiteRingSum({x}, A, add, zero, neg, mul, one, w) = w(x)206proof207have same : insert(x, ∅) = {x}208ext y209simp210have empty := Finite.empty211have fresh : ¬(x ∈∅) byexactset.empty at x212have extended : w : insert(x, ∅) → A by rwa same213have subset : ∅⊆ insert(x, ∅) bysimp [Subset, set.empty]214have closed : ∀ y ∈∅, w(y) ∈ A215intros y hy216exfalso217exactset.empty with hy218have restricted := restrict.function with*219have emptySum := finiteRingSum.empty with*220have inserted := finiteRingSum.insert with*221have member : x ∈ {x} bysimp [singleton.membership]222have value := FunctionBetween.apply_closed with*223rw same at inserted224rw [inserted, emptySum]225ring226227theorem finiteRingSum.single (C A add zero neg mul one a c : Set)228requiresring : IsCommRing(A, add, zero, neg, mul, one)229requires finite : Finite(C)230requires coefficient : a ∈ A231requires index : c ∈ C232shows finiteRingSum(C, A, add, zero, neg, mul, one, coefficientSingle(C, A, zero, a, c)) = a233proof234have ordinary := IsCommRing.ring withring235have zeroIn := IsRing.zero_in_carrier with ordinary236have weights := coefficientSingle.function at C, A, zero, a, c with*237have small := coefficientSingle.function at {c}, A, zero, a, c with*238have singletonMember : c ∈ {c}239settlewith singleton.membership240have subset : {c} ⊆ C241settlewith Subset, singleton.membership242have agreement : ∀ x ∈ {c}, coefficientSingle(C, A, zero, a, c)(x) = coefficientSingle({c}, A, zero, a, c)(x)243intros x hx244have equal := singleton.membership.forward at x, c with hx245haveleft:= coefficientSingle.same at C, A, zero, a, c with*246haveright:= coefficientSingle.same at {c}, A, zero, a, c with*247cc248have vanishes : ∀ x ∈ C, ¬(x ∈ {c}) → coefficientSingle(C, A, zero, a, c)(x) = zero249intros x hx outside250have different : x ≠ c251settlewith singleton.membership252exact coefficientSingle.other at C, A, zero, a, c, x with*253have reduced := finiteRingSum.zero_extension at C, {c}, A, add, zero, neg, mul, one, coefficientSingle(C, A, zero, a, c), coefficientSingle({c}, A, zero, a, c) with*254have singleton := finiteRingSum.singleton at A, add, zero, neg, mul, one, coefficientSingle({c}, A, zero, a, c), c with*255have value := coefficientSingle.same at {c}, A, zero, a, c with*256cc257258-- A fixed equality selector commutes with a finite sum.259theorem finiteRingSum.select (D A add zero neg mul one w v j i : Set)260requiresring : IsCommRing(A, add, zero, neg, mul, one)261requires finite : Finite(D)262requires weightsW : w : D → A263requires weightsV : v : D → A264requires values : ∀ d ∈ D, v(d) = singleValue(A, zero, w(d), j, i)265shows finiteRingSum(D, A, add, zero, neg, mul, one, v) =266 singleValue(A, zero, finiteRingSum(D, A, add, zero, neg, mul, one, w), j, i)267proof268have ordinary := IsCommRing.ring withring269have zeroIn := IsRing.zero_in_carrier with ordinary270have alternatives : i = j ∨ i ≠ j bytauto271cases alternatives with same | different272 . have equal : v = w273apply FunctionBetween.ext with weightsV, weightsW274intros d hd275have coefficient := FunctionBetween.apply_closed at w, D, A, d with*276have selected := singleValue.same at A, zero, w(d), j, i with*277have value := values with d, hd278cc279have selected := singleValue.same at A, zero, finiteRingSum(D, A, add, zero, neg, mul, one, w), j, i with*280cc281 . have vanishes : ∀ d ∈ D, v(d) = zero282intros d hd283have coefficient := FunctionBetween.apply_closed at w, D, A, d with*284have selected := singleValue.other at A, zero, w(d), j, i with*285have value := values with d, hd286cc287have sum := finiteRingSum.zero at D, A, add, zero, neg, mul, one, v with*288have selected := singleValue.other at A, zero, finiteRingSum(D, A, add, zero, neg, mul, one, w), j, i with*289cc290