1-- Pointwise linearity for finite products and sums over commutative rings (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.FiniteLinearity8import FiniteProduct910section Rings11variable (V A add zero neg mul one : Set)12notationring R := (A, add, zero, neg, mul, one)13hypothesisring : IsCommRing(R)14hypothesis finite : Finite(V)1516theorem finiteRingProduct.remove (w i : Set)17requires weights : w : V → A18requires member : i ∈ V19shows finiteRingProduct(V, R, w) = finiteRingProduct(V ∖ {i}, R, restrict(w, V ∖ {i})) * w(i)20proof21have subset : V ∖ {i} ⊆ V bysimp [Subset, difference.membership]22have smaller := Finite.subset with finite, subset23have fresh : ¬(i ∈ V ∖ {i}) bysimp [difference.membership, singleton.membership]24have restore := insert.restore with member25have expanded : w : insert(i, V ∖ {i}) → A by rwa restore26have equation := finiteRingProduct.insert with*27 rwa restore at equation2829-- Only the distinguished factor varies. Callers supply pointwise equations,30-- without constructing graphs for their sums or scalar multiples.31theorem finiteRingProduct.linear_at (w v h i a b : Set)32requires weightsW : w : V → A33requires weightsV : v : V → A34requires weightsH : h : V → A35requires member : i ∈ V36requires scalarA : a ∈ A37requires scalarB : b ∈ A38requires outsideV : ∀ j ∈ V, ¬(j = i) → v(j) = w(j)39requires outsideH : ∀ j ∈ V, ¬(j = i) → h(j) = w(j)40requires entry : h(i) = a * w(i) + b * v(i)41shows finiteRingProduct(V, R, h) = a * finiteRingProduct(V, R, w) + b * finiteRingProduct(V, R, v)42proof43have subset : V ∖ {i} ⊆ V bysimp [Subset, difference.membership]44have smaller := Finite.subset with finite, subset45have restrictedW := restrict.domain_function at w, V, A, V ∖ {i} with*46have restrictedV := restrict.domain_function at v, V, A, V ∖ {i} with*47have restrictedH := restrict.domain_function at h, V, A, V ∖ {i} with*48have sameV : ∀ j ∈ V ∖ {i}, restrict(v, V ∖ {i})(j) = restrict(w, V ∖ {i})(j)49intros j hj50have inV : j ∈ V bysimp [difference.membership]51have distinct : ¬(j = i) bysimp [difference.membership, singleton.membership]52have leftValue := restrict.domain_apply at v, V, A, V ∖ {i}, j with*53have rightValue := restrict.domain_apply at w, V, A, V ∖ {i}, j with*54rw [leftValue, rightValue]55exact outsideV with j, inV, distinct56have equalV := finiteRingProduct.congr with*57have sameH : ∀ j ∈ V ∖ {i}, restrict(h, V ∖ {i})(j) = restrict(w, V ∖ {i})(j)58intros j hj59have inV : j ∈ V bysimp [difference.membership]60have distinct : ¬(j = i) bysimp [difference.membership, singleton.membership]61have leftValue := restrict.domain_apply at h, V, A, V ∖ {i}, j with*62have rightValue := restrict.domain_apply at w, V, A, V ∖ {i}, j with*63rw [leftValue, rightValue]64exact outsideH with j, inV, distinct65have equalH := finiteRingProduct.congr at V ∖ {i}, A, add, zero, neg, mul, one, restrict(h, V ∖ {i}), restrict(w, V ∖ {i}) with*66have equationW := finiteRingProduct.remove at V, A, add, zero, neg, mul, one, w, i with*67have equationV := finiteRingProduct.remove at V, A, add, zero, neg, mul, one, v, i with*68have equationH := finiteRingProduct.remove at V, A, add, zero, neg, mul, one, h, i with*69have rest := finiteRingProduct.closed at V ∖ {i}, A, add, zero, neg, mul, one, restrict(w, V ∖ {i}) with*70have valueW := FunctionBetween.apply_closed at w, V, A, i with*71have valueV := FunctionBetween.apply_closed at v, V, A, i with*72rw [equationH, equationW, equationV, equalH, equalV, entry]73ring7475theorem finiteRingSum.linear (w v h a b : Set)76requires weightsW : w : V → A77requires weightsV : v : V → A78requires weightsH : h : V → A79requires scalarA : a ∈ A80requires scalarB : b ∈ A81requires entries : ∀ i ∈ V, h(i) = a * w(i) + b * v(i)82shows finiteRingSum(V, R, h) = a * finiteRingSum(V, R, w) + b * finiteRingSum(V, R, v)83proof84have scaledW := coefficientScale.function at V, A, add, zero, neg, mul, one, a, w with*85have scaledV := coefficientScale.function at V, A, add, zero, neg, mul, one, b, v with*86have combined := coefficientAdd.function at V, A, add, zero, neg, mul, one, coefficientScale(V, R, a, w), coefficientScale(V, R, b, v) with*87have equations : ∀ i ∈ V, h(i) = coefficientAdd(V, R, coefficientScale(V, R, a, w), coefficientScale(V, R, b, v))(i)88intros i hi89have sum := coefficientAdd.value at V, A, add, zero, neg, mul, one, coefficientScale(V, R, a, w), coefficientScale(V, R, b, v), i with*90have leftValue := coefficientScale.value at V, A, add, zero, neg, mul, one, a, w, i with*91have rightValue := coefficientScale.value at V, A, add, zero, neg, mul, one, b, v, i with*92rw [sum, leftValue, rightValue]93exact entries with i, hi94have equal := finiteRingSum.congr with*95have sum := finiteRingSum.add at V, A, add, zero, neg, mul, one, coefficientScale(V, R, a, w), coefficientScale(V, R, b, v) with*96have leftSum := finiteRingSum.scale at V, A, add, zero, neg, mul, one, w, a with*97have rightSum := finiteRingSum.scale at V, A, add, zero, neg, mul, one, v, b with*98rw [equal, sum, leftSum, rightSum]99rfl100101-- Pointwise scaling avoids an auxiliary coefficientScale graph at call sites.102theorem finiteRingSum.scale_eq (w v a : Set)103requires weightsW : w : V → A104requires weightsV : v : V → A105requires scalar : a ∈ R106requires entries : ∀ i ∈ V, v(i) = a * w(i)107shows finiteRingSum(V, R, v) = a * finiteRingSum(V, R, w)108proof109have zeroIn : R[0] ∈ R bytypecheck110have linear : ∀ i ∈ V, v(i) = a * w(i) + R[0] * w(i)111intros i hi112have closed := FunctionBetween.apply_closed at w, V, A, i with*113have entry := entries with i, hi114rw entry115ring116have equation := finiteRingSum.linear with*117have closed := finiteRingSum.closed at V, A, add, zero, neg, mul, one, w with*118rw equation119ring120121end Rings122