1-- Interchange of arbitrary finite rectangular sums over a commutative ring (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.DoubleSum8import SumSupport9import Cardinal.Product1011predicate RingRowValues (w A x n : Set) :=∀ j ∈ n, w((x, j)) ∈ A12predicate RingMatrixValues (w A m n : Set) :=∀ i ∈ m, RingRowValues(w, A, i, n)13predicate TransposedValues (w v m n : Set) :=∀ i ∈ m, ∀ j ∈ n, w((i, j)) = v((j, i))1415def ringRowSum (w add z x : Set, n : Nat) →Set16| w, add, z, x, zero => z17| w, add, z, x, succ(k) => call2(add, ringRowSum(w, add, z, x, k), w((x, k)))1819def ringDoubleSum (w add z : Set, m n : Nat) →Set20| w, add, z, zero, n => z21| w, add, z, succ(k), n => call2(add, ringDoubleSum(w, add, z, k, n), ringRowSum(w, add, z, k, n))2223theorem RingRowValues.prefix (w A x : Set, n : Nat)24requires values : RingRowValues(w, A, x, succ(n))25shows RingRowValues(w, A, x, n)26proof27intros j hj28have included := membership.into_successor with*29exact values with j, included3031theorem RingRowValues.last (w A x : Set, n : Nat)32requires values : RingRowValues(w, A, x, succ(n))33shows w((x, n)) ∈ A34proof35exact values with n, membership.self_successor at n with*3637theorem RingMatrixValues.prefix (w A n : Set, m : Nat)38requires values : RingMatrixValues(w, A, succ(m), n)39shows RingMatrixValues(w, A, m, n)40proof41intros i hi42have included := membership.into_successor with*43exact values with i, included4445theorem RingMatrixValues.last (w A n : Set, m : Nat)46requires values : RingMatrixValues(w, A, succ(m), n)47shows RingRowValues(w, A, m, n)48proof49exact values with m, membership.self_successor at m with*5051section Rings52variable (A add zero neg mul one : Set)53hypothesisring : IsCommRing(A, add, zero, neg, mul, one)54notationring R := (A, add, zero, neg, mul, one)5556theorem ringRowSum.closed (w x : Set, n : Nat)57shows RingRowValues(w, A, x, n) → ringRowSum(w, add, zero, x, n) ∈ A58proof59induction n60| zero =>61intro values62have ordinary := IsCommRing.ring withring63rw ringRowSum64exact IsRing.zero_in_carrier with ordinary65| succ(k) using ih =>66intro values67have ordinary := IsCommRing.ring withring68haveprefix:= RingRowValues.prefix at w, A, x, k with*69have last := RingRowValues.last at w, A, x, k with*70have previous := ih withprefix71rw ringRowSum72exact IsRing.add_closed with ordinary, previous, last7374theorem ringDoubleSum.closed (w : Set, m n : Nat)75shows RingMatrixValues(w, A, m, n) → ringDoubleSum(w, add, zero, m, n) ∈ A76proof77induction m78| zero =>79intro values80have ordinary := IsCommRing.ring withring81rw ringDoubleSum82exact IsRing.zero_in_carrier with ordinary83| succ(k) using ih =>84intro values85have ordinary := IsCommRing.ring withring86haveprefix:= RingMatrixValues.prefix at w, A, n, k with*87have last := RingMatrixValues.last at w, A, n, k with*88have previous := ih withprefix89have rowClosed := ringRowSum.closed at A, add, zero, neg, mul, one, w, k, n with*90have row := rowClosed with last91rw ringDoubleSum92exact IsRing.add_closed with ordinary, previous, row9394theorem ringDoubleSum.empty_columns (w : Set, m : Nat)95shows ringDoubleSum(w, add, zero, m, (0:Nat)) = zero96proof97induction m98| zero =>99rw ringDoubleSum100rfl101| succ(k) using ih =>102rw [ringDoubleSum, ringRowSum, ih]103ring104105-- A new column contributes one row of the transposed matrix.106theorem ringDoubleSum.extend_columns (w v : Set, m n : Nat)107shows RingMatrixValues(w, A, m, succ(n)) → RingRowValues(v, A, n, m) →108 (∀ i ∈ m, w((i, n)) = v((n, i))) →109 ringDoubleSum(w, add, zero, m, succ(n)) = ringDoubleSum(w, add, zero, m, n) + ringRowSum(v, add, zero, n, m)110proof111induction m112| zero =>113intros values rowValues transposed114simp [ringDoubleSum, ringRowSum]115ring116| succ(k) using ih =>117intros values rowValues transposed118haveprefix:= RingMatrixValues.prefix at w, A, succ(n), k with*119have last := RingMatrixValues.last at w, A, succ(n), k with*120have rowPrefix := RingRowValues.prefix at v, A, n, k with*121have rowLast := RingRowValues.last at v, A, n, k with*122have prefixTranspose : ∀ i ∈ k, w((i, n)) = v((n, i))123intros i hi124have included := membership.into_successor at i, k with*125exact transposed with i, included126have lastTranspose := transposed with k, membership.self_successor at k with*127have previous := ih withprefix, rowPrefix, prefixTranspose128have shorter : RingMatrixValues(w, A, k, n)129intros i hi130have row :=prefixwith i, hi131exact RingRowValues.prefix at w, A, i, n with*132have lastPrefix := RingRowValues.prefix at w, A, k, n with*133have totalClosed := ringDoubleSum.closed at A, add, zero, neg, mul, one, w, k, n with*134have totalIn := totalClosed with shorter135have columnClosed := ringRowSum.closed at A, add, zero, neg, mul, one, v, n, k with*136have columnIn := columnClosed with rowPrefix137have rowClosed := ringRowSum.closed at A, add, zero, neg, mul, one, w, k, n with*138have rowIn := rowClosed with lastPrefix139rw [ringDoubleSum, ringDoubleSum, ringRowSum, ringRowSum, previous, lastTranspose]140ring141142theorem ringDoubleSum.transpose (w v : Set, m n : Nat)143shows RingMatrixValues(w, A, m, n) → RingMatrixValues(v, A, n, m) → TransposedValues(w, v, m, n) →144 ringDoubleSum(w, add, zero, m, n) = ringDoubleSum(v, add, zero, n, m)145proof146induction n147| zero =>148intros valuesW valuesV transposed149have empty := ringDoubleSum.empty_columns at A, add, zero, neg, mul, one, w, m with*150rw [empty, ringDoubleSum]151rfl152| succ(k) using ih =>153intros valuesW valuesV transposed154have prefixW : RingMatrixValues(w, A, m, k)155have rows := valuesW156intros i hi157have row := rows with i, hi158exact RingRowValues.prefix at w, A, i, k with*159have prefixV := RingMatrixValues.prefix at v, A, m, k with*160have lastV := RingMatrixValues.last at v, A, m, k with*161have prefixTranspose : TransposedValues(w, v, m, k)162intros i hi j hj163have included := membership.into_successor at j, k with*164exact transposed with i, hi, j, included165have lastTranspose : ∀ i ∈ m, w((i, k)) = v((k, i))166intros i hi167exact transposed with i, hi, k, membership.self_successor at k with*168have previous := ih with prefixW, prefixV, prefixTranspose169have extension := ringDoubleSum.extend_columns at A, add, zero, neg, mul, one, w, v, m, k with*, valuesW, lastV, lastTranspose170rw [extension, ringDoubleSum, previous]171rfl172173end Rings174175-- A matrix is a function on a Cartesian rectangle.176theorem RingMatrixValues.of_function (w A m n : Set)177requires function : w : m × n → A178shows RingMatrixValues(w, A, m, n)179proof180intros i hi j hj181have pair := product.pair with hi, hj182exact FunctionBetween.apply_closed with*183184defgraph transposedMatrix (m n A w : Set) (p ∈ n × m) : A := w(productSwap(n, m)(p))185requires matrix : w : m × n → A186proof187have swap := productSwap.function at n, m188have pair := FunctionBetween.apply_closed with*189exact FunctionBetween.apply_closed with*190191theorem transposedMatrix.pair (m n A w i j : Set)192requires matrix : w : m × n → A193requires row : i ∈ m194requires column : j ∈ n195shows transposedMatrix(m, n, A, w)((j, i)) = w((i, j))196proof197have pair := product.pair at j, i, n, m with*198have swap := productSwap.pair at n, m, j, i with*199have value := transposedMatrix.value at m, n, A, w, (j, i) with*200cc201202theorem transposedMatrix.involution (m n A w : Set)203requires matrix : w : m × n → A204shows transposedMatrix(n, m, A, transposedMatrix(m, n, A, w)) = w205proof206have once := transposedMatrix.function at m, n, A, w with*207have twice := transposedMatrix.function at n, m, A, transposedMatrix(m, n, A, w) with*208apply FunctionBetween.ext with twice, matrix209intros p hp210obtain⟨bound, i, hi, j, hj, shape⟩:= product.membership.forward with hp211have first := transposedMatrix.pair at m, n, A, w, i, j with*212have second := transposedMatrix.pair at n, m, A, transposedMatrix(m, n, A, w), j, i with*213cc214215-- Public interface: one matrix graph, with all side conditions explicit.216theorem ringDoubleSum.interchange (A add zero neg mul one w : Set, m n : Nat)217requiresring : IsCommRing(A, add, zero, neg, mul, one)218requires matrix : w : m × n → A219shows ringDoubleSum(w, add, zero, m, n) = ringDoubleSum(transposedMatrix(m, n, A, w), add, zero, n, m)220proof221have transposed := transposedMatrix.function at m, n, A, w with*222have valuesW := RingMatrixValues.of_function with matrix223have valuesV := RingMatrixValues.of_function with transposed224have entries : TransposedValues(w, transposedMatrix(m, n, A, w), m, n)225intros i hi j hj226 symm227exact transposedMatrix.pair with*228have interchange := ringDoubleSum.transpose at A, add, zero, neg, mul, one, w, transposedMatrix(m, n, A, w), m, n with*229exact interchange with valuesW, valuesV, entries230