1-- Finite real sums2-- 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.Real.FiniteSum8import Analysis.Sequences9import Power1011-- FiniteSums12def realPartialSum (u : Set) (n : Nat) →Set13| u, zero => realZero14| u, succ(k) => realAddValue(realPartialSum(u, k), uₖ)1516notationbinder"∑"=> realPartialSum forReal1718theorem realPartialSum.zero (u : Set)19shows realPartialSum(u, 0) = (0:R)20proof21rw realPartialSum22rfl2324theorem realPartialSum.succ (u : Set, n : Nat)25shows ∑ i < succ(n), u(i) = realAddValue(∑ i < n, u(i), uₙ)26proof27rw realPartialSum28rfl2930theorem realPartialSum.real (u : Set, n : Nat)31requires sequence : RealSequence(u)32showsReal(∑ i < n, u(i))33proof34induction n35| zero =>36rw realPartialSum37exact realZero.real38| succ(k) using ih =>39rw realPartialSum40have termReal := RealSequence.value with sequence41have sumReal := realAddValue.real with ih, termReal42unfold call2 at sumReal43unfold realAddValue44exact sumReal4546-- Linearity makes finite sums usable independently of the integration proofs.47theorem realPartialSum.add (u v : Set, n : Nat)48requires sequenceU : RealSequence(u)49requires sequenceV : RealSequence(v)50shows ∑ i < n, addSequence(u, v)(i) =51 (∑ i < n, u(i)) + ∑ i < n, v(i)52proof53induction n54| zero =>55rw [realPartialSum.zero, realPartialSum.zero, realPartialSum.zero]56ring57| succ(k) using ih =>58have valueU := RealSequence.value with sequenceU59have valueV := RealSequence.value with sequenceV60have sumUV := addSequence.sequence with sequenceU, sequenceV61have value := addSequence.value with sequenceU, sequenceV, valueU, valueV62rw [realPartialSum.succ, realPartialSum.succ, realPartialSum.succ, ih, value]63ring6465-- Scalar multiplication commutes with a finite sum.66theorem realPartialSum.scale (u : Set, n : Nat, C : Real)67requires sequence : RealSequence(u)68shows ∑ k < n, mulSequence(constantSequence(C), u)(k) =69 C * (∑ i < n, u(i):R)70proof71induction n72| zero =>73rw [realPartialSum.zero, realPartialSum.zero]74ring75| succ(k) using ih =>76have constants := constantSequence.sequence at C77have scaled := mulSequence.sequence with constants, sequence78have constantValue := RealSequence.value with constants79have valueU := RealSequence.value with sequence80have value := mulSequence.value with constants, sequence, constantValue, valueU81have constant := constantSequence.value at C, k with*82rw [realPartialSum.succ, realPartialSum.succ, ih, value, constant]83ring8485theorem realPartialSum.neg (u : Set, n : Nat)86requires sequence : RealSequence(u)87shows ∑ i < n, negSequence(u)(i) = -(∑ i < n, u(i):R)88proof89induction n90| zero =>91rw [realPartialSum.zero, realPartialSum.zero]92ring93| succ(k) using ih =>94have valueU := RealSequence.value with sequence95have negated := negSequence.sequence with sequence96have value := negSequence.value with sequence, valueU97rw [realPartialSum.succ, realPartialSum.succ, ih, value]98ring99100theorem realPartialSum.sub (u v : Set, n : Nat)101requires sequenceU : RealSequence(u)102requires sequenceV : RealSequence(v)103shows ∑ i < n, subSequence(u, v)(i) =104 (∑ i < n, u(i):R) - (∑ i < n, v(i):R)105proof106have negated := negSequence.sequence with sequenceV107unfold subSequence108rw [realPartialSum.add, realPartialSum.neg]109unfold realSubValue110rfl111112-- Pointwise bounds pass to half-open finite sums, including the empty sum.113theorem realPartialSum.monotone (u v : Set, n : Nat)114requires sequenceU : RealSequence(u)115requires sequenceV : RealSequence(v)116requires bounded : ∀ k ∈ ℕ, (u[k]:R) ≤ (v[k]:R)117shows (∑ i < n, u(i):R) ≤ (∑ i < n, v(i):R)118proof119induction n120| zero =>121rw [realPartialSum.zero, realPartialSum.zero]122exact realLe.reflexive with realZero.real123| succ(k) using ih =>124rw [realPartialSum.succ, realPartialSum.succ]125have uk := RealSequence.value with sequenceU126have vk := RealSequence.value with sequenceV127have sumU := realPartialSum.real with sequenceU128have sumV := realPartialSum.real with sequenceV129have naturalK := nat.omega.forward at k withassumption130have bound := bounded with k, naturalK131unfold realAddValue132have added := realLe.add with sumU, sumV, uk, vk, ih, bound133unfold call2 at added134exact added135136-- Induct before introducing the bound, so it can be specialized to each137-- smaller prefix of the current partition.138theorem realPartialSum.monotone_prefix_aux (n : Nat)139shows∀ u, ∀ v, RealSequence(u) → RealSequence(v) →140 (∀ k ∈ ℕ, k < n → (u[k]:R) ≤ (v[k]:R)) →141 (∑ i < n, u(i):R) ≤ (∑ i < n, v(i):R)142proof143induction n144| zero =>145intros u v sequenceU sequenceV bounded146rw [realPartialSum.zero, realPartialSum.zero]147exact realLe.reflexive with realZero.real148| succ(k) using ih =>149intros u v sequenceU sequenceV bounded150have naturalK := nat.omega.forward at k withassumption151have before : k < succ(k)152unfold Less153exact LessEqual.reflexive at succ(k) with154 Naturals.constructor.succ at k withassumption155have termBound := bounded with k, naturalK, before156haveprefix : ∀ j ∈ ℕ, j < k → (u[j]:R) ≤ (v[j]:R)157intros j naturalJ smaller158have typedJ := nat.omega.backward with naturalJ159have below := Less.transitive_LessEqual at j, k, succ(k) with160 typedJ, assumption, Naturals.constructor.succ at k withassumption,161 smaller, LessEqual.successor at k withassumption162exact bounded with j, naturalJ, below163have sumBound := ih with u, v, sequenceU, sequenceV, prefix164rw [realPartialSum.succ, realPartialSum.succ]165have uk := RealSequence.value with sequenceU166have vk := RealSequence.value with sequenceV167have sumU := realPartialSum.real with sequenceU168have sumV := realPartialSum.real with sequenceV169unfold realAddValue170have added := realLe.add with sumU, sumV, uk, vk, sumBound, termBound171unfold call2 at added172exact added173174-- Only the first n terms need bounds; later values of the sequences do not175-- affect a finite sum.176theorem realPartialSum.monotone_prefix (u v : Set, n : Nat)177requires sequenceU : RealSequence(u)178requires sequenceV : RealSequence(v)179requires bounded : ∀ k ∈ ℕ, k < n → (u[k]:R) ≤ (v[k]:R)180shows (∑ i < n, u(i):R) ≤ (∑ i < n, v(i):R)181proof182exact realPartialSum.monotone_prefix_aux at n with183 u, v, sequenceU, sequenceV, bounded184185-- A finite sum only observes its first n terms, even if its sequences differ186-- at every later index.187theorem realPartialSum.eq_prefix_aux (n : Nat)188shows∀ u, ∀ v, RealSequence(u) → RealSequence(v) →189 (∀ k ∈ ℕ, k < n → u[k] = v[k]) →190 ∑ i < n, u(i) = ∑ i < n, v(i)191proof192induction n193| zero =>194intros u v sequenceU sequenceV equal195rw [realPartialSum.zero, realPartialSum.zero]196rfl197| succ(k) using ih =>198intros u v sequenceU sequenceV equal199have naturalK := nat.omega.forward at k withassumption200have before : k < succ(k)201unfold Less202exact LessEqual.reflexive at succ(k) with203 Naturals.constructor.succ at k withassumption204have termEqual := equal with k, naturalK, before205haveprefix : ∀ j ∈ ℕ, j < k → u[j] = v[j]206intros j naturalJ smaller207have typedJ := nat.omega.backward with naturalJ208have below := Less.transitive_LessEqual at j, k, succ(k) with209 typedJ, assumption, Naturals.constructor.succ at k withassumption,210 smaller, LessEqual.successor at k withassumption211exact equal with j, naturalJ, below212have sumEqual := ih with u, v, sequenceU, sequenceV, prefix213rw [realPartialSum.succ, realPartialSum.succ, sumEqual, termEqual]214rfl215216theorem realPartialSum.eq_prefix (u v : Set, n : Nat)217requires sequenceU : RealSequence(u)218requires sequenceV : RealSequence(v)219requires equal : ∀ k ∈ ℕ, k < n → u[k] = v[k]220shows ∑ i < n, u(i) = ∑ i < n, v(i)221proof222exact realPartialSum.eq_prefix_aux at n with223 u, v, sequenceU, sequenceV, equal224225-- ShiftedSums226defgraph shiftedRealSequence (u : Set, k : Nat) (n ∈ ℕ) : ℝ := u[add(k, n)]227requires sequence : RealSequence(u)228proof229have typedN := nat.omega.backward with member230exact RealSequence.value at u, add(k, n) with sequence231232theorem shiftedRealSequence.sequence (u : Set, k : Nat)233requires sequence : RealSequence(u)234shows RealSequence(shiftedRealSequence(u, k))235proof236unfold RealSequence237exact shiftedRealSequence.function with sequence238239-- Prefix and suffix sums agree on their shared boundary. This is the finite240-- sum operation needed for concatenating local refinements.241theorem realPartialSum.split_at (u : Set, n m : Nat)242requires sequence : RealSequence(u)243shows realPartialSum(u, add(n, m)) =244 (∑ i < n, u(i)) + ∑ i < m, shiftedRealSequence(u, n)(i)245proof246induction m247| zero =>248rw [add.right_unit, realPartialSum.zero]249haveprefix:= realPartialSum.real with sequence250have zero := realAddValue.zero_right withprefix251rw zero252rfl253| succ(k) using ih =>254have shifted := shiftedRealSequence.sequence at u, n with sequence255have step := realPartialSum.succ at u, add(n, k)256have suffixStep := realPartialSum.succ at shiftedRealSequence(u, n), k257have value := shiftedRealSequence.value at u, n, k with sequence258rw [add.succ_right, step, ih, suffixStep, value]259have term := RealSequence.value at u, add(n, k) with sequence260ring261262-- The geometric sequence is a set-theoretic function on naturals.263defgraph geometricTerms (X : Real) (n ∈ ℕ) : ℝ := realPow(X, n)264proof265have typedN := nat.omega.backward with member266exact realPow.real with typedN267268theorem geometricTerms.sequence (X : Real)269shows RealSequence(geometricTerms(X))270proof271unfold RealSequence272exact geometricTerms.function withassumption273274theorem geometricTerms.shifted (X : Real, m k : Nat)275shows shiftedRealSequence(geometricTerms(X), m)[k] =276 (X ^ m) * (geometricTerms(X)[k]:R)277proof278have sequence := geometricTerms.sequence at X279have shifted := shiftedRealSequence.value at geometricTerms(X), m, k with sequence280have index := add.closed at k, m with*281have value := geometricTerms.value withassumption, index282have valueK := geometricTerms.value at X, k with*283have power := realPow.add at X, m, k with*284 rwa [shifted, value, valueK]285286-- Concatenation of prefixes, with the second block rescaled by X^m.287theorem realPartialSum.geometric_split (X : Real, m n : Nat)288shows realPartialSum(geometricTerms(X), add(m, n)) =289 (∑ i < m, geometricTerms(X)(i):R) +290 (X ^ m) * (∑ i < n, geometricTerms(X)(i):R)291proof292have sequence := geometricTerms.sequence at X293have power := realPow.real at X, m with*294have constants := constantSequence.sequence with power295have scaled := mulSequence.sequence with constants, sequence296have shifted := shiftedRealSequence.sequence at geometricTerms(X), m with sequence297have equal : ∀ j ∈ ℕ, j < n →298 shiftedRealSequence(geometricTerms(X), m)[j] =299 mulSequence(constantSequence(X ^ m), geometricTerms(X))[j]300intros j naturalJ before301have typedJ := nat.omega.backward with naturalJ302have constant := constantSequence.value with power, typedJ303have term := RealSequence.value at geometricTerms(X), j with sequence304have constantTerm := RealSequence.value at constantSequence(X ^ m), j with constants305have product := mulSequence.value with constants, sequence, constantTerm, term306have shiftedTerm := geometricTerms.shifted at X, m, j with307*{2}, typedJ308 rwa [product, constant]309have suffix := realPartialSum.eq_prefix with shifted, scaled, equal310havesplit:= realPartialSum.split_at at geometricTerms(X), m, n with sequence311have scale := realPartialSum.scale at geometricTerms(X), n, X ^ m with sequence312calc313 realPartialSum(geometricTerms(X), add(m, n)) =314 (∑ i < m, geometricTerms(X)(i):R) +315 ∑ k < n, shiftedRealSequence(geometricTerms(X), m)(k) :=split316 _ = (∑ i < m, geometricTerms(X)(i):R) +317 ∑ k < n, mulSequence(constantSequence(X ^ m), geometricTerms(X))(k) :=bycc318 _ = (∑ i < m, geometricTerms(X)(i):R) +319 (X ^ m) * (∑ i < n, geometricTerms(X)(i):R) :=bycc320321-- Division-free geometric sum identity, valid also at X = 1.322theorem realPartialSum.geometric (X : Real, n : Nat)323shows ((1:R) - X) * (∑ j < n, geometricTerms(X)(j):R) =324 (1:R) - X ^ n325proof326induction n327| zero =>328rw [realPartialSum.zero, realPow.zero]329ring330| succ(k) using ih =>331have sequence := geometricTerms.sequence at X332have value := geometricTerms.value at X, k with*333rw [realPartialSum.succ, value, realPow.succ]334calc335 ((1:R) - X) * realAddValue(∑ j < k, geometricTerms(X)(j), X ^ k) =336 ((1:R) - X) * (∑ j < k, geometricTerms(X)(j):R) +337 ((1:R) - X) * X ^ k :=byring338 _ = ((1:R) - X ^ k) + ((1:R) - X) * X ^ k :=bycc339 _ = (1:R) - X * X ^ k :=byring340341theorem realPartialSum.geometric_quotient (X : Real, n : Nat)342requires nonzero : ((1:R) - X) ≠ (0:R)343shows ∑ i < n, geometricTerms(X)(i) =344 ((1:R) - X ^ n) / ((1:R) - X)345proof346have denominator := realSubValue.real with realOne.real347have power := realPow.real at X, n with*348have numerator := realSubValue.real with realOne.real, power349have sequence := geometricTerms.sequence at X350have inverseReal := realInvValue.real with denominator351have inverse := realInvValue.mul_right with nonzero352have identity := realPartialSum.geometric at X, n353have division := realDiv.eq_mul_inv with numerator, denominator354have commute := realMulValue.commutative with inverseReal, numerator355calc356 ∑ i < n, geometricTerms(X)(i) =357 (1:R) * (∑ i < n, geometricTerms(X)(i):R) :=byring358 _ = (((1:R) - X) * realInvValue((1:R) - X)) *359 (∑ i < n, geometricTerms(X)(i):R) :=bycc360 _ = realInvValue((1:R) - X) *361 (((1:R) - X) * (∑ i < n, geometricTerms(X)(i):R)) :=byring362 _ = realInvValue((1:R) - X) * ((1:R) - X ^ n) :=bysimp [identity]363 _ = ((1:R) - X ^ n) / ((1:R) - X) :=bycc364365-- The generic forward difference sequence of a real sequence.366defgraph adjacentDifferences (u : Set) (n ∈ ℕ) : ℝ :=367 realSubValue(u[succ(n)], u[n])368requires sequence : RealSequence(u)369proof370have typedN := nat.omega.backward with member371have atN := RealSequence.value with sequence372have atNext := RealSequence.value at u, succ(n) with sequence373exact realSubValue.real with atNext, atN374375theorem adjacentDifferences.sequence (u : Set)376requires sequence : RealSequence(u)377shows RealSequence(adjacentDifferences(u))378proof379unfold RealSequence380exact adjacentDifferences.function with sequence381382theorem realPartialSum.telescoping (u : Set, n : Nat)383requires sequence : RealSequence(u)384shows ∑ i < n, adjacentDifferences(u)(i) = (u[n]:R) - (u[0]:R)385proof386induction n387| zero =>388rw realPartialSum.zero389have atZero := RealSequence.value at u, 0with sequence390ring391| succ(k) using ih =>392have atZero := RealSequence.value with sequence393have atK := RealSequence.value with sequence394have atNext := RealSequence.value with sequence395have difference := adjacentDifferences.value with sequence396rw [realPartialSum.succ, difference, ih]397ring398399-- Discrete Leibniz rule. The first factor is sampled at the next index.400theorem adjacentDifferences.product (u v : Set, n : Nat)401requires sequenceU : RealSequence(u)402requires sequenceV : RealSequence(v)403shows adjacentDifferences(mulSequence(u, v))[n] =404 (u[succ(n)]:R) * (adjacentDifferences(v)[n]:R) +405 (v[n]:R) * (adjacentDifferences(u)[n]:R)406proof407have productSequence := mulSequence.sequence with sequenceU, sequenceV408have un := RealSequence.value with sequenceU409have vn := RealSequence.value with sequenceV410have unext := RealSequence.value at u, succ(n) with sequenceU411have vnext := RealSequence.value at v, succ(n) with sequenceV412have productN := mulSequence.value with sequenceU, sequenceV, un, vn413have productNext := mulSequence.value with sequenceU, sequenceV, unext, vnext414have differenceProduct := adjacentDifferences.value with productSequence415have differenceU := adjacentDifferences.value with sequenceU416have differenceV := adjacentDifferences.value with sequenceV417rw [differenceProduct, productNext, productN, differenceU, differenceV]418ring419420-- The two terms in the discrete product rule are sequences in their own right.421defgraph forwardProductIncrements (u v : Set) (n ∈ ℕ) : ℝ :=422 realMulValue(u[succ(n)], realSubValue(v[succ(n)], v[n]))423requires sequenceU : RealSequence(u)424requires sequenceV : RealSequence(v)425proof426have typedN := nat.omega.backward with member427have unext := RealSequence.value at u, succ(n) with sequenceU428have vn := RealSequence.value with sequenceV429have vnext := RealSequence.value at v, succ(n) with sequenceV430have difference := realSubValue.real with vnext, vn431have product := realMulValue.real with unext, difference432unfold realMulValue433unfold call2 at product434exact product435436defgraph backwardProductIncrements (u v : Set) (n ∈ ℕ) : ℝ :=437 realMulValue(v[n], realSubValue(u[succ(n)], u[n]))438requires sequenceU : RealSequence(u)439requires sequenceV : RealSequence(v)440proof441have typedN := nat.omega.backward with member442have un := RealSequence.value with sequenceU443have unext := RealSequence.value at u, succ(n) with sequenceU444have vn := RealSequence.value with sequenceV445have difference := realSubValue.real with unext, un446have product := realMulValue.real with vn, difference447unfold realMulValue448unfold call2 at product449exact product450451theorem forwardProductIncrements.sequence (u v : Set)452requires sequenceU : RealSequence(u)453requires sequenceV : RealSequence(v)454shows RealSequence(forwardProductIncrements(u, v))455proof456unfold RealSequence457exact forwardProductIncrements.function with sequenceU, sequenceV458459theorem backwardProductIncrements.sequence (u v : Set)460requires sequenceU : RealSequence(u)461requires sequenceV : RealSequence(v)462shows RealSequence(backwardProductIncrements(u, v))463proof464unfold RealSequence465exact backwardProductIncrements.function with sequenceU, sequenceV466467theorem adjacentDifferences.product_terms (u v : Set, n : Nat)468requires sequenceU : RealSequence(u)469requires sequenceV : RealSequence(v)470shows adjacentDifferences(mulSequence(u, v))[n] =471 addSequence(forwardProductIncrements(u, v), backwardProductIncrements(u, v))[n]472proof473have forward := forwardProductIncrements.sequence with sequenceU, sequenceV474have backward := backwardProductIncrements.sequence with sequenceU, sequenceV475have forwardReal := RealSequence.value with forward476have backwardReal := RealSequence.value with backward477have added := addSequence.value with forward, backward, forwardReal, backwardReal478have forwardValue := forwardProductIncrements.value with sequenceU, sequenceV479have backwardValue := backwardProductIncrements.value with sequenceU, sequenceV480have product := adjacentDifferences.product with sequenceU, sequenceV481rw [added, forwardValue, backwardValue]482have differenceU := adjacentDifferences.value with sequenceU483have differenceV := adjacentDifferences.value with sequenceV484rw [differenceU, differenceV] at product485simp [realMulValue, call2]486487-- Finite summation by parts, expressed without choosing an interval or grid.488theorem realPartialSum.product_telescoping (u v : Set, n : Nat)489requires sequenceU : RealSequence(u)490requires sequenceV : RealSequence(v)491shows (∑ i < n, forwardProductIncrements(u, v)(i):R) +492 (∑ i < n, backwardProductIncrements(u, v)(i):R) =493 (u[n]:R) * (v[n]:R) - (u[0]:R) * (v[0]:R)494proof495have forward := forwardProductIncrements.sequence with sequenceU, sequenceV496have backward := backwardProductIncrements.sequence with sequenceU, sequenceV497have productSequence := mulSequence.sequence with sequenceU, sequenceV498have differences := adjacentDifferences.sequence with productSequence499have added := addSequence.sequence with forward, backward500have equal : ∀ k ∈ ℕ, k < n →501 adjacentDifferences(mulSequence(u, v))[k] =502 addSequence(forwardProductIncrements(u, v), backwardProductIncrements(u, v))[k]503intros k naturalK before504have typedK := nat.omega.backward with naturalK505exact adjacentDifferences.product_terms with sequenceU, sequenceV506have sameSum := realPartialSum.eq_prefix with differences, added, equal507have sumAdd := realPartialSum.add with forward, backward508have telescope := realPartialSum.telescoping with productSequence509have un := RealSequence.value with sequenceU510have vn := RealSequence.value with sequenceV511have u0 := RealSequence.value at u, 0with sequenceU512have v0 := RealSequence.value at v, 0with sequenceV513have productN := mulSequence.value with sequenceU, sequenceV, un, vn514have productZero := mulSequence.value with sequenceU, sequenceV, u0, v0515rw [productN, productZero] at telescope516calc517 (∑ i < n, forwardProductIncrements(u, v)(i):R) +518 (∑ i < n, backwardProductIncrements(u, v)(i):R) =519 realPartialSum(addSequence(forwardProductIncrements(u, v),520 backwardProductIncrements(u, v)), n) :=bycc521 _ = ∑ k < n, adjacentDifferences(mulSequence(u, v))(k) :=bycc522 _ = (u[n]:R) * (v[n]:R) - (u[0]:R) * (v[0]:R) := telescope523524theorem realPartialSum.summation_by_parts (u v : Set, n : Nat)525requires sequenceU : RealSequence(u)526requires sequenceV : RealSequence(v)527shows ∑ i < n, forwardProductIncrements(u, v)(i) =528 ((u[n]:R) * (v[n]:R) - (u[0]:R) * (v[0]:R)) -529 (∑ i < n, backwardProductIncrements(u, v)(i):R)530proof531have forward := forwardProductIncrements.sequence with sequenceU, sequenceV532have backward := backwardProductIncrements.sequence with sequenceU, sequenceV533have un := RealSequence.value with sequenceU534have vn := RealSequence.value with sequenceV535have u0 := RealSequence.value with sequenceU536have v0 := RealSequence.value with sequenceV537have identity := realPartialSum.product_telescoping with sequenceU, sequenceV538calc539 ∑ i < n, forwardProductIncrements(u, v)(i) =540 ((∑ i < n, forwardProductIncrements(u, v)(i):R) +541 (∑ i < n, backwardProductIncrements(u, v)(i):R)) -542 (∑ i < n, backwardProductIncrements(u, v)(i):R) :=byring543 _ = ((u[n]:R) * (v[n]:R) - (u[0]:R) * (v[0]:R)) -544 (∑ i < n, backwardProductIncrements(u, v)(i):R) :=bycc545546-- Prefix sums themselves form a sequence; their adjacent difference is the547-- original sequence. This is the discrete fundamental theorem of calculus.548defgraph prefixSums (u : Set) (n ∈ ℕ) : ℝ := ∑ i < n, u(i)549requires sequence : RealSequence(u)550proof551have typedN := nat.omega.backward with member552exact realPartialSum.real with sequence553554theorem prefixSums.sequence (u : Set)555requires sequence : RealSequence(u)556shows RealSequence(prefixSums(u))557proof558unfold RealSequence559exact prefixSums.function with sequence560561theorem prefixSums.zero (u : Set)562requires sequence : RealSequence(u)563shows prefixSums(u)[0] = (0:R)564proof565have value := prefixSums.value at u, 0with sequence566 rwa realPartialSum.zero at value567568theorem prefixSums.difference (u : Set, n : Nat)569requires sequence : RealSequence(u)570shows adjacentDifferences(prefixSums(u))[n] = u[n]571proof572have prefixes := prefixSums.sequence with sequence573have delta := adjacentDifferences.value with prefixes574have next := prefixSums.value at u, succ(n) with sequence575have current := prefixSums.value with sequence576have term := RealSequence.value with sequence577rw [delta, next, current, realPartialSum.succ]578ring579580-- Abel's finite summation formula: move the difference from prefix sums to v.581theorem realPartialSum.abel (u v : Set, n : Nat)582requires sequenceU : RealSequence(u)583requires sequenceV : RealSequence(v)584shows ∑ i < n, mulSequence(u, v)(i) =585 (∑ i < n, u(i):R) * (v[n]:R) -586 (∑ k < n, forwardProductIncrements(prefixSums(u), v)(k):R)587proof588have prefixes := prefixSums.sequence with sequenceU589have products := mulSequence.sequence with sequenceU, sequenceV590have backward := backwardProductIncrements.sequence with prefixes, sequenceV591have forward := forwardProductIncrements.sequence with prefixes, sequenceV592have equal : ∀ k ∈ ℕ, k < n →593 backwardProductIncrements(prefixSums(u), v)[k] = mulSequence(u, v)[k]594intros k naturalK before595have typedK := nat.omega.backward with naturalK596have uk := RealSequence.value at u, k with sequenceU597have vk := RealSequence.value at v, k with sequenceV598have backwardValue := backwardProductIncrements.value at prefixSums(u), v, k with599 prefixes, sequenceV600have productValue := mulSequence.value with sequenceU, sequenceV, uk, vk601have delta := adjacentDifferences.value at prefixSums(u), k with prefixes602have difference := prefixSums.difference at u, k with sequenceU603rw delta at difference604rw [backwardValue, difference, productValue]605have commute := realMulValue.commutative with vk, uk606unfold realMulValue607unfold call2608unfold call2 at commute609exact commute610have sameSum := realPartialSum.eq_prefix with backward, products, equal611have telescope := realPartialSum.product_telescoping with prefixes, sequenceV612have prefixN := prefixSums.value with sequenceU613have prefixZero := prefixSums.zero with sequenceU614rw [prefixN, prefixZero] at telescope615have vn := RealSequence.value with sequenceV616have v0 := RealSequence.value with sequenceV617calc618 ∑ i < n, mulSequence(u, v)(i) =619 ∑ k < n, backwardProductIncrements(prefixSums(u), v)(k) :=bycc620 _ = ((∑ k < n, forwardProductIncrements(prefixSums(u), v)(k):R) +621 (∑ k < n, backwardProductIncrements(prefixSums(u), v)(k):R)) -622 (∑ k < n, forwardProductIncrements(prefixSums(u), v)(k):R) :=byring623 _ = ((∑ i < n, u(i):R) * (v[n]:R) - (0:R) * (v[0]:R)) -624 (∑ k < n, forwardProductIncrements(prefixSums(u), v)(k):R) :=bycc625 _ = (∑ i < n, u(i):R) * (v[n]:R) -626 (∑ k < n, forwardProductIncrements(prefixSums(u), v)(k):R) :=byring627