1-- Real analysis: Sequences2-- 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.Analysis.Sequences8import Metric910-- Section: Sequences11predicate RealSequence (u : Set) := FunctionBetween(u, ℕ, ℝ)1213-- The epsilon definition: eventually every term lies in the open14-- ball of radius E around L.15predicate ConvergesTo (u : Set) (L : Real) :=16 RealSequence(u) ∧17 (∀ E ∈ ℝ, 0 < E →18∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n →19 uₙ ∈ openBall(L, E))2021predicate EventuallyEqual (u v : Set) :=22∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n → uₙ = vₙ2324def negSequence (u : Set) : Set:=25 compose(realNeg, u, ℕ, ℝ, ℝ)2627def addSequence (u v : Set) : Set:=28 compose(realAdd, pairFunctions(u, v, ℕ, ℝ, ℝ), ℕ, ℝ × ℝ, ℝ)2930def subSequence (u v : Set) : Set:=31 addSequence(u, negSequence(v))3233def mulSequence (u v : Set) : Set:=34 compose(realMul, pairFunctions(u, v, ℕ, ℝ, ℝ), ℕ, ℝ × ℝ, ℝ)3536def invSequence (u : Set) : Set:=37 compose(realInv, u, ℕ, ℝ, ℝ)3839def divSequence (u v : Set) : Set:=40 compose(realDiv, pairFunctions(u, v, ℕ, ℝ, ℝ), ℕ, ℝ × ℝ, ℝ)4142-- A positive scale strictly larger than |A|.43def limitScale (A : Real) : Real:= abs(A) +14445-- The radius E/(2C), named so epsilon proofs need not expose the concrete46-- implementation of division by a positive real.47def scaledRadius (E C : Real) : Real:= half(E) / C4849-- A uniform bound for the reciprocal factors near a nonzero limit L.50def inverseScale (L : Real) : Real:=51 realInvValue(half(abs(L))) * abs(realInvValue(L))5253theorem limitScale.real (A : Real)54showsReal(limitScale(A))55proof56unfold limitScale57exact realAddValue.real at abs(A), realOne with58 abs.real at A withassumption, realOne.real5960theorem limitScale.positive (A : Real)61shows0 < limitScale(A)62proof63have absReal := abs.real at A64have oneStep := realLess.add_left with realZero.real, realOne.real, absReal, realZero.lt_one65have scaleReal := realAddValue.real with absReal, realOne.real66have zero := realAddValue.zero_right with absReal67rw zero at oneStep68unfold limitScale69exact realLe.transitive_less at realZero, abs(A), abs(A) +1with70 realZero.real, absReal, scaleReal,71 abs.nonnegative at A withassumption, oneStep7273theorem abs.lt_limitScale (A : Real)74shows abs(A) < limitScale(A)75proof76have absReal := abs.real at A77have step := realLess.add_left with realZero.real, realOne.real, absReal, realZero.lt_one78have zero := realAddValue.zero_right with absReal79rw zero at step80unfold limitScale81exact step8283theorem scaledRadius.real (E C : Real)84showsReal(scaledRadius(E, C))85proof86unfold scaledRadius87typecheck8889theorem scaledRadius.positive (E C : Real)90requires positiveE : 0 < E91requires positiveC : 0 < C92shows0 < scaledRadius(E, C)93proof94have inversePositive := IsOrderedField.positive_inverse with reals.ordered_field, positiveC95have halfPositive := half.positive with positiveE96have inverseReal := realInvValue.real at C97unfold scaledRadius98rw realDiv.eq_mul_inv99unfold realInvValue100unfold realInvValue at inverseReal101exact realMulValue.positive at half(E), realInv(C) with102 half.real at E withassumption,103 inverseReal,104 halfPositive, inversePositive105106theorem scaledRadius.cancel (E C : Real)107requires positiveC : 0 < C108shows C * scaledRadius(E, C) = half(E)109proof110have halfReal := half.real at E111have inverseReal := realInvValue.real at C112have nonzero : C ≠0113intro equal114rw equal at positiveC115exact IsOrderedField.irreflexive with reals.ordered_field, positiveC116have inverse := realInvValue.mul_right with nonzero117have inverseLaw : C * realInvValue(C) =1byexact inverse118have commute := realMulValue.commutative at C, half(E) with119assumption, halfReal120have firstAssoc := realMulValue.associative at121 C, half(E), realInvValue(C) withassumption, halfReal, inverseReal122have secondAssoc := realMulValue.associative at123 half(E), C, realInvValue(C) with halfReal, assumption, inverseReal124have one := realMulValue.one_right with halfReal125unfold scaledRadius126rw realDiv.eq_mul_inv127calc128 C * (half(E) * realInvValue(C)) =129 (C * half(E)) * realInvValue(C) :=bycc130 _ = (half(E) * C) * realInvValue(C) :=bycc131 _ = half(E) * (C * realInvValue(C)) := secondAssoc132 _ = half(E) *1:=bycc133 _ = half(E) := one134135theorem inverseScale.real (L : Real)136showsReal(inverseScale(L))137proof138unfold inverseScale139exact realMulValue.real at140 realInvValue(half(abs(L))), abs(realInvValue(L)) with141 realInvValue.real at half(abs(L)) with142 half.real at abs(L) with abs.real at L withassumption,143 abs.real at realInvValue(L) with realInvValue.real at L withassumption144145theorem inverseScale.positive (L : Real)146requires nonzero : L ≠0147shows0 < inverseScale(L)148proof149have absLReal := abs.real at L150have absLPositive := abs.positive_of_ne with nonzero151have halfReal := half.real with absLReal152have halfPositive := half.positive with absLPositive153have inverseHalfPositive := realInvValue.positive with halfPositive154have inverseLReal := realInvValue.real at L155have inverseLNonzero := realInvValue.nonzero with nonzero156have absInversePositive := abs.positive_of_ne with inverseLNonzero157unfold inverseScale158exact realMulValue.positive at159 realInvValue(half(abs(L))), abs(realInvValue(L)) with160 realInvValue.real at half(abs(L)) with halfReal,161 abs.real at realInvValue(L) with inverseLReal,162 inverseHalfPositive, absInversePositive163164theorem ConvergesTo.sequence (u : Set) (L : Real)165requires converges : ConvergesTo(u, L)166shows RealSequence(u)167proof168simp [ConvergesTo]169170theorem ConvergesTo.eventually (u : Set) (L E : Real)171requires converges : ConvergesTo(u, L)172requires positive : 0 < E173shows∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n →174 uₙ ∈ openBall(L, E)175proof176rcases converges with⟨sequence, eventually⟩177exact eventually with E, positive178179-- Two eventual properties hold together on a common tail. This packages the180-- elementary maximum-index argument for one or two sequences.181theorem ConvergesTo.common_eventually (u v : Set) (L M E D : Real)182requires convergesL : ConvergesTo(u, L)183requires convergesM : ConvergesTo(v, M)184requires positiveE : 0 < E185requires positiveD : 0 < D186shows∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n →187 (uₙ ∈ openBall(L, E) ∧ vₙ ∈ openBall(M, D))188proof189obtain⟨N, nNatural, closeL⟩:= ConvergesTo.eventually with convergesL, positiveE190obtain⟨M0, mNatural, closeM⟩:= ConvergesTo.eventually with convergesM, positiveD191have typedN : Nat(N) byexact nat.omega.backward at N with nNatural192have typedM : Nat(M0) byexact nat.omega.backward at M0 with mNatural193have comparison := Less.trichotomy with typedN, typedM194cases comparison with nLessM | rest195 . have nLeM := Less.implies_LessEqual at N, M0 with196 typedN, typedM, nLessM197witness M0198constructor199 . exact mNatural200 . intros n nInNaturals mLeN201have nLeLittleN := LessEqual.transitive with nLeM, mLeN202constructor203 . exact closeL with n, nInNaturals, nLeLittleN204 . exact closeM with n, nInNaturals, mLeN205 . cases rest with equal | mLessN206 . witness N207constructor208 . exact nNatural209 . intros n nInNaturals nLeLittleN210have mLeLittleN : M0 ≤ n by rwa ← equal211constructor212 . exact closeL with n, nInNaturals, nLeLittleN213 . exact closeM with n, nInNaturals, mLeLittleN214 . have mLeN := Less.implies_LessEqual at M0, N with215 typedM, typedN, mLessN216witness N217constructor218 . exact nNatural219 . intros n nInNaturals nLeLittleN220have mLeLittleN := LessEqual.transitive with mLeN, nLeLittleN221constructor222 . exact closeL with n, nInNaturals, nLeLittleN223 . exact closeM with n, nInNaturals, mLeLittleN224225theorem RealSequence.value (u : Set, n : Nat)226requires sequence : RealSequence(u)227showsReal(uₙ)228proof229unfold RealSequence at sequence230have nInNaturals : n ∈ ℕ bysimp [Nat]231obtain⟨A, realA, mapped⟩:= FunctionBetween.exists_value with sequence, nInNaturals232have applied := FunctionBetween.apply_value with sequence, mapped233rw applied234exact realA235236instance RealSequence.value_type (u : Set, n : Nat)237requires sequence : RealSequence(u)238showsReal(uₙ)239proof240exact RealSequence.value with sequence241242theorem negSequence.sequence (u : Set)243requires sequence : RealSequence(u)244shows RealSequence(negSequence(u))245proof246unfold RealSequence at sequence247unfold RealSequence248unfold negSequence249exact compose.function with sequence, realNeg.function250251theorem negSequence.value (u : Set, n : Nat)252requires sequence : RealSequence(u)253requires valueReal : Real(uₙ)254shows negSequence(u)[n] = -uₙ255proof256have nNatural : n ∈ ℕ bysimp [Nat]257have function : u : ℕ → ℝ byexact sequence258have value := compose.apply with function, realNeg.function, nNatural259simp [negSequence]260261theorem addSequence.sequence (u v : Set)262requires sequenceU : RealSequence(u)263requires sequenceV : RealSequence(v)264shows RealSequence(addSequence(u, v))265proof266have functionU : u : ℕ → ℝ byexact sequenceU267have functionV : v : ℕ → ℝ byexact sequenceV268have paired := pairFunctions.function with functionU, functionV269unfold RealSequence270unfold addSequence271exact compose.function with paired, realAdd.function272273theorem addSequence.value (u v : Set, n : Nat)274requires sequenceU : RealSequence(u)275requires sequenceV : RealSequence(v)276requires valueUReal : Real(uₙ)277requires valueVReal : Real(vₙ)278shows addSequence(u, v)[n] = uₙ + vₙ279proof280have nNatural : n ∈ ℕ bysimp [Nat]281have functionU : u : ℕ → ℝ byexact sequenceU282have functionV : v : ℕ → ℝ byexact sequenceV283have paired := pairFunctions.function with functionU, functionV284have outer := compose.apply with paired, realAdd.function, nNatural285have pairValue := pairFunctions.apply with functionU, functionV, nNatural286unfold addSequence287rw pairValue at outer288simp [call2]289290theorem mulSequence.sequence (u v : Set)291requires sequenceU : RealSequence(u)292requires sequenceV : RealSequence(v)293shows RealSequence(mulSequence(u, v))294proof295have functionU : u : ℕ → ℝ byexact sequenceU296have functionV : v : ℕ → ℝ byexact sequenceV297have paired := pairFunctions.function with functionU, functionV298unfold RealSequence299unfold mulSequence300exact compose.function with paired, realMul.function301302theorem mulSequence.value (u v : Set, n : Nat)303requires sequenceU : RealSequence(u)304requires sequenceV : RealSequence(v)305requires valueUReal : Real(uₙ)306requires valueVReal : Real(vₙ)307shows mulSequence(u, v)[n] = uₙ * vₙ308proof309have nNatural : n ∈ ℕ bysimp [Nat]310have functionU : u : ℕ → ℝ byexact sequenceU311have functionV : v : ℕ → ℝ byexact sequenceV312have paired := pairFunctions.function with functionU, functionV313have outer := compose.apply with paired, realMul.function, nNatural314have pairValue := pairFunctions.apply with functionU, functionV, nNatural315unfold mulSequence316rw pairValue at outer317simp [call2]318319theorem invSequence.sequence (u : Set)320requires sequence : RealSequence(u)321shows RealSequence(invSequence(u))322proof323unfold RealSequence at sequence324unfold RealSequence325unfold invSequence326exact compose.function with sequence, realInv.function327328theorem invSequence.value (u : Set, n : Nat)329requires sequence : RealSequence(u)330shows invSequence(u)[n] = realInvValue(uₙ)331proof332have nNatural : n ∈ ℕ bysimp [Nat]333have function : u : ℕ → ℝ byexact sequence334have value := compose.apply with function, realInv.function, nNatural335simp [invSequence, realInvValue]336337theorem divSequence.sequence (u v : Set)338requires sequenceU : RealSequence(u)339requires sequenceV : RealSequence(v)340shows RealSequence(divSequence(u, v))341proof342have functionU : u : ℕ → ℝ byexact sequenceU343have functionV : v : ℕ → ℝ byexact sequenceV344have paired := pairFunctions.function with functionU, functionV345unfold RealSequence346unfold divSequence347exact compose.function with paired, realDiv.function348349theorem divSequence.value (u v : Set, n : Nat)350requires sequenceU : RealSequence(u)351requires sequenceV : RealSequence(v)352shows divSequence(u, v)[n] = uₙ / vₙ353proof354have nNatural : n ∈ ℕ bysimp [Nat]355have functionU : u : ℕ → ℝ byexact sequenceU356have functionV : v : ℕ → ℝ byexact sequenceV357have paired := pairFunctions.function with functionU, functionV358have outer := compose.apply with paired, realDiv.function, nNatural359have pairValue := pairFunctions.apply with functionU, functionV, nNatural360unfold divSequence361rw pairValue at outer362simp [call2]363364theorem subSequence.sequence (u v : Set)365requires sequenceU : RealSequence(u)366requires sequenceV : RealSequence(v)367shows RealSequence(subSequence(u, v))368proof369have negSequenceV := negSequence.sequence with sequenceV370unfold subSequence371exact addSequence.sequence with sequenceU, negSequenceV372373theorem subSequence.value (u v : Set, n : Nat)374requires sequenceU : RealSequence(u)375requires sequenceV : RealSequence(v)376requires valueUReal : Real(uₙ)377requires valueVReal : Real(vₙ)378shows subSequence(u, v)[n] = uₙ - vₙ379proof380have negSequenceV := negSequence.sequence with sequenceV381have negValueReal := RealSequence.value with negSequenceV382have sumValue := addSequence.value with sequenceU, negSequenceV, valueUReal, negValueReal383have negValue := negSequence.value with sequenceV, valueVReal384unfold subSequence385unfold realSubValue386rw negValue at sumValue387exact sumValue388389theorem ConvergesTo.neg (u : Set) (L : Real)390requires converges : ConvergesTo(u, L)391shows ConvergesTo(negSequence(u), -L)392proof393have sequence := ConvergesTo.sequence with converges394have negLimitReal := realNegValue.real at L395constructor396 . exact negSequence.sequence with sequence397 . intros E realE positive398have typedE : Real(E) byexact realE399obtain⟨N, nNatural, close⟩:= ConvergesTo.eventually with converges, positive400witness N401constructor402 . exact nNatural403 . intros n nInNaturals nAfterN404have typedN : Nat(n) byexact nat.omega.backward at n with nInNaturals405have valueInReals := RealSequence.value with sequence406have typedValue : Real(u(n)) byexact valueInReals407have near := close with n, nInNaturals, nAfterN408have nearData := openBall.membership.forward at409 L, E, u(n) with near410rcases nearData with⟨realValue, within⟩411have valueShape := negSequence.value with sequence412have negValueReal := realNegValue.real with typedValue413have negDistance := dist.neg at u(n), L with414 typedValue, assumption415apply openBall.membership.backward416constructor417 . rw valueShape418exact negValueReal419 . rw valueShape420 rwa negDistance421422theorem ConvergesTo.add (u v : Set) (L M : Real)423requires convergesU : ConvergesTo(u, L)424requires convergesV : ConvergesTo(v, M)425shows ConvergesTo(addSequence(u, v), L + M)426proof427have sequenceU := ConvergesTo.sequence with convergesU428have sequenceV := ConvergesTo.sequence with convergesV429have sumLimitReal := realAddValue.real at L, M with*430constructor431 . exact addSequence.sequence with sequenceU, sequenceV432 . intros E realE positive433have typedE : Real(E) byexact realE434have radiusReal := half.real with typedE435have radiusPositive := half.positive with positive436obtain⟨N, nNatural, closeBoth⟩:= ConvergesTo.common_eventually with437 convergesU, convergesV, radiusPositive, radiusPositive438witness N439constructor440 . exact nNatural441 . intros n nInNaturals nAfterN442have typedN : Nat(n) byexact nat.omega.backward at n with nInNaturals443obtain⟨nearU, nearV⟩:= closeBoth with n, nInNaturals, nAfterN444have uInReals := RealSequence.value with sequenceU445have vInReals := RealSequence.value with sequenceV446have typedU : Real(u(n)) byexact uInReals447have typedV : Real(v(n)) byexact vInReals448have uData := openBall.membership.forward at449 L, half(E), u(n) with nearU450have vData := openBall.membership.forward at451 M, half(E), v(n) with nearV452rcases uData with⟨realU, closeU⟩453rcases vData with⟨realV, closeV⟩454have sumValueReal := realAddValue.real with typedU, typedV455have firstDistanceReal := dist.real at u(n), L with456 typedU, assumption457have secondDistanceReal := dist.real at v(n), M with458 typedV, assumption459have distanceSumReal := realAddValue.real with firstDistanceReal, secondDistanceReal460have totalDistanceReal := dist.real with sumValueReal, sumLimitReal461have distanceBound := dist.add_add at462 u(n), v(n), L, M with463 typedU, typedV, *{2}464have radiusSumBound := realLess.add with465 firstDistanceReal, radiusReal, secondDistanceReal, radiusReal, closeU, closeV466have doubled := half.add_self with typedE467rw doubled at radiusSumBound468have within := realLe.transitive_less with469 totalDistanceReal, distanceSumReal, typedE, distanceBound, radiusSumBound470have valueShape := addSequence.value with sequenceU, sequenceV471apply openBall.membership.backward472constructor473 . rw valueShape474unfold call2475unfold call2 at sumValueReal476exact sumValueReal477 . rw valueShape478unfold call2479unfold call2 at within480exact within481482-- Products of convergent real sequences converge to the product of their483-- limits. The estimate is the one used in a handwritten proof:484--485-- |uₙvₙ - LM| ≤ |uₙ| |vₙ - M| + |M| |uₙ - L|.486--487-- First make uₙ locally bounded, then assign half of epsilon to each term.488theorem ConvergesTo.mul (u v : Set) (L M : Real)489requires convergesU : ConvergesTo(u, L)490requires convergesV : ConvergesTo(v, M)491shows ConvergesTo(mulSequence(u, v), L * M)492proof493have sequenceU := ConvergesTo.sequence with convergesU494have sequenceV := ConvergesTo.sequence with convergesV495have productLimitReal := realMulValue.real at L, M with496*{2}497constructor498 . exact mulSequence.sequence with sequenceU, sequenceV499 . intros E realE positiveE500have typedE : Real(E) byexact realE501have scaleMReal := limitScale.real at M502have scaleMPositive := limitScale.positive at M503have radiusUReal := scaledRadius.real with typedE, scaleMReal504have radiusUPositive := scaledRadius.positive with positiveE, scaleMPositive505have absLReal := abs.real at L506have boundReal := realAddValue.real with radiusUReal, absLReal507have radiusAboveAbsL := realLess.add_right with realZero.real, radiusUReal, absLReal, radiusUPositive508have zeroPlusAbsL := realAddValue.zero_left with absLReal509rw zeroPlusAbsL at radiusAboveAbsL510have boundPositive := realLe.transitive_less at511 realZero, abs(L), scaledRadius(E, limitScale(M)) + abs(L) with512 realZero.real, absLReal, boundReal,513 abs.nonnegative at L withassumption, radiusAboveAbsL514have radiusVReal := scaledRadius.real with typedE, boundReal515have radiusVPositive := scaledRadius.positive with positiveE, boundPositive516obtain⟨N, nNatural, closeBoth⟩:= ConvergesTo.common_eventually with517 convergesU, convergesV, radiusUPositive, radiusVPositive518witness N519constructor520 . exact nNatural521 . intros n nInNaturals nAfterN522have typedN : Nat(n) byexact nat.omega.backward at n with nInNaturals523obtain⟨nearU, nearV⟩:= closeBoth with n, nInNaturals, nAfterN524have typedU := RealSequence.value with sequenceU525have typedV := RealSequence.value with sequenceV526have uData := openBall.membership.forward at527 L, scaledRadius(E, limitScale(M)), uₙ with nearU528have vData := openBall.membership.forward at529 M, scaledRadius(E, scaledRadius(E, limitScale(M)) + abs(L)), vₙ530with nearV531rcases uData with⟨realU, closeU⟩532rcases vData with⟨realV, closeV⟩533534-- Closeness to L supplies the local bound |uₙ| < radiusU + |L|.535have absUReal := abs.real with typedU536have distUReal := dist.real at uₙ, L with typedU537have distVReal := dist.real at vₙ, M with typedV538have absUBound := abs.le_dist_add_abs at uₙ, L with539 typedU, assumption540have closeUWithAbsL := realLess.add_right with distUReal, radiusUReal, absLReal, closeU541have distPlusAbsReal := realAddValue.real with distUReal, absLReal542have uBounded := realLe.transitive_less with543 absUReal, distPlusAbsReal, boundReal, absUBound, closeUWithAbsL544545-- Each summand in the product estimate is strictly below E/2.546have uBoundedLe := realLess.implies_le with absUReal, boundReal, uBounded547have distVNonnegative := dist.nonnegative at vₙ, M with548 typedV, assumption549have firstWeak := realLe.mul_right_of_nonnegative with550 absUReal, boundReal, distVReal, uBoundedLe, distVNonnegative551have firstStrict := realLess.mul_left_of_positive with552 distVReal, radiusVReal, boundReal, closeV, boundPositive553have firstTermReal := realMulValue.real with absUReal, distVReal554have firstMiddleReal := realMulValue.real with boundReal, distVReal555have firstUpperReal := realMulValue.real with boundReal, radiusVReal556have firstBelowProduct := realLe.transitive_less with557 firstTermReal, firstMiddleReal, firstUpperReal, firstWeak, firstStrict558have firstCancellation := scaledRadius.cancel with typedE, boundReal, boundPositive559rw firstCancellation at firstBelowProduct560561have absMReal := abs.real at M562have absMLess := abs.lt_limitScale at M563have absMLe := realLess.implies_le with absMReal, scaleMReal, absMLess564have distUNonnegative := dist.nonnegative at uₙ, L with565 typedU, assumption566have secondWeak := realLe.mul_right_of_nonnegative with567 absMReal, scaleMReal, distUReal, absMLe, distUNonnegative568have secondStrict := realLess.mul_left_of_positive with569 distUReal, radiusUReal, scaleMReal, closeU, scaleMPositive570have secondTermReal := realMulValue.real with absMReal, distUReal571have secondMiddleReal := realMulValue.real with scaleMReal, distUReal572have secondUpperReal := realMulValue.real with scaleMReal, radiusUReal573have secondBelowProduct := realLe.transitive_less with574 secondTermReal, secondMiddleReal, secondUpperReal, secondWeak, secondStrict575have secondCancellation := scaledRadius.cancel with typedE, scaleMReal, scaleMPositive576rw secondCancellation at secondBelowProduct577578have estimate := dist.mul_mul at uₙ, vₙ, L, M with579 typedU, typedV, *{2}580have halfReal := half.real with typedE581have sumBelow := realLess.add with582 firstTermReal, halfReal, secondTermReal, halfReal, firstBelowProduct, secondBelowProduct583have doubled := half.add_self with typedE584rw doubled at sumBelow585have productValueReal := realMulValue.real with typedU, typedV586have totalDistanceReal := dist.real with productValueReal, productLimitReal587have estimateSumReal := realAddValue.real with firstTermReal, secondTermReal588have within := realLe.transitive_less with589 totalDistanceReal, estimateSumReal, typedE, estimate, sumBelow590have valueShape := mulSequence.value with sequenceU, sequenceV, typedU, typedV591apply openBall.membership.backward592constructor593 . rw valueShape594exact productValueReal595 . rw valueShape596exact within597598-- A convergent sequence may be inverted when its limit is nonzero. The599-- proof is the textbook one: first keep the sequence at least |L|/2 away600-- from zero, then use601--602-- |uₙ⁻¹ - L⁻¹| = |uₙ - L| |uₙ⁻¹| |L⁻¹|.603theorem ConvergesTo.inv (u : Set) (L : Real)604requires converges : ConvergesTo(u, L)605requires nonzero : L ≠0606shows ConvergesTo(invSequence(u), realInvValue(L))607proof608have sequence := ConvergesTo.sequence with converges609have inverseLimitReal := realInvValue.real at L610constructor611 . exact invSequence.sequence with sequence612 . intros E realE positiveE613have typedE : Real(E) byexact realE614have absLReal := abs.real at L615have absLPositive := abs.positive_of_ne with nonzero616have halfAbsLReal := half.real with absLReal617have halfAbsLPositive := half.positive with absLPositive618have scaleReal := inverseScale.real at L619have scalePositive := inverseScale.positive with nonzero620have radiusReal := scaledRadius.real with typedE, scaleReal621have radiusPositive := scaledRadius.positive with positiveE, scalePositive622obtain⟨N, nNatural, closeBoth⟩:= ConvergesTo.common_eventually with623 converges, converges, halfAbsLPositive, radiusPositive624witness N625constructor626 . exact nNatural627 . intros n nInNaturals nAfterN628have typedN : Nat(n) byexact nat.omega.backward at n with nInNaturals629obtain⟨nearZero, nearE⟩:= closeBoth with n, nInNaturals, nAfterN630have typedU := RealSequence.value with sequence631have zeroData := openBall.membership.forward at632 L, half(abs(L)), uₙ with nearZero633have epsilonData := openBall.membership.forward at634 L, scaledRadius(E, inverseScale(L)), uₙ with nearE635rcases zeroData with⟨realU, closeZero⟩636rcases epsilonData with⟨realUAgain, closeE⟩637638have lower := abs.half_lt_of_dist_lt_half with typedU, nonzero, closeZero639have nonzeroU : uₙ ≠0640intro equal641have absoluteZero := abs.zero642rw [equal, absoluteZero] at lower643have irreflexive := realLess.irreflexive_on644have cycle := realLess.transitive with645 realZero.real, halfAbsLReal, realZero.real, halfAbsLPositive, lower646exact irreflexive with realZero, cycle647648-- Reciprocation reverses the lower bound |L|/2 < |uₙ|.649have inverseBound := realInvValue.antitone_positive with halfAbsLReal, halfAbsLPositive, lower650have absInverseU := abs.inv with typedU, nonzeroU651rw← absInverseU at inverseBound652653have inverseLReal := realInvValue.real at L654have inverseLNonzero := realInvValue.nonzero with nonzero655have absInverseLReal := abs.real with inverseLReal656have absInverseLPositive := abs.positive_of_ne with inverseLNonzero657have factorBound := realLess.mul_right_of_positive at658 abs(realInvValue(uₙ)), realInvValue(half(abs(L))),659 abs(realInvValue(L)) with660 abs.real at realInvValue(uₙ) with661 realInvValue.real at uₙ with typedU,662 realInvValue.real at half(abs(L)) with halfAbsLReal,663 absInverseLReal, inverseBound, absInverseLPositive664have factorBoundScale : abs(realInvValue(uₙ)) *665 abs(realInvValue(L)) < inverseScale(L)666unfold inverseScale667exact factorBound668669-- Multiply the two strict estimates, using nonnegativity of distance670-- for the weak first step.671have distanceReal := dist.real at uₙ, L with typedU672have factorReal := realMulValue.real at673 abs(realInvValue(uₙ)), abs(realInvValue(L)) with674 abs.real at realInvValue(uₙ) with675 realInvValue.real at uₙ with typedU,676 absInverseLReal677have distanceNonnegative := dist.nonnegative at uₙ, L with678 typedU, assumption679have factorLe := realLess.implies_le with factorReal, scaleReal, factorBoundScale680have weakProduct := realLe.mul_left_of_nonnegative with681 factorReal, scaleReal, distanceReal, factorLe, distanceNonnegative682have strictProduct := realLess.mul_right_of_positive with683 distanceReal, radiusReal, scaleReal, closeE, scalePositive684have lowerProductReal := realMulValue.real with distanceReal, factorReal685have middleProductReal := realMulValue.real with distanceReal, scaleReal686have upperProductReal := realMulValue.real with radiusReal, scaleReal687have productBelow := realLe.transitive_less with688 lowerProductReal, middleProductReal, upperProductReal, weakProduct, strictProduct689have cancellation := scaledRadius.cancel with typedE, scaleReal, scalePositive690have commute := realMulValue.commutative with radiusReal, scaleReal691rw [commute, cancellation] at productBelow692have halfBelowE := half.lt_self with typedE, positiveE693have halfReal := half.real with typedE694have productBelowE := realLess.transitive with695 lowerProductReal, halfReal, typedE, productBelow, halfBelowE696have inverseDistance := dist.inv_inv with typedU, nonzeroU, nonzero697rw← inverseDistance at productBelowE698699have valueShape := invSequence.value with sequence700apply openBall.membership.backward701constructor702 . rw valueShape703exact realInvValue.real with typedU704 . rw valueShape705exact productBelowE706707theorem ConvergesTo.sub (u v : Set) (L M : Real)708requires convergesU : ConvergesTo(u, L)709requires convergesV : ConvergesTo(v, M)710shows ConvergesTo(subSequence(u, v), L - M)711proof712have negConverges := ConvergesTo.neg with convergesV713have sumConverges := ConvergesTo.add with convergesU, negConverges714unfold subSequence715unfold realSubValue716exact sumConverges717718-- A real sequence has at most one limit. The proof uses the ball of radius719-- half the distance between two proposed limits.720theorem ConvergesTo.unique (u : Set) (L M : Real)721requires convergesL : ConvergesTo(u, L)722requires convergesM : ConvergesTo(u, M)723shows L = M724proof725by_contra unequal726have distancePositive := dist.positive_of_ne with unequal727have radiusPositive := half.positive with distancePositive728obtain⟨n, nNatural, closeBoth⟩:= ConvergesTo.common_eventually with729 convergesL, convergesM, radiusPositive, radiusPositive730have typedN : Nat(n) byexact nat.omega.backward at n with nNatural731have nLeN := LessEqual.reflexive with typedN732obtain⟨nearL, nearM⟩:= closeBoth with n, nNatural, nLeN733have sequence := ConvergesTo.sequence with convergesL734have valueInReals := RealSequence.value with sequence735have equal := openBall.half_radius_unique with nearL, nearM736exact unequal with equal737738def constantSequence (L : Real) : Set:=739 { p ∈ ℕ × ℝ |∃ n ∈ ℕ, p = (n ↦ L) }740741theorem constantSequence.relates (L : Real, n : Nat)742shows relates(constantSequence(L), n, L)743proof744have nInNaturals : n ∈ ℕ bysimp [Nat]745have lInReals : L ∈ ℝ bysimp [Real]746unfold relates747apply constantSequence.membership.backward748constructor749 . exact product.pair with nInNaturals, lInReals750 . refine⟨n, nInNaturals, rfl⟩751752theorem constantSequence.function (L : Real)753shows constantSequence(L) : ℕ → ℝ754proof755constructor756intros p member757obtain⟨bounded, witnesses⟩:= constantSequence.membership.forward with member758exact bounded759 . constructor760intros n A nA B nB761unfold relates at nA762obtain⟨_, i, iNatural, firstShape⟩:= constantSequence.membership.forward with nA763unfold relates at nB764obtain⟨_, j, jNatural, secondShape⟩:= constantSequence.membership.forward with nB765have firstCoordinates := orderedPair.injective with firstShape766have secondCoordinates := orderedPair.injective with secondShape767rcases firstCoordinates with⟨_, equalA⟩768rcases secondCoordinates with⟨_, equalB⟩769rw [equalA, equalB]770rfl771 . intros n nNatural772witness L773constructor774 . settlewithReal775 . have typedN : Nat(n)776exact nNatural777exact constantSequence.relates withassumption, typedN778779theorem constantSequence.sequence (L : Real)780shows RealSequence(constantSequence(L))781proof782unfold RealSequence783exact constantSequence.function withassumption784785theorem constantSequence.value (L : Real, n : Nat)786shows constantSequence(L)(n) = L787proof788have function := constantSequence.function at L789have mapped := constantSequence.relates with*790exact FunctionBetween.apply_value with function, mapped791792theorem constantSequence.converges (L : Real)793shows ConvergesTo(constantSequence(L), L)794proof795constructor796 . exact constantSequence.sequence at L797 . intros E realE positive798witness0799constructor800 . exact nat.omega.forward at0with Naturals.constructor.zero801 . intros n nNatural zeroLeN802have typedN : Nat(n) byexact nNatural803have value := constantSequence.value withassumption, typedN804rw value805exact openBall.center with positive806807-- Changing finitely many terms cannot change the limit of a sequence.808theorem ConvergesTo.eventually_equal (u v : Set) (L : Real)809requires converges : ConvergesTo(u, L)810requires sequenceV : RealSequence(v)811requires eventuallyEqual : EventuallyEqual(u, v)812shows ConvergesTo(v, L)813proof814rcases converges with⟨sequenceU, eventuallyClose⟩815obtain⟨M, mNatural, equalAfterM⟩:= eventuallyEqual816have typedM : Nat(M) byexact nat.omega.backward at M with mNatural817constructor818 . exact sequenceV819 . intros E realE positive820obtain⟨N, nNatural, closeAfterN⟩:=821 eventuallyClose with E, realE, positive822have typedN : Nat(N) byexact nat.omega.backward at N with nNatural823have comparison := Less.trichotomy with typedN, typedM824cases comparison with nLessM | rest825 . witness M826constructor827 . exact mNatural828 . intros n nInNaturals mLeN829have nLeM := Less.implies_LessEqual with nLessM830have nLeLittleN := LessEqual.transitive with nLeM, mLeN831have close := closeAfterN with n, nInNaturals, nLeLittleN832have equal := equalAfterM with n, nInNaturals, mLeN833 rwa equal at close834 . cases rest with equalNM | mLessN835 . witness N836constructor837 . exact nNatural838 . intros n nInNaturals nLeLittleN839have close := closeAfterN with n, nInNaturals, nLeLittleN840have mLeLittleN : M ≤ n by rwa ← equalNM841have equal := equalAfterM with n, nInNaturals, mLeLittleN842 rwa equal at close843844 . witness N845constructor846 . exact nNatural847 . intros n nInNaturals nLeLittleN848have mLeN := Less.implies_LessEqual with typedM, typedN, mLessN849have mLeLittleN := LessEqual.transitive with typedM, typedN, mLeN, nLeLittleN850have close := closeAfterN with n, nInNaturals, nLeLittleN851have equal := equalAfterM with n, nInNaturals, mLeLittleN852 rwa equal at close853854-- Quotients now follow from the product and reciprocal rules. The short855-- proof is precisely the payoff of treating `/` as the field operation.856theorem ConvergesTo.div (u v : Set) (L M : Real)857requires convergesU : ConvergesTo(u, L)858requires convergesV : ConvergesTo(v, M)859requires nonzeroM : M ≠0860shows ConvergesTo(divSequence(u, v), L / M)861proof862have sequenceU := ConvergesTo.sequence with convergesU863have sequenceV := ConvergesTo.sequence with convergesV864have inverseConverges := ConvergesTo.inv with convergesV, nonzeroM865have productConverges := ConvergesTo.mul with convergesU, inverseConverges866have limitShape := realDiv.eq_mul_inv at L, M with*867rw limitShape868apply ConvergesTo.eventually_equal with productConverges869 . exact divSequence.sequence with sequenceU, sequenceV870witness0871constructor872 . exact nat.omega.forward at0with Naturals.constructor.zero873 . intros n nNatural zeroLeN874have typedN : Nat(n) byexact nat.omega.backward at n with nNatural875have inverseSequence := invSequence.sequence with sequenceV876have inverseValueReal := RealSequence.value with inverseSequence877have valueUReal := RealSequence.value with sequenceU878have valueVReal := RealSequence.value with sequenceV879have mulValue := mulSequence.value with sequenceU, inverseSequence, valueUReal, inverseValueReal880have invValue := invSequence.value with sequenceV881have divValue := divSequence.value with sequenceU, sequenceV882have quotientValue := realDiv.eq_mul_inv with valueUReal, valueVReal883rw [mulValue, invValue, divValue, quotientValue]884rfl885886-- Section: OrderLimits887theorem openBall.order_characterization (X C E : Real)888shows X ∈ openBall(C, E) ↔ (C - E < X ∧ X < C + E)889proof890have differenceReal := realSubValue.real at X, C with*891have negDifferenceReal := realNegValue.real with differenceReal892have negDifference : -(X - C) = C - X893unfold realSubValue894have negCReal := realNegValue.real at C895have negXReal := realNegValue.real at X896have distributed := realNegValue.add at X, -C with897assumption, negCReal898have involutive := realNegValue.involutive at C899have commute := realAddValue.commutative at -X, C with900 negXReal, assumption901cc902constructor903 . intro member904obtain⟨_, within⟩:= openBall.membership.forward with member905unfold dist at within906have upperDifference := realLe.transitive_less at907 X - C, abs(X - C), E with908 differenceReal, abs.real at X - C with differenceReal, assumption,909 abs.upper at X - C with differenceReal, within910have lowerDifference := realLe.transitive_less at911 -(X - C), abs(X - C), E with912 negDifferenceReal, abs.real at X - C with differenceReal, assumption,913 abs.upper_neg at X - C with differenceReal, within914have upper := realLess.add_right at X - C, E, C with915 differenceReal, *{2}, upperDifference916have lower := realLess.add_right at -(X - C), E, X with917 negDifferenceReal, *{2}, lowerDifference918have upperLeft := realSubValue.add_right_cancel at X, C with919*{2}920have upperRight := realAddValue.commutative at E, C with921*{2}922rw [upperLeft, upperRight] at upper923rw negDifference at lower924have lowerLeft := realSubValue.add_right_cancel at C, X with925*{2}926rw lowerLeft at lower927have lowerRight := realAddValue.commutative at E, X with928*{2}929rw lowerRight at lower930have lowerShifted : (C - E) + E < X + E931have cancel := realSubValue.add_right_cancel at C, E with932*{2}933 rwa cancel934have cMinusEReal := realSubValue.real at C, E with*935have lowerFinal := realLess.add_right_iff.forward with lowerShifted936constructor937 . exact lowerFinal938 . exact upper939 . intro bounds940rcases bounds with⟨lower, upper⟩941have sumCEReal := realAddValue.real at C, E with*942have sumXEReal := realAddValue.real at X, E with*943have negCReal := realNegValue.real at C944have negXReal := realNegValue.real at X945have cMinusEReal := realSubValue.real at C, E with*946have upperDifference := realLess.add_right at X, C + E, -C with947assumption, sumCEReal, negCReal, upper948have lowerDifference := realLess.add_right at C - E, X, E with949 cMinusEReal, *{2}, lower950have cancelCE := realSubValue.add_right_cancel at C, E with951*{2}952rw cancelCE at lowerDifference953have lowerDifferenceAgain := realLess.add_right at954 C, X + E, -X with955assumption, sumXEReal, negXReal, lowerDifference956have commuteCE := realAddValue.commutative at C, E with957*{2}958rw commuteCE at upperDifference959have cancelEC := realSubValue.add_cancel_right at E, C with960*{2}961unfold realSubValue at cancelEC962rw cancelEC at upperDifference963have commuteXE := realAddValue.commutative at X, E with964*{2}965rw commuteXE at lowerDifferenceAgain966have cancelEX := realSubValue.add_cancel_right at E, X with967*{2}968unfold realSubValue at cancelEX969rw cancelEX at lowerDifferenceAgain970have sign :=Real.sign_cases with differenceReal971apply openBall.membership.backward972constructor973 . settlewithReal974 . unfold dist975cases sign with nonpositive | nonnegative976 . have nonpositiveLe := realLe.of_subset at X - C, realZero with977 differenceReal, realZero.real, nonpositive978have absolute := abs.of_nonpositive with nonpositiveLe979rw [absolute, negDifference]980unfold realSubValue981exact lowerDifferenceAgain982 . have nonnegativeLe := realLe.of_subset at realZero, X - C with983 realZero.real, differenceReal, nonnegative984have absolute := abs.of_nonnegative with nonnegativeLe985rw absolute986unfold realSubValue987exact upperDifference988989-- A sequence is eventually bounded when one positive real bounds the990-- absolute values of all terms in a tail.991predicate EventuallyBounded (u : Set) :=992 RealSequence(u) ∧993 (∃ B ∈ ℝ, 0 < B ∧994 (∃ N ∈ ℕ, (∀ n ∈ ℕ, N ≤ n →995 u(n) ∈ openBall(realZero, B))))996997predicate NonnegativeTerms (u : Set) :=998∀ n ∈ ℕ, RealLe(realZero, u(n))9991000predicate PointwiseLE (u v : Set) :=1001∀ n ∈ ℕ, RealLe(u(n), v(n))10021003predicate BoundedAboveBy (u : Set) (B : Real) :=1004∀ n ∈ ℕ, RealLe(u(n), B)10051006predicate BoundedBelowBy (u : Set) (A : Real) :=1007∀ n ∈ ℕ, RealLe(A, u(n))10081009predicate UnitIntervalTerms (u : Set) :=1010∀ n ∈ ℕ,1011 RealLe(realZero, u(n)) ∧ RealLe(u(n), realOne)10121013-- Every convergent sequence is bounded on a tail. The familiar estimate1014-- |uₙ| ≤ |uₙ - L| + |L| gives the explicit bound |L| + 1.1015-- A value within half of E of C on both sides lies in the open E-ball around C.1016theorem openBall.of_half_bounds (Q C E : Real)1017requires positive : 0 < E1018requires low : C - half(E) ≤ Q1019requires high : Q≤ C + half(E)1020shows Q ∈ openBall(C, E)1021proof1022have halfLess := half.lt_self with*1023have bounds : C - E < Q ∧ Q < C + E1024constructor1025 . linarith1026 . linarith1027exact openBall.order_characterization.backward with bounds10281029theorem ConvergesTo.eventually_bounded (u : Set) (L : Real)1030requires converges : ConvergesTo(u, L)1031shows EventuallyBounded(u)1032proof1033have boundReal := limitScale.real at L1034have boundPositive := limitScale.positive at L1035obtain⟨N, nNatural, close⟩:= ConvergesTo.eventually with converges, realZero.lt_one1036constructor1037 . exact ConvergesTo.sequence with converges1038 . witness limitScale(L)1039constructor1040exact boundReal1041 . constructor1042 . exact boundPositive1043 . witness N1044constructor1045 . exact nNatural1046 . intros n nInNaturals nAfterN1047have sequence := ConvergesTo.sequence with converges1048have typedN : Nat(n) byexact nat.omega.backward at n with nInNaturals1049have typedValue := RealSequence.value with sequence1050have near := close with n, nInNaturals, nAfterN1051have nearData := openBall.membership.forward at1052 L, realOne, uₙ with near1053rcases nearData with⟨_, distanceLessOne⟩1054have distanceReal := dist.real at uₙ, L with typedValue1055have absLReal := abs.real at L1056have sumReal := realAddValue.real with distanceReal, absLReal1057have absoluteBound := abs.le_dist_add_abs at uₙ, L with1058 typedValue, assumption1059have sumBelow := realLess.add_right with distanceReal, realOne.real, absLReal, distanceLessOne1060have absValueReal := abs.real with typedValue1061have onePlusAbsReal := realAddValue.real with realOne.real, absLReal1062have strictBound := realLe.transitive_less with1063 absValueReal, sumReal, onePlusAbsReal, absoluteBound, sumBelow1064have commute := realAddValue.commutative with realOne.real, absLReal1065unfold limitScale1066rw commute at strictBound1067apply openBall.membership.backward1068constructor1069exact typedValue1070 . unfold dist1071have zero := realSubValue.zero_right with typedValue1072 rwa zero10731074-- A nonnegative sequence cannot converge to a negative number. The proof1075-- chooses the ball of radius -L/2 around a hypothetical negative limit L;1076-- every point in that ball is still negative.1077theorem ConvergesTo.nonnegative_of_nonnegative_terms (u : Set) (L : Real)1078requires converges : ConvergesTo(u, L)1079requires nonnegative : NonnegativeTerms(u)1080shows0≤ L1081proof1082have sign :=Real.sign_cases at L1083cases sign with nonpositive | nonnegativeCut1084 . by_contra notNonnegative1085have unequalZero : L ≠01086intro equalZero1087apply notNonnegative1088rw equalZero1089exact realLe.reflexive with realZero.real1090have negative : L < 01091apply realLess.characterization.backward1092unfold RealLess1093refine⟨assumption, realZero.real, _⟩1094unfold ProperSubset1095refine⟨nonpositive, unequalZero⟩1096have negativeView := realLess.characterization.forward with negative1097have reversed := RealLess.neg_reverse at L, realZero with1098assumption, realZero.real, negativeView1099have positiveNeg : 0 < -L1100apply realLess.characterization.backward1101 rwa realNegValue.zero at reversed1102have negLReal := realNegValue.real at L1103have radiusReal := half.real with negLReal1104have radiusPositive := half.positive with positiveNeg1105obtain⟨N, nNatural, close⟩:= ConvergesTo.eventually with converges, radiusPositive1106have typedN : Nat(N) byexact nat.omega.backward at N with nNatural1107have nLeN := LessEqual.reflexive with typedN1108have near := close with N, nNatural, nLeN1109have sequence := ConvergesTo.sequence with converges1110have typedValue := RealSequence.value with sequence1111have nearData := openBall.membership.forward at1112 L, half(-L), u[N] with near1113rcases nearData with⟨_, distanceBelowHalf⟩1114have halfBelowNeg := half.lt_self with positiveNeg1115have distanceReal := dist.real at u[N], L with typedValue1116have distanceBelowNeg := realLess.transitive with1117 distanceReal, radiusReal, negLReal, distanceBelowHalf, halfBelowNeg1118have differenceReal := realSubValue.real at u[N], L with1119 typedValue, assumption1120have differenceAbsoluteReal := abs.real with differenceReal1121have differenceUpper := abs.upper with differenceReal1122unfold dist at distanceBelowNeg1123have differenceBelowNeg := realLe.transitive_less with1124 differenceReal, differenceAbsoluteReal, negLReal, differenceUpper, distanceBelowNeg1125have shifted := realLess.add_right at1126 u[N] - L, -L, L with1127 differenceReal, negLReal, assumption, differenceBelowNeg1128have cancel := realSubValue.add_right_cancel at u[N], L with1129 typedValue, assumption1130have inverse := realAddValue.neg_left at L1131rw [cancel, inverse] at shifted1132have termNonnegativeView := nonnegative with N, nNatural1133have termNonnegative := realLe.characterization.backward with termNonnegativeView1134have impossible := realLe.transitive_less with1135 realZero.real, typedValue, realZero.real, termNonnegative, shifted1136exact IsOrderedField.irreflexive with reals.ordered_field, impossible1137 . exact realLe.of_subset at realZero, L with1138 realZero.real, assumption, nonnegativeCut11391140-- Termwise order passes to limits. Apply the preceding theorem to the1141-- convergent difference vₙ - uₙ, then translate 0 ≤ M - L by L.1142theorem ConvergesTo.le_of_le_terms (u v : Set) (L M : Real)1143requires convergesU : ConvergesTo(u, L)1144requires convergesV : ConvergesTo(v, M)1145requiresordered : PointwiseLE(u, v)1146shows L ≤ M1147proof1148have sequenceU := ConvergesTo.sequence with convergesU1149have sequenceV := ConvergesTo.sequence with convergesV1150have differenceConverges := ConvergesTo.sub with convergesV, convergesU1151have differenceNonnegative : NonnegativeTerms(subSequence(v, u))1152intros n nNatural1153have typedN : Nat(n) byexact nat.omega.backward at n with nNatural1154have typedU := RealSequence.value with sequenceU1155have typedV := RealSequence.value with sequenceV1156have value := subSequence.value with sequenceV, sequenceU, typedV, typedU1157have termOrderView :=orderedwith n, nNatural1158have termOrder := realLe.characterization.backward with termOrderView1159have subset := realLe.subset with typedU, typedV, termOrder1160have nonnegativeDifference := realSubValue.nonnegative_of_subset with typedU, typedV, subset1161have differenceReal := realSubValue.real with typedV, typedU1162rw value1163have nonnegativeLe := realLe.of_subset with realZero.real, nonnegativeDifference1164exact realLe.characterization.forward with nonnegativeLe1165have limitDifferenceNonnegative := ConvergesTo.nonnegative_of_nonnegative_terms with1166 differenceConverges, differenceNonnegative1167have differenceReal := realSubValue.real at M, L with*1168have translated := realLe.add_right at1169 realZero, M - L, L with1170 realZero.real, differenceReal, assumption,1171 limitDifferenceNonnegative1172have zero := realAddValue.zero_left at L1173have cancel := realSubValue.add_right_cancel at M, L with1174*{2}1175 rwa [zero, cancel] at translated11761177theorem ConvergesTo.le_constant (u : Set) (L B : Real)1178requires converges : ConvergesTo(u, L)1179requires bounded : BoundedAboveBy(u, B)1180shows L ≤ B1181proof1182have constantConverges := constantSequence.converges at B1183apply ConvergesTo.le_of_le_terms with converges, constantConverges1184intros n nNatural1185have typedN : Nat(n) byexact nat.omega.backward at n with nNatural1186have value := constantSequence.value at B, n withassumption, typedN1187rw value1188exact bounded with n, nNatural11891190theorem ConvergesTo.ge_constant (u : Set) (L A : Real)1191requires converges : ConvergesTo(u, L)1192requires bounded : BoundedBelowBy(u, A)1193shows A ≤ L1194proof1195have constantConverges := constantSequence.converges at A1196apply ConvergesTo.le_of_le_terms with constantConverges, converges1197intros n nNatural1198have typedN : Nat(n) byexact nat.omega.backward at n with nNatural1199have value := constantSequence.value at A, n withassumption, typedN1200rw value1201exact bounded with n, nNatural12021203-- The squeeze theorem now has its textbook order-theoretic proof: pass both1204-- inequalities to the limit and use antisymmetry.1205theorem ConvergesTo.squeeze (u v w : Set) (L : Real)1206requires convergesU : ConvergesTo(u, L)1207requires sequenceV : RealSequence(v)1208requires convergesW : ConvergesTo(w, L)1209requires lower : PointwiseLE(u, v)1210requires upper : PointwiseLE(v, w)1211shows ConvergesTo(v, L)1212proof1213constructor1214 . exact sequenceV1215 . intros E realE positiveE1216have typedE : Real(E) byexact realE1217obtain⟨N, nNatural, close⟩:= ConvergesTo.common_eventually with1218 convergesU, convergesW, positiveE, positiveE1219witness N1220constructor1221 . exact nNatural1222 . intros n nInNaturals nAfterN1223have typedN : Nat(n) byexact nat.omega.backward at n with nInNaturals1224have sequenceU := ConvergesTo.sequence with convergesU1225have sequenceW := ConvergesTo.sequence with convergesW1226have typedU := RealSequence.value with sequenceU1227have typedV := RealSequence.value with sequenceV1228have typedW := RealSequence.value with sequenceW1229obtain⟨nearU, nearW⟩:= close with n, nInNaturals, nAfterN1230have intervalU := openBall.order_characterization.forward at1231 uₙ, L, E with typedU, assumption, typedE, nearU1232have intervalW := openBall.order_characterization.forward at1233 wₙ, L, E with typedW, assumption, typedE, nearW1234rcases intervalU with⟨lowerU, _⟩1235rcases intervalW with⟨_, upperW⟩1236have uLeVView := lower with n, nInNaturals1237have vLeWView := upper with n, nInNaturals1238have uLeV := realLe.characterization.backward with uLeVView1239have vLeW := realLe.characterization.backward with vLeWView1240have lowerEndpointReal := realSubValue.real at L, E with1241assumption, typedE1242have lowerV := realLess.transitive_le with lowerEndpointReal, typedU, typedV, lowerU, uLeV1243have upperV := realLe.transitive_less with typedV, typedW, vLeW, upperW1244apply openBall.order_characterization.backward with typedV1245constructor1246 . exact lowerV1247 . exact upperV1248