1-- Bounded sets in a metric space: sets of bounded diameter, balls and2-- finite unions, the range of a Cauchy sequence, and images under3-- Lipschitz maps4-- Part of Cumulus, the Grace17 mathematics library.5-- Copyright (c) 2026 Grant Passmore.6-- Released under the Apache License 2.0. See LICENSE in the repository root.7-- Authors: Grant Passmore89module Grace.Cumulus.Metric.Bounded10import Sequences1112predicate IsBounded (X d S : Set) :=13 (S ⊆ X) ∧ (∃ r ∈ ℝ, ∀ x ∈ S, ∀ y ∈ S, d(x, y) ≤ r)1415theorem IsBounded.subset (X d S : Set)16requires bounded : IsBounded(X, d, S)17shows S ⊆ X18proof19exact bounded.left2021theorem IsBounded.bound (X d S : Set)22requires bounded : IsBounded(X, d, S)23shows∃ r ∈ ℝ, ∀ x ∈ S, ∀ y ∈ S, d(x, y) ≤ r24proof25exact bounded.right2627theorem IsBounded.of_bound (X d S : Set, r : Real)28requires inside : S ⊆ X29requires bound : ∀ x ∈ S, ∀ y ∈ S, d(x, y) ≤ r30shows IsBounded(X, d, S)31proof32have realR : r ∈ ℝ bytypecheck33exact⟨inside, r, realR, bound⟩3435theorem IsBounded.empty (X d : Set)36shows IsBounded(X, d, ∅)37proof38apply IsBounded.of_bound at X, d, ∅, (0:R) with (empty.subset at X)39intros x hx40exfalso41exact empty.membership with hx4243theorem IsBounded.singleton (X d x : Set)44requires metric : IsMetric(X, d)45requires hx : x ∈ X46shows IsBounded(X, d, {x})47proof48have inside : {x} ⊆ X49intros z hz50have same := singleton.membership.forward with hz51 rwa same52apply IsBounded.of_bound at X, d, {x}, (0:R) with inside53intros y hy z hz54have sameY := singleton.membership.forward with hy55have sameZ := singleton.membership.forward with hz56rw [sameY, sameZ]57haveself:= IsMetric.self with metric, hx58rwself59exact realLe.reflexive6061theorem IsBounded.of_subset (X d S T : Set)62requires bounded : IsBounded(X, d, T)63requires inside : S ⊆ T64shows IsBounded(X, d, S)65proof66obtain⟨insideT, r, hr, bound⟩:= bounded67refine⟨(Subset.transitive with inside, insideT), r, hr, ?_⟩68intros x hx y hy69exact bound with x, (inside with x, hx), y, (inside with y, hy)7071theorem IsBounded.intersection2 (X d S T : Set)72requires bounded : IsBounded(X, d, S)73shows IsBounded(X, d, S ∩ T)74proof75exact IsBounded.of_subset with bounded, (intersection.subset_left at S, T)7677theorem IsBounded.ball (X d x : Set, r : Real)78requires metric : IsMetric(X, d)79requires hx : x ∈ X80shows IsBounded(X, d, ball(X, d, x, r))81proof82apply IsBounded.of_bound at X, d, ball(X, d, x, r), r + r with83 (ball.subset at X, d, x, r)84intros y hy z hz85have hyX := ball.point with hy86have hzX := ball.point with hz87have nearY := ball.distance with hy88have nearZ := ball.distance with hz89have triangle := IsMetric.triangle_from with metric, hx, hyX, hzX90have dxy := IsMetric.real with metric, hx, hyX91have dxz := IsMetric.real with metric, hx, hzX92have dyz := IsMetric.real with metric, hyX, hzX93linarith9495theorem IsBounded.closedBall (X d x : Set, r : Real)96requires metric : IsMetric(X, d)97requires hx : x ∈ X98shows IsBounded(X, d, closedBall(X, d, x, r))99proof100apply IsBounded.of_bound at X, d, closedBall(X, d, x, r), r + r with101 (closedBall.subset at X, d, x, r)102intros y hy z hz103have hyX := closedBall.point with hy104have hzX := closedBall.point with hz105have nearY := closedBall.distance with hy106have nearZ := closedBall.distance with hz107have triangle := IsMetric.triangle_from with metric, hx, hyX, hzX108have dxy := IsMetric.real with metric, hx, hyX109have dxz := IsMetric.real with metric, hx, hzX110have dyz := IsMetric.real with metric, hyX, hzX111linarith112113theorem IsBounded.sphere (X d x : Set, r : Real)114requires metric : IsMetric(X, d)115requires hx : x ∈ X116shows IsBounded(X, d, sphere(X, d, x, r))117proof118have bounded := IsBounded.closedBall at X, d, x, r with metric, hx119exact IsBounded.of_subset with bounded, (sphere.subset_closedBall with120 metric, hx)121122theorem IsBounded.of_ball (X d S x : Set, r : Real)123requires metric : IsMetric(X, d)124requires hx : x ∈ X125requires inside : S ⊆ ball(X, d, x, r)126shows IsBounded(X, d, S)127proof128exact IsBounded.of_subset with (IsBounded.ball at X, d, x, r with129 metric, hx), inside130131theorem IsBounded.of_closedBall (X d S x : Set, r : Real)132requires metric : IsMetric(X, d)133requires hx : x ∈ X134requires inside : S ⊆ closedBall(X, d, x, r)135shows IsBounded(X, d, S)136proof137exact IsBounded.of_subset with (IsBounded.closedBall at X, d, x, r with138 metric, hx), inside139140-- A nonempty bounded set lies in a ball around any of its points.141theorem IsBounded.ball_around (X d S x : Set)142requires metric : IsMetric(X, d)143requires bounded : IsBounded(X, d, S)144requires hx : x ∈ S145shows∃ r ∈ ℝ, 0 < r ∧ S ⊆ ball(X, d, x, r)146proof147obtain⟨inside, r, hr, bound⟩:= bounded148have hxX := inside with x, hx149haveself:= IsMetric.self with metric, hxX150have nonnegative : (0:R) ≤ r151have selfBound := bound with x, hx, x, hx152rwselfat selfBound153exact selfBound154have radiusReal : r +1∈ ℝ bytypecheck155have positive : (0:R) < r +1bylinarith156refine⟨r +1, radiusReal, positive, ?_⟩157intros y hy158have hyX := inside with y, hy159have dxy := IsMetric.real with metric, hxX, hyX160have near := bound with x, hx, y, hy161apply ball.of_distance with hyX162linarith163164theorem IsBounded.in_ball (X d S : Set)165requires metric : IsMetric(X, d)166requires bounded : IsBounded(X, d, S)167requires nonempty : Nonempty(S)168shows∃ x ∈ X, ∃ r ∈ ℝ, 0 < r ∧ S ⊆ ball(X, d, x, r)169proof170obtain⟨x, hx⟩:= nonempty171have hxX := IsBounded.subset with bounded, x, hx172obtain⟨r, hr, positive, inside⟩:=173 IsBounded.ball_around with metric, bounded, hx174exact⟨x, hxX, r, hr, positive, inside⟩175176theorem IsBounded.iff_ball (X d S : Set)177requires metric : IsMetric(X, d)178requires nonempty : Nonempty(S)179shows IsBounded(X, d, S) ↔∃ x ∈ X, ∃ r ∈ ℝ, S ⊆ ball(X, d, x, r)180proof181constructor182 . intro bounded183obtain⟨x, hx, r, hr, positive, inside⟩:=184 IsBounded.in_ball with metric, bounded, nonempty185exact⟨x, hx, r, hr, inside⟩186 . intro data187obtain⟨x, hx, r, hr, inside⟩:= data188exact IsBounded.of_ball with metric, hx, inside189190theorem IsBounded.nonnegative_bound (X d S : Set)191requires metric : IsMetric(X, d)192requires bounded : IsBounded(X, d, S)193shows∃ r ∈ ℝ, 0≤ r ∧∀ x ∈ S, ∀ y ∈ S, d(x, y) ≤ r194proof195obtain⟨inside, r, hr, bound⟩:= bounded196havesplit : Nonempty(S) ∨¬Nonempty(S) bytauto197casessplitwith nonempty | empty198 . obtain⟨x, hx⟩:= nonempty199have hxX := inside with x, hx200haveself:= IsMetric.self with metric, hxX201have selfBound := bound with x, hx, x, hx202rwselfat selfBound203exact⟨r, hr, selfBound, bound⟩204 . have zeroReal : (0:R) ∈ ℝ bytypecheck205have reflexive : (0:R) ≤0bylinarith206refine⟨(0:R), zeroReal, reflexive, ?_⟩207intros x hx208exfalso209apply empty210exact⟨x, hx⟩211212-- The union of two bounded sets is bounded.213theorem IsBounded.union2 (X d S T : Set)214requires metric : IsMetric(X, d)215requires boundedS : IsBounded(X, d, S)216requires boundedT : IsBounded(X, d, T)217shows IsBounded(X, d, S ∪ T)218proof219have insideS := IsBounded.subset with boundedS220have insideT := IsBounded.subset with boundedT221have inside := union2.subset with insideS, insideT222have splitS : Nonempty(S) ∨¬Nonempty(S) bytauto223have splitT : Nonempty(T) ∨¬Nonempty(T) bytauto224cases splitS with nonemptyS | emptyS225 . cases splitT with nonemptyT | emptyT226 . obtain⟨s, hs⟩:= nonemptyS227obtain⟨t, ht⟩:= nonemptyT228have hsX := insideS with s, hs229have htX := insideT with t, ht230obtain⟨r, hr, positiveR, ballS⟩:=231 IsBounded.ball_around with metric, boundedS, hs232obtain⟨q, hq, positiveQ, ballT⟩:=233 IsBounded.ball_around with metric, boundedT, ht234have dst := IsMetric.real with metric, hsX, htX235apply IsBounded.of_bound at236 X, d, S ∪ T, (r + d(s, t) + q) + (r + d(s, t) + q) with237 inside238have reach : ∀ x ∈ S ∪ T, d(s, x) ≤ r + d(s, t) + q239intros x hx240have hxX := inside with x, hx241have dsx := IsMetric.real with metric, hsX, hxX242havecases:= union2.membership.forward with hx243casescaseswith inS | inT244 . have near := ball.distance with (ballS with x, inS)245have nonnegative := IsMetric.nonnegative with metric, hsX, htX246linarith247 . have near := ball.distance with (ballT with x, inT)248have dtx := IsMetric.real with metric, htX, hxX249have triangle := IsMetric.triangle with metric, hsX, htX, hxX250linarith251intros x hx y hy252have hxX := inside with x, hx253have hyX := inside with y, hy254have reachX := reach with x, hx255have reachY := reach with y, hy256have triangle := IsMetric.triangle_from with metric, hsX, hxX, hyX257have dsx := IsMetric.real with metric, hsX, hxX258have dsy := IsMetric.real with metric, hsX, hyX259have dxy := IsMetric.real with metric, hxX, hyX260linarith261 . have equal : T =∅262apply Subset.antisymmetric263 . intros t ht264exfalso265apply emptyT266exact⟨t, ht⟩267 . exact empty.subset at T268rw equal269rw union2.right_empty270exact boundedS271 . have equal : S =∅272apply Subset.antisymmetric273 . intros s hs274exfalso275apply emptyS276exact⟨s, hs⟩277 . exact empty.subset at S278rw equal279rw union2.left_empty280exact boundedT281282theorem IsBounded.union_singleton (X d S x : Set)283requires metric : IsMetric(X, d)284requires bounded : IsBounded(X, d, S)285requires hx : x ∈ X286shows IsBounded(X, d, {x} ∪ S)287proof288exact IsBounded.union2 with metric, (IsBounded.singleton with metric, hx),289 bounded290291theorem IsBounded.pair (X d x y : Set)292requires metric : IsMetric(X, d)293requires hx : x ∈ X294requires hy : y ∈ X295shows IsBounded(X, d, {x, y})296proof297rw pair.eq_union2298exact IsBounded.union2 with metric, (IsBounded.singleton with metric, hx),299 (IsBounded.singleton with metric, hy)300301-- The range of a Cauchy sequence is bounded.302theorem IsCauchy.range_bounded (X d u : Set)303requires metric : IsMetric(X, d)304requires cauchy : IsCauchy(X, d, u)305shows IsBounded(X, d, functionImage(u, ℕ, X))306proof307have sequence := IsCauchy.sequence with cauchy308obtain⟨r, hr, close⟩:= IsCauchy.bounded with metric, cauchy309have zero : 0∈ ℕ byexact nat.omega.forward at0with310 Naturals.constructor.zero311have term0 := SequenceIn.term_of_member with sequence, zero312apply IsBounded.of_bound at X, d, functionImage(u, ℕ, X), r + r with313 (functionImage.subset at u, ℕ, X)314intros x hx y hy315obtain⟨hxX, m, hm, shapeX⟩:= functionImage.membership.forward with hx316obtain⟨hyX, n, hn, shapeY⟩:= functionImage.membership.forward with hy317have closeM := close with m, hm318have closeN := close with n, hn319rw← shapeX at closeM320rw← shapeY at closeN321have triangle := IsMetric.triangle_from with metric, term0, hxX, hyX322have d0x := IsMetric.real with metric, term0, hxX323have d0y := IsMetric.real with metric, term0, hyX324have dxy := IsMetric.real with metric, hxX, hyX325linarith326327theorem ConvergesIn.range_bounded (X d u x : Set)328requires metric : IsMetric(X, d)329requires converges : ConvergesIn(X, d, u, x)330shows IsBounded(X, d, functionImage(u, ℕ, X))331proof332have cauchy := ConvergesIn.cauchy with metric, converges333exact IsCauchy.range_bounded with metric, cauchy334335-- Lipschitz maps send bounded sets to bounded sets.336theorem IsLipschitz.image_bounded (f X d Y e S : Set) (K : Real)337requires metricD : IsMetric(X, d)338requires metricE : IsMetric(Y, e)339requires lipschitz : IsLipschitz(f, X, d, Y, e, K)340requires bounded : IsBounded(X, d, S)341shows IsBounded(Y, e, functionImage(f, S, Y))342proof343have function := IsLipschitz.function with lipschitz344have nonnegative := IsLipschitz.nonnegative with lipschitz345have inside := IsBounded.subset with bounded346obtain⟨r, hr, bound⟩:= IsBounded.bound with bounded347apply IsBounded.of_bound at Y, e, functionImage(f, S, Y), K * r with348 (functionImage.subset at f, S, Y)349intros v hv w hw350obtain⟨hvY, x, hx, shapeV⟩:= functionImage.membership.forward with hv351obtain⟨hwY, y, hy, shapeW⟩:= functionImage.membership.forward with hw352rw [shapeV, shapeW]353have hxX := inside with x, hx354have hyX := inside with y, hy355have estimate := IsLipschitz.bound with lipschitz, hxX, hyX356have distance := bound with x, hx, y, hy357have dxy := IsMetric.real with metricD, hxX, hyX358have scaled := realLe.mul_left_of_nonnegative with distance, nonnegative359have imageX := FunctionBetween.apply_closed with function, hxX360have imageY := FunctionBetween.apply_closed with function, hyX361have exy := IsMetric.real with metricE, imageX, imageY362linarith363