Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 8fbf296

Browse files
sgouezelavigad
authored andcommitted
feat(topology/metric_space/hausdorff_distance): Hausdorff distance
1 parent be88cec commit 8fbf296

File tree

5 files changed

+1289
-46
lines changed

5 files changed

+1289
-46
lines changed

src/topology/basic.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,7 +1988,17 @@ let ⟨T, cT, hT⟩ := is_open_Union_countable (λ s:S, s.1) (λ s, H s.1 s.2) i
19881988
by rwa [sUnion_image, sUnion_eq_Union]⟩
19891989

19901990
variable (α)
1991+
/-- The type of open subsets of a topological space. -/
19911992
def opens := {s : set α // _root_.is_open s}
1993+
1994+
/-- The type of closed subsets of a topological space. -/
1995+
def closeds := {s : set α // is_closed s}
1996+
1997+
/-- The type of non-empty compact subsets of a topological space. The
1998+
non-emptiness will be useful in metric spaces, as we will be able to put
1999+
a distance (and not merely an edistance) on this space. -/
2000+
def nonempty_compacts := {s : set α // s ≠ ∅ ∧ compact s}
2001+
19922002
variable {α}
19932003

19942004
namespace opens

src/topology/continuity.lean

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -996,6 +996,22 @@ compact_iff_compact_univ.trans ⟨λ h, ⟨h⟩, @compact_space.compact_univ _ _
996996

997997
end subtype
998998

999+
section nonempty_compacts
1000+
variables [topological_space α]
1001+
open topological_space
1002+
1003+
instance nonempty_compacts.to_compact_space {p : nonempty_compacts α} : compact_space p.val :=
1004+
⟨compact_iff_compact_univ.1 p.property.2
1005+
1006+
instance nonempty_compacts.to_nonempty {p : nonempty_compacts α} : nonempty p.val :=
1007+
nonempty_subtype.2 $ ne_empty_iff_exists_mem.1 p.property.1
1008+
1009+
/-- Associate to a nonempty compact subset the corresponding closed subset -/
1010+
def nonempty_compacts.to_closeds [t2_space α] (s : nonempty_compacts α) : closeds α :=
1011+
⟨s.val, closed_of_compact _ s.property.2
1012+
1013+
end nonempty_compacts
1014+
9991015
section quotient
10001016
variables [topological_space α] [topological_space β] [topological_space γ]
10011017
variables {r : α → α → Prop} {s : setoid α}

src/topology/metric_space/cau_seq_filter.lean

Lines changed: 118 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,94 @@ of the subsequence, and then the convergence of the original sequence. All this
2525
completely bypassed by the following proof, which avoids any use of subsequences and is written
2626
partly in terms of filters. -/
2727

28+
namespace ennreal
29+
30+
/-In this paragraph, we prove useful properties of the sequence `half_pow n := 2^{-n}` in ennreal.
31+
Some of them are instrumental in this file to get Cauchy sequences, but others are proved
32+
here only for use in further applications of the completeness criterion
33+
`emetric.complete_of_convergent_controlled_sequences` below. -/
34+
35+
/-- An auxiliary positive sequence that tends to `0` in `ennreal`, with good behavior. -/
36+
noncomputable def half_pow (n : ℕ) : ennreal := ennreal.of_real ((1 / 2) ^ n)
37+
38+
lemma half_pow_pos (n : ℕ) : 0 < half_pow n :=
39+
begin
40+
have : (0 : real) < (1/2)^n := pow_pos (by norm_num) _,
41+
simpa [half_pow] using this
42+
end
43+
44+
lemma half_pow_tendsto_zero : tendsto (λn, half_pow n) at_top (nhds 0) :=
45+
begin
46+
unfold half_pow,
47+
rw ← ennreal.of_real_zero,
48+
apply ennreal.tendsto_of_real,
49+
exact tendsto_pow_at_top_nhds_0_of_lt_1 (by norm_num) (by norm_num)
50+
end
51+
52+
lemma half_pow_add_succ (n : ℕ) : half_pow (n+1) + half_pow (n+1) = half_pow n :=
53+
begin
54+
have : (0 : real) ≤ (1/2)^(n+1) := (le_of_lt (pow_pos (by norm_num) _)),
55+
simp only [half_pow, eq.symm (ennreal.of_real_add this this)],
56+
apply congr_arg,
57+
simp only [pow_add, one_div_eq_inv, pow_one],
58+
ring,
59+
end
60+
61+
lemma half_pow_mono (m k : ℕ) (h : m ≤ k) : half_pow k ≤ half_pow m :=
62+
ennreal.of_real_le_of_real (pow_le_pow_of_le_one (by norm_num) (by norm_num) h)
63+
64+
lemma edist_le_two_mul_half_pow [emetric_space β] {k l N : ℕ} (hk : N ≤ k) (hl : N ≤ l)
65+
{u : ℕ → β} (h : ∀n, edist (u n) (u (n+1)) ≤ half_pow n) :
66+
edist (u k) (u l) ≤ 2 * half_pow N :=
67+
begin
68+
have ineq_rec : ∀m, ∀k≥m, half_pow k + edist (u m) (u (k+1)) ≤ 2 * half_pow m,
69+
{ assume m,
70+
refine nat.le_induction _ (λk km hk, _),
71+
{ calc half_pow m + edist (u m) (u (m+1)) ≤ half_pow m + half_pow m : add_le_add_left' (h m)
72+
... = 2 * half_pow m : by simp [(mul_two _).symm, mul_comm] },
73+
{ calc half_pow (k + 1) + edist (u m) (u (k + 1 + 1))
74+
≤ half_pow (k+1) + (edist (u m) (u (k+1)) + edist (u (k+1)) (u (k+2))) :
75+
add_le_add_left' (edist_triangle _ _ _)
76+
... ≤ half_pow (k+1) + (edist (u m) (u (k+1)) + half_pow (k+1)) :
77+
add_le_add_left' (add_le_add_left' (h (k+1)))
78+
... = (half_pow(k+1) + half_pow(k+1)) + edist (u m) (u (k+1)) : by simp [add_comm]
79+
... = half_pow k + edist (u m) (u (k+1)) : by rw half_pow_add_succ
80+
... ≤ 2 * half_pow m : hk }},
81+
have Imk : ∀m, ∀k≥m, edist (u m) (u k) ≤ 2 * half_pow m,
82+
{ assume m k hk,
83+
by_cases h : m = k,
84+
{ simp [h, le_of_lt (half_pow_pos k)] },
85+
{ have I : m < k := lt_of_le_of_ne hk h,
86+
have : 0 < k := lt_of_le_of_lt (nat.zero_le _) ‹m < k›,
87+
let l := nat.pred k,
88+
have : k = l+1 := (nat.succ_pred_eq_of_pos ‹0 < k›).symm,
89+
rw this,
90+
have : m ≤ l := begin rw this at I, apply nat.le_of_lt_succ I end,
91+
calc edist (u m) (u (l+1)) ≤ half_pow l + edist (u m) (u (l+1)) : le_add_left (le_refl _)
92+
... ≤ 2 * half_pow m : ineq_rec m l ‹m ≤ l› }},
93+
by_cases h : k ≤ l,
94+
{ calc edist (u k) (u l) ≤ 2 * half_pow k : Imk k l h
95+
... ≤ 2 * half_pow N :
96+
canonically_ordered_semiring.mul_le_mul (le_refl _) (half_pow_mono N k hk) },
97+
{ simp at h,
98+
calc edist (u k) (u l) = edist (u l) (u k) : edist_comm _ _
99+
... ≤ 2 * half_pow l : Imk l k (le_of_lt h)
100+
... ≤ 2 * half_pow N :
101+
canonically_ordered_semiring.mul_le_mul (le_refl _) (half_pow_mono N l hl) }
102+
end
103+
104+
lemma cauchy_seq_of_edist_le_half_pow [emetric_space β]
105+
{u : ℕ → β} (h : ∀n, edist (u n) (u (n+1)) ≤ half_pow n) : cauchy_seq u :=
106+
begin
107+
refine emetric.cauchy_seq_iff_le_tendsto_0.2 ⟨λn:ℕ, 2 * half_pow n, ⟨_, _⟩⟩,
108+
{ exact λk l N hk hl, edist_le_two_mul_half_pow hk hl h },
109+
{ have : tendsto (λn, 2 * half_pow n) at_top (nhds (2 * 0)) :=
110+
ennreal.tendsto_mul_right half_pow_tendsto_zero (by simp),
111+
simpa using this }
112+
end
113+
114+
end ennreal
115+
28116
namespace sequentially_complete
29117

30118
section
@@ -37,59 +125,43 @@ We give the argument in the more general setting of emetric spaces, and speciali
37125
metric spaces at the end.
38126
-/
39127
variables [emetric_space β] {f : filter β} (hf : cauchy f) (B : ℕ → ennreal) (hB : ∀n, 0 < B n)
40-
41-
/--A positive sequence that tends to `0` in `ennreal`-/
42-
noncomputable def F (n : ℕ) : ennreal := nnreal.of_real (1 / ((n : ℝ) + 1))
43-
44-
lemma F_pos (n : ℕ) : 0 < F n :=
45-
begin
46-
simp only [F, -one_div_eq_inv, ennreal.zero_lt_coe_iff, add_comm, ennreal.zero_lt_coe_iff, add_comm, nnreal.of_real_pos],
47-
apply one_div_pos_of_pos,
48-
have : (↑n : ℝ) ≥ 0 := nat.cast_nonneg _,
49-
by linarith
50-
end
51-
52-
lemma F_lim : tendsto (λn, F n) at_top (nhds 0) :=
53-
begin
54-
unfold F,
55-
rw [← ennreal.coe_zero, ennreal.tendsto_coe, ← nnreal.of_real_zero],
56-
exact nnreal.tendsto_of_real tendsto_one_div_add_at_top_nhds_0_nat
57-
end
128+
open ennreal
58129

59130
/--Auxiliary sequence, which is bounded by `B`, positive, and tends to `0`.-/
60-
noncomputable def FB (B : ℕ → ennreal) (hB : ∀n, 0 < B n) (n : ℕ) :=
61-
(F n) ⊓ (B n)
131+
noncomputable def B2 (B : ℕ → ennreal) (hB : ∀n, 0 < B n) (n : ℕ) :=
132+
(half_pow n) ⊓ (B n)
62133

63-
lemma FB_pos (n : ℕ) : 0 < (FB B hB n) :=
64-
by unfold FB; simp [F_pos n, hB n]
134+
lemma B2_pos (n : ℕ) : 0 < B2 B hB n :=
135+
by unfold B2; simp [half_pow_pos n, hB n]
65136

66-
lemma FB_lim : tendsto (λn, FB B hB n) at_top (nhds 0) :=
137+
lemma B2_lim : tendsto (λn, B2 B hB n) at_top (nhds 0) :=
67138
begin
68-
have : ∀n, FB B hB n ≤ F n := λn, lattice.inf_le_left,
69-
exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds F_lim (by simp) (by simp [this])
139+
have : ∀n, B2 B hB n ≤ half_pow n := λn, lattice.inf_le_left,
140+
exact tendsto_of_tendsto_of_tendsto_of_le_of_le tendsto_const_nhds half_pow_tendsto_zero
141+
(by simp) (by simp [this])
70142
end
71143

72-
/-- Define a decreasing sequence of sets in the filter `f`, of diameter bounded by `FB n`. -/
144+
/-- Define a decreasing sequence of sets in the filter `f`, of diameter bounded by `B2 n`. -/
73145
def set_seq_of_cau_filter : ℕ → set β
74-
| 0 := some ((emetric.cauchy_iff.1 hf).2 _ (FB_pos B hB 0))
75-
| (n+1) := (set_seq_of_cau_filter n) ∩ some ((emetric.cauchy_iff.1 hf).2 _ (FB_pos B hB (n + 1)))
146+
| 0 := some ((emetric.cauchy_iff.1 hf).2 _ (B2_pos B hB 0))
147+
| (n+1) := (set_seq_of_cau_filter n) ∩ some ((emetric.cauchy_iff.1 hf).2 _ (B2_pos B hB (n + 1)))
76148

77149
/-- These sets are in the filter. -/
78150
lemma set_seq_of_cau_filter_mem_sets : ∀ n, set_seq_of_cau_filter hf B hB n ∈ f.sets
79-
| 0 := some (some_spec ((emetric.cauchy_iff.1 hf).2 _ (FB_pos B hB 0)))
151+
| 0 := some (some_spec ((emetric.cauchy_iff.1 hf).2 _ (B2_pos B hB 0)))
80152
| (n+1) := inter_mem_sets (set_seq_of_cau_filter_mem_sets n)
81-
(some (some_spec ((emetric.cauchy_iff.1 hf).2 _ (FB_pos B hB (n + 1)))))
153+
(some (some_spec ((emetric.cauchy_iff.1 hf).2 _ (B2_pos B hB (n + 1)))))
82154

83155
/-- These sets are nonempty. -/
84156
lemma set_seq_of_cau_filter_inhabited (n : ℕ) : ∃ x, x ∈ set_seq_of_cau_filter hf B hB n :=
85157
inhabited_of_mem_sets (emetric.cauchy_iff.1 hf).1 (set_seq_of_cau_filter_mem_sets hf B hB n)
86158

87-
/-- By construction, their diameter is controlled by `FB n`. -/
159+
/-- By construction, their diameter is controlled by `B2 n`. -/
88160
lemma set_seq_of_cau_filter_spec : ∀ n, ∀ {x y},
89-
x ∈ set_seq_of_cau_filter hf B hB n → y ∈ set_seq_of_cau_filter hf B hB n → edist x y < FB B hB n
90-
| 0 := some_spec (some_spec ((emetric.cauchy_iff.1 hf).2 _ (FB_pos B hB 0)))
161+
x ∈ set_seq_of_cau_filter hf B hB n → y ∈ set_seq_of_cau_filter hf B hB n → edist x y < B2 B hB n
162+
| 0 := some_spec (some_spec ((emetric.cauchy_iff.1 hf).2 _ (B2_pos B hB 0)))
91163
| (n+1) := λ x y hx hy,
92-
some_spec (some_spec ((emetric.cauchy_iff.1 hf).2 _ (FB_pos B hB (n+1)))) x y
164+
some_spec (some_spec ((emetric.cauchy_iff.1 hf).2 _ (B2_pos B hB (n+1)))) x y
93165
(mem_of_mem_inter_right hx) (mem_of_mem_inter_right hy)
94166

95167
-- this must exist somewhere, no?
@@ -121,27 +193,27 @@ some (set_seq_of_cau_filter_inhabited hf B hB n)
121193
lemma seq_of_cau_filter_mem_set_seq (n : ℕ) : seq_of_cau_filter hf B hB n ∈ set_seq_of_cau_filter hf B hB n :=
122194
some_spec (set_seq_of_cau_filter_inhabited hf B hB n)
123195

124-
/-- The distance between points in the sequence is bounded by `FB N`. -/
196+
/-- The distance between points in the sequence is bounded by `B2 N`. -/
125197
lemma seq_of_cau_filter_bound {N n k : ℕ} (hn : N ≤ n) (hk : N ≤ k) :
126-
edist (seq_of_cau_filter hf B hB n) (seq_of_cau_filter hf B hB k) < FB B hB N :=
198+
edist (seq_of_cau_filter hf B hB n) (seq_of_cau_filter hf B hB k) < B2 B hB N :=
127199
set_seq_of_cau_filter_spec hf B hB N
128200
(set_seq_of_cau_filter_monotone hf B hB hn (seq_of_cau_filter_mem_set_seq hf B hB n))
129201
(set_seq_of_cau_filter_monotone hf B hB hk (seq_of_cau_filter_mem_set_seq hf B hB k))
130202

131-
/-- The approximating sequence is indeed Cauchy as `FB n` tends to `0` with `n`. -/
203+
/-- The approximating sequence is indeed Cauchy as `B2 n` tends to `0` with `n`. -/
132204
lemma seq_of_cau_filter_is_cauchy :
133205
cauchy_seq (seq_of_cau_filter hf B hB) :=
134-
emetric.cauchy_seq_iff_le_tendsto_0.2FB B hB,
135-
λ n m N hn hm, le_of_lt (seq_of_cau_filter_bound hf B hB hn hm), FB_lim B hB⟩
206+
emetric.cauchy_seq_iff_le_tendsto_0.2B2 B hB,
207+
λ n m N hn hm, le_of_lt (seq_of_cau_filter_bound hf B hB hn hm), B2_lim B hB⟩
136208

137209
/-- If the approximating Cauchy sequence is converging, to a limit `y`, then the
138210
original Cauchy filter `f` is also converging, to the same limit.
139211
Given `t1` in the filter `f` and `t2` a neighborhood of `y`, it suffices to show that `t1 ∩ t2` is
140212
nonempty.
141213
Pick `ε` so that the ε-eball around `y` is contained in `t2`.
142-
Pick `n` with `FB n < ε/2`, and `n2` such that `dist(seq n2, y) < ε/2`. Let `N = max(n, n2)`.
214+
Pick `n` with `B2 n < ε/2`, and `n2` such that `dist(seq n2, y) < ε/2`. Let `N = max(n, n2)`.
143215
We defined `seq` by looking at a decreasing sequence of sets of `f` with shrinking radius.
144-
The Nth one has radius `< FB N < ε/2`. This set is in `f`, so we can find an element `x` that's
216+
The Nth one has radius `< B2 N < ε/2`. This set is in `f`, so we can find an element `x` that's
145217
also in `t1`.
146218
`dist(x, seq N) < ε/2` since `seq N` is in this set, and `dist (seq N, y) < ε/2`,
147219
so `x` is in the ε-ball around `y`, and thus in `t2`. -/
@@ -154,9 +226,9 @@ begin
154226
rcases emetric.mem_nhds_iff.1 ht2 with ⟨ε, hε, ht2'⟩,
155227
cases emetric.cauchy_iff.1 hf with hfb _,
156228
have : ε / 2 > 0 := ennreal.half_pos hε,
157-
rcases inhabited_of_mem_sets (by simp) ((tendsto_orderable.1 (FB_lim B hB)).2 _ this)
229+
rcases inhabited_of_mem_sets (by simp) ((tendsto_orderable.1 (B2_lim B hB)).2 _ this)
158230
with ⟨n, hnε⟩,
159-
simp only [set.mem_set_of_eq] at hnε, -- hnε : ε / 2 > FB B hB n
231+
simp only [set.mem_set_of_eq] at hnε, -- hnε : ε / 2 > B2 B hB n
160232
cases (emetric.tendsto_at_top _).1 H _ this with n2 hn2,
161233
let N := max n n2,
162234
have ht1sn : t1 ∩ set_seq_of_cau_filter hf B hB N ∈ f.sets,
@@ -170,13 +242,13 @@ begin
170242
(set_seq_of_cau_filter_monotone hf B hB (le_max_left n n2)) (seq_of_cau_filter_mem_set_seq hf B hB N),
171243
have I2 : x ∈ set_seq_of_cau_filter hf B hB n :=
172244
(set_seq_of_cau_filter_monotone hf B hB (le_max_left n n2)) hx.2,
173-
have hdist1 : edist x (seq_of_cau_filter hf B hB N) < FB B hB n :=
245+
have hdist1 : edist x (seq_of_cau_filter hf B hB N) < B2 B hB n :=
174246
set_seq_of_cau_filter_spec hf B hB _ I2 I1,
175247
have hdist2 : edist (seq_of_cau_filter hf B hB N) y < ε / 2 :=
176248
hn2 N (le_max_right _ _),
177249
have hdist : edist x y < ε := calc
178250
edist x y ≤ edist x (seq_of_cau_filter hf B hB N) + edist (seq_of_cau_filter hf B hB N) y : edist_triangle _ _ _
179-
... < FB B hB n + ε/2 : ennreal.add_lt_add hdist1 hdist2
251+
... < B2 B hB n + ε/2 : ennreal.add_lt_add hdist1 hdist2
180252
... ≤ ε/2 + ε/2 : add_le_add_right' (le_of_lt hnε)
181253
... = ε : ennreal.add_halves _,
182254
have hxt2 : x ∈ t2, from ht2' hdist,
@@ -220,7 +292,7 @@ theorem emetric.complete_of_convergent_controlled_sequences {α : Type u} [emetr
220292
let u := sequentially_complete.seq_of_cau_filter hf B hB,
221293
-- It satisfies the required bound.
222294
have : ∀N n m : ℕ, N ≤ n → N ≤ m → edist (u n) (u m) < B N := λN n m hn hm, calc
223-
edist (u n) (u m) < sequentially_complete.FB B hB N :
295+
edist (u n) (u m) < sequentially_complete.B2 B hB N :
224296
sequentially_complete.seq_of_cau_filter_bound hf B hB hn hm
225297
... ≤ B N : lattice.inf_le_right,
226298
-- Therefore, it converges by assumption. Let `x` be its limit.

0 commit comments

Comments
 (0)