l3lab/ntp-mathlib huggingface dataset:
/-- If `f '' U` is open, then `f⁻¹ℱ U ≅ ℱ (f '' U)`.  -/
@[simps!]
def pullbackObjObjOfImageOpen {X Y : TopCat.{v}} (f : X ⟶ Y) (ℱ : Y.Presheaf C) (U : Opens X)
    (H : IsOpen (f '' SetLike.coe U)) : (pullbackObj f ℱ).obj (op U) ≅ ℱ.obj (op ⟨_, H⟩) := by
  let x : CostructuredArrow (Opens.map f).op (op U) := CostructuredArrow.mk
    (@homOfLE _ _ _ ((Opens.map f).obj ⟨_, H⟩) (Set.image_preimage.le_u_l _)).op
  have hx : IsTerminal x :=
    { lift := fun s ↦ by
        fapply CostructuredArrow.homMk
        change op (unop _) ⟶ op (⟨_, H⟩ : Opens _)
        · refine' (homOfLE _).op
          apply (Set.image_subset f s.pt.hom.unop.le).trans
          exact Set.image_preimage.l_u_le (SetLike.coe s.pt.left.unop)
        · simp [autoParam, eq_iff_true_of_subsingleton]
      -- porting note : add `fac`, `uniq` manually
      fac := fun _ _ => by ext; simp [eq_iff_true_of_subsingleton]
      uniq := fun _ _ _ => by ext; simp [eq_iff_true_of_subsingleton] }
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
f : X ⟶ Y
ℱ : Presheaf C Y
U : Opens ↑X
H : IsOpen (⇑f '' ↑U)
x : CostructuredArrow (Opens.map f).op (op U) :=
  CostructuredArrow.mk (homOfLE (_ : ↑U ≤ (fun a => f a) ⁻¹' ((fun a => f a) '' ↑U))).op
hx : IsTerminal x
⊢ (pullbackObj f ℱ).obj (op U) ≅ ℱ.obj (op { carrier := ⇑f '' ↑U, is_open' := H })

Next tactic:
exact IsColimit.coconePointUniqueUpToIso (colimit.isColimit _) (colimitOfDiagramTerminal hx _)
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : (Opens ↑Y)ᵒᵖ
⊢ IsOpen (⇑(𝟙 Y) '' ↑U.unop)

Next tactic:
simpa using U.unop.2
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : (Opens ↑Y)ᵒᵖ
⊢ op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U

Next tactic:
simp
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
⊢ (pullbackObj (𝟙 Y) ℱ).map i ≫
      ((fun U =>
            pullbackObjObjOfImageOpen (𝟙 Y) ℱ U.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) ≪≫
              ℱ.mapIso
                (eqToIso (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U)))
          V).hom =
    ((fun U =>
            pullbackObjObjOfImageOpen (𝟙 Y) ℱ U.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) ≪≫
              ℱ.mapIso
                (eqToIso (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U)))
          U).hom ≫
      ℱ.map i

Next tactic:
simp only [pullbackObj_obj]
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      simp only [pullbackObj_obj]
      

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
⊢ (pullbackObj (𝟙 Y) ℱ).map i ≫
      (pullbackObjObjOfImageOpen (𝟙 Y) ℱ V.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) ≪≫
          ℱ.mapIso
            (eqToIso (_ : op { carrier := ⇑(𝟙 Y) '' ↑V.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) } = V))).hom =
    (pullbackObjObjOfImageOpen (𝟙 Y) ℱ U.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) ≪≫
          ℱ.mapIso
            (eqToIso (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U))).hom ≫
      ℱ.map i

Next tactic:
ext
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      simp only [pullbackObj_obj]
      ext
      

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
j✝ : CostructuredArrow (Opens.map (𝟙 Y)).op U
⊢ colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ U) j✝ ≫
      (pullbackObj (𝟙 Y) ℱ).map i ≫
        (pullbackObjObjOfImageOpen (𝟙 Y) ℱ V.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) ≪≫
            ℱ.mapIso
              (eqToIso
                (_ : op { carrier := ⇑(𝟙 Y) '' ↑V.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) } = V))).hom =
    colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ U) j✝ ≫
      (pullbackObjObjOfImageOpen (𝟙 Y) ℱ U.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) ≪≫
            ℱ.mapIso
              (eqToIso
                (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U))).hom ≫
        ℱ.map i

Next tactic:
simp only [Functor.comp_obj, CostructuredArrow.proj_obj, pullbackObj_map,
        Iso.trans_hom, Functor.mapIso_hom, eqToIso.hom, Category.assoc]
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      simp only [pullbackObj_obj]
      ext
      simp only [Functor.comp_obj, CostructuredArrow.proj_obj, pullbackObj_map,
        Iso.trans_hom, Functor.mapIso_hom, eqToIso.hom, Category.assoc]
      

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
j✝ : CostructuredArrow (Opens.map (𝟙 Y)).op U
⊢ colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ U) j✝ ≫
      colimit.pre (Lan.diagram (Opens.map (𝟙 Y)).op ℱ V) (CostructuredArrow.map i) ≫
        (pullbackObjObjOfImageOpen (𝟙 Y) ℱ V.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop))).hom ≫
          ℱ.map (eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑V.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) } = V)) =
    colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ U) j✝ ≫
      (pullbackObjObjOfImageOpen (𝟙 Y) ℱ U.unop (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop))).hom ≫
        ℱ.map (eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U)) ≫
          ℱ.map i

Next tactic:
erw [colimit.pre_desc_assoc, colimit.ι_desc_assoc, colimit.ι_desc_assoc]
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      simp only [pullbackObj_obj]
      ext
      simp only [Functor.comp_obj, CostructuredArrow.proj_obj, pullbackObj_map,
        Iso.trans_hom, Functor.mapIso_hom, eqToIso.hom, Category.assoc]
      erw [colimit.pre_desc_assoc, colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
j✝ : CostructuredArrow (Opens.map (𝟙 Y)).op U
⊢ (Cocone.whisker (CostructuredArrow.map i)
              (coconeOfDiagramTerminal
                (IsLimit.mk fun s =>
                  CostructuredArrow.homMk
                    (let_fun this :=
                      (homOfLE
                          (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op V.unop)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
                    this))
                (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op V.unop)))).ι.app
        j✝ ≫
      ℱ.map (eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑V.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) } = V)) =
    (coconeOfDiagramTerminal
              (IsLimit.mk fun s =>
                CostructuredArrow.homMk
                  (let_fun this :=
                    (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U.unop)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
                  this))
              (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U.unop))).ι.app
        j✝ ≫
      ℱ.map (eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U)) ≫
        ℱ.map i

Next tactic:
dsimp
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      simp only [pullbackObj_obj]
      ext
      simp only [Functor.comp_obj, CostructuredArrow.proj_obj, pullbackObj_map,
        Iso.trans_hom, Functor.mapIso_hom, eqToIso.hom, Category.assoc]
      erw [colimit.pre_desc_assoc, colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      dsimp
      

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
j✝ : CostructuredArrow (Opens.map (𝟙 Y)).op U
⊢ ℱ.map
        (IsTerminal.from
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op V.unop)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            ((CostructuredArrow.map i).obj j✝)).left ≫
      ℱ.map (eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑V.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) } = V)) =
    ℱ.map
        (IsTerminal.from
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U.unop)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            j✝).left ≫
      ℱ.map (eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U)) ≫
        ℱ.map i

Next tactic:
simp only [← ℱ.map_comp]
/-- The pullback along the identity is isomorphic to the original presheaf. -/
def id : pullbackObj (𝟙 _) ℱ ≅ ℱ :=
  NatIso.ofComponents
    (fun U =>
      pullbackObjObjOfImageOpen (𝟙 _) ℱ (unop U) (by simpa using U.unop.2) ≪≫
        ℱ.mapIso (eqToIso (by simp)))
    fun {U V} i => by
      simp only [pullbackObj_obj]
      ext
      simp only [Functor.comp_obj, CostructuredArrow.proj_obj, pullbackObj_map,
        Iso.trans_hom, Functor.mapIso_hom, eqToIso.hom, Category.assoc]
      erw [colimit.pre_desc_assoc, colimit.ι_desc_assoc, colimit.ι_desc_assoc]
      dsimp
      simp only [← ℱ.map_comp]
      -- Porting note : `congr` does not work, but `congr 1` does
      

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U V : (Opens ↑Y)ᵒᵖ
i : U ⟶ V
j✝ : CostructuredArrow (Opens.map (𝟙 Y)).op U
⊢ ℱ.map
      ((IsTerminal.from
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op V.unop)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            ((CostructuredArrow.map i).obj j✝)).left ≫
        eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑V.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑V.unop)) } = V)) =
    ℱ.map
      ((IsTerminal.from
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U.unop)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            j✝).left ≫
        eqToHom (_ : op { carrier := ⇑(𝟙 Y) '' ↑U.unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑U.unop)) } = U) ≫ i)

Next tactic:
congr 1
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ (Opens.map (𝟙 Y)).op.obj (op U) = op U

Next tactic:
simp
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by simp))) := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ (id ℱ).inv.app (op U) =
    colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
      (CostructuredArrow.mk (eqToHom (_ : (Opens.map (𝟙 Y)).op.obj (op U) = op U)))

Next tactic:
rw [← Category.id_comp ((id ℱ).inv.app (op U)), ← NatIso.app_inv, Iso.comp_inv_eq]
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by simp))) := by
  rw [← Category.id_comp ((id ℱ).inv.app (op U)), ← NatIso.app_inv, Iso.comp_inv_eq]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ 𝟙 (ℱ.obj (op U)) =
    colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (CostructuredArrow.mk (eqToHom (_ : (Opens.map (𝟙 Y)).op.obj (op U) = op U))) ≫
      ((id ℱ).app (op U)).hom

Next tactic:
dsimp [id]
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by simp))) := by
  rw [← Category.id_comp ((id ℱ).inv.app (op U)), ← NatIso.app_inv, Iso.comp_inv_eq]
  dsimp [id]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ 𝟙 (ℱ.obj (op U)) =
    colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U)) (CostructuredArrow.mk (𝟙 (op ((Opens.map (𝟙 Y)).obj U)))) ≫
      colimit.desc (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
          (coconeOfDiagramTerminal
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))) ≫
        ℱ.map
          (eqToHom
            (_ : op { carrier := ⇑(𝟙 Y) '' ↑(op U).unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑(op U).unop)) } = op U))

Next tactic:
erw [colimit.ι_desc_assoc]
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by simp))) := by
  rw [← Category.id_comp ((id ℱ).inv.app (op U)), ← NatIso.app_inv, Iso.comp_inv_eq]
  dsimp [id]
  erw [colimit.ι_desc_assoc]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ 𝟙 (ℱ.obj (op U)) =
    (coconeOfDiagramTerminal
              (IsLimit.mk fun s =>
                CostructuredArrow.homMk
                  (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
              (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))).ι.app
        (CostructuredArrow.mk (𝟙 (op ((Opens.map (𝟙 Y)).obj U)))) ≫
      ℱ.map
        (eqToHom
          (_ : op { carrier := ⇑(𝟙 Y) '' ↑(op U).unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑(op U).unop)) } = op U))

Next tactic:
dsimp
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by simp))) := by
  rw [← Category.id_comp ((id ℱ).inv.app (op U)), ← NatIso.app_inv, Iso.comp_inv_eq]
  dsimp [id]
  erw [colimit.ι_desc_assoc]
  dsimp
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ 𝟙 (ℱ.obj (op U)) =
    ℱ.map
        (IsTerminal.from
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            (CostructuredArrow.mk (𝟙 (op ((Opens.map (𝟙 Y)).obj U))))).left ≫
      ℱ.map
        (eqToHom
          (_ : op { carrier := ⇑(𝟙 Y) '' ↑(op U).unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑(op U).unop)) } = op U))

Next tactic:
rw [← ℱ.map_comp, ← ℱ.map_id]
theorem id_inv_app (U : Opens Y) :
    (id ℱ).inv.app (op U) =
      colimit.ι (Lan.diagram (Opens.map (𝟙 Y)).op ℱ (op U))
        (@CostructuredArrow.mk _ _ _ _ _ (op U) _ (eqToHom (by simp))) := by
  rw [← Category.id_comp ((id ℱ).inv.app (op U)), ← NatIso.app_inv, Iso.comp_inv_eq]
  dsimp [id]
  erw [colimit.ι_desc_assoc]
  dsimp
  rw [← ℱ.map_comp, ← ℱ.map_id]; 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : TopCat
ℱ : Presheaf C Y
U : Opens ↑Y
⊢ ℱ.map (𝟙 (op U)) =
    ℱ.map
      ((IsTerminal.from
            (IsLimit.mk fun s =>
              CostructuredArrow.homMk
                (homOfLE (_ : ⇑(𝟙 Y) '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op)
            (CostructuredArrow.mk (𝟙 (op ((Opens.map (𝟙 Y)).obj U))))).left ≫
        eqToHom
          (_ : op { carrier := ⇑(𝟙 Y) '' ↑(op U).unop, is_open' := (_ : IsOpen (⇑(𝟙 Y) '' ↑(op U).unop)) } = op U))

Next tactic:
rfl
theorem id_pushforward {X : TopCat.{w}} : pushforward C (𝟙 X) = 𝟭 (X.Presheaf C) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
⊢ pushforward C (𝟙 X) = 𝟭 (Presheaf C X)

Next tactic:
apply CategoryTheory.Functor.ext
theorem id_pushforward {X : TopCat.{w}} : pushforward C (𝟙 X) = 𝟭 (X.Presheaf C) := by
  apply CategoryTheory.Functor.ext
  · 

Proof state:
case h_map
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
⊢ autoParam
    (∀ (X_1 Y : Presheaf C X) (f : X_1 ⟶ Y),
      (pushforward C (𝟙 X)).map f =
        eqToHom (_ : ?F.obj X_1 = ?G.obj X_1) ≫
          (𝟭 (Presheaf C X)).map f ≫ eqToHom (_ : (𝟭 (Presheaf C X)).obj Y = (pushforward C (𝟙 X)).obj Y))
    _auto✝

Next tactic:
intros a b f
theorem id_pushforward {X : TopCat.{w}} : pushforward C (𝟙 X) = 𝟭 (X.Presheaf C) := by
  apply CategoryTheory.Functor.ext
  · intros a b f
    

Proof state:
case h_map
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
a b : Presheaf C X
f : a ⟶ b
⊢ (pushforward C (𝟙 X)).map f =
    eqToHom (_ : ?F.obj a = ?G.obj a) ≫
      (𝟭 (Presheaf C X)).map f ≫ eqToHom (_ : (𝟭 (Presheaf C X)).obj b = (pushforward C (𝟙 X)).obj b)

Next tactic:
ext U
theorem id_pushforward {X : TopCat.{w}} : pushforward C (𝟙 X) = 𝟭 (X.Presheaf C) := by
  apply CategoryTheory.Functor.ext
  · intros a b f
    ext U
    · 

Proof state:
case h_map.w
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
a b : Presheaf C X
f : a ⟶ b
U : Opens ↑X
⊢ ((pushforward C (𝟙 X)).map f).app (op U) =
    (eqToHom (_ : ?F.obj a = ?G.obj a) ≫
          (𝟭 (Presheaf C X)).map f ≫ eqToHom (_ : (𝟭 (Presheaf C X)).obj b = (pushforward C (𝟙 X)).obj b)).app
      (op U)

Next tactic:
erw [NatTrans.congr f (Opens.op_map_id_obj (op U))]
theorem id_pushforward {X : TopCat.{w}} : pushforward C (𝟙 X) = 𝟭 (X.Presheaf C) := by
  apply CategoryTheory.Functor.ext
  · intros a b f
    ext U
    · erw [NatTrans.congr f (Opens.op_map_id_obj (op U))]
      

Proof state:
case h_map.w
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
a b : Presheaf C X
f : a ⟶ b
U : Opens ↑X
⊢ a.map (eqToHom (_ : (Opens.map (𝟙 X)).op.obj (op U) = op U)) ≫
      f.app (op U) ≫ b.map (eqToHom (_ : op U = (Opens.map (𝟙 X)).op.obj (op U))) =
    (eqToHom (_ : ?F.obj a = ?G.obj a) ≫
          (𝟭 (Presheaf C X)).map f ≫ eqToHom (_ : (𝟭 (Presheaf C X)).obj b = (pushforward C (𝟙 X)).obj b)).app
      (op U)
case h_obj
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
⊢ ∀ (X_1 : Presheaf C X), (pushforward C (𝟙 X)).obj X_1 = (𝟭 (Presheaf C X)).obj X_1

Next tactic:
simp only [Functor.op_obj, eqToHom_refl, CategoryTheory.Functor.map_id,
        Category.comp_id, Category.id_comp, Functor.id_obj, Functor.id_map]
theorem id_pushforward {X : TopCat.{w}} : pushforward C (𝟙 X) = 𝟭 (X.Presheaf C) := by
  apply CategoryTheory.Functor.ext
  · intros a b f
    ext U
    · erw [NatTrans.congr f (Opens.op_map_id_obj (op U))]
      simp only [Functor.op_obj, eqToHom_refl, CategoryTheory.Functor.map_id,
        Category.comp_id, Category.id_comp, Functor.id_obj, Functor.id_map]
      

Proof state:
case h_obj
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
⊢ ∀ (X_1 : Presheaf C X), (pushforward C (𝟙 X)).obj X_1 = (𝟭 (Presheaf C X)).obj X_1

Next tactic:
apply Pushforward.id_eq
@[simp]
theorem toPushforwardOfIso_app {X Y : TopCat} (H₁ : X ≅ Y) {ℱ : X.Presheaf C} {𝒢 : Y.Presheaf C}
    (H₂ : H₁.hom _* ℱ ⟶ 𝒢) (U : (Opens X)ᵒᵖ) :
    (toPushforwardOfIso H₁ H₂).app U =
      ℱ.map (eqToHom (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
H₁ : X ≅ Y
ℱ : Presheaf C X
𝒢 : Presheaf C Y
H₂ : H₁.hom _* ℱ ⟶ 𝒢
U : (Opens ↑X)ᵒᵖ
⊢ U = (Opens.map H₁.hom).op.obj (op ((Opens.map H₁.inv).obj U.unop))

Next tactic:
simp [Opens.map, Set.preimage_preimage]
@[simp]
theorem toPushforwardOfIso_app {X Y : TopCat} (H₁ : X ≅ Y) {ℱ : X.Presheaf C} {𝒢 : Y.Presheaf C}
    (H₂ : H₁.hom _* ℱ ⟶ 𝒢) (U : (Opens X)ᵒᵖ) :
    (toPushforwardOfIso H₁ H₂).app U =
      ℱ.map (eqToHom (by simp [Opens.map, Set.preimage_preimage])) ≫
        H₂.app (op ((Opens.map H₁.inv).obj (unop U))) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
H₁ : X ≅ Y
ℱ : Presheaf C X
𝒢 : Presheaf C Y
H₂ : H₁.hom _* ℱ ⟶ 𝒢
U : (Opens ↑X)ᵒᵖ
⊢ (toPushforwardOfIso H₁ H₂).app U =
    ℱ.map
        (eqToHom
          (_ :
            U =
              op
                {
                  carrier :=
                    ⇑H₁.hom ⁻¹'
                      ↑(op { carrier := ⇑H₁.inv ⁻¹' ↑U.unop, is_open' := (_ : IsOpen (⇑H₁.inv ⁻¹' ↑U.unop)) }).unop,
                  is_open' :=
                    (_ :
                      IsOpen
                        (⇑H₁.hom ⁻¹'
                          ↑(op
                                { carrier := ⇑H₁.inv ⁻¹' ↑U.unop,
                                  is_open' := (_ : IsOpen (⇑H₁.inv ⁻¹' ↑U.unop)) }).unop)) })) ≫
      H₂.app (op ((Opens.map H₁.inv).obj U.unop))

Next tactic:
delta toPushforwardOfIso
@[simp]
theorem toPushforwardOfIso_app {X Y : TopCat} (H₁ : X ≅ Y) {ℱ : X.Presheaf C} {𝒢 : Y.Presheaf C}
    (H₂ : H₁.hom _* ℱ ⟶ 𝒢) (U : (Opens X)ᵒᵖ) :
    (toPushforwardOfIso H₁ H₂).app U =
      ℱ.map (eqToHom (by simp [Opens.map, Set.preimage_preimage])) ≫
        H₂.app (op ((Opens.map H₁.inv).obj (unop U))) := by
  delta toPushforwardOfIso
  -- Porting note : originally is a single invocation of `simp`
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
H₁ : X ≅ Y
ℱ : Presheaf C X
𝒢 : Presheaf C Y
H₂ : H₁.hom _* ℱ ⟶ 𝒢
U : (Opens ↑X)ᵒᵖ
⊢ ((Adjunction.homEquiv (presheafEquivOfIso C H₁).toAdjunction ℱ 𝒢) H₂).app U =
    ℱ.map
        (eqToHom
          (_ :
            U =
              op
                {
                  carrier :=
                    ⇑H₁.hom ⁻¹'
                      ↑(op { carrier := ⇑H₁.inv ⁻¹' ↑U.unop, is_open' := (_ : IsOpen (⇑H₁.inv ⁻¹' ↑U.unop)) }).unop,
                  is_open' :=
                    (_ :
                      IsOpen
                        (⇑H₁.hom ⁻¹'
                          ↑(op
                                { carrier := ⇑H₁.inv ⁻¹' ↑U.unop,
                                  is_open' := (_ : IsOpen (⇑H₁.inv ⁻¹' ↑U.unop)) }).unop)) })) ≫
      H₂.app (op ((Opens.map H₁.inv).obj U.unop))

Next tactic:
simp only [pushforwardObj_obj, Functor.op_obj, Equivalence.toAdjunction, Adjunction.homEquiv_unit,
    Functor.id_obj, Functor.comp_obj, Adjunction.mkOfUnitCounit_unit, unop_op, eqToHom_map]