1-- Closed sets in a metric space: closed balls, spheres, and points are2-- closed; a point lies in the closure of a set exactly when every ball3-- around it meets the set4-- 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.Closed10import Open1112predicate MetricClosed (X d C : Set) := IsClosed(X, metricTopology(X, d), C)1314theorem MetricClosed.subset (X d C : Set)15requires closed : MetricClosed(X, d, C)16shows C ⊆ X17proof18unfold MetricClosed at closed19exact closed.left2021theorem MetricClosed.complement_open (X d C : Set)22requires closed : MetricClosed(X, d, C)23shows MetricOpen(X, d, complement(X, C))24proof25unfold MetricClosed at closed26exact metricTopology.open with closed.right2728theorem MetricClosed.of_complement_open (X d C : Set)29requires inside : C ⊆ X30requiresopen : MetricOpen(X, d, complement(X, C))31shows MetricClosed(X, d, C)32proof33unfold MetricClosed34exact⟨inside, (metricTopology.of_open withopen)⟩3536theorem MetricOpen.complement_closed (X d U : Set)37requires metric : IsMetric(X, d)38requiresopen : MetricOpen(X, d, U)39shows MetricClosed(X, d, complement(X, U))40proof41have topology := metricTopology.topology with metric42exact Open.complement_closed with topology, (metricTopology.of_open withopen)4344theorem MetricClosed.whole (X d : Set)45requires metric : IsMetric(X, d)46shows MetricClosed(X, d, X)47proof48exact IsClosed.whole with (metricTopology.topology with metric)4950theorem MetricClosed.empty (X d : Set)51requires metric : IsMetric(X, d)52shows MetricClosed(X, d, ∅)53proof54exact IsClosed.empty with (metricTopology.topology with metric)5556theorem MetricClosed.union2 (X d C D : Set)57requires metric : IsMetric(X, d)58requires hC : MetricClosed(X, d, C)59requires hD : MetricClosed(X, d, D)60shows MetricClosed(X, d, C ∪ D)61proof62have topology := metricTopology.topology with metric63unfold MetricClosed at hC64unfold MetricClosed at hD65exact IsClosed.union2 with topology, hC, hD6667theorem MetricClosed.intersection2 (X d C D : Set)68requires metric : IsMetric(X, d)69requires hC : MetricClosed(X, d, C)70requires hD : MetricClosed(X, d, D)71shows MetricClosed(X, d, C ∩ D)72proof73have topology := metricTopology.topology with metric74unfold MetricClosed at hC75unfold MetricClosed at hD76exact IsClosed.intersection2 with topology, hC, hD7778theorem MetricClosed.family_intersection (X d S : Set)79requires metric : IsMetric(X, d)80requires nonempty : Nonempty(S)81requires closed : ∀ C ∈ S, MetricClosed(X, d, C)82shows MetricClosed(X, d, ⋂(S))83proof84have topology := metricTopology.topology with metric85have members : ∀ C ∈ S, IsClosed(X, metricTopology(X, d), C)86intros C hC87have closedC := closed with C, hC88unfold MetricClosed at closedC89exact closedC90exact IsClosed.family_intersection with topology, nonempty, members9192-- A point outside a closed set has a ball missing the set.93theorem MetricClosed.ball_disjoint (X d C x : Set)94requires closed : MetricClosed(X, d, C)95requires hx : x ∈ X96requires outside : ¬x ∈ C97shows∃ r ∈ ℝ, 0 < r ∧ Disjoint(ball(X, d, x, r), C)98proof99haveopen:= MetricClosed.complement_open with closed100have member : x ∈ complement(X, C) := complement.membership.backward with101⟨hx, outside⟩102obtain⟨r, hr, positive, inside⟩:= MetricOpen.ball_inside withopen, member103refine⟨r, hr, positive, ?_⟩104apply Disjoint.iff.backward105intros y hy hyC106have away := complement.membership.forward with (inside with y, hy)107exact away.right with hyC108109theorem MetricClosed.of_ball_disjoint (X d C : Set)110requires inside : C ⊆ X111requires separated :112∀ x ∈ X, ¬x ∈ C →∃ r ∈ ℝ, 0 < r ∧ Disjoint(ball(X, d, x, r), C)113shows MetricClosed(X, d, C)114proof115apply MetricClosed.of_complement_open with inside116constructor117 . exact complement.subset at X, C118 . intros x hx119have parts := complement.membership.forward with hx120obtain⟨r, hr, positive, disjoint⟩:=121 separated with x, parts.left, parts.right122refine⟨r, hr, positive, ?_⟩123intros y hy124have hyX := ball.point with hy125have away := Disjoint.iff.forward with disjoint126exact complement.membership.backward with⟨hyX, (away with y, hy)⟩127128-- A point of X every ball around which meets a closed set belongs to it.129theorem MetricClosed.of_balls_meet (X d C x : Set)130requires closed : MetricClosed(X, d, C)131requires hx : x ∈ X132requires meets : ∀ r ∈ ℝ, 0 < r → Nonempty(ball(X, d, x, r) ∩ C)133shows x ∈ C134proof135by_contra outside136obtain⟨r, hr, positive, disjoint⟩:=137 MetricClosed.ball_disjoint with closed, hx, outside138obtain⟨y, hy⟩:= meets with r, hr, positive139have both := intersection.membership.forward with hy140have away := Disjoint.iff.forward with disjoint141exact away with y, both.left, both.right142143theorem MetricClosed.of_limit_points (X d C : Set)144requires inside : C ⊆ X145requires limits : ∀ x ∈ X,146 (∀ r ∈ ℝ, 0 < r → Nonempty(ball(X, d, x, r) ∩ C)) → x ∈ C147shows MetricClosed(X, d, C)148proof149apply MetricClosed.of_ball_disjoint with inside150intros x hx outside151by_contra none152apply outside153apply limits with x, hx154intros r hr positive155by_contra empty156apply none157refine⟨r, hr, positive, ?_⟩158apply Disjoint.iff.backward159intros y hy hyC160apply empty161witness y162exact intersection.membership.backward with⟨hy, hyC⟩163164theorem closedBall.closed (X d x : Set, r : Real)165requires metric : IsMetric(X, d)166requires hx : x ∈ X167shows MetricClosed(X, d, closedBall(X, d, x, r))168proof169apply MetricClosed.of_ball_disjoint with (closedBall.subset at X, d, x, r)170intros y hy outside171have dxy := IsMetric.real with metric, hx, hy172have far : r < d(x, y)173have order := realLess.trichotomy at r, d(x, y)174rcases order with less | equal | greater175 . exact less176 . exfalso177apply outside178apply closedBall.of_distance with hy179rw← equal180exact realLe.reflexive181 . exfalso182apply outside183exact closedBall.of_distance with hy, (realLess.implies_le with greater)184have radiusReal : d(x, y) - r ∈ ℝ bytypecheck185have positive : (0:R) < d(x, y) - r bylinarith186refine⟨d(x, y) - r, radiusReal, positive, ?_⟩187apply Disjoint.iff.backward188intros z hz inBall189have hzX := ball.point with hz190have near := ball.distance with hz191have close := closedBall.distance with inBall192have triangle := IsMetric.triangle_to with metric, hx, hy, hzX193have dyz := IsMetric.real with metric, hy, hzX194have dxz := IsMetric.real with metric, hx, hzX195linarith196197theorem ball.complement_closed (X d x : Set, r : Real)198requires metric : IsMetric(X, d)199requires hx : x ∈ X200shows MetricClosed(X, d, complement(X, ball(X, d, x, r)))201proof202exact MetricOpen.complement_closed with metric, (ball.open with metric, hx)203204theorem closedBall.complement_open (X d x : Set, r : Real)205requires metric : IsMetric(X, d)206requires hx : x ∈ X207shows MetricOpen(X, d, complement(X, closedBall(X, d, x, r)))208proof209exact MetricClosed.complement_open with (closedBall.closed with metric, hx)210211theorem sphere.closed (X d x : Set, r : Real)212requires metric : IsMetric(X, d)213requires hx : x ∈ X214shows MetricClosed(X, d, sphere(X, d, x, r))215proof216apply MetricClosed.of_ball_disjoint with (sphere.subset at X, d, x, r)217intros y hy outside218have dxy := IsMetric.real with metric, hx, hy219have order := realLess.trichotomy at d(x, y), r220rcases order with less | equal | greater221 . have radiusReal : r - d(x, y) ∈ ℝ bytypecheck222have positive : (0:R) < r - d(x, y) bylinarith223refine⟨r - d(x, y), radiusReal, positive, ?_⟩224apply Disjoint.iff.backward225intros z hz onSphere226have hzX := ball.point with hz227have near := ball.distance with hz228obtain⟨hzX2, equal⟩:= sphere.membership.forward with onSphere229have triangle := IsMetric.triangle with metric, hx, hy, hzX230have dyz := IsMetric.real with metric, hy, hzX231have dxz := IsMetric.real with metric, hx, hzX232linarith233 . exfalso234apply outside235exact sphere.membership.backward with⟨hy, equal⟩236 . have radiusReal : d(x, y) - r ∈ ℝ bytypecheck237have positive : (0:R) < d(x, y) - r bylinarith238refine⟨d(x, y) - r, radiusReal, positive, ?_⟩239apply Disjoint.iff.backward240intros z hz onSphere241have hzX := ball.point with hz242have near := ball.distance with hz243obtain⟨hzX2, equal⟩:= sphere.membership.forward with onSphere244have triangle := IsMetric.triangle_to with metric, hx, hy, hzX245have dyz := IsMetric.real with metric, hy, hzX246have dxz := IsMetric.real with metric, hx, hzX247linarith248249theorem singleton.metric_closed (X d x : Set)250requires metric : IsMetric(X, d)251requires hx : x ∈ X252shows MetricClosed(X, d, {x})253proof254have topology := metricTopology.topology with metric255have hausdorff := metricTopology.hausdorff with metric256exact IsHausdorff.singleton_closed with topology, hausdorff, hx257258theorem sphere.eq_difference (X d x : Set, r : Real)259requires metric : IsMetric(X, d)260requires hx : x ∈ X261shows sphere(X, d, x, r) = closedBall(X, d, x, r) ∖ ball(X, d, x, r)262proof263have disjoint := sphere.disjoint_ball at X, d, x, r264have separated := Disjoint.iff.forward with disjoint265ext y266constructor267 . intro hy268have inside := sphere.subset_closedBall with metric, hx269have inClosed := inside with y, hy270apply difference.membership.backward271exact⟨inClosed, (separated with y, hy)⟩272 . intro hy273have parts := difference.membership.forward with hy274havesplit:= closedBall.eq_ball_union_sphere with metric, hx275rwsplitat parts276havecases:= union2.membership.forward with parts.left277casescaseswith inBall | onSphere278 . exfalso279exact parts.right with inBall280 . exact onSphere281282-- Closure: a point is in the closure of A exactly when every ball around283-- it meets A.284theorem metricClosure.membership (X d A x : Set)285requires metric : IsMetric(X, d)286requires hA : A ⊆ X287shows x ∈ closure(X, metricTopology(X, d), A) ↔288 x ∈ X ∧ (∀ r ∈ ℝ, 0 < r → Nonempty(ball(X, d, x, r) ∩ A))289proof290have topology := metricTopology.topology with metric291have characterization :=292 closure.membership at X, metricTopology(X, d), A, x with293 topology, hA294constructor295 . intro hx296obtain⟨hxX, touches⟩:= characterization.forward with hx297refine⟨hxX, ?_⟩298intros r hr positive299have openBall := ball.member_topology at X, d, x, r with metric, hxX300have center := ball.center with metric, hxX, positive301exact touches with ball(X, d, x, r), openBall, center302 . intro data303obtain⟨hxX, meets⟩:= data304apply characterization.backward305refine⟨hxX, ?_⟩306intros U hU hxU307obtain⟨r, hr, positive, inside⟩:= metricTopology.ball_inside with hU, hxU308obtain⟨y, hy⟩:= meets with r, hr, positive309have both := intersection.membership.forward with hy310witness y311exact intersection.membership.backward with⟨(inside with312 y, both.left), both.right⟩313314theorem metricClosure.ball_meets (X d A x : Set, r : Real)315requires metric : IsMetric(X, d)316requires hA : A ⊆ X317requires hx : x ∈ closure(X, metricTopology(X, d), A)318requires positive : 0 < r319shows Nonempty(ball(X, d, x, r) ∩ A)320proof321have characterization := metricClosure.membership at X, d, A, x with322 metric, hA323obtain⟨hxX, meets⟩:= characterization.forward with hx324have realR : r ∈ ℝ bytypecheck325exact meets with r, realR, positive326327theorem metricClosure.of_balls_meet (X d A x : Set)328requires metric : IsMetric(X, d)329requires hA : A ⊆ X330requires hx : x ∈ X331requires meets : ∀ r ∈ ℝ, 0 < r → Nonempty(ball(X, d, x, r) ∩ A)332shows x ∈ closure(X, metricTopology(X, d), A)333proof334have characterization := metricClosure.membership at X, d, A, x with335 metric, hA336exact characterization.backward with⟨hx, meets⟩337338theorem ball.closure_subset_closedBall (X d x : Set, r : Real)339requires metric : IsMetric(X, d)340requires hx : x ∈ X341shows342 closure(X, metricTopology(X, d), ball(X, d, x, r)) ⊆ closedBall(X, d, x, r)343proof344have topology := metricTopology.topology with metric345have closed := closedBall.closed at X, d, x, r with metric, hx346have inside := ball.subset_closedBall with metric, hx347unfold MetricClosed at closed348exact closure.least with closed, inside349350theorem closedBall.closure (X d x : Set, r : Real)351requires metric : IsMetric(X, d)352requires hx : x ∈ X353shows closure(X, metricTopology(X, d), closedBall(X, d, x, r)) =354 closedBall(X, d, x, r)355proof356have topology := metricTopology.topology with metric357have closed := closedBall.closed at X, d, x, r with metric, hx358unfold MetricClosed at closed359exact closure.of_closed with topology, closed360361-- A set is dense exactly when every ball meets it.362theorem metricDense.iff (X d A : Set)363requires metric : IsMetric(X, d)364requires hA : A ⊆ X365shows IsDense(X, metricTopology(X, d), A) ↔366 (∀ x ∈ X, ∀ r ∈ ℝ, 0 < r → Nonempty(ball(X, d, x, r) ∩ A))367proof368have topology := metricTopology.topology with metric369constructor370 . intro dense371intros x hx r hr positive372unfold IsDense at dense373have inClosure : x ∈ closure(X, metricTopology(X, d), A)374rw dense375exact hx376exact metricClosure.ball_meets with metric, hA, inClosure, positive377 . intro meets378unfold IsDense379apply Subset.antisymmetric380 . exact closure.subset with topology, hA381 . intros x hx382exact metricClosure.of_balls_meet with metric, hA, hx, (meets with x, hx)383384theorem metricDense.whole (X d : Set)385requires metric : IsMetric(X, d)386shows IsDense(X, metricTopology(X, d), X)387proof388have topology := metricTopology.topology with metric389unfold IsDense390exact closure.of_closed with topology, (IsClosed.whole with topology)391