l3lab/ntp-mathlib huggingface dataset:
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    

Proof state:
case h.e'_4.h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ x = y

Next tactic:
apply_fun (D.ι _).base
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · 

Proof state:
case h.e'_4.h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ (ι D.toGlueData i).base x = (ι D.toGlueData i).base y

Next tactic:
exact h2.symm
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · 

Proof state:
case h.e'_4.h.inj
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ Function.Injective ⇑(ι D.toGlueData i).base

Next tactic:
have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      

Proof state:
case h.e'_4.h.inj
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
this :
  ι (mapGlueData D.toGlueData (forget C)) i ≫ (gluedIso D.toGlueData (forget C)).inv = (forget C).map (ι D.toGlueData i)
⊢ Function.Injective ⇑(ι D.toGlueData i).base

Next tactic:
dsimp at this
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      

Proof state:
case h.e'_4.h.inj
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
this : ι (mapGlueData D.toGlueData (forget C)) i ≫ (gluedIso D.toGlueData (forget C)).inv = (ι D.toGlueData i).base
⊢ Function.Injective ⇑(ι D.toGlueData i).base

Next tactic:
rw [← this, coe_comp]
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      

Proof state:
case h.e'_4.h.inj
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
this : ι (mapGlueData D.toGlueData (forget C)) i ≫ (gluedIso D.toGlueData (forget C)).inv = (ι D.toGlueData i).base
⊢ Function.Injective (⇑(gluedIso D.toGlueData (forget C)).inv ∘ ⇑(ι (mapGlueData D.toGlueData (forget C)) i))

Next tactic:
refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      

Proof state:
case h.e'_4.h.inj
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
this : ι (mapGlueData D.toGlueData (forget C)) i ≫ (gluedIso D.toGlueData (forget C)).inv = (ι D.toGlueData i).base
⊢ Function.Injective ⇑(gluedIso D.toGlueData (forget C)).inv

Next tactic:
rw [← TopCat.mono_iff_injective]
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      

Proof state:
case h.e'_4.h.inj
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
x : ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
y : (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
h1 : y ∈ U
h2 :
  (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base y =
    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base x
e_1✝ :
  ↑↑(CategoryTheory.GlueData.U D.toGlueData i) =
    (CategoryTheory.forget TopCat).obj ↑(CategoryTheory.GlueData.U D.toGlueData i)
this : ι (mapGlueData D.toGlueData (forget C)) i ≫ (gluedIso D.toGlueData (forget C)).inv = (ι D.toGlueData i).base
⊢ Mono (gluedIso D.toGlueData (forget C)).inv

Next tactic:
infer_instance
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      infer_instance
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ ιInvApp D U ≫ diagramOverOpenπ D U i =
    (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
      (eqToHom
        (_ :
          op U =
            op
              ((Opens.map
                    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData))
                        (op (WalkingMultispan.right i)).unop).base).obj
                ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U))))

Next tactic:
delta ιInvApp
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      infer_instance
  delta ιInvApp
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ limit.lift (diagramOverOpen D U)
        { pt := (CategoryTheory.GlueData.U D.toGlueData i).presheaf.obj (op U),
          π := NatTrans.mk fun j => ιInvAppπApp D U j.unop } ≫
      diagramOverOpenπ D U i =
    (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
      (eqToHom
        (_ :
          op U =
            op
              ((Opens.map
                    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData))
                        (op (WalkingMultispan.right i)).unop).base).obj
                ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U))))

Next tactic:
rw [limit.lift_π]
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      infer_instance
  delta ιInvApp
  rw [limit.lift_π]
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ { pt := (CategoryTheory.GlueData.U D.toGlueData i).presheaf.obj (op U),
            π := NatTrans.mk fun j => ιInvAppπApp D U j.unop }.π.app
      (op (WalkingMultispan.right i)) =
    (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
      (eqToHom
        (_ :
          op U =
            op
              ((Opens.map
                    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData))
                        (op (WalkingMultispan.right i)).unop).base).obj
                ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U))))

Next tactic:
change D.opensImagePreimageMap i i U = _
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      infer_instance
  delta ιInvApp
  rw [limit.lift_π]
  change D.opensImagePreimageMap i i U = _
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ opensImagePreimageMap D i i U =
    (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
      (eqToHom
        (_ :
          op U =
            op
              ((Opens.map
                    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData))
                        (op (WalkingMultispan.right i)).unop).base).obj
                ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U))))

Next tactic:
dsimp [opensImagePreimageMap]
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      infer_instance
  delta ιInvApp
  rw [limit.lift_π]
  change D.opensImagePreimageMap i i U = _
  dsimp [opensImagePreimageMap]
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ (f D.toGlueData i i).c.app (op U) ≫
      (t D.toGlueData i i).c.app (op ((Opens.map (f D.toGlueData i i).base).obj U)) ≫
        IsOpenImmersion.invApp (_ : IsOpenImmersion (f D.toGlueData i i))
            { carrier := ⇑(t D.toGlueData i i).base ⁻¹' (⇑(f D.toGlueData i i).base ⁻¹' ↑U),
              is_open' :=
                (_ :
                  IsOpen
                    (⇑(t D.toGlueData i i).base ⁻¹' ↑((Opens.map (f D.toGlueData i i).base).op.obj (op U)).unop)) } ≫
          (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
            (eqToHom
                (_ :
                  (Opens.map (ι D.toGlueData i).base).obj
                      ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U) =
                    (IsOpenImmersion.openFunctor (_ : IsOpenImmersion (f D.toGlueData i i))).obj
                      ((Opens.map (t D.toGlueData i i).base).obj ((Opens.map (f D.toGlueData i i).base).obj U)))).op =
    (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
      (eqToHom
        (_ :
          op U =
            op
              ((Opens.map
                    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base).obj
                ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U))))

Next tactic:
rw [congr_app (D.t_id _), id_c_app, ← Functor.map_comp]
/-- `ιInvApp` is the left inverse of `D.ι i` on `U`. -/
theorem ιInvApp_π {i : D.J} (U : Opens (D.U i).carrier) :
    ∃ eq, D.ιInvApp U ≫ D.diagramOverOpenπ U i = (D.U i).presheaf.map (eqToHom eq) := by
  fconstructor
  -- Porting note: I don't know what the magic was in Lean3 proof, it just skipped the proof of `eq`
  · congr; ext1; change _ = _ ⁻¹' (_ '' _); ext1 x
    simp only [SetLike.mem_coe, diagram_l, diagram_r, unop_op, Set.mem_preimage, Set.mem_image]
    refine ⟨fun h => ⟨_, h, rfl⟩, ?_⟩
    rintro ⟨y, h1, h2⟩
    convert h1 using 1
    delta ι Multicoequalizer.π at h2
    apply_fun (D.ι _).base
    · exact h2.symm
    · have := D.ι_gluedIso_inv (PresheafedSpace.forget _) i
      dsimp at this
      rw [← this, coe_comp]
      refine Function.Injective.comp ?_ (TopCat.GlueData.ι_injective D.toTopGlueData i)
      rw [← TopCat.mono_iff_injective]
      infer_instance
  delta ιInvApp
  rw [limit.lift_π]
  change D.opensImagePreimageMap i i U = _
  dsimp [opensImagePreimageMap]
  rw [congr_app (D.t_id _), id_c_app, ← Functor.map_comp]
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
D : GlueData C
inst✝ : HasLimits C
i : D.J
U : Opens ↑↑(CategoryTheory.GlueData.U D.toGlueData i)
⊢ (f D.toGlueData i i).c.app (op U) ≫
      (V D.toGlueData (i, i)).presheaf.map
          (𝟙 (op ((Opens.map (f D.toGlueData i i).base).obj U)) ≫
            eqToHom
              (_ :
                (Opens.map (𝟙 (V D.toGlueData (i, i))).base).op.obj (op ((Opens.map (f D.toGlueData i i).base).obj U)) =
                  (Opens.map (t D.toGlueData i i).base).op.obj (op ((Opens.map (f D.toGlueData i i).base).obj U)))) ≫
        IsOpenImmersion.invApp (_ : IsOpenImmersion (f D.toGlueData i i))
            { carrier := ⇑(t D.toGlueData i i).base ⁻¹' (⇑(f D.toGlueData i i).base ⁻¹' ↑U),
              is_open' :=
                (_ :
                  IsOpen
                    (⇑(t D.toGlueData i i).base ⁻¹' ↑((Opens.map (f D.toGlueData i i).base).op.obj (op U)).unop)) } ≫
          (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
            (eqToHom
                (_ :
                  (Opens.map (ι D.toGlueData i).base).obj
                      ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U) =
                    (IsOpenImmersion.openFunctor (_ : IsOpenImmersion (f D.toGlueData i i))).obj
                      ((Opens.map (t D.toGlueData i i).base).obj ((Opens.map (f D.toGlueData i i).base).obj U)))).op =
    (CategoryTheory.GlueData.U D.toGlueData i).presheaf.map
      (eqToHom
        (_ :
          op U =
            op
              ((Opens.map
                    (colimit.ι (MultispanIndex.multispan (diagram D.toGlueData)) (WalkingMultispan.right i)).base).obj
                ((IsOpenMap.functor (_ : IsOpenMap ⇑(ι D.toGlueData i).base)).obj U))))

Next tactic:
erw [IsOpenImmersion.inv_naturality_assoc, IsOpenImmersion.app_inv_app'_assoc]