l3lab/ntp-mathlib huggingface dataset:
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    

Proof state:
case intro.intro.intro.intro.intro.intro.intro.mk.intro.intro.intro.mk.intro.intro
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α) × Quotient (separationSetoid α))
hs : s ∈ map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
U : Set (α × α)
hU : U ∈ 𝓤 α
hUo : IsOpen U
hUs : U ○ U ⊆ (fun p => (⟦p.1⟧, ⟦p.2⟧)) ⁻¹' s
x y : α
hxyU : (x, y) ∈ U
y' z : α
hyzU : (y', z) ∈ U
hy : ⟦(y', z).1⟧ = ⟦(x, y).2⟧
this : y' ⤳ y
⊢ (⟦(x, y).1⟧, ⟦(y', z).2⟧) ∈ s

Next tactic:
exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
  isOpen_uniformity s := isOpen_coinduced.trans <| by
    

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α))
⊢ IsOpen (Quotient.mk' ⁻¹' s) ↔
    ∀ x ∈ s,
      {p | p.1 = x → p.2 ∈ s} ∈
        { uniformity := map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α),
            refl := (_ : 𝓟 idRel ≤ map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)),
            symm := (_ : Tendsto Prod.swap (map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)) (map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α))),
            comp :=
              (_ :
                ∀ s ∈ map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α),
                  s ∈ Filter.lift' (map (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)) fun s => s ○ s) }.uniformity

Next tactic:
simp only [_root_.isOpen_uniformity, Quotient.forall, mem_map', mem_setOf_eq]
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
  isOpen_uniformity s := isOpen_coinduced.trans <| by
    simp only [_root_.isOpen_uniformity, Quotient.forall, mem_map', mem_setOf_eq]
    

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α))
⊢ (∀ x ∈ Quotient.mk' ⁻¹' s, {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s} ∈ 𝓤 α) ↔
    ∀ (a : α), ⟦a⟧ ∈ s → {x | ⟦x.1⟧ = ⟦a⟧ → ⟦x.2⟧ ∈ s} ∈ 𝓤 α

Next tactic:
refine forall₂_congr fun x _ => ⟨fun h => ?_, fun h => mem_of_superset h ?_⟩
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
  isOpen_uniformity s := isOpen_coinduced.trans <| by
    simp only [_root_.isOpen_uniformity, Quotient.forall, mem_map', mem_setOf_eq]
    refine forall₂_congr fun x _ => ⟨fun h => ?_, fun h => mem_of_superset h ?_⟩
    · 

Proof state:
case refine_1
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α))
x : α
x✝ : x ∈ Quotient.mk' ⁻¹' s
h : {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s} ∈ 𝓤 α
⊢ {x_1 | ⟦x_1.1⟧ = ⟦x⟧ → ⟦x_1.2⟧ ∈ s} ∈ 𝓤 α

Next tactic:
rcases comp_mem_uniformity_sets h with ⟨t, ht, hts⟩
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
  isOpen_uniformity s := isOpen_coinduced.trans <| by
    simp only [_root_.isOpen_uniformity, Quotient.forall, mem_map', mem_setOf_eq]
    refine forall₂_congr fun x _ => ⟨fun h => ?_, fun h => mem_of_superset h ?_⟩
    · rcases comp_mem_uniformity_sets h with ⟨t, ht, hts⟩
      

Proof state:
case refine_1.intro.intro
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α))
x : α
x✝ : x ∈ Quotient.mk' ⁻¹' s
h : {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s} ∈ 𝓤 α
t : Set (α × α)
ht : t ∈ 𝓤 α
hts : t ○ t ⊆ {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s}
⊢ {x_1 | ⟦x_1.1⟧ = ⟦x⟧ → ⟦x_1.2⟧ ∈ s} ∈ 𝓤 α

Next tactic:
refine mem_of_superset ht fun (y, z) hyz hyx => @hts (x, z) ⟨y, ?_, hyz⟩ rfl
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
  isOpen_uniformity s := isOpen_coinduced.trans <| by
    simp only [_root_.isOpen_uniformity, Quotient.forall, mem_map', mem_setOf_eq]
    refine forall₂_congr fun x _ => ⟨fun h => ?_, fun h => mem_of_superset h ?_⟩
    · rcases comp_mem_uniformity_sets h with ⟨t, ht, hts⟩
      refine mem_of_superset ht fun (y, z) hyz hyx => @hts (x, z) ⟨y, ?_, hyz⟩ rfl
      

Proof state:
case refine_1.intro.intro
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α))
x : α
x✝¹ : x ∈ Quotient.mk' ⁻¹' s
h : {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s} ∈ 𝓤 α
t : Set (α × α)
ht : t ∈ 𝓤 α
hts : t ○ t ⊆ {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s}
x✝ : α × α
y z : α
hyz : (y, z) ∈ t
hyx : ⟦(y, z).1⟧ = ⟦x⟧
⊢ ((x, z).1, y) ∈ t

Next tactic:
exact Quotient.exact hyx.symm _ ht
instance separationSetoid.uniformSpace {α : Type u} [UniformSpace α] :
    UniformSpace (Quotient (separationSetoid α)) where
  toTopologicalSpace := instTopologicalSpaceQuotient
  uniformity := map (fun p : α × α => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 α)
  refl := le_trans (by simp [Quotient.exists_rep]) (Filter.map_mono refl_le_uniformity)
  symm := tendsto_map' <| tendsto_map.comp tendsto_swap_uniformity
  comp s hs := by
    rcases comp_open_symm_mem_uniformity_sets hs with ⟨U, hU, hUo, -, hUs⟩
    refine' mem_of_superset (mem_lift' <| image_mem_map hU) ?_
    simp only [subset_def, Prod.forall, mem_compRel, mem_image, Prod.ext_iff]
    rintro _ _ ⟨_, ⟨⟨x, y⟩, hxyU, rfl, rfl⟩, ⟨⟨y', z⟩, hyzU, hy, rfl⟩⟩
    have : y' ⤳ y := separationRel_iff_specializes.1 (Quotient.exact hy)
    exact @hUs (x, z) ⟨y', this.mem_open (UniformSpace.isOpen_ball _ hUo) hxyU, hyzU⟩
  isOpen_uniformity s := isOpen_coinduced.trans <| by
    simp only [_root_.isOpen_uniformity, Quotient.forall, mem_map', mem_setOf_eq]
    refine forall₂_congr fun x _ => ⟨fun h => ?_, fun h => mem_of_superset h ?_⟩
    · rcases comp_mem_uniformity_sets h with ⟨t, ht, hts⟩
      refine mem_of_superset ht fun (y, z) hyz hyx => @hts (x, z) ⟨y, ?_, hyz⟩ rfl
      exact Quotient.exact hyx.symm _ ht
    · 

Proof state:
case refine_2
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
s : Set (Quotient (separationSetoid α))
x : α
x✝ : x ∈ Quotient.mk' ⁻¹' s
h : {x_1 | ⟦x_1.1⟧ = ⟦x⟧ → ⟦x_1.2⟧ ∈ s} ∈ 𝓤 α
⊢ {x_1 | ⟦x_1.1⟧ = ⟦x⟧ → ⟦x_1.2⟧ ∈ s} ⊆ {p | p.1 = x → p.2 ∈ Quotient.mk' ⁻¹' s}

Next tactic:
exact fun y hy hyx => hy <| congr_arg _ hyx
theorem uniformContinuous_quotient_lift₂ {f : α → β → γ}
    {h : ∀ a c b d, (a, b) ∈ 𝓢 α → (c, d) ∈ 𝓢 β → f a c = f b d}
    (hf : UniformContinuous fun p : α × β => f p.1 p.2) :
    UniformContinuous fun p : _ × _ => Quotient.lift₂ f h p.1 p.2 := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β → γ
h : ∀ (a : α) (c : β) (b : α) (d : β), (a, b) ∈ 𝓢 α → (c, d) ∈ 𝓢 β → f a c = f b d
hf : UniformContinuous fun p => f p.1 p.2
⊢ UniformContinuous fun p => Quotient.lift₂ f h p.1 p.2

Next tactic:
rw [UniformContinuous, uniformity_prod_eq_prod, uniformity_quotient, uniformity_quotient,
    Filter.prod_map_map_eq, Filter.tendsto_map'_iff, Filter.tendsto_map'_iff]
theorem uniformContinuous_quotient_lift₂ {f : α → β → γ}
    {h : ∀ a c b d, (a, b) ∈ 𝓢 α → (c, d) ∈ 𝓢 β → f a c = f b d}
    (hf : UniformContinuous fun p : α × β => f p.1 p.2) :
    UniformContinuous fun p : _ × _ => Quotient.lift₂ f h p.1 p.2 := by
  rw [UniformContinuous, uniformity_prod_eq_prod, uniformity_quotient, uniformity_quotient,
    Filter.prod_map_map_eq, Filter.tendsto_map'_iff, Filter.tendsto_map'_iff]
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β → γ
h : ∀ (a : α) (c : β) (b : α) (d : β), (a, b) ∈ 𝓢 α → (c, d) ∈ 𝓢 β → f a c = f b d
hf : UniformContinuous fun p => f p.1 p.2
⊢ Tendsto
    (((fun x => (Quotient.lift₂ f h x.1.1 x.1.2, Quotient.lift₂ f h x.2.1 x.2.2)) ∘ fun p =>
        ((p.1.1, p.2.1), p.1.2, p.2.2)) ∘
      fun p => ((⟦p.1.1⟧, ⟦p.1.2⟧), ⟦p.2.1⟧, ⟦p.2.2⟧))
    (𝓤 α ×ˢ 𝓤 β) (𝓤 γ)

Next tactic:
rwa [UniformContinuous, uniformity_prod_eq_prod, Filter.tendsto_map'_iff] at hf
theorem comap_quotient_le_uniformity :
    ((𝓤 <| Quotient <| separationSetoid α).comap fun p : α × α => (⟦p.fst⟧, ⟦p.snd⟧)) ≤ 𝓤 α :=
  ((((𝓤 α).basis_sets.map _).comap _).le_basis_iff uniformity_hasBasis_open).2 fun U hU =>
    ⟨U, hU.1, fun ⟨x, y⟩ ⟨⟨x', y'⟩, hx', h⟩ => by
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
U : Set (α × α)
hU : U ∈ 𝓤 α ∧ IsOpen U
x✝¹ : α × α
x y : α
x✝ : (x, y) ∈ (fun p => (⟦p.1⟧, ⟦p.2⟧)) ⁻¹' ((fun p => (⟦p.1⟧, ⟦p.2⟧)) '' id U)
x' y' : α
hx' : (x', y') ∈ id U
h : (fun p => (⟦p.1⟧, ⟦p.2⟧)) (x', y') = (fun p => (⟦p.1⟧, ⟦p.2⟧)) (x, y)
⊢ (x, y) ∈ id U

Next tactic:
simp only [Prod.ext_iff, Quotient.eq] at h
theorem comap_quotient_le_uniformity :
    ((𝓤 <| Quotient <| separationSetoid α).comap fun p : α × α => (⟦p.fst⟧, ⟦p.snd⟧)) ≤ 𝓤 α :=
  ((((𝓤 α).basis_sets.map _).comap _).le_basis_iff uniformity_hasBasis_open).2 fun U hU =>
    ⟨U, hU.1, fun ⟨x, y⟩ ⟨⟨x', y'⟩, hx', h⟩ => by
      simp only [Prod.ext_iff, Quotient.eq] at h
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
U : Set (α × α)
hU : U ∈ 𝓤 α ∧ IsOpen U
x✝¹ : α × α
x y : α
x✝ : (x, y) ∈ (fun p => (⟦p.1⟧, ⟦p.2⟧)) ⁻¹' ((fun p => (⟦p.1⟧, ⟦p.2⟧)) '' id U)
x' y' : α
hx' : (x', y') ∈ id U
h : x' ≈ x ∧ y' ≈ y
⊢ (x, y) ∈ id U

Next tactic:
exact (((separationRel_iff_inseparable.1 h.1).prod
        (separationRel_iff_inseparable.1 h.2)).mem_open_iff hU.2).1 hx'
instance separated_separation : SeparatedSpace (Quotient (separationSetoid α)) :=
  ⟨Set.ext fun ⟨a, b⟩ =>
      Quotient.inductionOn₂ a b fun a b =>
        ⟨fun h =>
          have : a ≈ b := fun s hs =>
            have :
              s ∈ (𝓤 <| Quotient <| separationSetoid α).comap fun p : α × α => (⟦p.1⟧, ⟦p.2⟧) :=
              comap_quotient_le_uniformity hs
            let ⟨t, ht, hts⟩ := this
            hts (by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
x✝ : Quotient (separationSetoid α) × Quotient (separationSetoid α)
a✝ b✝ : Quotient (separationSetoid α)
a b : α
h : (⟦a⟧, ⟦b⟧) ∈ 𝓢 (Quotient (separationSetoid α))
s : Set (α × α)
hs : s ∈ (𝓤 α).sets
this : s ∈ Filter.comap (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 (Quotient (separationSetoid α)))
t : Set (Quotient (separationSetoid α) × Quotient (separationSetoid α))
ht : t ∈ 𝓤 (Quotient (separationSetoid α))
hts : (fun p => (⟦p.1⟧, ⟦p.2⟧)) ⁻¹' t ⊆ s
⊢ (a, b) ∈ (fun p => (⟦p.1⟧, ⟦p.2⟧)) ⁻¹' t

Next tactic:
dsimp [preimage]
instance separated_separation : SeparatedSpace (Quotient (separationSetoid α)) :=
  ⟨Set.ext fun ⟨a, b⟩ =>
      Quotient.inductionOn₂ a b fun a b =>
        ⟨fun h =>
          have : a ≈ b := fun s hs =>
            have :
              s ∈ (𝓤 <| Quotient <| separationSetoid α).comap fun p : α × α => (⟦p.1⟧, ⟦p.2⟧) :=
              comap_quotient_le_uniformity hs
            let ⟨t, ht, hts⟩ := this
            hts (by dsimp [preimage]; 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
x✝ : Quotient (separationSetoid α) × Quotient (separationSetoid α)
a✝ b✝ : Quotient (separationSetoid α)
a b : α
h : (⟦a⟧, ⟦b⟧) ∈ 𝓢 (Quotient (separationSetoid α))
s : Set (α × α)
hs : s ∈ (𝓤 α).sets
this : s ∈ Filter.comap (fun p => (⟦p.1⟧, ⟦p.2⟧)) (𝓤 (Quotient (separationSetoid α)))
t : Set (Quotient (separationSetoid α) × Quotient (separationSetoid α))
ht : t ∈ 𝓤 (Quotient (separationSetoid α))
hts : (fun p => (⟦p.1⟧, ⟦p.2⟧)) ⁻¹' t ⊆ s
⊢ (⟦a⟧, ⟦b⟧) ∈ t

Next tactic:
exact h t ht
theorem eq_of_separated_of_uniformContinuous [SeparatedSpace β] {f : α → β} {x y : α}
    (H : UniformContinuous f) (h : x ≈ y) : f x = f y :=
  separated_def.1 (by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
x y : α
H : UniformContinuous f
h : x ≈ y
⊢ SeparatedSpace β

Next tactic:
infer_instance
theorem lift_mk [SeparatedSpace β] {f : α → β} (h : UniformContinuous f) (a : α) :
    lift f ⟦a⟧ = f a := by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
h : UniformContinuous f
a : α
⊢ lift f ⟦a⟧ = f a

Next tactic:
rw [lift, dif_pos h]
theorem lift_mk [SeparatedSpace β] {f : α → β} (h : UniformContinuous f) (a : α) :
    lift f ⟦a⟧ = f a := by rw [lift, dif_pos h]; 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
h : UniformContinuous f
a : α
⊢ Quotient.lift f (_ : ∀ (x x_1 : α), x ≈ x_1 → f x = f x_1) ⟦a⟧ = f a

Next tactic:
rfl
theorem uniformContinuous_lift [SeparatedSpace β] (f : α → β) : UniformContinuous (lift f) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
⊢ UniformContinuous (lift f)

Next tactic:
by_cases hf : UniformContinuous f
theorem uniformContinuous_lift [SeparatedSpace β] (f : α → β) : UniformContinuous (lift f) := by
  by_cases hf : UniformContinuous f
  · 

Proof state:
case pos
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
hf : UniformContinuous f
⊢ UniformContinuous (lift f)

Next tactic:
rw [lift, dif_pos hf]
theorem uniformContinuous_lift [SeparatedSpace β] (f : α → β) : UniformContinuous (lift f) := by
  by_cases hf : UniformContinuous f
  · rw [lift, dif_pos hf]
    

Proof state:
case pos
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
hf : UniformContinuous f
⊢ UniformContinuous (Quotient.lift f (_ : ∀ (x x_1 : α), x ≈ x_1 → f x = f x_1))

Next tactic:
exact uniformContinuous_quotient_lift hf
theorem uniformContinuous_lift [SeparatedSpace β] (f : α → β) : UniformContinuous (lift f) := by
  by_cases hf : UniformContinuous f
  · rw [lift, dif_pos hf]
    exact uniformContinuous_quotient_lift hf
  · 

Proof state:
case neg
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
hf : ¬UniformContinuous f
⊢ UniformContinuous (lift f)

Next tactic:
rw [lift, dif_neg hf]
theorem uniformContinuous_lift [SeparatedSpace β] (f : α → β) : UniformContinuous (lift f) := by
  by_cases hf : UniformContinuous f
  · rw [lift, dif_pos hf]
    exact uniformContinuous_quotient_lift hf
  · rw [lift, dif_neg hf]
    

Proof state:
case neg
α : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
inst✝ : SeparatedSpace β
f : α → β
hf : ¬UniformContinuous f
⊢ UniformContinuous fun x => f (Nonempty.some (_ : Nonempty α))

Next tactic:
exact uniformContinuous_of_const fun a _ => rfl
theorem map_mk {f : α → β} (h : UniformContinuous f) (a : α) : map f ⟦a⟧ = ⟦f a⟧ := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
h : UniformContinuous f
a : α
⊢ map f ⟦a⟧ = ⟦f a⟧

Next tactic:
rw [map, lift_mk (uniformContinuous_quotient_mk'.comp h)]
theorem map_mk {f : α → β} (h : UniformContinuous f) (a : α) : map f ⟦a⟧ = ⟦f a⟧ := by
  rw [map, lift_mk (uniformContinuous_quotient_mk'.comp h)]; 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
h : UniformContinuous f
a : α
⊢ (Quotient.mk' ∘ f) a = ⟦f a⟧

Next tactic:
rfl
theorem map_unique {f : α → β} (hf : UniformContinuous f)
    {g : SeparationQuotient α → SeparationQuotient β}
    (comm : Quotient.mk _ ∘ f = g ∘ Quotient.mk _) : map f = g := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
hf : UniformContinuous f
g : SeparationQuotient α → SeparationQuotient β
comm : Quotient.mk (separationSetoid β) ∘ f = g ∘ Quotient.mk (separationSetoid α)
⊢ map f = g

Next tactic:
ext ⟨a⟩
theorem map_unique {f : α → β} (hf : UniformContinuous f)
    {g : SeparationQuotient α → SeparationQuotient β}
    (comm : Quotient.mk _ ∘ f = g ∘ Quotient.mk _) : map f = g := by
  ext ⟨a⟩
  

Proof state:
case h.mk
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
hf : UniformContinuous f
g : SeparationQuotient α → SeparationQuotient β
comm : Quotient.mk (separationSetoid β) ∘ f = g ∘ Quotient.mk (separationSetoid α)
x✝ : SeparationQuotient α
a : α
⊢ map f (Quot.mk Setoid.r a) = g (Quot.mk Setoid.r a)

Next tactic:
calc
    map f ⟦a⟧ = ⟦f a⟧ := map_mk hf a
    _ = g ⟦a⟧ := congr_fun comm a
theorem map_comp {f : α → β} {g : β → γ} (hf : UniformContinuous f) (hg : UniformContinuous g) :
    map g ∘ map f = map (g ∘ f) :=
  (map_unique (hg.comp hf) <| by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
g : β → γ
hf : UniformContinuous f
hg : UniformContinuous g
⊢ Quotient.mk (separationSetoid γ) ∘ g ∘ f = (map g ∘ map f) ∘ Quotient.mk (separationSetoid α)

Next tactic:
simp only [Function.comp, map_mk, hf, hg]
theorem separation_prod {a₁ a₂ : α} {b₁ b₂ : β} : (a₁, b₁) ≈ (a₂, b₂) ↔ a₁ ≈ a₂ ∧ b₁ ≈ b₂ := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a₁ a₂ : α
b₁ b₂ : β
⊢ (a₁, b₁) ≈ (a₂, b₂) ↔ a₁ ≈ a₂ ∧ b₁ ≈ b₂

Next tactic:
constructor
theorem separation_prod {a₁ a₂ : α} {b₁ b₂ : β} : (a₁, b₁) ≈ (a₂, b₂) ↔ a₁ ≈ a₂ ∧ b₁ ≈ b₂ := by
  constructor
  · 

Proof state:
case mp
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a₁ a₂ : α
b₁ b₂ : β
⊢ (a₁, b₁) ≈ (a₂, b₂) → a₁ ≈ a₂ ∧ b₁ ≈ b₂

Next tactic:
intro h
theorem separation_prod {a₁ a₂ : α} {b₁ b₂ : β} : (a₁, b₁) ≈ (a₂, b₂) ↔ a₁ ≈ a₂ ∧ b₁ ≈ b₂ := by
  constructor
  · intro h
    

Proof state:
case mp
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a₁ a₂ : α
b₁ b₂ : β
h : (a₁, b₁) ≈ (a₂, b₂)
⊢ a₁ ≈ a₂ ∧ b₁ ≈ b₂

Next tactic:
exact
      ⟨separated_of_uniformContinuous uniformContinuous_fst h,
        separated_of_uniformContinuous uniformContinuous_snd h⟩
theorem separation_prod {a₁ a₂ : α} {b₁ b₂ : β} : (a₁, b₁) ≈ (a₂, b₂) ↔ a₁ ≈ a₂ ∧ b₁ ≈ b₂ := by
  constructor
  · intro h
    exact
      ⟨separated_of_uniformContinuous uniformContinuous_fst h,
        separated_of_uniformContinuous uniformContinuous_snd h⟩
  · 

Proof state:
case mpr
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a₁ a₂ : α
b₁ b₂ : β
⊢ a₁ ≈ a₂ ∧ b₁ ≈ b₂ → (a₁, b₁) ≈ (a₂, b₂)

Next tactic:
rintro ⟨eqv_α, eqv_β⟩ r r_in