Skip to content

Commit 3e979fb

Browse files
committed
feat(MetricSpace/Ultra): IsUltrametricDist and basic facts on open/closed sets in such spaces (#14433)
TODO in future PRs - add "all triangles are isosceles" in such normed spaces - totally disconnected space - give instances of this to Z_p, Q_p, etc Co-authored-by: Yakov Pechersky <pechersky@users.noreply.github.com>
1 parent 863c4af commit 3e979fb

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4439,6 +4439,7 @@ import Mathlib.Topology.MetricSpace.Sequences
44394439
import Mathlib.Topology.MetricSpace.ShrinkingLemma
44404440
import Mathlib.Topology.MetricSpace.ThickenedIndicator
44414441
import Mathlib.Topology.MetricSpace.Thickening
4442+
import Mathlib.Topology.MetricSpace.Ultra.Basic
44424443
import Mathlib.Topology.Metrizable.Basic
44434444
import Mathlib.Topology.Metrizable.ContinuousMap
44444445
import Mathlib.Topology.Metrizable.Uniformity
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/-
2+
Copyright (c) 2024 Yakov Pechersky. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Yakov Pechersky
5+
-/
6+
import Mathlib.Topology.MetricSpace.Pseudo.Lemmas
7+
8+
/-!
9+
## Ultrametric spaces
10+
11+
This file defines ultrametric spaces, implemented as a mixin on the `Dist`,
12+
so that it can apply on pseudometric spaces as well.
13+
14+
## Main definitions
15+
16+
* `IsUltrametricDist X`: Annotates `dist : X → X → ℝ` as respecting the ultrametric inequality
17+
of `dist(x, z) ≤ max {dist(x,y), dist(y,z)}`
18+
19+
## Implementation details
20+
21+
The mixin could have been defined as a hypothesis to be carried around, instead of relying on
22+
typeclass synthesis. However, since we declare a (pseudo)metric space on a type using
23+
typeclass arguments, one can declare the ultrametricity at the same time.
24+
For example, one could say `[Norm K] [Fact (IsNonarchimedean (norm : K → ℝ))]`,
25+
26+
The file imports a later file in the hierarchy of pseudometric spaces, since
27+
`Metric.isClosed_ball` and `Metric.isClosed_sphere` is proven in a later file
28+
using more conceptual results.
29+
30+
TODO: Generalize to ultrametric uniformities
31+
32+
## Tags
33+
34+
ultrametric, nonarchimedean
35+
-/
36+
37+
variable {X : Type*}
38+
39+
/-- The `dist : X → X → ℝ` respects the ultrametric inequality
40+
of `dist(x, z) ≤ max (dist(x,y)) (dist(y,z))`. -/
41+
class IsUltrametricDist (X : Type*) [Dist X] : Prop where
42+
dist_triangle_max : ∀ x y z : X, dist x z ≤ max (dist x y) (dist y z)
43+
44+
open Metric
45+
46+
variable [PseudoMetricSpace X] [IsUltrametricDist X] (x y z : X) (r s : ℝ)
47+
48+
lemma dist_triangle_max : dist x z ≤ max (dist x y) (dist y z) :=
49+
IsUltrametricDist.dist_triangle_max x y z
50+
51+
namespace IsUltrametricDist
52+
53+
lemma ball_eq_of_mem {x y : X} {r : ℝ} (h : y ∈ ball x r) : ball x r = ball y r := by
54+
ext a
55+
simp_rw [mem_ball] at h ⊢
56+
constructor <;> intro h' <;>
57+
exact (dist_triangle_max _ _ _).trans_lt (max_lt h' (dist_comm x _ ▸ h))
58+
59+
lemma mem_ball_iff {x y: X} {r : ℝ} : y ∈ ball x r ↔ x ∈ ball y r := by
60+
cases lt_or_le 0 r with
61+
| inl hr =>
62+
constructor <;> intro h <;>
63+
rw [← ball_eq_of_mem h] <;>
64+
simp [hr]
65+
| inr hr => simp [ball_eq_empty.mpr hr]
66+
67+
lemma ball_subset_trichotomy :
68+
ball x r ⊆ ball y s ∨ ball y s ⊆ ball x r ∨ Disjoint (ball x r) (ball y s) := by
69+
wlog hrs : r ≤ s generalizing x y r s
70+
· rw [disjoint_comm, ← or_assoc, or_comm (b := _ ⊆ _), or_assoc]
71+
exact this y x s r (lt_of_not_le hrs).le
72+
· refine Set.disjoint_or_nonempty_inter (ball x r) (ball y s) |>.symm.imp (fun h ↦ ?_) (Or.inr ·)
73+
obtain ⟨hxz, hyz⟩ := (Set.mem_inter_iff _ _ _).mp h.some_mem
74+
have hx := ball_subset_ball hrs (x := x)
75+
rwa [ball_eq_of_mem hyz |>.trans (ball_eq_of_mem <| hx hxz).symm]
76+
77+
lemma ball_eq_or_disjoint :
78+
ball x r = ball y r ∨ Disjoint (ball x r) (ball y r) := by
79+
refine Set.disjoint_or_nonempty_inter (ball x r) (ball y r) |>.symm.imp (fun h ↦ ?_) id
80+
have h₁ := ball_eq_of_mem <| Set.inter_subset_left h.some_mem
81+
have h₂ := ball_eq_of_mem <| Set.inter_subset_right h.some_mem
82+
exact h₁.trans h₂.symm
83+
84+
lemma closedBall_eq_of_mem {x y: X} {r : ℝ} (h : y ∈ closedBall x r) :
85+
closedBall x r = closedBall y r := by
86+
ext
87+
simp_rw [mem_closedBall] at h ⊢
88+
constructor <;> intro h' <;>
89+
exact (dist_triangle_max _ _ _).trans (max_le h' (dist_comm x _ ▸ h))
90+
91+
lemma mem_closedBall_iff {x y: X} {r : ℝ} :
92+
y ∈ closedBall x r ↔ x ∈ closedBall y r := by
93+
cases le_or_lt 0 r with
94+
| inl hr =>
95+
constructor <;> intro h <;>
96+
rw [← closedBall_eq_of_mem h] <;>
97+
simp [hr]
98+
| inr hr => simp [closedBall_eq_empty.mpr hr]
99+
100+
lemma closedBall_subset_trichotomy :
101+
closedBall x r ⊆ closedBall y s ∨ closedBall y s ⊆ closedBall x r ∨
102+
Disjoint (closedBall x r) (closedBall y s) := by
103+
wlog hrs : r ≤ s generalizing x y r s
104+
· rw [disjoint_comm, ← or_assoc, or_comm (b := _ ⊆ _), or_assoc]
105+
exact this y x s r (lt_of_not_le hrs).le
106+
· refine Set.disjoint_or_nonempty_inter (closedBall x r) (closedBall y s) |>.symm.imp
107+
(fun h ↦ ?_) (Or.inr ·)
108+
obtain ⟨hxz, hyz⟩ := (Set.mem_inter_iff _ _ _).mp h.some_mem
109+
have hx := closedBall_subset_closedBall hrs (x := x)
110+
rwa [closedBall_eq_of_mem hyz |>.trans (closedBall_eq_of_mem <| hx hxz).symm]
111+
112+
lemma isClosed_ball (x : X) (r : ℝ) : IsClosed (ball x r) := by
113+
cases le_or_lt r 0 with
114+
| inl hr =>
115+
simp [ball_eq_empty.mpr hr]
116+
| inr h =>
117+
rw [← isOpen_compl_iff, isOpen_iff]
118+
simp only [Set.mem_compl_iff, not_lt, gt_iff_lt]
119+
intro y hy
120+
cases ball_eq_or_disjoint x y r with
121+
| inl hd =>
122+
rw [hd] at hy
123+
simp [h.not_le] at hy
124+
| inr hd =>
125+
use r
126+
simp [h, hy, ← Set.le_iff_subset, le_compl_iff_disjoint_left, hd]
127+
128+
lemma isClopen_ball : IsClopen (ball x r) := ⟨isClosed_ball x r, isOpen_ball⟩
129+
130+
lemma frontier_ball_eq_empty : frontier (ball x r) = ∅ :=
131+
isClopen_iff_frontier_eq_empty.mp (isClopen_ball x r)
132+
133+
lemma closedBall_eq_or_disjoint :
134+
closedBall x r = closedBall y r ∨ Disjoint (closedBall x r) (closedBall y r) := by
135+
refine Set.disjoint_or_nonempty_inter (closedBall x r) (closedBall y r) |>.symm.imp
136+
(fun h ↦ ?_) id
137+
have h₁ := closedBall_eq_of_mem <| Set.inter_subset_left h.some_mem
138+
have h₂ := closedBall_eq_of_mem <| Set.inter_subset_right h.some_mem
139+
exact h₁.trans h₂.symm
140+
141+
lemma isOpen_closedBall {r : ℝ} (hr : r ≠ 0) : IsOpen (closedBall x r) := by
142+
cases lt_or_gt_of_ne hr with
143+
| inl h =>
144+
simp [closedBall_eq_empty.mpr h]
145+
| inr h =>
146+
rw [isOpen_iff]
147+
simp only [Set.mem_compl_iff, not_lt, gt_iff_lt]
148+
intro y hy
149+
cases closedBall_eq_or_disjoint x y r with
150+
| inl hd =>
151+
use r
152+
simp [h, hd, ball_subset_closedBall]
153+
| inr hd =>
154+
simp [closedBall_eq_of_mem hy, h.not_lt] at hd
155+
156+
lemma isClopen_closedBall {r : ℝ} (hr : r ≠ 0) : IsClopen (closedBall x r) :=
157+
⟨Metric.isClosed_ball, isOpen_closedBall x hr⟩
158+
159+
lemma frontier_closedBall_eq_empty {r : ℝ} (hr : r ≠ 0) : frontier (closedBall x r) = ∅ :=
160+
isClopen_iff_frontier_eq_empty.mp (isClopen_closedBall x hr)
161+
162+
lemma isOpen_sphere {r : ℝ} (hr : r ≠ 0) : IsOpen (sphere x r) := by
163+
rw [← closedBall_diff_ball, sdiff_eq]
164+
exact (isOpen_closedBall x hr).inter (isClosed_ball x r).isOpen_compl
165+
166+
lemma isClopen_sphere {r : ℝ} (hr : r ≠ 0) : IsClopen (sphere x r) :=
167+
⟨Metric.isClosed_sphere, isOpen_sphere x hr⟩
168+
169+
end IsUltrametricDist

0 commit comments

Comments
 (0)