1-- Coordinate convergence and squared-distance continuity describe the same limits.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.Complex.SequentialContinuity8import Compactness910theorem realSquare.abs_lt_of_lt_square (a e : Real)11requires positive : realZero < e12requires small : a * a < e * e13shows abs(a) < e14proof15have nonnegative := abs.nonnegative at a with*16have eNonnegative := realLess.implies_le at realZero, e with*17have squareNonnegative := realMulValue.square_nonnegative at a with*18have squareAbs := abs.of_nonnegative at a * a with*19have multiplicative := abs.mul at a, a with*20have square : abs(a) * abs(a) = a * a bycc21have comparison : e ≤ abs(a) ∨¬(e ≤ abs(a)) bytauto22cases comparison with large | notLarge23 . have first := realLe.mul_left_of_nonnegative at e, abs(a), e with*24have second := realLe.mul_right_of_nonnegative at e, abs(a), abs(a) with*25have bound := realLe.transitive at e * e, e * abs(a), abs(a) * abs(a) with*26rw square at bound27have impossible := realLess.transitive_le at a * a, e * e, a * a with*28have irrefl := realLess.irreflexive_on29exfalso30exact irrefl with a * a, impossible31 . exact realLess.of_not_le at e, abs(a) with*3233def complexDistanceSequence (u a : Set) : Set:=34 addSequence(35 mulSequence(subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a)))),36 mulSequence(subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a)))))3738def complexMappedSequence (f u : Set) : Set:= compose(f, u, ℕ, complexCarrier, complexCarrier)3940section Complexes41notationring ℂ := (complexCarrier, complexAdd, complexZero, complexNeg, complexMul, complexOne)42notationring R := (ℝ, realAdd, realZero, realNeg, realMul, realOne)4344theorem complexNormSquared.difference_coordinates (z a : Set)45requires first : z ∈ ℂ46requires second : a ∈ ℂ47shows complexNormSquared(ℂ[z - a]) = R[(Euclidean.x(z) - Euclidean.x(a)) * (Euclidean.x(z) - Euclidean.x(a)) + (Euclidean.y(z) - Euclidean.y(a)) * (Euclidean.y(z) - Euclidean.y(a))]48proof49have zPoint := complex.point with first50have aPoint := complex.point with second51rw [complexNormSquared.difference_distance, Euclidean.distanceSquared.coordinates]52ring5354theorem complexNormSquared.small_coordinates (z a : Set) (e : Real)55requires first : z ∈ ℂ56requires second : a ∈ ℂ57requires positive : R[0] < e58requires small : complexNormSquared(ℂ[z - a]) < R[e * e]59shows Euclidean.x(z) ∈ openBall(Euclidean.x(a), e) ∧ Euclidean.y(z) ∈ openBall(Euclidean.y(a), e)60proof61have zPoint := complex.point with first62have aPoint := complex.point with second63have ax := Euclidean.x.real at a with*64have ay := Euclidean.y.real at a with*65have xx := realMulValue.square_nonnegative at R[Euclidean.x(z) - Euclidean.x(a)] with*66have yy := realMulValue.square_nonnegative at R[Euclidean.y(z) - Euclidean.y(a)] with*67have sums := realLe.nonnegative_sum_bounds at R[(Euclidean.x(z) - Euclidean.x(a)) * (Euclidean.x(z) - Euclidean.x(a))], R[(Euclidean.y(z) - Euclidean.y(a)) * (Euclidean.y(z) - Euclidean.y(a))] with*68rw complexNormSquared.difference_coordinates at small69have xSmall := realLe.transitive_less at R[(Euclidean.x(z) - Euclidean.x(a)) * (Euclidean.x(z) - Euclidean.x(a))], R[(Euclidean.x(z) - Euclidean.x(a)) * (Euclidean.x(z) - Euclidean.x(a)) + (Euclidean.y(z) - Euclidean.y(a)) * (Euclidean.y(z) - Euclidean.y(a))], R[e * e] with*70have ySmall := realLe.transitive_less at R[(Euclidean.y(z) - Euclidean.y(a)) * (Euclidean.y(z) - Euclidean.y(a))], R[(Euclidean.x(z) - Euclidean.x(a)) * (Euclidean.x(z) - Euclidean.x(a)) + (Euclidean.y(z) - Euclidean.y(a)) * (Euclidean.y(z) - Euclidean.y(a))], R[e * e] with*71have xAbs := realSquare.abs_lt_of_lt_square at R[Euclidean.x(z) - Euclidean.x(a)], e with*72have yAbs := realSquare.abs_lt_of_lt_square at R[Euclidean.y(z) - Euclidean.y(a)], e with*73have xIn : Euclidean.x(z) ∈ ℝ bytypecheck74have yIn : Euclidean.y(z) ∈ ℝ bytypecheck75constructor76 . apply openBall.membership.backward77constructor78 . exact xIn79 . unfold dist80unfold realSubValue81exact xAbs82 . apply openBall.membership.backward83constructor84 . exact yIn85 . unfold dist86unfold realSubValue87exact yAbs888990theorem complexDistanceSequence.converges_zero (u a : Set)91requires converges : ComplexConvergesTo(u, a)92shows ConvergesTo(complexDistanceSequence(u, a), R[0])93proof94rcases converges with⟨sequence, member, horizontal, vertical⟩95have point := complex.point with member96have xConstant := constantSequence.converges at Euclidean.x(a) with*97have yConstant := constantSequence.converges at Euclidean.y(a) with*98have xDiff := ConvergesTo.sub at complexSequenceX(u), constantSequence(Euclidean.x(a)), Euclidean.x(a), Euclidean.x(a) with*99have yDiff := ConvergesTo.sub at complexSequenceY(u), constantSequence(Euclidean.y(a)), Euclidean.y(a), Euclidean.y(a) with*100unfold realSubValue at xDiff101unfold realSubValue at yDiff102have xx := ConvergesTo.mul at subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), R[Euclidean.x(a) - Euclidean.x(a)], R[Euclidean.x(a) - Euclidean.x(a)] with*103have yy := ConvergesTo.mul at subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), R[Euclidean.y(a) - Euclidean.y(a)], R[Euclidean.y(a) - Euclidean.y(a)] with*104have sum := ConvergesTo.add at mulSequence(subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a)))), mulSequence(subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a)))), R[(Euclidean.x(a) - Euclidean.x(a)) * (Euclidean.x(a) - Euclidean.x(a))], R[(Euclidean.y(a) - Euclidean.y(a)) * (Euclidean.y(a) - Euclidean.y(a))] with*105have zero : R[(Euclidean.x(a) - Euclidean.x(a)) * (Euclidean.x(a) - Euclidean.x(a)) + (Euclidean.y(a) - Euclidean.y(a)) * (Euclidean.y(a) - Euclidean.y(a))] = R[0]106ring107rw zero at sum108unfold complexDistanceSequence109exact sum110111theorem complexDistanceSequence.value (u a : Set) (n : Nat)112requires sequence : ComplexSequence(u)113requires center : a ∈ ℂ114shows complexDistanceSequence(u, a)(n) = complexNormSquared(ℂ[u(n) - a])115proof116have point := complex.point with center117have horizontal := complexSequenceX.sequence with*118have vertical := complexSequenceY.sequence with*119have xConstant := constantSequence.sequence at Euclidean.x(a) with*120have yConstant := constantSequence.sequence at Euclidean.y(a) with*121have xDiff := subSequence.sequence at complexSequenceX(u), constantSequence(Euclidean.x(a)) with*122have yDiff := subSequence.sequence at complexSequenceY(u), constantSequence(Euclidean.y(a)) with*123have xx := mulSequence.sequence at subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))) with*124have yy := mulSequence.sequence at subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))) with*125have xReal := RealSequence.value at complexSequenceX(u), n with*126have yReal := RealSequence.value at complexSequenceY(u), n with*127have cxReal := RealSequence.value at constantSequence(Euclidean.x(a)), n with*128have cyReal := RealSequence.value at constantSequence(Euclidean.y(a)), n with*129have dxReal := RealSequence.value at subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), n with*130have dyReal := RealSequence.value at subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), n with*131have xxReal := RealSequence.value at mulSequence(subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a))), subSequence(complexSequenceX(u), constantSequence(Euclidean.x(a)))), n with*132have yyReal := RealSequence.value at mulSequence(subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a))), subSequence(complexSequenceY(u), constantSequence(Euclidean.y(a)))), n with*133have function : u : ℕ → ℂ byexact sequence134have member := FunctionBetween.apply_closed at u, ℕ, ℂ, n with*135unfold complexDistanceSequence136rw [addSequence.value, mulSequence.value, mulSequence.value, subSequence.value, subSequence.value, constantSequence.value, constantSequence.value, complexSequenceX.value, complexSequenceY.value, complexNormSquared.difference_coordinates]137simp [realSubValue]138139theorem ComplexConvergesTo.eventually_squared_distance (u a : Set) (e : Real)140requires converges : ComplexConvergesTo(u, a)141requires positive : R[0] < e142shows∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n → complexNormSquared(ℂ[u(n) - a]) < e143proof144have distanceLimit := complexDistanceSequence.converges_zero with*145have distanceSequence := ConvergesTo.sequence at complexDistanceSequence(u, a), R[0] with*146obtain⟨N, natural, close⟩:= ConvergesTo.eventually at complexDistanceSequence(u, a), R[0], e with*147rcases converges with⟨sequence, member, horizontal, vertical⟩148refine⟨N, natural, ?_⟩149intros n nIn after150have nNat := nat.omega.backward at n with*151have termReal := RealSequence.value with*152have near := close with n, nIn, after153have interval := openBall.order_characterization.forward with*154have upper := interval.right155 rwa [realAddValue.zero_left, complexDistanceSequence.value] at upper156157theorem ComplexConvergesTo.of_squared_distance (u a : Set)158requires sequence : ComplexSequence(u)159requires center : a ∈ ℂ160requires close : ∀ e ∈ ℝ, R[0] < e →∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n → complexNormSquared(ℂ[u(n) - a]) < e161shows ComplexConvergesTo(u, a)162proof163have point := complex.point with center164have horizontal := complexSequenceX.sequence with*165have vertical := complexSequenceY.sequence with*166have function : u : ℕ → ℂ byexact sequence167have both : ∀ e ∈ ℝ, R[0] < e →∃ N ∈ ℕ, ∀ n ∈ ℕ, N ≤ n →168 complexSequenceX(u)(n) ∈ openBall(Euclidean.x(a), e) ∧ complexSequenceY(u)(n) ∈ openBall(Euclidean.y(a), e)169intros e eIn positive170have squarePositive := realMulValue.positive with*171obtain⟨N, natural, small⟩:= close with R[e * e], squarePositive172refine⟨N, natural, ?_⟩173intros n nIn after174have nNat := nat.omega.backward at n with*175have member := FunctionBetween.apply_closed at u, ℕ, ℂ, n with*176have distance := small with n, nIn, after177have coordinates := complexNormSquared.small_coordinates with*178 rwa [complexSequenceX.value, complexSequenceY.value]179unfold ComplexConvergesTo180refine⟨sequence, center, ?_⟩181constructor182 . unfold ConvergesTo183refine⟨horizontal, ?_⟩184intros e eIn positive185obtain⟨N, natural, closeBoth⟩:= both with e, eIn, positive186refine⟨N, natural, ?_⟩187intros n nIn after188have near := closeBoth with n, nIn, after189exact near.left190 . unfold ConvergesTo191refine⟨vertical, ?_⟩192intros e eIn positive193obtain⟨N, natural, closeBoth⟩:= both with e, eIn, positive194refine⟨N, natural, ?_⟩195intros n nIn after196have near := closeBoth with n, nIn, after197exact near.right198199theorem complexMappedSequence.sequence (f u : Set)200requires function : f : ℂ → ℂ201requires sequence : ComplexSequence(u)202shows ComplexSequence(complexMappedSequence(f, u))203proof204have uFunction : u : ℕ → ℂ byexact sequence205unfold ComplexSequence206unfold complexMappedSequence207exact compose.function with*208209theorem complexMappedSequence.value (f u : Set) (n : Nat)210requires function : f : ℂ → ℂ211requires sequence : ComplexSequence(u)212shows complexMappedSequence(f, u)(n) = f(u(n))213proof214have uFunction : u : ℕ → ℂ byexact sequence215unfold complexMappedSequence216exact compose.apply with*217218theorem ComplexContinuousAt.converges (f u a : Set)219requires continuous : ComplexContinuousAt(f, a)220requires converges : ComplexConvergesTo(u, a)221shows ComplexConvergesTo(complexMappedSequence(f, u), f(a))222proof223have convergesAgain := converges224rcases converges with⟨sequence, center, horizontal, vertical⟩225rcases continuous with⟨function, centerAgain, local⟩226have mapped := complexMappedSequence.sequence with*227have image := FunctionBetween.apply_closed with*228have uFunction : u : ℕ → ℂ byexact sequence229apply ComplexConvergesTo.of_squared_distance with mapped, image230intros e eIn positive231obtain⟨d, dIn, dPositive, nearImage⟩:= local with e, eIn, positive232obtain⟨N, natural, nearInput⟩:= ComplexConvergesTo.eventually_squared_distance at u, a, d with*233refine⟨N, natural, ?_⟩234intros n nIn after235have nNat := nat.omega.backward at n with*236have member := FunctionBetween.apply_closed at u, ℕ, ℂ, n with*237have near := nearInput with n, nIn, after238rw complexMappedSequence.value239exact nearImage with u(n), member, near240241theorem complexPolynomial.converges (u a : Set) (cs : List(ℂ))242requires converges : ComplexConvergesTo(u, a)243shows ComplexConvergesTo(complexMappedSequence(complexPolynomial(cs), u), complexPolynomial(cs)(a))244proof245have center : a ∈ ℂ246rcases converges with⟨sequence, center, horizontal, vertical⟩247exact center248have continuous := complexPolynomial.continuous_at with*249exact ComplexContinuousAt.converges with*250251theorem complexPolynomial.norm_converges (u a : Set) (cs : List(ℂ))252requires converges : ComplexConvergesTo(u, a)253shows ConvergesTo(complexNormSequence(complexMappedSequence(complexPolynomial(cs), u)), complexNormSquared(complexPolynomial(cs)(a)))254proof255have mapped := complexPolynomial.converges with*256exact ComplexConvergesTo.norm_squared with*257258end Complexes259