l3lab/ntp-mathlib huggingface dataset:
private theorem eq_of_glueDist_eq_zero (Φ : Z → X) (Ψ : Z → Y) (ε : ℝ) (ε0 : 0 < ε) :
    ∀ p q : Sum X Y, glueDist Φ Ψ ε p q = 0 → p = q
  | .inl x, .inl y, h => by rw [eq_of_dist_eq_zero h]
  | .inl x, .inr y, h => by exfalso; linarith [le_glueDist_inl_inr Φ Ψ ε x y]
  | .inr x, .inl y, h => by exfalso; linarith [le_glueDist_inr_inl Φ Ψ ε x y]
  | .inr x, .inr y, h => by 

Proof state:
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ✝ : Z → X
Ψ✝ : Z → Y
ε✝ : ℝ
inst✝ : Nonempty Z
Φ : Z → X
Ψ : Z → Y
ε : ℝ
ε0 : 0 < ε
x y : Y
h : glueDist Φ Ψ ε (Sum.inr x) (Sum.inr y) = 0
⊢ Sum.inr x = Sum.inr y

Next tactic:
rw [eq_of_dist_eq_zero h]
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  

Proof state:
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
⊢ s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε a b < δ → (a, b) ∈ s

Next tactic:
simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  

Proof state:
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
⊢ ((∃ ε > 0, ∀ {a b : X}, dist a b < ε → (Sum.inl a, Sum.inl b) ∈ s) ∧
      ∃ ε > 0, ∀ {a b : Y}, dist a b < ε → (Sum.inr a, Sum.inr b) ∈ s) ↔
    ∃ δ > 0, ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε a b < δ → (a, b) ∈ s

Next tactic:
constructor
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · 

Proof state:
case mp
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
⊢ ((∃ ε > 0, ∀ {a b : X}, dist a b < ε → (Sum.inl a, Sum.inl b) ∈ s) ∧
      ∃ ε > 0, ∀ {a b : Y}, dist a b < ε → (Sum.inr a, Sum.inr b) ∈ s) →
    ∃ δ > 0, ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε a b < δ → (a, b) ∈ s

Next tactic:
rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    

Proof state:
case mp.intro.intro.intro.intro.intro
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
⊢ ∃ δ > 0, ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε a b < δ → (a, b) ∈ s

Next tactic:
refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    

Proof state:
case mp.intro.intro.intro.intro.intro
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
⊢ ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε a b < min (min δX δY) ε → (a, b) ∈ s

Next tactic:
rintro (a | a) (b | b) h
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> 

Proof state:
case mp.intro.intro.intro.intro.intro.inl.inl
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a b : X
h : glueDist Φ Ψ ε (Sum.inl a) (Sum.inl b) < min (min δX δY) ε
⊢ (Sum.inl a, Sum.inl b) ∈ s

Next tactic:
simp only [lt_min_iff] at h
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> 

Proof state:
case mp.intro.intro.intro.intro.intro.inl.inr
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a : X
b : Y
h : glueDist Φ Ψ ε (Sum.inl a) (Sum.inr b) < min (min δX δY) ε
⊢ (Sum.inl a, Sum.inr b) ∈ s

Next tactic:
simp only [lt_min_iff] at h
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> 

Proof state:
case mp.intro.intro.intro.intro.intro.inr.inl
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a : Y
b : X
h : glueDist Φ Ψ ε (Sum.inr a) (Sum.inl b) < min (min δX δY) ε
⊢ (Sum.inr a, Sum.inl b) ∈ s

Next tactic:
simp only [lt_min_iff] at h
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> 

Proof state:
case mp.intro.intro.intro.intro.intro.inr.inr
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a b : Y
h : glueDist Φ Ψ ε (Sum.inr a) (Sum.inr b) < min (min δX δY) ε
⊢ (Sum.inr a, Sum.inr b) ∈ s

Next tactic:
simp only [lt_min_iff] at h
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · 

Proof state:
case mp.intro.intro.intro.intro.intro.inl.inl
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a b : X
h :
  (glueDist Φ Ψ ε (Sum.inl a) (Sum.inl b) < δX ∧ glueDist Φ Ψ ε (Sum.inl a) (Sum.inl b) < δY) ∧
    glueDist Φ Ψ ε (Sum.inl a) (Sum.inl b) < ε
⊢ (Sum.inl a, Sum.inl b) ∈ s

Next tactic:
exact hX h.1.1
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · 

Proof state:
case mp.intro.intro.intro.intro.intro.inl.inr
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a : X
b : Y
h :
  (glueDist Φ Ψ ε (Sum.inl a) (Sum.inr b) < δX ∧ glueDist Φ Ψ ε (Sum.inl a) (Sum.inr b) < δY) ∧
    glueDist Φ Ψ ε (Sum.inl a) (Sum.inr b) < ε
⊢ (Sum.inl a, Sum.inr b) ∈ s

Next tactic:
exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
    · 

Proof state:
case mp.intro.intro.intro.intro.intro.inr.inl
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a : Y
b : X
h :
  (glueDist Φ Ψ ε (Sum.inr a) (Sum.inl b) < δX ∧ glueDist Φ Ψ ε (Sum.inr a) (Sum.inl b) < δY) ∧
    glueDist Φ Ψ ε (Sum.inr a) (Sum.inl b) < ε
⊢ (Sum.inr a, Sum.inl b) ∈ s

Next tactic:
exact absurd h.2 (le_glueDist_inr_inl _ _ _ _ _).not_lt
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
    · exact absurd h.2 (le_glueDist_inr_inl _ _ _ _ _).not_lt
    · 

Proof state:
case mp.intro.intro.intro.intro.intro.inr.inr
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
δX : ℝ
δX0 : δX > 0
hX : ∀ {a b : X}, dist a b < δX → (Sum.inl a, Sum.inl b) ∈ s
δY : ℝ
δY0 : δY > 0
hY : ∀ {a b : Y}, dist a b < δY → (Sum.inr a, Sum.inr b) ∈ s
a b : Y
h :
  (glueDist Φ Ψ ε (Sum.inr a) (Sum.inr b) < δX ∧ glueDist Φ Ψ ε (Sum.inr a) (Sum.inr b) < δY) ∧
    glueDist Φ Ψ ε (Sum.inr a) (Sum.inr b) < ε
⊢ (Sum.inr a, Sum.inr b) ∈ s

Next tactic:
exact hY h.1.2
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
    · exact absurd h.2 (le_glueDist_inr_inl _ _ _ _ _).not_lt
    · exact hY h.1.2
  · 

Proof state:
case mpr
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε : ℝ
inst✝ : Nonempty Z
hε : 0 < ε
s : Set ((X ⊕ Y) × (X ⊕ Y))
⊢ (∃ δ > 0, ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε a b < δ → (a, b) ∈ s) →
    (∃ ε > 0, ∀ {a b : X}, dist a b < ε → (Sum.inl a, Sum.inl b) ∈ s) ∧
      ∃ ε > 0, ∀ {a b : Y}, dist a b < ε → (Sum.inr a, Sum.inr b) ∈ s

Next tactic:
rintro ⟨ε, ε0, H⟩
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
    · exact absurd h.2 (le_glueDist_inr_inl _ _ _ _ _).not_lt
    · exact hY h.1.2
  · rintro ⟨ε, ε0, H⟩
    

Proof state:
case mpr.intro.intro
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε✝ : ℝ
inst✝ : Nonempty Z
hε : 0 < ε✝
s : Set ((X ⊕ Y) × (X ⊕ Y))
ε : ℝ
ε0 : ε > 0
H : ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε✝ a b < ε → (a, b) ∈ s
⊢ (∃ ε > 0, ∀ {a b : X}, dist a b < ε → (Sum.inl a, Sum.inl b) ∈ s) ∧
    ∃ ε > 0, ∀ {a b : Y}, dist a b < ε → (Sum.inr a, Sum.inr b) ∈ s

Next tactic:
constructor
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
    · exact absurd h.2 (le_glueDist_inr_inl _ _ _ _ _).not_lt
    · exact hY h.1.2
  · rintro ⟨ε, ε0, H⟩
    constructor <;> 

Proof state:
case mpr.intro.intro.left
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε✝ : ℝ
inst✝ : Nonempty Z
hε : 0 < ε✝
s : Set ((X ⊕ Y) × (X ⊕ Y))
ε : ℝ
ε0 : ε > 0
H : ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε✝ a b < ε → (a, b) ∈ s
⊢ ∃ ε > 0, ∀ {a b : X}, dist a b < ε → (Sum.inl a, Sum.inl b) ∈ s

Next tactic:
exact ⟨ε, ε0, fun h => H _ _ h⟩
theorem Sum.mem_uniformity_iff_glueDist (hε : 0 < ε) (s : Set ((X ⊕ Y) × (X ⊕ Y))) :
    s ∈ 𝓤 (X ⊕ Y) ↔ ∃ δ > 0, ∀ a b, glueDist Φ Ψ ε a b < δ → (a, b) ∈ s := by
  simp only [Sum.uniformity, Filter.mem_sup, Filter.mem_map, mem_uniformity_dist, mem_preimage]
  constructor
  · rintro ⟨⟨δX, δX0, hX⟩, δY, δY0, hY⟩
    refine ⟨min (min δX δY) ε, lt_min (lt_min δX0 δY0) hε, ?_⟩
    rintro (a | a) (b | b) h <;> simp only [lt_min_iff] at h
    · exact hX h.1.1
    · exact absurd h.2 (le_glueDist_inl_inr _ _ _ _ _).not_lt
    · exact absurd h.2 (le_glueDist_inr_inl _ _ _ _ _).not_lt
    · exact hY h.1.2
  · rintro ⟨ε, ε0, H⟩
    constructor <;> 

Proof state:
case mpr.intro.intro.right
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ : Z → X
Ψ : Z → Y
ε✝ : ℝ
inst✝ : Nonempty Z
hε : 0 < ε✝
s : Set ((X ⊕ Y) × (X ⊕ Y))
ε : ℝ
ε0 : ε > 0
H : ∀ (a b : X ⊕ Y), glueDist Φ Ψ ε✝ a b < ε → (a, b) ∈ s
⊢ ∃ ε > 0, ∀ {a b : Y}, dist a b < ε → (Sum.inr a, Sum.inr b) ∈ s

Next tactic:
exact ⟨ε, ε0, fun h => H _ _ h⟩
/-- Given two maps `Φ` and `Ψ` intro metric spaces `X` and `Y` such that the distances between
`Φ p` and `Φ q`, and between `Ψ p` and `Ψ q`, coincide up to `2 ε` where `ε > 0`, one can almost
glue the two spaces `X` and `Y` along the images of `Φ` and `Ψ`, so that `Φ p` and `Ψ p` are
at distance `ε`. -/
def glueMetricApprox (Φ : Z → X) (Ψ : Z → Y) (ε : ℝ) (ε0 : 0 < ε)
    (H : ∀ p q, |dist (Φ p) (Φ q) - dist (Ψ p) (Ψ q)| ≤ 2 * ε) : MetricSpace (X ⊕ Y) where
  dist := glueDist Φ Ψ ε
  dist_self := glueDist_self Φ Ψ ε
  dist_comm := glueDist_comm Φ Ψ ε
  dist_triangle := glueDist_triangle Φ Ψ ε H
  edist_dist _ _ := by 

Proof state:
X : Type u
Y : Type v
Z : Type w
inst✝² : MetricSpace X
inst✝¹ : MetricSpace Y
Φ✝ : Z → X
Ψ✝ : Z → Y
ε✝ : ℝ
inst✝ : Nonempty Z
Φ : Z → X
Ψ : Z → Y
ε : ℝ
ε0 : 0 < ε
H : ∀ (p q : Z), |dist (Φ p) (Φ q) - dist (Ψ p) (Ψ q)| ≤ 2 * ε
x✝¹ x✝ : X ⊕ Y
⊢ (fun x y => ↑{ val := glueDist Φ Ψ ε x y, property := (_ : 0 ≤ glueDist Φ Ψ ε x y) }) x✝¹ x✝ =
    ENNReal.ofReal (dist x✝¹ x✝)

Next tactic:
exact ENNReal.coe_nnreal_eq _
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  

Proof state:
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
p q : X ⊕ Y
x : X
y : Y
⊢ Sum.dist p q = glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 p q

Next tactic:
cases p
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> 

Proof state:
case inl
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
q : X ⊕ Y
x : X
y : Y
val✝ : X
⊢ Sum.dist (Sum.inl val✝) q =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inl val✝) q

Next tactic:
cases q
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> 

Proof state:
case inr
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
q : X ⊕ Y
x : X
y val✝ : Y
⊢ Sum.dist (Sum.inr val✝) q =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inr val✝) q

Next tactic:
cases q
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> 

Proof state:
case inl.inl
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y : Y
val✝¹ val✝ : X
⊢ Sum.dist (Sum.inl val✝¹) (Sum.inl val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inl val✝¹)
      (Sum.inl val✝)

Next tactic:
first |rfl|simp [Sum.dist, glueDist, dist_comm, add_comm,
    add_left_comm, add_assoc]
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> first |

Proof state:
case inl.inl
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y : Y
val✝¹ val✝ : X
⊢ Sum.dist (Sum.inl val✝¹) (Sum.inl val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inl val✝¹)
      (Sum.inl val✝)

Next tactic:
rfl
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> 

Proof state:
case inl.inr
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y : Y
val✝¹ : X
val✝ : Y
⊢ Sum.dist (Sum.inl val✝¹) (Sum.inr val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inl val✝¹)
      (Sum.inr val✝)

Next tactic:
first |rfl|simp [Sum.dist, glueDist, dist_comm, add_comm,
    add_left_comm, add_assoc]
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> first |

Proof state:
case inl.inr
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y : Y
val✝¹ : X
val✝ : Y
⊢ Sum.dist (Sum.inl val✝¹) (Sum.inr val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inl val✝¹)
      (Sum.inr val✝)

Next tactic:
rfl
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> first |rfl|

Proof state:
case inl.inr
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y : Y
val✝¹ : X
val✝ : Y
⊢ Sum.dist (Sum.inl val✝¹) (Sum.inr val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inl val✝¹)
      (Sum.inr val✝)

Next tactic:
simp [Sum.dist, glueDist, dist_comm, add_comm,
    add_left_comm, add_assoc]
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> 

Proof state:
case inr.inl
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y val✝¹ : Y
val✝ : X
⊢ Sum.dist (Sum.inr val✝¹) (Sum.inl val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inr val✝¹)
      (Sum.inl val✝)

Next tactic:
first |rfl|simp [Sum.dist, glueDist, dist_comm, add_comm,
    add_left_comm, add_assoc]
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> first |

Proof state:
case inr.inl
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y val✝¹ : Y
val✝ : X
⊢ Sum.dist (Sum.inr val✝¹) (Sum.inl val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inr val✝¹)
      (Sum.inl val✝)

Next tactic:
rfl
theorem Sum.dist_eq_glueDist {p q : X ⊕ Y} (x : X) (y : Y) :
    Sum.dist p q =
      glueDist (fun _ : Unit => Nonempty.some ⟨x⟩) (fun _ : Unit => Nonempty.some ⟨y⟩) 1 p q := by
  cases p <;> cases q <;> first |rfl|

Proof state:
case inr.inl
X : Type u
Y : Type v
Z : Type w
inst✝¹ : MetricSpace X
inst✝ : MetricSpace Y
x : X
y val✝¹ : Y
val✝ : X
⊢ Sum.dist (Sum.inr val✝¹) (Sum.inl val✝) =
    glueDist (fun x_1 => Nonempty.some (_ : Nonempty X)) (fun x => Nonempty.some (_ : Nonempty Y)) 1 (Sum.inr val✝¹)
      (Sum.inl val✝)

Next tactic:
simp [Sum.dist, glueDist, dist_comm, add_comm,
    add_left_comm, add_assoc]