l3lab/ntp-mathlib huggingface dataset:
theorem embedding_of_pullback_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S} (H₁ : Embedding f)
    (H₂ : Embedding g) : Embedding (limit.π (cospan f g) WalkingCospan.one) := by
  convert H₂.comp (snd_embedding_of_left_embedding H₁ g)
  erw [← coe_comp]
  congr
  rw [← limit.w _ WalkingCospan.Hom.inr]
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H₁ : Embedding ⇑f
H₂ : Embedding ⇑g
e_2✝ : (forget TopCat).obj ((cospan f g).obj WalkingCospan.one) = (forget TopCat).obj S
⊢ ⇑(limit.π (cospan f g) WalkingCospan.right ≫ (cospan f g).map WalkingCospan.Hom.inr) = ⇑(pullback.snd ≫ g)

Next tactic:
rfl
theorem snd_openEmbedding_of_left_openEmbedding {X Y S : TopCat} {f : X ⟶ S} (H : OpenEmbedding f)
    (g : Y ⟶ S) : OpenEmbedding <| ⇑(pullback.snd : pullback f g ⟶ Y) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
H : OpenEmbedding ⇑f
g : Y ⟶ S
⊢ OpenEmbedding ⇑pullback.snd

Next tactic:
convert (homeoOfIso (asIso (pullback.snd : pullback (𝟙 S) g ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₂ := 𝟙 Y) f g (𝟙 _) g H
        (homeoOfIso (Iso.refl _)).openEmbedding (𝟙 _) rfl (by simp))
theorem snd_openEmbedding_of_left_openEmbedding {X Y S : TopCat} {f : X ⟶ S} (H : OpenEmbedding f)
    (g : Y ⟶ S) : OpenEmbedding <| ⇑(pullback.snd : pullback f g ⟶ Y) := by
  convert (homeoOfIso (asIso (pullback.snd : pullback (𝟙 S) g ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₂ := 𝟙 Y) f g (𝟙 _) g H
        (homeoOfIso (Iso.refl _)).openEmbedding (𝟙 _) rfl (by 

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
H : OpenEmbedding ⇑f
g : Y ⟶ S
⊢ g ≫ 𝟙 S = 𝟙 Y ≫ g

Next tactic:
simp
theorem snd_openEmbedding_of_left_openEmbedding {X Y S : TopCat} {f : X ⟶ S} (H : OpenEmbedding f)
    (g : Y ⟶ S) : OpenEmbedding <| ⇑(pullback.snd : pullback f g ⟶ Y) := by
  convert (homeoOfIso (asIso (pullback.snd : pullback (𝟙 S) g ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₂ := 𝟙 Y) f g (𝟙 _) g H
        (homeoOfIso (Iso.refl _)).openEmbedding (𝟙 _) rfl (by simp))
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
H : OpenEmbedding ⇑f
g : Y ⟶ S
e_2✝ : (forget TopCat).obj Y = ↑Y
⊢ ⇑pullback.snd =
    ⇑(homeoOfIso (asIso pullback.snd)) ∘
      ⇑(pullback.map f g (𝟙 S) g f (𝟙 Y) (𝟙 S) (_ : f ≫ 𝟙 S = f ≫ 𝟙 S) (_ : g ≫ 𝟙 S = 𝟙 Y ≫ g))

Next tactic:
erw [← coe_comp]
theorem snd_openEmbedding_of_left_openEmbedding {X Y S : TopCat} {f : X ⟶ S} (H : OpenEmbedding f)
    (g : Y ⟶ S) : OpenEmbedding <| ⇑(pullback.snd : pullback f g ⟶ Y) := by
  convert (homeoOfIso (asIso (pullback.snd : pullback (𝟙 S) g ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₂ := 𝟙 Y) f g (𝟙 _) g H
        (homeoOfIso (Iso.refl _)).openEmbedding (𝟙 _) rfl (by simp))
  erw [← coe_comp]
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
H : OpenEmbedding ⇑f
g : Y ⟶ S
e_2✝ : (forget TopCat).obj Y = ↑Y
⊢ ⇑pullback.snd =
    ⇑(pullback.map f g (𝟙 S) g f (𝟙 Y) (𝟙 S) (_ : f ≫ 𝟙 S = f ≫ 𝟙 S) (_ : g ≫ 𝟙 S = 𝟙 Y ≫ g) ≫ (asIso pullback.snd).hom)

Next tactic:
simp
theorem fst_openEmbedding_of_right_openEmbedding {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (H : OpenEmbedding g) : OpenEmbedding <| ⇑(pullback.fst : pullback f g ⟶ X) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H : OpenEmbedding ⇑g
⊢ OpenEmbedding ⇑pullback.fst

Next tactic:
convert (homeoOfIso (asIso (pullback.fst : pullback f (𝟙 S) ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₁ := 𝟙 X) f g f (𝟙 _)
        (homeoOfIso (Iso.refl _)).openEmbedding H (𝟙 _) rfl (by simp))
theorem fst_openEmbedding_of_right_openEmbedding {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (H : OpenEmbedding g) : OpenEmbedding <| ⇑(pullback.fst : pullback f g ⟶ X) := by
  convert (homeoOfIso (asIso (pullback.fst : pullback f (𝟙 S) ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₁ := 𝟙 X) f g f (𝟙 _)
        (homeoOfIso (Iso.refl _)).openEmbedding H (𝟙 _) rfl (by 

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H : OpenEmbedding ⇑g
⊢ g ≫ 𝟙 S = g ≫ 𝟙 S

Next tactic:
simp
theorem fst_openEmbedding_of_right_openEmbedding {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (H : OpenEmbedding g) : OpenEmbedding <| ⇑(pullback.fst : pullback f g ⟶ X) := by
  convert (homeoOfIso (asIso (pullback.fst : pullback f (𝟙 S) ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₁ := 𝟙 X) f g f (𝟙 _)
        (homeoOfIso (Iso.refl _)).openEmbedding H (𝟙 _) rfl (by simp))
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H : OpenEmbedding ⇑g
e_2✝ : (forget TopCat).obj X = ↑X
⊢ ⇑pullback.fst =
    ⇑(homeoOfIso (asIso pullback.fst)) ∘
      ⇑(pullback.map f g f (𝟙 S) (𝟙 X) g (𝟙 S) (_ : f ≫ 𝟙 S = f ≫ 𝟙 S) (_ : g ≫ 𝟙 S = g ≫ 𝟙 S))

Next tactic:
erw [← coe_comp]
theorem fst_openEmbedding_of_right_openEmbedding {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (H : OpenEmbedding g) : OpenEmbedding <| ⇑(pullback.fst : pullback f g ⟶ X) := by
  convert (homeoOfIso (asIso (pullback.fst : pullback f (𝟙 S) ⟶ _))).openEmbedding.comp
      (pullback_map_openEmbedding_of_open_embeddings (i₁ := 𝟙 X) f g f (𝟙 _)
        (homeoOfIso (Iso.refl _)).openEmbedding H (𝟙 _) rfl (by simp))
  erw [← coe_comp]
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H : OpenEmbedding ⇑g
e_2✝ : (forget TopCat).obj X = ↑X
⊢ ⇑pullback.fst =
    ⇑(pullback.map f g f (𝟙 S) (𝟙 X) g (𝟙 S) (_ : f ≫ 𝟙 S = f ≫ 𝟙 S) (_ : g ≫ 𝟙 S = g ≫ 𝟙 S) ≫ (asIso pullback.fst).hom)

Next tactic:
simp
/-- If `X ⟶ S`, `Y ⟶ S` are open embeddings, then so is `X ×ₛ Y ⟶ S`. -/
theorem openEmbedding_of_pullback_open_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S}
    (H₁ : OpenEmbedding f) (H₂ : OpenEmbedding g) :
    OpenEmbedding (limit.π (cospan f g) WalkingCospan.one) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H₁ : OpenEmbedding ⇑f
H₂ : OpenEmbedding ⇑g
⊢ OpenEmbedding ⇑(limit.π (cospan f g) WalkingCospan.one)

Next tactic:
convert H₂.comp (snd_openEmbedding_of_left_openEmbedding H₁ g)
/-- If `X ⟶ S`, `Y ⟶ S` are open embeddings, then so is `X ×ₛ Y ⟶ S`. -/
theorem openEmbedding_of_pullback_open_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S}
    (H₁ : OpenEmbedding f) (H₂ : OpenEmbedding g) :
    OpenEmbedding (limit.π (cospan f g) WalkingCospan.one) := by
  convert H₂.comp (snd_openEmbedding_of_left_openEmbedding H₁ g)
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H₁ : OpenEmbedding ⇑f
H₂ : OpenEmbedding ⇑g
e_2✝ : (forget TopCat).obj ((cospan f g).obj WalkingCospan.one) = (forget TopCat).obj S
⊢ ⇑(limit.π (cospan f g) WalkingCospan.one) = ⇑g ∘ ⇑pullback.snd

Next tactic:
erw [← coe_comp]
/-- If `X ⟶ S`, `Y ⟶ S` are open embeddings, then so is `X ×ₛ Y ⟶ S`. -/
theorem openEmbedding_of_pullback_open_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S}
    (H₁ : OpenEmbedding f) (H₂ : OpenEmbedding g) :
    OpenEmbedding (limit.π (cospan f g) WalkingCospan.one) := by
  convert H₂.comp (snd_openEmbedding_of_left_openEmbedding H₁ g)
  erw [← coe_comp]
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H₁ : OpenEmbedding ⇑f
H₂ : OpenEmbedding ⇑g
e_2✝ : (forget TopCat).obj ((cospan f g).obj WalkingCospan.one) = (forget TopCat).obj S
⊢ ⇑(limit.π (cospan f g) WalkingCospan.one) = ⇑(pullback.snd ≫ g)

Next tactic:
congr
/-- If `X ⟶ S`, `Y ⟶ S` are open embeddings, then so is `X ×ₛ Y ⟶ S`. -/
theorem openEmbedding_of_pullback_open_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S}
    (H₁ : OpenEmbedding f) (H₂ : OpenEmbedding g) :
    OpenEmbedding (limit.π (cospan f g) WalkingCospan.one) := by
  convert H₂.comp (snd_openEmbedding_of_left_openEmbedding H₁ g)
  erw [← coe_comp]
  congr
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H₁ : OpenEmbedding ⇑f
H₂ : OpenEmbedding ⇑g
e_2✝ : (forget TopCat).obj ((cospan f g).obj WalkingCospan.one) = (forget TopCat).obj S
⊢ ⇑(limit.π (cospan f g) WalkingCospan.one) = ⇑(pullback.snd ≫ g)

Next tactic:
rw [← limit.w _ WalkingCospan.Hom.inr]
/-- If `X ⟶ S`, `Y ⟶ S` are open embeddings, then so is `X ×ₛ Y ⟶ S`. -/
theorem openEmbedding_of_pullback_open_embeddings {X Y S : TopCat} {f : X ⟶ S} {g : Y ⟶ S}
    (H₁ : OpenEmbedding f) (H₂ : OpenEmbedding g) :
    OpenEmbedding (limit.π (cospan f g) WalkingCospan.one) := by
  convert H₂.comp (snd_openEmbedding_of_left_openEmbedding H₁ g)
  erw [← coe_comp]
  congr
  rw [← limit.w _ WalkingCospan.Hom.inr]
  

Proof state:
case h.e'_5.h
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
H₁ : OpenEmbedding ⇑f
H₂ : OpenEmbedding ⇑g
e_2✝ : (forget TopCat).obj ((cospan f g).obj WalkingCospan.one) = (forget TopCat).obj S
⊢ ⇑(limit.π (cospan f g) WalkingCospan.right ≫ (cospan f g).map WalkingCospan.Hom.inr) = ⇑(pullback.snd ≫ g)

Next tactic:
rfl
theorem fst_iso_of_right_embedding_range_subset {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (hg : Embedding g) (H : Set.range f ⊆ Set.range g) :
    IsIso (pullback.fst : pullback f g ⟶ X) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
hg : Embedding ⇑g
H : Set.range ⇑f ⊆ Set.range ⇑g
⊢ IsIso pullback.fst

Next tactic:
let esto : (pullback f g : TopCat) ≃ₜ X :=
    (Homeomorph.ofEmbedding _ (fst_embedding_of_right_embedding f hg)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            rw [pullback_fst_range]
            exact ⟨_, (H (Set.mem_range_self x)).choose_spec.symm⟩⟩
        left_inv := fun ⟨_, _⟩ => rfl
        right_inv := fun x => rfl }
theorem fst_iso_of_right_embedding_range_subset {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (hg : Embedding g) (H : Set.range f ⊆ Set.range g) :
    IsIso (pullback.fst : pullback f g ⟶ X) := by
  let esto : (pullback f g : TopCat) ≃ₜ X :=
    (Homeomorph.ofEmbedding _ (fst_embedding_of_right_embedding f hg)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
hg : Embedding ⇑g
H : Set.range ⇑f ⊆ Set.range ⇑g
x : ↑X
⊢ x ∈ Set.range ⇑pullback.fst

Next tactic:
rw [pullback_fst_range]
theorem fst_iso_of_right_embedding_range_subset {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (hg : Embedding g) (H : Set.range f ⊆ Set.range g) :
    IsIso (pullback.fst : pullback f g ⟶ X) := by
  let esto : (pullback f g : TopCat) ≃ₜ X :=
    (Homeomorph.ofEmbedding _ (fst_embedding_of_right_embedding f hg)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            rw [pullback_fst_range]
            

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
hg : Embedding ⇑g
H : Set.range ⇑f ⊆ Set.range ⇑g
x : ↑X
⊢ x ∈ {x | ∃ y, f x = g y}

Next tactic:
exact ⟨_, (H (Set.mem_range_self x)).choose_spec.symm⟩
theorem fst_iso_of_right_embedding_range_subset {X Y S : TopCat} (f : X ⟶ S) {g : Y ⟶ S}
    (hg : Embedding g) (H : Set.range f ⊆ Set.range g) :
    IsIso (pullback.fst : pullback f g ⟶ X) := by
  let esto : (pullback f g : TopCat) ≃ₜ X :=
    (Homeomorph.ofEmbedding _ (fst_embedding_of_right_embedding f hg)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            rw [pullback_fst_range]
            exact ⟨_, (H (Set.mem_range_self x)).choose_spec.symm⟩⟩
        left_inv := fun ⟨_, _⟩ => rfl
        right_inv := fun x => rfl }
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
g : Y ⟶ S
hg : Embedding ⇑g
H : Set.range ⇑f ⊆ Set.range ⇑g
esto : ↑(pullback f g) ≃ₜ ↑X :=
  Homeomorph.trans (Homeomorph.ofEmbedding ⇑pullback.fst (_ : Embedding ⇑pullback.fst))
    (Homeomorph.mk
      { toFun := Subtype.val, invFun := fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.fst) },
        left_inv :=
          (_ :
            ∀ (x : ↑(Set.range ⇑pullback.fst)),
              (fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.fst) }) ↑x = x),
        right_inv :=
          (_ :
            ∀ (x : ↑X),
              ↑((fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.fst) }) x) =
                ↑((fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.fst) }) x)) })
⊢ IsIso pullback.fst

Next tactic:
convert IsIso.of_iso (isoOfHomeo esto)
theorem snd_iso_of_left_embedding_range_subset {X Y S : TopCat} {f : X ⟶ S} (hf : Embedding f)
    (g : Y ⟶ S) (H : Set.range g ⊆ Set.range f) : IsIso (pullback.snd : pullback f g ⟶ Y) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
hf : Embedding ⇑f
g : Y ⟶ S
H : Set.range ⇑g ⊆ Set.range ⇑f
⊢ IsIso pullback.snd

Next tactic:
let esto : (pullback f g : TopCat) ≃ₜ Y :=
    (Homeomorph.ofEmbedding _ (snd_embedding_of_left_embedding hf g)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            rw [pullback_snd_range]
            exact ⟨_, (H (Set.mem_range_self x)).choose_spec⟩⟩
        left_inv := fun ⟨_, _⟩ => rfl
        right_inv := fun x => rfl }
theorem snd_iso_of_left_embedding_range_subset {X Y S : TopCat} {f : X ⟶ S} (hf : Embedding f)
    (g : Y ⟶ S) (H : Set.range g ⊆ Set.range f) : IsIso (pullback.snd : pullback f g ⟶ Y) := by
  let esto : (pullback f g : TopCat) ≃ₜ Y :=
    (Homeomorph.ofEmbedding _ (snd_embedding_of_left_embedding hf g)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
hf : Embedding ⇑f
g : Y ⟶ S
H : Set.range ⇑g ⊆ Set.range ⇑f
x : ↑Y
⊢ x ∈ Set.range ⇑pullback.snd

Next tactic:
rw [pullback_snd_range]
theorem snd_iso_of_left_embedding_range_subset {X Y S : TopCat} {f : X ⟶ S} (hf : Embedding f)
    (g : Y ⟶ S) (H : Set.range g ⊆ Set.range f) : IsIso (pullback.snd : pullback f g ⟶ Y) := by
  let esto : (pullback f g : TopCat) ≃ₜ Y :=
    (Homeomorph.ofEmbedding _ (snd_embedding_of_left_embedding hf g)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            rw [pullback_snd_range]
            

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
hf : Embedding ⇑f
g : Y ⟶ S
H : Set.range ⇑g ⊆ Set.range ⇑f
x : ↑Y
⊢ x ∈ {y | ∃ x, f x = g y}

Next tactic:
exact ⟨_, (H (Set.mem_range_self x)).choose_spec⟩
theorem snd_iso_of_left_embedding_range_subset {X Y S : TopCat} {f : X ⟶ S} (hf : Embedding f)
    (g : Y ⟶ S) (H : Set.range g ⊆ Set.range f) : IsIso (pullback.snd : pullback f g ⟶ Y) := by
  let esto : (pullback f g : TopCat) ≃ₜ Y :=
    (Homeomorph.ofEmbedding _ (snd_embedding_of_left_embedding hf g)).trans
      { toFun := Subtype.val
        invFun := fun x =>
          ⟨x, by
            rw [pullback_snd_range]
            exact ⟨_, (H (Set.mem_range_self x)).choose_spec⟩⟩
        left_inv := fun ⟨_, _⟩ => rfl
        right_inv := fun x => rfl }
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X✝ Y✝ Z : TopCat
X Y S : TopCat
f : X ⟶ S
hf : Embedding ⇑f
g : Y ⟶ S
H : Set.range ⇑g ⊆ Set.range ⇑f
esto : ↑(pullback f g) ≃ₜ ↑Y :=
  Homeomorph.trans (Homeomorph.ofEmbedding ⇑pullback.snd (_ : Embedding ⇑pullback.snd))
    (Homeomorph.mk
      { toFun := Subtype.val, invFun := fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.snd) },
        left_inv :=
          (_ :
            ∀ (x : ↑(Set.range ⇑pullback.snd)),
              (fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.snd) }) ↑x = x),
        right_inv :=
          (_ :
            ∀ (x : ↑Y),
              ↑((fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.snd) }) x) =
                ↑((fun x => { val := x, property := (_ : x ∈ Set.range ⇑pullback.snd) }) x)) })
⊢ IsIso pullback.snd

Next tactic:
convert IsIso.of_iso (isoOfHomeo esto)
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
⊢ ⇑pullback.snd '' (⇑pullback.fst ⁻¹' U) = ⇑g ⁻¹' (⇑f '' U)

Next tactic:
ext x
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
x : (forget TopCat).obj Y
⊢ x ∈ ⇑pullback.snd '' (⇑pullback.fst ⁻¹' U) ↔ x ∈ ⇑g ⁻¹' (⇑f '' U)

Next tactic:
constructor
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  constructor
  · 

Proof state:
case h.mp
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
x : (forget TopCat).obj Y
⊢ x ∈ ⇑pullback.snd '' (⇑pullback.fst ⁻¹' U) → x ∈ ⇑g ⁻¹' (⇑f '' U)

Next tactic:
rintro ⟨y, hy, rfl⟩
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    

Proof state:
case h.mp.intro.intro
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
y : (forget TopCat).obj (pullback f g)
hy : y ∈ ⇑pullback.fst ⁻¹' U
⊢ pullback.snd y ∈ ⇑g ⁻¹' (⇑f '' U)

Next tactic:
exact
      ⟨(pullback.fst : pullback f g ⟶ _) y, hy, ConcreteCategory.congr_hom pullback.condition y⟩
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.fst : pullback f g ⟶ _) y, hy, ConcreteCategory.congr_hom pullback.condition y⟩
  · 

Proof state:
case h.mpr
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
x : (forget TopCat).obj Y
⊢ x ∈ ⇑g ⁻¹' (⇑f '' U) → x ∈ ⇑pullback.snd '' (⇑pullback.fst ⁻¹' U)

Next tactic:
rintro ⟨y, hy, eq⟩
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.fst : pullback f g ⟶ _) y, hy, ConcreteCategory.congr_hom pullback.condition y⟩
  · rintro ⟨y, hy, eq⟩
    

Proof state:
case h.mpr.intro.intro
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
x : (forget TopCat).obj Y
y : (forget TopCat).obj X
hy : y ∈ U
eq : f y = g x
⊢ x ∈ ⇑pullback.snd '' (⇑pullback.fst ⁻¹' U)

Next tactic:
exact ⟨(TopCat.pullbackIsoProdSubtype f g).inv ⟨⟨_, _⟩, eq⟩, by simpa, by simp⟩
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.fst : pullback f g ⟶ _) y, hy, ConcreteCategory.congr_hom pullback.condition y⟩
  · rintro ⟨y, hy, eq⟩
    exact ⟨(TopCat.pullbackIsoProdSubtype f g).inv ⟨⟨_, _⟩, eq⟩, by 

Proof state:
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
x : (forget TopCat).obj Y
y : (forget TopCat).obj X
hy : y ∈ U
eq : f y = g x
⊢ (pullbackIsoProdSubtype f g).inv { val := (y, x), property := eq } ∈ ⇑pullback.fst ⁻¹' U

Next tactic:
simpa
theorem pullback_snd_image_fst_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set X) :
    (pullback.snd : pullback f g ⟶ _) '' ((pullback.fst : pullback f g ⟶ _) ⁻¹' U) =
      g ⁻¹' (f '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.fst : pullback f g ⟶ _) y, hy, ConcreteCategory.congr_hom pullback.condition y⟩
  · rintro ⟨y, hy, eq⟩
    exact ⟨(TopCat.pullbackIsoProdSubtype f g).inv ⟨⟨_, _⟩, eq⟩, by simpa, by 

Proof state:
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑X
x : (forget TopCat).obj Y
y : (forget TopCat).obj X
hy : y ∈ U
eq : f y = g x
⊢ pullback.snd ((pullbackIsoProdSubtype f g).inv { val := (y, x), property := eq }) = x

Next tactic:
simp
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
⊢ ⇑pullback.fst '' (⇑pullback.snd ⁻¹' U) = ⇑f ⁻¹' (⇑g '' U)

Next tactic:
ext x
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
x : (forget TopCat).obj X
⊢ x ∈ ⇑pullback.fst '' (⇑pullback.snd ⁻¹' U) ↔ x ∈ ⇑f ⁻¹' (⇑g '' U)

Next tactic:
constructor
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  constructor
  · 

Proof state:
case h.mp
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
x : (forget TopCat).obj X
⊢ x ∈ ⇑pullback.fst '' (⇑pullback.snd ⁻¹' U) → x ∈ ⇑f ⁻¹' (⇑g '' U)

Next tactic:
rintro ⟨y, hy, rfl⟩
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    

Proof state:
case h.mp.intro.intro
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
y : (forget TopCat).obj (pullback f g)
hy : y ∈ ⇑pullback.snd ⁻¹' U
⊢ pullback.fst y ∈ ⇑f ⁻¹' (⇑g '' U)

Next tactic:
exact
      ⟨(pullback.snd : pullback f g ⟶ _) y, hy,
        (ConcreteCategory.congr_hom pullback.condition y).symm⟩
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.snd : pullback f g ⟶ _) y, hy,
        (ConcreteCategory.congr_hom pullback.condition y).symm⟩
  · 

Proof state:
case h.mpr
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
x : (forget TopCat).obj X
⊢ x ∈ ⇑f ⁻¹' (⇑g '' U) → x ∈ ⇑pullback.fst '' (⇑pullback.snd ⁻¹' U)

Next tactic:
rintro ⟨y, hy, eq⟩
theorem pullback_fst_image_snd_preimage (f : X ⟶ Z) (g : Y ⟶ Z) (U : Set Y) :
    (pullback.fst : pullback f g ⟶ _) '' ((pullback.snd : pullback f g ⟶ _) ⁻¹' U) =
      f ⁻¹' (g '' U) := by
  ext x
  constructor
  · rintro ⟨y, hy, rfl⟩
    exact
      ⟨(pullback.snd : pullback f g ⟶ _) y, hy,
        (ConcreteCategory.congr_hom pullback.condition y).symm⟩
  · rintro ⟨y, hy, eq⟩
    

Proof state:
case h.mpr.intro.intro
J : Type v
inst✝ : SmallCategory J
X Y Z : TopCat
f : X ⟶ Z
g : Y ⟶ Z
U : Set ↑Y
x : (forget TopCat).obj X
y : (forget TopCat).obj Y
hy : y ∈ U
eq : g y = f x
⊢ x ∈ ⇑pullback.fst '' (⇑pullback.snd ⁻¹' U)

Next tactic:
exact ⟨(TopCat.pullbackIsoProdSubtype f g).inv ⟨⟨_, _⟩, eq.symm⟩, by simpa, by simp⟩