1-- Finite products in commutative rings, independent of enumeration (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.Ring.FiniteProduct8import SumSupport910def indexedRingProduct (w f mul u1 : Set, n : Nat) →Set11| w, f, mul, u1, zero => u112| w, f, mul, u1, succ(k) => call2(mul, indexedRingProduct(w, f, mul, u1, k), w(f(k)))1314def matchingProductRow (A u1 mul w f x : Set, n : Nat) →Set15| A, u1, mul, w, f, x, zero => u116| A, u1, mul, w, f, x, succ(k) => call2(mul, matchingProductRow(A, u1, mul, w, f, x, k), singleValue(A, u1, w(x), x, f(k)))1718def matchingProductTotal (A u1 mul w f g : Set, n m : Nat) →Set19| A, u1, mul, w, f, g, n, zero => u120| A, u1, mul, w, f, g, n, succ(k) => call2(mul, matchingProductTotal(A, u1, mul, w, f, g, n, k), matchingProductRow(A, u1, mul, w, f, g(k), n))21descends m2223section Rings24variable (A add zero neg mul one w : Set)25hypothesisring : IsCommRing(A, add, zero, neg, mul, one)26notationring R := (A, add, zero, neg, mul, one)2728theorem indexedRingProduct.closed (f : Set, n : Nat)29shows WeightedValues(w, f, A, n) → indexedRingProduct(w, f, mul, one, n) ∈ A30proof31induction n32| zero =>33have ordinary := IsCommRing.ring withring34have multiplicative := IsRing.multiplicative with ordinary35intro values36rw indexedRingProduct37exact IsMonoid.unit_in_carrier with multiplicative38| succ(k) using ih =>39have ordinary := IsCommRing.ring withring40have multiplicative := IsRing.multiplicative with ordinary41intro values42haveprefix:= WeightedValues.prefix at w, f, A, k with*43have last := WeightedValues.last at w, f, A, k with*44have previous := ih withprefix45rw indexedRingProduct46exact IsRing.mul_closed with ordinary, previous, last4748theorem matchingProductRow.closed (f x : Set, n : Nat)49requires value : w(x) ∈ A50shows matchingProductRow(A, one, mul, w, f, x, n) ∈ A51proof52induction n53| zero =>54have ordinary := IsCommRing.ring withring55have multiplicative := IsRing.multiplicative with ordinary56have oneIn := IsMonoid.unit_in_carrier with multiplicative57 rwa matchingProductRow58| succ(k) using ih =>59have ordinary := IsCommRing.ring withring60have multiplicative := IsRing.multiplicative with ordinary61have oneIn := IsMonoid.unit_in_carrier with multiplicative62have last := singleValue.closed at A, one, w(x), x, f(k) with*63rw matchingProductRow64exact IsRing.mul_closed with ordinary, ih, last6566theorem matchingProductTotal.closed (f g : Set, n m : Nat)67shows WeightedValues(w, g, A, m) → matchingProductTotal(A, one, mul, w, f, g, n, m) ∈ A68proof69induction m70| zero =>71have ordinary := IsCommRing.ring withring72have multiplicative := IsRing.multiplicative with ordinary73intro values74rw matchingProductTotal75exact IsMonoid.unit_in_carrier with multiplicative76| succ(k) using ih =>77have ordinary := IsCommRing.ring withring78have multiplicative := IsRing.multiplicative with ordinary79intro values80haveprefix:= WeightedValues.prefix at w, g, A, k with*81have last := WeightedValues.last at w, g, A, k with*82have previous := ih withprefix83have row := matchingProductRow.closed at A, add, zero, neg, mul, one, w, f, g(k), n with*84rw matchingProductTotal85exact IsRing.mul_closed with ordinary, previous, row8687theorem matchingProductRow.absent (f x : Set, n : Nat)88requires value : w(x) ∈ A89shows (∀ i ∈ n, f(i) ≠ x) → matchingProductRow(A, one, mul, w, f, x, n) = one90proof91induction n92| zero =>93have ordinary := IsCommRing.ring withring94have multiplicative := IsRing.multiplicative with ordinary95have oneIn := IsMonoid.unit_in_carrier with multiplicative96intro absent97rw matchingProductRow98rfl99| succ(k) using ih =>100have ordinary := IsCommRing.ring withring101have multiplicative := IsRing.multiplicative with ordinary102have oneIn := IsMonoid.unit_in_carrier with multiplicative103intro absent104haveprefix : ∀ i ∈ k, f(i) ≠ x105intros i before106have included := membership.into_successor at i, k with*107exact absent with i, included108have last := absent with k, membership.self_successor at k with*109have previous := ih withprefix110have entry := singleValue.other at A, one, w(x), x, f(k) with*111rw [matchingProductRow, previous, entry]112ring113114theorem matchingProductRow.unique (f x : Set, n : Nat)115requires value : w(x) ∈ A116shows DistinctValues(f, n) → Occurs(f, n, x) → matchingProductRow(A, one, mul, w, f, x, n) = w(x)117proof118induction n119| zero =>120have ordinary := IsCommRing.ring withring121have multiplicative := IsRing.multiplicative with ordinary122have oneIn := IsMonoid.unit_in_carrier with multiplicative123intros distinct occurs124rcases occurs with⟨i, impossible, same⟩125exfalso126simp [nat.zero, set.empty]127| succ(k) using ih =>128have ordinary := IsCommRing.ring withring129have multiplicative := IsRing.multiplicative with ordinary130have oneIn := IsMonoid.unit_in_carrier with multiplicative131intros distinct occurs132have alternatives : f(k) = x ∨ f(k) ≠ x bytauto133cases alternatives with last | other134 . have fresh := DistinctValues.last_fresh at f, k with*135have absent : ∀ i ∈ k, f(i) ≠ x136intros i before equal137have different := fresh with i, before138rw← last at equal139exact different with equal140have previous := matchingProductRow.absent at A, add, zero, neg, mul, one, w, f, x, k with*141have entry := singleValue.same at A, one, w(x), x, f(k) with*142rw [matchingProductRow, previous, entry]143ring144 . obtain⟨position, before, equal⟩:= Occurs.forward at f, succ(k), x with occurs145have shape := membership.successor_forward{n := k} with before146have earlier : position ∈ k147cases shape with inside | atLast148 . exact inside149 . exfalso150rw atLast at equal151exact other with equal152haveprefix:= DistinctValues.prefix at f, k with*153have occurrence : Occurs(f, k, x)154unfold Occurs155refine⟨position, earlier, equal⟩156have previous := ih withprefix, occurrence157have entry := singleValue.other at A, one, w(x), x, f(k) with*158rw [matchingProductRow, previous, entry]159ring160161theorem matchingProductWeight.symmetric (x y : Set)162requires xValue : w(x) ∈ A163requires yValue : w(y) ∈ A164shows singleValue(A, one, w(x), x, y) = singleValue(A, one, w(y), y, x)165proof166have ordinary := IsCommRing.ring withring167have multiplicative := IsRing.multiplicative with ordinary168have oneIn := IsMonoid.unit_in_carrier with multiplicative169have alternatives : x = y ∨ x ≠ y bytauto170cases alternatives with same | different171 . rw same172rfl173 . have reverse : y ≠ x174intro equal175have impossible : x = y bycc176exact different with impossible177haveleft:= singleValue.other at A, one, w(x), x, y with*178haveright:= singleValue.other at A, one, w(y), y, x with*179cc180181theorem matchingProductTotal.empty_left (f g : Set, m : Nat)182shows matchingProductTotal(A, one, mul, w, f, g, (0:Nat), m) = one183proof184induction m185| zero =>186rw matchingProductTotal187rfl188| succ(k) using ih =>189rw [matchingProductTotal, matchingProductRow, ih]190ring191192theorem matchingProductTotal.extend_left (f g : Set, n m : Nat)193requires value : w(f(n)) ∈ A194shows WeightedValues(w, g, A, m) →195 matchingProductTotal(A, one, mul, w, f, g, succ(n), m) =196 matchingProductTotal(A, one, mul, w, f, g, n, m) * matchingProductRow(A, one, mul, w, g, f(n), m)197proof198induction m199| zero =>200have ordinary := IsCommRing.ring withring201have multiplicative := IsRing.multiplicative with ordinary202have oneIn := IsMonoid.unit_in_carrier with multiplicative203intro values204simp [matchingProductTotal, matchingProductRow]205ring206| succ(k) using ih =>207have ordinary := IsCommRing.ring withring208have multiplicative := IsRing.multiplicative with ordinary209have oneIn := IsMonoid.unit_in_carrier with multiplicative210intro values211haveprefix:= WeightedValues.prefix at w, g, A, k with*212have last := WeightedValues.last at w, g, A, k with*213have previous := ih withprefix214have symmetric := matchingProductWeight.symmetric at A, add, zero, neg, mul, one, w, g(k), f(n) with*215have totalBound := matchingProductTotal.closed at A, add, zero, neg, mul, one, w, f, g, n, k with*216have totalIn := totalBound withprefix217have rowLeftIn := matchingProductRow.closed at A, add, zero, neg, mul, one, w, g, f(n), k with*218have rowRightIn := matchingProductRow.closed at A, add, zero, neg, mul, one, w, f, g(k), n with*219have entryIn := singleValue.closed at A, one, w(f(n)), f(n), g(k) with*220rw [matchingProductTotal, matchingProductTotal, matchingProductRow, matchingProductRow, previous, symmetric]221ring222223theorem matchingProductTotal.transpose (f g : Set, m n : Nat)224requires valuesG : WeightedValues(w, g, A, m)225shows WeightedValues(w, f, A, n) →226 matchingProductTotal(A, one, mul, w, f, g, n, m) = matchingProductTotal(A, one, mul, w, g, f, m, n)227proof228induction n229| zero =>230intro valuesF231have empty := matchingProductTotal.empty_left at A, add, zero, neg, mul, one, w, f, g, m with*232rw [empty, matchingProductTotal]233rfl234| succ(k) using ih =>235intro valuesF236haveprefix:= WeightedValues.prefix at w, f, A, k with*237have last := WeightedValues.last at w, f, A, k with*238have previous := ih withprefix239have extended := matchingProductTotal.extend_left at A, add, zero, neg, mul, one, w, f, g, k, m with*240rw [extended, matchingProductTotal, previous]241rfl242243theorem matchingProductTotal.product (f g : Set, n m : Nat)244requires distinct : DistinctValues(f, n)245shows WeightedValues(w, g, A, m) → (∀ j ∈ m, Occurs(f, n, g(j))) →246 matchingProductTotal(A, one, mul, w, f, g, n, m) = indexedRingProduct(w, g, mul, one, m)247proof248induction m249| zero =>250intros values covered251simp [matchingProductTotal, indexedRingProduct]252| succ(k) using ih =>253intros values covered254haveprefix : ∀ j ∈ k, Occurs(f, n, g(j))255intros j before256have included := membership.into_successor at j, k with*257exact covered with j, included258have last := covered with k, membership.self_successor at k with*259have valuePrefix := WeightedValues.prefix at w, g, A, k with*260have valueLast := WeightedValues.last at w, g, A, k with*261have row := matchingProductRow.unique at A, add, zero, neg, mul, one, w, f, g(k), n with*262have previous := ih with valuePrefix, prefix263rw [matchingProductTotal, indexedRingProduct, previous, row]264rfl265266theorem indexedRingProduct.same_entries (f g : Set, n m : Nat)267requires valuesF : WeightedValues(w, f, A, n)268requires valuesG : WeightedValues(w, g, A, m)269requires distinctF : DistinctValues(f, n)270requires distinctG : DistinctValues(g, m)271requires coveredF : ∀ i ∈ n, Occurs(g, m, f(i))272requires coveredG : ∀ j ∈ m, Occurs(f, n, g(j))273shows indexedRingProduct(w, f, mul, one, n) = indexedRingProduct(w, g, mul, one, m)274proof275haveleft:= matchingProductTotal.product at A, add, zero, neg, mul, one, w, g, f, m, n with*276haveright:= matchingProductTotal.product at A, add, zero, neg, mul, one, w, f, g, n, m with*277have transpose := matchingProductTotal.transpose at A, add, zero, neg, mul, one, w, f, g, m, n with*278rw [←left, ←right]279 symm280exact transpose with valuesF281282theorem indexedRingProduct.reindex (V f g : Set, n m : Nat)283requires weights : w : V → A284requires enumerationF : BijectiveBetween(f, n, V)285requires enumerationG : BijectiveBetween(g, m, V)286shows indexedRingProduct(w, f, mul, one, n) = indexedRingProduct(w, g, mul, one, m)287proof288have injF := Bijective.injective with enumerationF289have injG := Bijective.injective with enumerationG290have surjF := Bijective.surjective with enumerationF291have surjG := Bijective.surjective with enumerationG292have fnF := Injective.function with injF293have fnG := Injective.function with injG294have distinctF := Injective.distinct_values with injF295have distinctG := Injective.distinct_values with injG296have valuesF : WeightedValues(w, f, A, n)297intros i hi298have member := FunctionBetween.apply_closed with*299exact FunctionBetween.apply_closed with*300have valuesG : WeightedValues(w, g, A, m)301intros j hj302have member := FunctionBetween.apply_closed with*303exact FunctionBetween.apply_closed with*304have coveredF : ∀ i ∈ n, Occurs(g, m, f(i))305intros i hi306have member := FunctionBetween.apply_closed with*307exact Surjective.occurs with*308have coveredG : ∀ j ∈ m, Occurs(f, n, g(j))309intros j hj310have member := FunctionBetween.apply_closed with*311exact Surjective.occurs with*312exact indexedRingProduct.same_entries with*313314theorem indexedRingProduct.mul (v h f : Set, n : Nat)315shows WeightedValues(w, f, A, n) → WeightedValues(v, f, A, n) →316 (∀ i ∈ n, h(f(i)) = w(f(i)) * v(f(i))) →317 indexedRingProduct(h, f, mul, one, n) = indexedRingProduct(w, f, mul, one, n) * indexedRingProduct(v, f, mul, one, n)318proof319induction n320| zero =>321intros valuesW valuesV equations322simp [indexedRingProduct]323ring324| succ(k) using ih =>325intros valuesW valuesV equations326have prefixW := WeightedValues.prefix at w, f, A, k with*327have prefixV := WeightedValues.prefix at v, f, A, k with*328have lastW := WeightedValues.last at w, f, A, k with*329have lastV := WeightedValues.last at v, f, A, k with*330haveprefix : ∀ i ∈ k, h(f(i)) = w(f(i)) * v(f(i))331intros i hi332have next := membership.into_successor at i, k with*333exact equations with i, next334have last := equations with k, membership.self_successor at k with*335have previous := ih with prefixW, prefixV, prefix336have closureW := indexedRingProduct.closed at A, add, zero, neg, mul, one, w, f, k with*337have productW := closureW with prefixW338have closureV := indexedRingProduct.closed at A, add, zero, neg, mul, one, v, f, k with*339have productV := closureV with prefixV340rw [indexedRingProduct, indexedRingProduct, indexedRingProduct, previous, last]341ring342343end Rings344345defunique finiteRingProduct (V A add zero neg mul one w : Set) (product ∈ A) :=346∃ n, Nat(n) ∧∃ f, BijectiveBetween(f, n, V) ∧ product = indexedRingProduct(w, f, mul, one, n)347requiresring : IsCommRing(A, add, zero, neg, mul, one)348requires finite : Finite(V)349requires weights : w : V → A350proof351obtain⟨n, natural, equivalent⟩:= finite352obtain⟨f, bijective⟩:= equivalent353have enumeration := converse.bijective at f, V, n with bijective354have function := converse.function_of_bijective at f, V, n with bijective355have values := WeightedValues.of_functions with weights, function356have closure := indexedRingProduct.closed at A, add, zero, neg, mul, one, w, converse(f, V, n), n with*357have productIn := closure with values358witness indexedRingProduct(w, converse(f, V, n), mul, one, n)359refine⟨productIn, n, natural, converse(f, V, n), enumeration, rfl⟩360uniqueness361intros u uIn first v vIn second362obtain⟨n, naturalN, f, enumerationF, valueF⟩:= first363obtain⟨m, naturalM, g, enumerationG, valueG⟩:= second364have same := indexedRingProduct.reindex at A, add, zero, neg, mul, one, w, V, f, g, n, m with*365cc366367notationscoped finiteRingProduct(V, R, w) => finiteRingProduct(V, R.carrier, R.add, R.zero, R.neg, R.mul, R.one, w)368369theorem finiteRingProduct.closed (V A add zero neg mul one w : Set)370requiresring : IsCommRing(A, add, zero, neg, mul, one)371requires finite : Finite(V)372requires weights : w : V → A373shows finiteRingProduct(V, A, add, zero, neg, mul, one, w) ∈ A374proof375have selected := finiteRingProduct.selected at V, A, add, zero, neg, mul, one, w with*376exact selected.left377378theorem finiteRingProduct.enumeration (V A add zero neg mul one w f : Set, n : Nat)379requiresring : IsCommRing(A, add, zero, neg, mul, one)380requires weights : w : V → A381requires enumeration : BijectiveBetween(f, n, V)382shows finiteRingProduct(V, A, add, zero, neg, mul, one, w) = indexedRingProduct(w, f, mul, one, n)383proof384have reverse := converse.bijective with enumeration385have cardinality : HasCardinality(V, n)386unfold HasCardinality387refine⟨assumption, ?_⟩388unfold Equipotent389refine⟨converse(f, n, V), reverse⟩390have finite := Finite.from_cardinality with cardinality391have selected := finiteRingProduct.selected at V, A, add, zero, neg, mul, one, w with*392obtain⟨m, naturalM, g, enumerationG, value⟩:= selected.right393have same := indexedRingProduct.reindex at A, add, zero, neg, mul, one, w, V, g, f, m, n with*394cc395396theorem indexedRingProduct.congr (w v f g mul one : Set, n : Nat)397shows (∀ i ∈ n, w(f(i)) = v(g(i))) → indexedRingProduct(w, f, mul, one, n) = indexedRingProduct(v, g, mul, one, n)398proof399induction n400| zero =>401intro values402simp [indexedRingProduct]403| succ(k) using ih =>404intro values405haveprefix : ∀ i ∈ k, w(f(i)) = v(g(i))406intros i before407have included := membership.into_successor at i, k with*408exact values with i, included409have last := values with k, membership.self_successor at k with*410have previous := ih withprefix411rw [indexedRingProduct, indexedRingProduct, previous, last]412rfl413414theorem finiteRingProduct.congr (V A add zero neg mul one w v : Set)415requiresring : IsCommRing(A, add, zero, neg, mul, one)416requires finite : Finite(V)417requires weightsW : w : V → A418requires weightsV : v : V → A419requires values : ∀ x ∈ V, w(x) = v(x)420shows finiteRingProduct(V, A, add, zero, neg, mul, one, w) = finiteRingProduct(V, A, add, zero, neg, mul, one, v)421proof422have equal := FunctionBetween.ext with weightsW, weightsV, values423rw equal424rfl425426theorem indexedRingProduct.one (A add zero neg mul one w f : Set, n : Nat)427requiresring : IsCommRing(A, add, zero, neg, mul, one)428shows (∀ i ∈ n, w(f(i)) = one) → indexedRingProduct(w, f, mul, one, n) = one429proof430induction n431| zero =>432intro values433rw indexedRingProduct434rfl435| succ(k) using ih =>436intro values437haveprefix : ∀ i ∈ k, w(f(i)) = one438intros i before439have included := membership.into_successor at i, k with*440exact values with i, included441have last := values with k, membership.self_successor at k with*442have previous := ih withprefix443rw [indexedRingProduct, previous, last]444ring445446theorem finiteRingProduct.one (V A add zero neg mul one w : Set)447requiresring : IsCommRing(A, add, zero, neg, mul, one)448requires finite : Finite(V)449requires weights : w : V → A450requires values : ∀ x ∈ V, w(x) = one451shows finiteRingProduct(V, A, add, zero, neg, mul, one, w) = one452proof453have selected := finiteRingProduct.selected at V, A, add, zero, neg, mul, one, w with*454obtain⟨n, natural, f, enumeration, equation⟩:= selected.right455have injective := Bijective.injective with enumeration456have function := Injective.function with injective457have unitValues : ∀ i ∈ n, w(f(i)) = one458intros i hi459have member := FunctionBetween.apply_closed with*460exact values with f(i), member461have unitProduct := indexedRingProduct.one at A, add, zero, neg, mul, one, w, f, n with*462rw equation463exact unitProduct with unitValues464465section Rings466variable (A add zero neg mul one w : Set)467hypothesisring : IsCommRing(A, add, zero, neg, mul, one)468notationring R := (A, add, zero, neg, mul, one)469470theorem matchingProductRow.one (f x : Set, n : Nat)471requires neutral : w(x) = one472shows matchingProductRow(A, one, mul, w, f, x, n) = one473proof474induction n475| zero =>476rw matchingProductRow477rfl478| succ(k) using ih =>479have ordinary := IsCommRing.ring withring480have multiplicative := IsRing.multiplicative with ordinary481have oneIn := IsMonoid.unit_in_carrier with multiplicative482have value : w(x) ∈ A by rwa neutral483have alternatives : f(k) = x ∨ f(k) ≠ x bytauto484have entry : singleValue(A, one, w(x), x, f(k)) = one485cases alternatives with same | different486 . have selected := singleValue.same at A, one, w(x), x, f(k) with*487cc488 . exact singleValue.other at A, one, w(x), x, f(k) with*489rw [matchingProductRow, ih, entry]490ring491492theorem matchingProductRow.covered_or_one (f x : Set, n : Nat)493requires value : w(x) ∈ A494requires distinct : DistinctValues(f, n)495requires covered : Occurs(f, n, x) ∨ w(x) = one496shows matchingProductRow(A, one, mul, w, f, x, n) = w(x)497proof498cases covered with occurs | neutral499 . have unique := matchingProductRow.unique at A, add, zero, neg, mul, one, w, f, x, n with*500exact unique with distinct, occurs501 . have empty := matchingProductRow.one at A, add, zero, neg, mul, one, w, f, x, n with*502cc503504theorem matchingProductTotal.support_product (f g : Set, n m : Nat)505requires distinct : DistinctValues(f, n)506shows WeightedValues(w, g, A, m) → (∀ j ∈ m, Occurs(f, n, g(j)) ∨ w(g(j)) = one) →507 matchingProductTotal(A, one, mul, w, f, g, n, m) = indexedRingProduct(w, g, mul, one, m)508proof509induction m510| zero =>511intros values covered512simp [matchingProductTotal, indexedRingProduct]513| succ(k) using ih =>514intros values covered515haveprefix : ∀ j ∈ k, Occurs(f, n, g(j)) ∨ w(g(j)) = one516intros j before517have included := membership.into_successor at j, k with*518exact covered with j, included519have last := covered with k, membership.self_successor at k with*520have valuePrefix := WeightedValues.prefix at w, g, A, k with*521have valueLast := WeightedValues.last at w, g, A, k with*522have row := matchingProductRow.covered_or_one at A, add, zero, neg, mul, one, w, f, g(k), n with*523have previous := ih with valuePrefix, prefix524rw [matchingProductTotal, indexedRingProduct, previous, row]525rfl526527theorem indexedRingProduct.same_nonunit_entries (f g : Set, n m : Nat)528requires valuesF : WeightedValues(w, f, A, n)529requires valuesG : WeightedValues(w, g, A, m)530requires distinctF : DistinctValues(f, n)531requires distinctG : DistinctValues(g, m)532requires coveredF : ∀ i ∈ n, Occurs(g, m, f(i)) ∨ w(f(i)) = one533requires coveredG : ∀ j ∈ m, Occurs(f, n, g(j)) ∨ w(g(j)) = one534shows indexedRingProduct(w, f, mul, one, n) = indexedRingProduct(w, g, mul, one, m)535proof536haveleft:= matchingProductTotal.support_product at A, add, zero, neg, mul, one, w, g, f, m, n with*, valuesF, coveredF537haveright:= matchingProductTotal.support_product at A, add, zero, neg, mul, one, w, f, g, n, m with*, valuesG, coveredG538have transpose := matchingProductTotal.transpose at A, add, zero, neg, mul, one, w, f, g, m, n with*539rw [←left, ←right]540 symm541exact transpose with valuesF542543end Rings544545theorem finiteRingProduct.restrict (V S A add zero neg mul one w : Set)546requiresring : IsCommRing(A, add, zero, neg, mul, one)547requires finite : Finite(V)548requires weights : w : V → A549requires subset : S ⊆ V550requires neutral : ∀ x ∈ V, ¬(x ∈ S) → w(x) = one551shows finiteRingProduct(V, A, add, zero, neg, mul, one, w) =552 finiteRingProduct(S, A, add, zero, neg, mul, one, restrict(w, S))553proof554have finiteS := Finite.subset with finite, subset555have closed : ∀ x ∈ S, w(x) ∈ A556intros x hx557have included := subset558have member := included with x, hx559exact FunctionBetween.apply_closed with*560have restricted := restrict.function with*561have selectedV := finiteRingProduct.selected at V, A, add, zero, neg, mul, one, w with*562have selectedS := finiteRingProduct.selected at S, A, add, zero, neg, mul, one, restrict(w, S) with*563obtain⟨n, naturalN, f, enumerationF, equationV⟩:= selectedV.right564obtain⟨m, naturalM, g, enumerationG, equationS⟩:= selectedS.right565have injF := Bijective.injective with enumerationF566have injG := Bijective.injective with enumerationG567have surjF := Bijective.surjective with enumerationF568have surjG := Bijective.surjective with enumerationG569have functionF := Injective.function with injF570have functionG := Injective.function with injG571have distinctF := Injective.distinct_values with injF572have distinctG := Injective.distinct_values with injG573have valuesF := WeightedValues.of_functions with weights, functionF574have valuesG : WeightedValues(w, g, A, m)575intros i hi576have member := FunctionBetween.apply_closed with*577exact closed with g(i), member578have coveredF : ∀ i ∈ n, Occurs(g, m, f(i)) ∨ w(f(i)) = one579intros i hi580have member := FunctionBetween.apply_closed with*581have alternatives : f(i) ∈ S ∨¬(f(i) ∈ S) bytauto582cases alternatives with inside | outside583 . left584exact Surjective.occurs with*585 . right586exact neutral with f(i), member, outside587have coveredG : ∀ i ∈ m, Occurs(f, n, g(i)) ∨ w(g(i)) = one588intros i hi589have inS := FunctionBetween.apply_closed with*590have included := subset591have inV := included with g(i), inS592left593exact Surjective.occurs with*594have same := indexedRingProduct.same_nonunit_entries with valuesF, valuesG, distinctF, distinctG, coveredF, coveredG595have pointwise : ∀ i ∈ m, w(g(i)) = restrict(w, S)(g(i))596intros i hi597have inS := FunctionBetween.apply_closed with*598 symm599exact restrict.apply with*600have congr := indexedRingProduct.congr at w, restrict(w, S), g, g, mul, one, m with naturalM601have equal := congr with pointwise602cc603604theorem finiteRingProduct.reindex (D E A add zero neg mul one w v f : Set)605requiresring : IsCommRing(A, add, zero, neg, mul, one)606requires finite : Finite(D)607requires weightsW : w : D → A608requires weightsV : v : E → A609requires bijective : BijectiveBetween(f, D, E)610requires values : ∀ d ∈ D, w(d) = v(f(d))611shows finiteRingProduct(D, A, add, zero, neg, mul, one, w) = finiteRingProduct(E, A, add, zero, neg, mul, one, v)612proof613have selected := finiteRingProduct.selected at D, A, add, zero, neg, mul, one, w with*614obtain⟨n, natural, g, enumeration, equation⟩:= selected.right615have composed := compose.bijective at f, g, n, D, E with*616have injF := Bijective.injective with bijective617have injG := Bijective.injective with enumeration618have functionF := Injective.function with injF619have functionG := Injective.function with injG620have equationV := finiteRingProduct.enumeration at E, A, add, zero, neg, mul, one, v, compose(f, g, n, D, E), n with*621have pointwise : ∀ i ∈ n, w(g(i)) = v(compose(f, g, n, D, E)(i))622intros i hi623have member := FunctionBetween.apply_closed at g, n, D, i with*624have value := values with g(i), member625have composite := compose.apply at f, g, n, D, E, i with*626cc627have congr := indexedRingProduct.congr at w, v, g, compose(f, g, n, D, E), mul, one, n with natural628have same := congr with pointwise629cc630631-- The smaller-domain weights may be represented by any agreeing graph.632theorem finiteRingProduct.unit_extension (D S A add zero neg mul one w v : Set)633requiresring : IsCommRing(A, add, zero, neg, mul, one)634requires finite : Finite(D)635requires weightsW : w : D → A636requires weightsV : v : S → A637requires subset : S ⊆ D638requires agreement : ∀ s ∈ S, w(s) = v(s)639requires neutral : ∀ d ∈ D, ¬(d ∈ S) → w(d) = one640shows finiteRingProduct(D, A, add, zero, neg, mul, one, w) = finiteRingProduct(S, A, add, zero, neg, mul, one, v)641proof642have closed : ∀ s ∈ S, w(s) ∈ A643intros s hs644have value := FunctionBetween.apply_closed with*645have equal := agreement with s, hs646 rwa equal647have restricted := restrict.function with*648have same : restrict(w, S) = v649apply FunctionBetween.ext with restricted, weightsV650intros s hs651have value := restrict.apply with*652have equal := agreement with s, hs653cc654have product := finiteRingProduct.restrict with*655 rwa same at product656657658theorem finiteRingProduct.empty (A add zero neg mul one w : Set)659requiresring : IsCommRing(A, add, zero, neg, mul, one)660requires weights : w : ∅→ A661shows finiteRingProduct(∅, A, add, zero, neg, mul, one, w) = one662proof663have finite := Finite.empty664have values : ∀ x ∈∅, w(x) = one665intros x impossible666exfalso667exactset.empty with impossible668exact finiteRingProduct.one withring, finite, weights, values669670theorem finiteRingProduct.insert (V A add zero neg mul one w a : Set)671requiresring : IsCommRing(A, add, zero, neg, mul, one)672requires finite : Finite(V)673requires weights : w : insert(a, V) → A674requires fresh : ¬(a ∈ V)675shows finiteRingProduct(insert(a, V), A, add, zero, neg, mul, one, w) =676 call2(mul, finiteRingProduct(V, A, add, zero, neg, mul, one, restrict(w, V)), w(a))677proof678have subset : V ⊆ insert(a, V)679intros x hx680exact insert.contains with hx681have closed : ∀ x ∈ V, w(x) ∈ A682intros x hx683have member := insert.contains at x, a, V with hx684exact FunctionBetween.apply_closed at w, insert(a, V), A, x with*685have restricted := restrict.function at w, insert(a, V), A, V, A with*686have selected := finiteRingProduct.selected at V, A, add, zero, neg, mul, one, restrict(w, V) with*687obtain⟨n, natural, f, enumeration, equation⟩:= selected.right688have injective := Bijective.injective with enumeration689have function := Injective.function with injective690have nFresh := membership.irreflexive at n691have extended := adjoinMap.bijective with enumeration, nFresh, fresh692have successor := natural.successor_as_insert with natural693rw← successor at extended694have extendedInjective := Bijective.injective with extended695have extendedFunction := Injective.function with extendedInjective696have extendedProduct := finiteRingProduct.enumeration at insert(a, V), A, add, zero, neg, mul, one, w, adjoinMap(f, n, a), succ(n) with*697have oldValues : ∀ i ∈ n, w(adjoinMap(f, n, a)(i)) = restrict(w, V)(f(i))698intros i hi699have oldMember := FunctionBetween.apply_closed at f, n, V, i with*700have oldEdge := FunctionBetween.relates_apply at f, n, V, i with*701have edge := adjoinMap.relates_old at f, n, a, i, f(i) with oldEdge702have next := membership.into_successor at i, n with*703have value := FunctionBetween.apply_value at adjoinMap(f, n, a), succ(n), insert(a, V), i, f(i) with*704have restrictedValue := restrict.apply at w, insert(a, V), A, V, A, f(i) with*705cc706have congr := indexedRingProduct.congr at w, restrict(w, V), adjoinMap(f, n, a), f, mul, one, n with natural707haveprefix:= congr with oldValues708have newIndex := membership.self_successor with natural709have newEdge := adjoinMap.relates_new at f, n, a710have newValue := FunctionBetween.apply_value at adjoinMap(f, n, a), succ(n), insert(a, V), n, a with*711rw [extendedProduct, indexedRingProduct, prefix, newValue, equation]712rfl713714theorem finiteRingProduct.singleton (A add zero neg mul one w x : Set)715requiresring : IsCommRing(A, add, zero, neg, mul, one)716requires weights : w : {x} → A717shows finiteRingProduct({x}, A, add, zero, neg, mul, one, w) = w(x)718proof719have same : insert(x, ∅) = {x}720ext y721simp722have empty := Finite.empty723have fresh : ¬(x ∈∅) byexactset.empty at x724have extended : w : insert(x, ∅) → A by rwa same725have subset : ∅⊆ insert(x, ∅) bysimp [Subset, set.empty]726have closed : ∀ y ∈∅, w(y) ∈ A727intros y hy728exfalso729exactset.empty with hy730have restricted := restrict.function with*731have emptyProduct := finiteRingProduct.empty with*732have inserted := finiteRingProduct.insert with*733have member : x ∈ {x} bysimp [singleton.membership]734have value := FunctionBetween.apply_closed with*735rw same at inserted736rw [inserted, emptyProduct]737ring738739theorem finiteRingProduct.mul (D A add zero neg mul one w v h : Set)740requiresring : IsCommRing(A, add, zero, neg, mul, one)741requires finite : Finite(D)742requires weightsW : w : D → A743requires weightsV : v : D → A744requires weightsH : h : D → A745requires equations : ∀ x ∈ D, h(x) = call2(mul, w(x), v(x))746shows finiteRingProduct(D, A, add, zero, neg, mul, one, h) = call2(mul, finiteRingProduct(D, A, add, zero, neg, mul, one, w), finiteRingProduct(D, A, add, zero, neg, mul, one, v))747proof748have selected := finiteRingProduct.selected at D, A, add, zero, neg, mul, one, w with*749obtain⟨n, natural, f, enumeration, valueW⟩:= selected.right750have injective := Bijective.injective with enumeration751have function := Injective.function with injective752have valuesW := WeightedValues.of_functions with weightsW, function753have valuesV := WeightedValues.of_functions with weightsV, function754have valueV := finiteRingProduct.enumeration at D, A, add, zero, neg, mul, one, v, f, n with*755have valueH := finiteRingProduct.enumeration at D, A, add, zero, neg, mul, one, h, f, n with*756have pointwise : ∀ i ∈ n, h(f(i)) = call2(mul, w(f(i)), v(f(i)))757intros i hi758have member := FunctionBetween.apply_closed with*759exact equations with f(i), member760have multiply := indexedRingProduct.mul with*, valuesW, valuesV, pointwise761cc762