l3lab/ntp-mathlib huggingface dataset:
/--
The map of a binary fan is a limit iff the fork consisting of the mapped morphisms is a limit. This
essentially lets us commute `BinaryFan.mk` with `Functor.mapCone`.
-/
def isLimitMapConeBinaryFanEquiv :
    IsLimit (G.mapCone (BinaryFan.mk f g)) ≃ IsLimit (BinaryFan.mk (G.map f) (G.map g)) :=
  (IsLimit.postcomposeHomEquiv (diagramIsoPair _) _).symm.trans
    (IsLimit.equivIsoLimit
      (Cones.ext (Iso.refl _)
        (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
⊢ ∀ (j : Discrete WalkingPair),
    ((Cones.postcompose (diagramIsoPair (pair X Y ⋙ G)).hom).obj (G.mapCone (BinaryFan.mk f g))).π.app j =
      (Iso.refl ((Cones.postcompose (diagramIsoPair (pair X Y ⋙ G)).hom).obj (G.mapCone (BinaryFan.mk f g))).pt).hom ≫
        (BinaryFan.mk (G.map f) (G.map g)).π.app j

Next tactic:
rintro (_ | _)
/--
The map of a binary fan is a limit iff the fork consisting of the mapped morphisms is a limit. This
essentially lets us commute `BinaryFan.mk` with `Functor.mapCone`.
-/
def isLimitMapConeBinaryFanEquiv :
    IsLimit (G.mapCone (BinaryFan.mk f g)) ≃ IsLimit (BinaryFan.mk (G.map f) (G.map g)) :=
  (IsLimit.postcomposeHomEquiv (diagramIsoPair _) _).symm.trans
    (IsLimit.equivIsoLimit
      (Cones.ext (Iso.refl _)
        (by rintro (_ | _) <;> 

Proof state:
case mk.left
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
⊢ ((Cones.postcompose (diagramIsoPair (pair X Y ⋙ G)).hom).obj (G.mapCone (BinaryFan.mk f g))).π.app
      { as := WalkingPair.left } =
    (Iso.refl ((Cones.postcompose (diagramIsoPair (pair X Y ⋙ G)).hom).obj (G.mapCone (BinaryFan.mk f g))).pt).hom ≫
      (BinaryFan.mk (G.map f) (G.map g)).π.app { as := WalkingPair.left }

Next tactic:
simp
/--
The map of a binary fan is a limit iff the fork consisting of the mapped morphisms is a limit. This
essentially lets us commute `BinaryFan.mk` with `Functor.mapCone`.
-/
def isLimitMapConeBinaryFanEquiv :
    IsLimit (G.mapCone (BinaryFan.mk f g)) ≃ IsLimit (BinaryFan.mk (G.map f) (G.map g)) :=
  (IsLimit.postcomposeHomEquiv (diagramIsoPair _) _).symm.trans
    (IsLimit.equivIsoLimit
      (Cones.ext (Iso.refl _)
        (by rintro (_ | _) <;> 

Proof state:
case mk.right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
⊢ ((Cones.postcompose (diagramIsoPair (pair X Y ⋙ G)).hom).obj (G.mapCone (BinaryFan.mk f g))).π.app
      { as := WalkingPair.right } =
    (Iso.refl ((Cones.postcompose (diagramIsoPair (pair X Y ⋙ G)).hom).obj (G.mapCone (BinaryFan.mk f g))).pt).hom ≫
      (BinaryFan.mk (G.map f) (G.map g)).π.app { as := WalkingPair.right }

Next tactic:
simp
/-- If the product comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesLimitPair.ofIsoProdComparison [i : IsIso (prodComparison G X Y)] :
    PreservesLimit (pair X Y) G := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
inst✝¹ : HasBinaryProduct X Y
inst✝ : HasBinaryProduct (G.obj X) (G.obj Y)
i : IsIso (prodComparison G X Y)
⊢ PreservesLimit (pair X Y) G

Next tactic:
apply preservesLimitOfPreservesLimitCone (prodIsProd X Y)
/-- If the product comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesLimitPair.ofIsoProdComparison [i : IsIso (prodComparison G X Y)] :
    PreservesLimit (pair X Y) G := by
  apply preservesLimitOfPreservesLimitCone (prodIsProd X Y)
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
inst✝¹ : HasBinaryProduct X Y
inst✝ : HasBinaryProduct (G.obj X) (G.obj Y)
i : IsIso (prodComparison G X Y)
⊢ IsLimit (G.mapCone (BinaryFan.mk prod.fst prod.snd))

Next tactic:
apply (isLimitMapConeBinaryFanEquiv _ _ _).symm _
/-- If the product comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesLimitPair.ofIsoProdComparison [i : IsIso (prodComparison G X Y)] :
    PreservesLimit (pair X Y) G := by
  apply preservesLimitOfPreservesLimitCone (prodIsProd X Y)
  apply (isLimitMapConeBinaryFanEquiv _ _ _).symm _
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
inst✝¹ : HasBinaryProduct X Y
inst✝ : HasBinaryProduct (G.obj X) (G.obj Y)
i : IsIso (prodComparison G X Y)
⊢ IsLimit (BinaryFan.mk (G.map prod.fst) (G.map prod.snd))

Next tactic:
refine @IsLimit.ofPointIso _ _ _ _ _ _ _ (limit.isLimit (pair (G.obj X) (G.obj Y))) ?_
/-- If the product comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesLimitPair.ofIsoProdComparison [i : IsIso (prodComparison G X Y)] :
    PreservesLimit (pair X Y) G := by
  apply preservesLimitOfPreservesLimitCone (prodIsProd X Y)
  apply (isLimitMapConeBinaryFanEquiv _ _ _).symm _
  refine @IsLimit.ofPointIso _ _ _ _ _ _ _ (limit.isLimit (pair (G.obj X) (G.obj Y))) ?_
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
inst✝¹ : HasBinaryProduct X Y
inst✝ : HasBinaryProduct (G.obj X) (G.obj Y)
i : IsIso (prodComparison G X Y)
⊢ IsIso (IsLimit.lift (limit.isLimit (pair (G.obj X) (G.obj Y))) (BinaryFan.mk (G.map prod.fst) (G.map prod.snd)))

Next tactic:
apply i
instance : IsIso (prodComparison G X Y) := by
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
inst✝² : HasBinaryProduct X Y
inst✝¹ : HasBinaryProduct (G.obj X) (G.obj Y)
inst✝ : PreservesLimit (pair X Y) G
⊢ IsIso (prodComparison G X Y)

Next tactic:
rw [← PreservesLimitPair.iso_hom]
instance : IsIso (prodComparison G X Y) := by
  rw [← PreservesLimitPair.iso_hom]
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : P ⟶ X
g : P ⟶ Y
inst✝² : HasBinaryProduct X Y
inst✝¹ : HasBinaryProduct (G.obj X) (G.obj Y)
inst✝ : PreservesLimit (pair X Y) G
⊢ IsIso (PreservesLimitPair.iso G X Y).hom

Next tactic:
infer_instance
/-- The map of a binary cofan is a colimit iff
the cofork consisting of the mapped morphisms is a colimit.
This essentially lets us commute `BinaryCofan.mk` with `Functor.mapCocone`.
-/
def isColimitMapCoconeBinaryCofanEquiv :
    IsColimit (Functor.mapCocone G (BinaryCofan.mk f g))
    ≃ IsColimit (BinaryCofan.mk (G.map f) (G.map g)) :=
  (IsColimit.precomposeHomEquiv (diagramIsoPair _).symm _).symm.trans
    (IsColimit.equivIsoColimit
      (Cocones.ext (Iso.refl _)
        (by 

Proof state:
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
⊢ ∀ (j : Discrete WalkingPair),
    ((Cocones.precompose (diagramIsoPair (pair X Y ⋙ G)).symm.hom).obj (G.mapCocone (BinaryCofan.mk f g))).ι.app j ≫
        (Iso.refl
            ((Cocones.precompose (diagramIsoPair (pair X Y ⋙ G)).symm.hom).obj
                (G.mapCocone (BinaryCofan.mk f g))).pt).hom =
      (BinaryCofan.mk (G.map f) (G.map g)).ι.app j

Next tactic:
rintro (_ | _)
/-- The map of a binary cofan is a colimit iff
the cofork consisting of the mapped morphisms is a colimit.
This essentially lets us commute `BinaryCofan.mk` with `Functor.mapCocone`.
-/
def isColimitMapCoconeBinaryCofanEquiv :
    IsColimit (Functor.mapCocone G (BinaryCofan.mk f g))
    ≃ IsColimit (BinaryCofan.mk (G.map f) (G.map g)) :=
  (IsColimit.precomposeHomEquiv (diagramIsoPair _).symm _).symm.trans
    (IsColimit.equivIsoColimit
      (Cocones.ext (Iso.refl _)
        (by rintro (_ | _) <;> 

Proof state:
case mk.left
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
⊢ ((Cocones.precompose (diagramIsoPair (pair X Y ⋙ G)).symm.hom).obj (G.mapCocone (BinaryCofan.mk f g))).ι.app
        { as := WalkingPair.left } ≫
      (Iso.refl
          ((Cocones.precompose (diagramIsoPair (pair X Y ⋙ G)).symm.hom).obj
              (G.mapCocone (BinaryCofan.mk f g))).pt).hom =
    (BinaryCofan.mk (G.map f) (G.map g)).ι.app { as := WalkingPair.left }

Next tactic:
simp
/-- The map of a binary cofan is a colimit iff
the cofork consisting of the mapped morphisms is a colimit.
This essentially lets us commute `BinaryCofan.mk` with `Functor.mapCocone`.
-/
def isColimitMapCoconeBinaryCofanEquiv :
    IsColimit (Functor.mapCocone G (BinaryCofan.mk f g))
    ≃ IsColimit (BinaryCofan.mk (G.map f) (G.map g)) :=
  (IsColimit.precomposeHomEquiv (diagramIsoPair _).symm _).symm.trans
    (IsColimit.equivIsoColimit
      (Cocones.ext (Iso.refl _)
        (by rintro (_ | _) <;> 

Proof state:
case mk.right
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₂
inst✝ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
⊢ ((Cocones.precompose (diagramIsoPair (pair X Y ⋙ G)).symm.hom).obj (G.mapCocone (BinaryCofan.mk f g))).ι.app
        { as := WalkingPair.right } ≫
      (Iso.refl
          ((Cocones.precompose (diagramIsoPair (pair X Y ⋙ G)).symm.hom).obj
              (G.mapCocone (BinaryCofan.mk f g))).pt).hom =
    (BinaryCofan.mk (G.map f) (G.map g)).ι.app { as := WalkingPair.right }

Next tactic:
simp
/-- If the coproduct comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesColimitPair.ofIsoCoprodComparison [i : IsIso (coprodComparison G X Y)] :
    PreservesColimit (pair X Y) G := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
inst✝¹ : HasBinaryCoproduct X Y
inst✝ : HasBinaryCoproduct (G.obj X) (G.obj Y)
i : IsIso (coprodComparison G X Y)
⊢ PreservesColimit (pair X Y) G

Next tactic:
apply preservesColimitOfPreservesColimitCocone (coprodIsCoprod X Y)
/-- If the coproduct comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesColimitPair.ofIsoCoprodComparison [i : IsIso (coprodComparison G X Y)] :
    PreservesColimit (pair X Y) G := by
  apply preservesColimitOfPreservesColimitCocone (coprodIsCoprod X Y)
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
inst✝¹ : HasBinaryCoproduct X Y
inst✝ : HasBinaryCoproduct (G.obj X) (G.obj Y)
i : IsIso (coprodComparison G X Y)
⊢ IsColimit (G.mapCocone (BinaryCofan.mk coprod.inl coprod.inr))

Next tactic:
apply (isColimitMapCoconeBinaryCofanEquiv _ _ _).symm _
/-- If the coproduct comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesColimitPair.ofIsoCoprodComparison [i : IsIso (coprodComparison G X Y)] :
    PreservesColimit (pair X Y) G := by
  apply preservesColimitOfPreservesColimitCocone (coprodIsCoprod X Y)
  apply (isColimitMapCoconeBinaryCofanEquiv _ _ _).symm _
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
inst✝¹ : HasBinaryCoproduct X Y
inst✝ : HasBinaryCoproduct (G.obj X) (G.obj Y)
i : IsIso (coprodComparison G X Y)
⊢ IsColimit (BinaryCofan.mk (G.map coprod.inl) (G.map coprod.inr))

Next tactic:
refine @IsColimit.ofPointIso _ _ _ _ _ _ _ (colimit.isColimit (pair (G.obj X) (G.obj Y))) ?_
/-- If the coproduct comparison map for `G` at `(X,Y)` is an isomorphism, then `G` preserves the
pair of `(X,Y)`.
-/
def PreservesColimitPair.ofIsoCoprodComparison [i : IsIso (coprodComparison G X Y)] :
    PreservesColimit (pair X Y) G := by
  apply preservesColimitOfPreservesColimitCocone (coprodIsCoprod X Y)
  apply (isColimitMapCoconeBinaryCofanEquiv _ _ _).symm _
  refine @IsColimit.ofPointIso _ _ _ _ _ _ _ (colimit.isColimit (pair (G.obj X) (G.obj Y))) ?_
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
inst✝¹ : HasBinaryCoproduct X Y
inst✝ : HasBinaryCoproduct (G.obj X) (G.obj Y)
i : IsIso (coprodComparison G X Y)
⊢ IsIso
    (IsColimit.desc (colimit.isColimit (pair (G.obj X) (G.obj Y)))
      (BinaryCofan.mk (G.map coprod.inl) (G.map coprod.inr)))

Next tactic:
apply i
instance : IsIso (coprodComparison G X Y) := by
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
inst✝² : HasBinaryCoproduct X Y
inst✝¹ : HasBinaryCoproduct (G.obj X) (G.obj Y)
inst✝ : PreservesColimit (pair X Y) G
⊢ IsIso (coprodComparison G X Y)

Next tactic:
rw [← PreservesColimitPair.iso_hom]
instance : IsIso (coprodComparison G X Y) := by
  rw [← PreservesColimitPair.iso_hom]
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
G : C ⥤ D
P X Y Z : C
f : X ⟶ P
g : Y ⟶ P
inst✝² : HasBinaryCoproduct X Y
inst✝¹ : HasBinaryCoproduct (G.obj X) (G.obj Y)
inst✝ : PreservesColimit (pair X Y) G
⊢ IsIso (PreservesColimitPair.iso G X Y).hom

Next tactic:
infer_instance
instance (priority := 100) UniformSpace.to_regularSpace : RegularSpace α :=
  RegularSpace.ofBasis
    (fun a => by
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a : α
⊢ HasBasis (𝓝 a) (?m.55 a) (?m.56 a)

Next tactic:
rw [nhds_eq_comap_uniformity]
instance (priority := 100) UniformSpace.to_regularSpace : RegularSpace α :=
  RegularSpace.ofBasis
    (fun a => by
      rw [nhds_eq_comap_uniformity]
      

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a : α
⊢ HasBasis (Filter.comap (Prod.mk a) (𝓤 α)) (?m.55 a) (?m.56 a)
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ α → Sort ?u.51
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ (a : α) → ?m.54 a → Prop
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ (a : α) → ?m.54 a → Set α

Next tactic:
exact uniformity_hasBasis_closed.comap _
instance (priority := 100) UniformSpace.to_regularSpace : RegularSpace α :=
  RegularSpace.ofBasis
    (fun a => by
      rw [nhds_eq_comap_uniformity]
      exact uniformity_hasBasis_closed.comap _)
    fun a V hV => by 

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a : α
V : Set (α × α)
hV : V ∈ 𝓤 α ∧ IsClosed V
⊢ IsClosed (Prod.mk a ⁻¹' id V)

Next tactic:
exact hV.2.preimage <| continuous_const.prod_mk continuous_id
theorem separationRel_iff_specializes {a b : α} : (a, b) ∈ 𝓢 α ↔ a ⤳ b := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
a b : α
⊢ (a, b) ∈ 𝓢 α ↔ a ⤳ b

Next tactic:
simp only [(𝓤 α).basis_sets.mem_separationRel, id, mem_setOf_eq,
    (nhds_basis_uniformity (𝓤 α).basis_sets).specializes_iff]
theorem separated_def {α : Type u} [UniformSpace α] :
    SeparatedSpace α ↔ ∀ x y, (∀ r ∈ 𝓤 α, (x, y) ∈ r) → x = y := by
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
⊢ SeparatedSpace α ↔ ∀ (x y : α), (∀ r ∈ 𝓤 α, (x, y) ∈ r) → x = y

Next tactic:
simp only [separatedSpace_iff, Set.ext_iff, Prod.forall, mem_idRel, separationRel, mem_sInter]
theorem separated_def {α : Type u} [UniformSpace α] :
    SeparatedSpace α ↔ ∀ x y, (∀ r ∈ 𝓤 α, (x, y) ∈ r) → x = y := by
  simp only [separatedSpace_iff, Set.ext_iff, Prod.forall, mem_idRel, separationRel, mem_sInter]
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
⊢ (∀ (a b : α), (a, b) ∈ ker (𝓤 α) ↔ a = b) ↔ ∀ (x y : α), (∀ r ∈ 𝓤 α, (x, y) ∈ r) → x = y

Next tactic:
exact forall₂_congr fun _ _ => ⟨Iff.mp, fun h => ⟨h, fun H U hU => H ▸ refl_mem_uniformity hU⟩⟩
theorem separated_def' {α : Type u} [UniformSpace α] :
    SeparatedSpace α ↔ ∀ x y, x ≠ y → ∃ r ∈ 𝓤 α, (x, y) ∉ r :=
  separated_def.trans <| forall₂_congr fun x y => by 

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
x y : α
⊢ (∀ r ∈ 𝓤 α, (x, y) ∈ r) → x = y ↔ x ≠ y → ∃ r ∈ 𝓤 α, (x, y) ∉ r

Next tactic:
rw [← not_imp_not]
theorem separated_def' {α : Type u} [UniformSpace α] :
    SeparatedSpace α ↔ ∀ x y, x ≠ y → ∃ r ∈ 𝓤 α, (x, y) ∉ r :=
  separated_def.trans <| forall₂_congr fun x y => by rw [← not_imp_not]; 

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u
inst✝ : UniformSpace α
x y : α
⊢ (¬x = y → ¬∀ r ∈ 𝓤 α, (x, y) ∈ r) ↔ x ≠ y → ∃ r ∈ 𝓤 α, (x, y) ∉ r

Next tactic:
simp [not_forall]
theorem eq_of_forall_symmetric {α : Type*} [UniformSpace α] [SeparatedSpace α] {x y : α}
    (h : ∀ {V}, V ∈ 𝓤 α → SymmetricRel V → (x, y) ∈ V) : x = y :=
  eq_of_uniformity_basis hasBasis_symmetric (by 

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝⁴ : UniformSpace α✝
inst✝³ : UniformSpace β
inst✝² : UniformSpace γ
α : Type u_1
inst✝¹ : UniformSpace α
inst✝ : SeparatedSpace α
x y : α
h : ∀ {V : Set (α × α)}, V ∈ 𝓤 α → SymmetricRel V → (x, y) ∈ V
⊢ ∀ {i : Set (α × α)}, i ∈ 𝓤 α ∧ SymmetricRel i → (x, y) ∈ id i

Next tactic:
simpa [and_imp]
theorem idRel_sub_separationRel (α : Type*) [UniformSpace α] : idRel ⊆ 𝓢 α := by
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u_1
inst✝ : UniformSpace α
⊢ idRel ⊆ 𝓢 α

Next tactic:
unfold separationRel
theorem idRel_sub_separationRel (α : Type*) [UniformSpace α] : idRel ⊆ 𝓢 α := by
  unfold separationRel
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u_1
inst✝ : UniformSpace α
⊢ idRel ⊆ ker (𝓤 α)

Next tactic:
rw [idRel_subset]
theorem idRel_sub_separationRel (α : Type*) [UniformSpace α] : idRel ⊆ 𝓢 α := by
  unfold separationRel
  rw [idRel_subset]
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u_1
inst✝ : UniformSpace α
⊢ ∀ (a : α), (a, a) ∈ ker (𝓤 α)

Next tactic:
intro x
theorem idRel_sub_separationRel (α : Type*) [UniformSpace α] : idRel ⊆ 𝓢 α := by
  unfold separationRel
  rw [idRel_subset]
  intro x
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u_1
inst✝ : UniformSpace α
x : α
⊢ (x, x) ∈ ker (𝓤 α)

Next tactic:
suffices ∀ t ∈ 𝓤 α, (x, x) ∈ t by simpa only [refl_mem_uniformity]
theorem idRel_sub_separationRel (α : Type*) [UniformSpace α] : idRel ⊆ 𝓢 α := by
  unfold separationRel
  rw [idRel_subset]
  intro x
  suffices ∀ t ∈ 𝓤 α, (x, x) ∈ t by 

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u_1
inst✝ : UniformSpace α
x : α
this : ∀ t ∈ 𝓤 α, (x, x) ∈ t
⊢ (x, x) ∈ ker (𝓤 α)

Next tactic:
simpa only [refl_mem_uniformity]
theorem idRel_sub_separationRel (α : Type*) [UniformSpace α] : idRel ⊆ 𝓢 α := by
  unfold separationRel
  rw [idRel_subset]
  intro x
  suffices ∀ t ∈ 𝓤 α, (x, x) ∈ t by simpa only [refl_mem_uniformity]
  

Proof state:
α✝ : Type u
β : Type v
γ : Type w
inst✝³ : UniformSpace α✝
inst✝² : UniformSpace β
inst✝¹ : UniformSpace γ
α : Type u_1
inst✝ : UniformSpace α
x : α
⊢ ∀ t ∈ 𝓤 α, (x, x) ∈ t

Next tactic:
exact fun t => refl_mem_uniformity
theorem separationRel_comap {f : α → β}
    (h : ‹UniformSpace α› = UniformSpace.comap f ‹UniformSpace β›) :
    𝓢 α = Prod.map f f ⁻¹' 𝓢 β := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
h : inst✝² = UniformSpace.comap f inst✝¹
⊢ 𝓢 α = Prod.map f f ⁻¹' 𝓢 β

Next tactic:
subst h
theorem separationRel_comap {f : α → β}
    (h : ‹UniformSpace α› = UniformSpace.comap f ‹UniformSpace β›) :
    𝓢 α = Prod.map f f ⁻¹' 𝓢 β := by
  subst h
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
⊢ 𝓢 α = Prod.map f f ⁻¹' 𝓢 β

Next tactic:
dsimp [separationRel]
theorem separationRel_comap {f : α → β}
    (h : ‹UniformSpace α› = UniformSpace.comap f ‹UniformSpace β›) :
    𝓢 α = Prod.map f f ⁻¹' 𝓢 β := by
  subst h
  dsimp [separationRel]
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
f : α → β
⊢ ker (𝓤 α) = Prod.map f f ⁻¹' ker (𝓤 β)

Next tactic:
simp_rw [uniformity_comap, ((𝓤 β).comap_hasBasis $ Prod.map f f).ker, ker_def, preimage_iInter]
protected theorem Filter.HasBasis.separationRel {ι : Sort*} {p : ι → Prop} {s : ι → Set (α × α)}
    (h : HasBasis (𝓤 α) p s) : 𝓢 α = ⋂ (i) (_ : p i), s i := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
ι : Sort u_1
p : ι → Prop
s : ι → Set (α × α)
h : HasBasis (𝓤 α) p s
⊢ 𝓢 α = ⋂ i, ⋂ (_ : p i), s i

Next tactic:
unfold separationRel
protected theorem Filter.HasBasis.separationRel {ι : Sort*} {p : ι → Prop} {s : ι → Set (α × α)}
    (h : HasBasis (𝓤 α) p s) : 𝓢 α = ⋂ (i) (_ : p i), s i := by
  unfold separationRel
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
ι : Sort u_1
p : ι → Prop
s : ι → Set (α × α)
h : HasBasis (𝓤 α) p s
⊢ ker (𝓤 α) = ⋂ i, ⋂ (_ : p i), s i

Next tactic:
rw [h.ker]
theorem separationRel_eq_inter_closure : 𝓢 α = ⋂₀ (closure '' (𝓤 α).sets) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ 𝓢 α = ⋂₀ (closure '' (𝓤 α).sets)

Next tactic:
simp [uniformity_hasBasis_closure.separationRel]
theorem isClosed_separationRel : IsClosed (𝓢 α) := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ IsClosed (𝓢 α)

Next tactic:
rw [separationRel_eq_inter_closure]
theorem isClosed_separationRel : IsClosed (𝓢 α) := by
  rw [separationRel_eq_inter_closure]
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ IsClosed (⋂₀ (closure '' (𝓤 α).sets))

Next tactic:
apply isClosed_sInter
theorem isClosed_separationRel : IsClosed (𝓢 α) := by
  rw [separationRel_eq_inter_closure]
  apply isClosed_sInter
  

Proof state:
case a
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ ∀ t ∈ closure '' (𝓤 α).sets, IsClosed t

Next tactic:
rintro _ ⟨t, -, rfl⟩
theorem isClosed_separationRel : IsClosed (𝓢 α) := by
  rw [separationRel_eq_inter_closure]
  apply isClosed_sInter
  rintro _ ⟨t, -, rfl⟩
  

Proof state:
case a.intro.intro
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
t : Set (α × α)
⊢ IsClosed (closure t)

Next tactic:
exact isClosed_closure
theorem separated_iff_t2 : SeparatedSpace α ↔ T2Space α := by
  

Proof state:
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ SeparatedSpace α ↔ T2Space α

Next tactic:
constructor
theorem separated_iff_t2 : SeparatedSpace α ↔ T2Space α := by
  constructor <;> 

Proof state:
case mp
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ SeparatedSpace α → T2Space α

Next tactic:
intro h
theorem separated_iff_t2 : SeparatedSpace α ↔ T2Space α := by
  constructor <;> 

Proof state:
case mpr
α : Type u
β : Type v
γ : Type w
inst✝² : UniformSpace α
inst✝¹ : UniformSpace β
inst✝ : UniformSpace γ
⊢ T2Space α → SeparatedSpace α

Next tactic:
intro h