l3lab/ntp-mathlib huggingface dataset:
theorem pushforward_eq' {X Y : TopCat.{w}} {f g : X ⟶ Y} (h : f = g) (ℱ : X.Presheaf C) :
    f _* ℱ = g _* ℱ := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
⊢ f _* ℱ = g _* ℱ

Next tactic:
rw [h]
@[simp]
theorem pushforwardEq_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y}
    (h : f = g) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq h ℱ).hom.app U =
      ℱ.map (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ (Opens.map f).op.obj U ⟶ (Opens.map g).op.obj U

Next tactic:
dsimp [Functor.op]
@[simp]
theorem pushforwardEq_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y}
    (h : f = g) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq h ℱ).hom.app U =
      ℱ.map (by dsimp [Functor.op]; 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ op ((Opens.map f).obj U.unop) ⟶ op ((Opens.map g).obj U.unop)

Next tactic:
apply Quiver.Hom.op
@[simp]
theorem pushforwardEq_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y}
    (h : f = g) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq h ℱ).hom.app U =
      ℱ.map (by dsimp [Functor.op]; apply Quiver.Hom.op; 

Proof state:
case f
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ (Opens.map g).obj U.unop ⟶ (Opens.map f).obj U.unop

Next tactic:
apply eqToHom
@[simp]
theorem pushforwardEq_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y}
    (h : f = g) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq h ℱ).hom.app U =
      ℱ.map (by dsimp [Functor.op]; apply Quiver.Hom.op; apply eqToHom; 

Proof state:
case f.p
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ (Opens.map g).obj U.unop = (Opens.map f).obj U.unop

Next tactic:
rw [h]
@[simp]
theorem pushforwardEq_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y}
    (h : f = g) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq h ℱ).hom.app U =
      ℱ.map (by dsimp [Functor.op]; apply Quiver.Hom.op; apply eqToHom; rw [h]) :=
  by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ (pushforwardEq h ℱ).hom.app U = ℱ.map (id (eqToHom (_ : (Opens.map g).obj U.unop = (Opens.map f).obj U.unop)).op)

Next tactic:
simp [pushforwardEq]
theorem pushforward_eq'_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y} (h : f = g) (ℱ : X.Presheaf C)
    (U) : NatTrans.app (eqToHom (pushforward_eq' h ℱ)) U = ℱ.map (eqToHom (by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ (Opens.map f).op.obj U = (Opens.map g).op.obj U

Next tactic:
rw [h]
theorem pushforward_eq'_hom_app {X Y : TopCat.{w}} {f g : X ⟶ Y} (h : f = g) (ℱ : X.Presheaf C)
    (U) : NatTrans.app (eqToHom (pushforward_eq' h ℱ)) U = ℱ.map (eqToHom (by rw [h])) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f g : X ⟶ Y
h : f = g
ℱ : Presheaf C X
U : (Opens ↑Y)ᵒᵖ
⊢ (eqToHom (_ : f _* ℱ = g _* ℱ)).app U = ℱ.map (eqToHom (_ : (Opens.map f).op.obj U = (Opens.map g).op.obj U))

Next tactic:
rw [eqToHom_app, eqToHom_map]
@[simp (high)]
theorem pushforwardEq_rfl {X Y : TopCat.{w}} (f : X ⟶ Y) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq (rfl : f = f) ℱ).hom.app (op U) = 𝟙 _ := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
ℱ : Presheaf C X
U : Opens ↑Y
⊢ (pushforwardEq (_ : f = f) ℱ).hom.app (op U) = 𝟙 ((f _* ℱ).obj (op U))

Next tactic:
dsimp [pushforwardEq]
@[simp (high)]
theorem pushforwardEq_rfl {X Y : TopCat.{w}} (f : X ⟶ Y) (ℱ : X.Presheaf C) (U) :
    (pushforwardEq (rfl : f = f) ℱ).hom.app (op U) = 𝟙 _ := by
  dsimp [pushforwardEq]
  

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

Next tactic:
simp
theorem id_eq : 𝟙 X _* ℱ = ℱ := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
⊢ 𝟙 X _* ℱ = ℱ

Next tactic:
unfold pushforwardObj
theorem id_eq : 𝟙 X _* ℱ = ℱ := by
  unfold pushforwardObj
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
⊢ (Opens.map (𝟙 X)).op ⋙ ℱ = ℱ

Next tactic:
rw [Opens.map_id_eq]
theorem id_eq : 𝟙 X _* ℱ = ℱ := by
  unfold pushforwardObj
  rw [Opens.map_id_eq]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
⊢ (𝟭 (Opens ↑X)).op ⋙ ℱ = ℱ

Next tactic:
erw [Functor.id_comp]
@[simp (high)]
theorem id_hom_app' (U) (p) : (id ℱ).hom.app (op ⟨U, p⟩) = ℱ.map (𝟙 (op ⟨U, p⟩)) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
U : Set ↑X
p : IsOpen U
⊢ (id ℱ).hom.app (op { carrier := U, is_open' := p }) = ℱ.map (𝟙 (op { carrier := U, is_open' := p }))

Next tactic:
dsimp [id]
@[simp (high)]
theorem id_hom_app' (U) (p) : (id ℱ).hom.app (op ⟨U, p⟩) = ℱ.map (𝟙 (op ⟨U, p⟩)) := by
  dsimp [id]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
U : Set ↑X
p : IsOpen U
⊢ (whiskerRight (NatTrans.op (Opens.mapId X).inv) ℱ ≫ (Functor.leftUnitor ℱ).hom).app
      (op { carrier := U, is_open' := p }) =
    ℱ.map (𝟙 (op { carrier := U, is_open' := p }))

Next tactic:
simp [CategoryStruct.comp]
@[simp]
theorem id_hom_app (U) : (id ℱ).hom.app U = ℱ.map (eqToHom (Opens.op_map_id_obj U)) := by
  -- was `tidy`, see porting note above.
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
U : (Opens ↑X)ᵒᵖ
⊢ (id ℱ).hom.app U = ℱ.map (eqToHom (_ : (Opens.map (𝟙 X)).op.obj U = U))

Next tactic:
induction U
@[simp]
theorem id_hom_app (U) : (id ℱ).hom.app U = ℱ.map (eqToHom (Opens.op_map_id_obj U)) := by
  -- was `tidy`, see porting note above.
  induction U
  

Proof state:
case h
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
X✝ : Opens ↑X
⊢ (id ℱ).hom.app (op X✝) = ℱ.map (eqToHom (_ : (Opens.map (𝟙 X)).op.obj (op X✝) = op X✝))

Next tactic:
apply id_hom_app'
@[simp]
theorem id_inv_app' (U) (p) : (id ℱ).inv.app (op ⟨U, p⟩) = ℱ.map (𝟙 (op ⟨U, p⟩)) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
U : Set ↑X
p : IsOpen U
⊢ (id ℱ).inv.app (op { carrier := U, is_open' := p }) = ℱ.map (𝟙 (op { carrier := U, is_open' := p }))

Next tactic:
dsimp [id]
@[simp]
theorem id_inv_app' (U) (p) : (id ℱ).inv.app (op ⟨U, p⟩) = ℱ.map (𝟙 (op ⟨U, p⟩)) := by
  dsimp [id]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
U : Set ↑X
p : IsOpen U
⊢ ((Functor.leftUnitor ℱ).inv ≫ whiskerRight (NatTrans.op (Opens.mapId X).hom) ℱ).app
      (op { carrier := U, is_open' := p }) =
    ℱ.map (𝟙 (op { carrier := U, is_open' := p }))

Next tactic:
simp [CategoryStruct.comp]
@[simp]
theorem comp_hom_app {Y Z : TopCat.{w}} (f : X ⟶ Y) (g : Y ⟶ Z) (U) :
    (comp ℱ f g).hom.app U = 𝟙 _ := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
Y Z : TopCat
f : X ⟶ Y
g : Y ⟶ Z
U : (Opens ↑Z)ᵒᵖ
⊢ (comp ℱ f g).hom.app U = 𝟙 (((f ≫ g) _* ℱ).obj U)

Next tactic:
simp [comp]
@[simp]
theorem comp_inv_app {Y Z : TopCat.{w}} (f : X ⟶ Y) (g : Y ⟶ Z) (U) :
    (comp ℱ f g).inv.app U = 𝟙 _ := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X : TopCat
ℱ : Presheaf C X
Y Z : TopCat
f : X ⟶ Y
g : Y ⟶ Z
U : (Opens ↑Z)ᵒᵖ
⊢ (comp ℱ f g).inv.app U = 𝟙 ((g _* (f _* ℱ)).obj U)

Next tactic:
simp [comp]
/-- A morphism of presheaves gives rise to a morphisms of the pushforwards of those presheaves.
-/
@[simps]
def pushforwardMap {X Y : TopCat.{w}} (f : X ⟶ Y) {ℱ 𝒢 : X.Presheaf C} (α : ℱ ⟶ 𝒢) :
    f _* ℱ ⟶ f _* 𝒢 where
  app U := α.app _
  naturality _ _ i := by 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
ℱ 𝒢 : Presheaf C X
α : ℱ ⟶ 𝒢
x✝¹ x✝ : (Opens ↑Y)ᵒᵖ
i : x✝¹ ⟶ x✝
⊢ (f _* ℱ).map i ≫ (fun U => α.app ((Opens.map f).op.obj U)) x✝ =
    (fun U => α.app ((Opens.map f).op.obj U)) x✝¹ ≫ (f _* 𝒢).map i

Next tactic:
erw [α.naturality]
/-- A morphism of presheaves gives rise to a morphisms of the pushforwards of those presheaves.
-/
@[simps]
def pushforwardMap {X Y : TopCat.{w}} (f : X ⟶ Y) {ℱ 𝒢 : X.Presheaf C} (α : ℱ ⟶ 𝒢) :
    f _* ℱ ⟶ f _* 𝒢 where
  app U := α.app _
  naturality _ _ i := by erw [α.naturality]; 

Proof state:
C : Type u
inst✝ : Category.{v, u} C
X Y : TopCat
f : X ⟶ Y
ℱ 𝒢 : Presheaf C X
α : ℱ ⟶ 𝒢
x✝¹ x✝ : (Opens ↑Y)ᵒᵖ
i : x✝¹ ⟶ x✝
⊢ α.app ((Opens.map f).op.obj x✝¹) ≫ 𝒢.map ((Opens.map f).op.map i) =
    (fun U => α.app ((Opens.map f).op.obj U)) x✝¹ ≫ (f _* 𝒢).map i

Next tactic:
rfl
/-- 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
  

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)
⊢ (pullbackObj f ℱ).obj (op U) ≅ ℱ.obj (op { carrier := ⇑f '' ↑U, is_open' := H })

Next tactic:
let x : CostructuredArrow (Opens.map f).op (op U) := CostructuredArrow.mk
    (@homOfLE _ _ _ ((Opens.map f).obj ⟨_, H⟩) (Set.image_preimage.le_u_l _)).op
/-- 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
  

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
⊢ (pullbackObj f ℱ).obj (op U) ≅ ℱ.obj (op { carrier := ⇑f '' ↑U, is_open' := H })

Next tactic:
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] }
/-- 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
        

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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ s.pt ⟶ (asEmptyCone x).pt

Next tactic:
fapply CostructuredArrow.homMk
/-- 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
        

Proof state:
case g
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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ s.pt.left ⟶ (asEmptyCone x).pt.left
case w
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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ autoParam ((Opens.map f).op.map ?g ≫ (asEmptyCone x).pt.hom = s.pt.hom) _auto✝

Next tactic:
change op (unop _) ⟶ op (⟨_, H⟩ : Opens _)
/-- 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 _)
        · 

Proof state:
case g
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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ op s.pt.1.unop ⟶ op { carrier := ⇑f '' ↑U, is_open' := H }

Next tactic:
refine' (homOfLE _).op
/-- 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
          

Proof state:
case g
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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ { carrier := ⇑f '' ↑U, is_open' := H } ≤ s.pt.1.unop

Next tactic:
apply (Set.image_subset f s.pt.hom.unop.le).trans
/-- 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
          

Proof state:
case g
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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ ⇑f '' ↑((Opens.map f).op.obj s.pt.left).unop ⊆ ↑s.pt.1.unop

Next tactic:
exact Set.image_preimage.l_u_le (SetLike.coe s.pt.left.unop)
/-- 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)
        · 

Proof state:
case w
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
s : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
⊢ autoParam
    ((Opens.map f).op.map
          (let_fun this := (homOfLE (_ : ⇑f '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
          this) ≫
        (asEmptyCone x).pt.hom =
      s.pt.hom)
    _auto✝

Next tactic:
simp [autoParam, eq_iff_true_of_subsingleton]
/-- 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 

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
x✝¹ : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
x✝ : Discrete PEmpty.{1}
⊢ (fun s =>
          CostructuredArrow.homMk
            (let_fun this := (homOfLE (_ : ⇑f '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
            this))
        x✝¹ ≫
      (asEmptyCone x).π.app x✝ =
    x✝¹.π.app x✝

Next tactic:
ext
/-- 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; 

Proof state:
case h
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
x✝¹ : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
x✝ : Discrete PEmpty.{1}
⊢ ((fun s =>
            CostructuredArrow.homMk
              (let_fun this :=
                (homOfLE (_ : ⇑f '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
              this))
          x✝¹ ≫
        (asEmptyCone x).π.app x✝).left =
    (x✝¹.π.app x✝).left

Next tactic:
simp [eq_iff_true_of_subsingleton]
/-- 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 

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
x✝² : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
x✝¹ : x✝².pt ⟶ (asEmptyCone x).pt
x✝ : ∀ (j : Discrete PEmpty.{1}), x✝¹ ≫ (asEmptyCone x).π.app j = x✝².π.app j
⊢ x✝¹ =
    (fun s =>
        CostructuredArrow.homMk
          (let_fun this := (homOfLE (_ : ⇑f '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
          this))
      x✝²

Next tactic:
ext
/-- 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; 

Proof state:
case h
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
x✝² : Cone (Functor.empty (CostructuredArrow (Opens.map f).op (op U)))
x✝¹ : x✝².pt ⟶ (asEmptyCone x).pt
x✝ : ∀ (j : Discrete PEmpty.{1}), x✝¹ ≫ (asEmptyCone x).π.app j = x✝².π.app j
⊢ x✝¹.left =
    ((fun s =>
          CostructuredArrow.homMk
            (let_fun this := (homOfLE (_ : ⇑f '' ↑((Functor.fromPUnit (op U)).obj s.pt.right).unop ⊆ ↑s.pt.1.unop)).op;
            this))
        x✝²).left

Next tactic:
simp [eq_iff_true_of_subsingleton]