l3lab/ntp-mathlib huggingface dataset:
theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) :
    Function.Surjective (f.1.app (op U)) := by
  refine' app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => _
  -- Now we need to prove our initial claim: That we can find preimages of `t` locally.
  -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x`
  obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t)
  -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁`
  obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀
  

Proof state:
case intro.intro.intro.intro
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : HasColimits C
X Y Z : TopCat
inst✝⁴ : ConcreteCategory C
inst✝³ : PreservesFilteredColimits (forget C)
inst✝² : HasLimits C
inst✝¹ : PreservesLimits (forget C)
inst✝ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
h : ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)
t : (forget C).obj (G.val.obj (op U))
x : ↥U
s₀ : (forget C).obj ((stalkFunctor C ↑x).obj F.val)
hs₀ : ((stalkFunctor C ↑x).map f.val) s₀ = (germ (Sheaf.presheaf G) x) t
V₁ : Opens ↑X
hxV₁ : ↑x ∈ V₁
s₁ : (forget C).obj ((Sheaf.presheaf F).obj (op V₁))
hs₁ : (germ (Sheaf.presheaf F) { val := ↑x, property := hxV₁ }) s₁ = s₀
⊢ ∃ V, ∃ (_ : ↑x ∈ V), ∃ iVU s, (f.val.app (op V)) s = (G.val.map iVU.op) t

Next tactic:
subst hs₁
theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) :
    Function.Surjective (f.1.app (op U)) := by
  refine' app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => _
  -- Now we need to prove our initial claim: That we can find preimages of `t` locally.
  -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x`
  obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t)
  -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁`
  obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀
  subst hs₁; 

Proof state:
case intro.intro.intro.intro
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : HasColimits C
X Y Z : TopCat
inst✝⁴ : ConcreteCategory C
inst✝³ : PreservesFilteredColimits (forget C)
inst✝² : HasLimits C
inst✝¹ : PreservesLimits (forget C)
inst✝ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
h : ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)
t : (forget C).obj (G.val.obj (op U))
x : ↥U
V₁ : Opens ↑X
hxV₁ : ↑x ∈ V₁
s₁ : (forget C).obj ((Sheaf.presheaf F).obj (op V₁))
hs₀ :
  ((stalkFunctor C ↑x).map f.val) ((germ (Sheaf.presheaf F) { val := ↑x, property := hxV₁ }) s₁) =
    (germ (Sheaf.presheaf G) x) t
⊢ ∃ V, ∃ (_ : ↑x ∈ V), ∃ iVU s, (f.val.app (op V)) s = (G.val.map iVU.op) t

Next tactic:
rename' hs₀ => hs₁
theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) :
    Function.Surjective (f.1.app (op U)) := by
  refine' app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => _
  -- Now we need to prove our initial claim: That we can find preimages of `t` locally.
  -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x`
  obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t)
  -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁`
  obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀
  subst hs₁; rename' hs₀ => hs₁
  

Proof state:
case intro.intro.intro.intro
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : HasColimits C
X Y Z : TopCat
inst✝⁴ : ConcreteCategory C
inst✝³ : PreservesFilteredColimits (forget C)
inst✝² : HasLimits C
inst✝¹ : PreservesLimits (forget C)
inst✝ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
h : ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)
t : (forget C).obj (G.val.obj (op U))
x : ↥U
V₁ : Opens ↑X
hxV₁ : ↑x ∈ V₁
s₁ : (forget C).obj ((Sheaf.presheaf F).obj (op V₁))
hs₁ :
  ((stalkFunctor C ↑x).map f.val) ((germ (Sheaf.presheaf F) { val := ↑x, property := hxV₁ }) s₁) =
    (germ (Sheaf.presheaf G) x) t
⊢ ∃ V, ∃ (_ : ↑x ∈ V), ∃ iVU s, (f.val.app (op V)) s = (G.val.map iVU.op) t

Next tactic:
erw [stalkFunctor_map_germ_apply V₁ ⟨x.1, hxV₁⟩ f.1 s₁] at hs₁
theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) :
    Function.Surjective (f.1.app (op U)) := by
  refine' app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => _
  -- Now we need to prove our initial claim: That we can find preimages of `t` locally.
  -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x`
  obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t)
  -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁`
  obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀
  subst hs₁; rename' hs₀ => hs₁
  erw [stalkFunctor_map_germ_apply V₁ ⟨x.1, hxV₁⟩ f.1 s₁] at hs₁
  -- Now, the germ of `f.app (op V₁) s₁` equals the germ of `t`, hence they must coincide on
  -- some open neighborhood `V₂`.
  

Proof state:
case intro.intro.intro.intro
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : HasColimits C
X Y Z : TopCat
inst✝⁴ : ConcreteCategory C
inst✝³ : PreservesFilteredColimits (forget C)
inst✝² : HasLimits C
inst✝¹ : PreservesLimits (forget C)
inst✝ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
h : ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)
t : (forget C).obj (G.val.obj (op U))
x : ↥U
V₁ : Opens ↑X
hxV₁ : ↑x ∈ V₁
s₁ : (forget C).obj ((Sheaf.presheaf F).obj (op V₁))
hs₁ :
  (colimit.ι ((OpenNhds.inclusion ↑{ val := ↑x, property := hxV₁ }).op ⋙ G.val)
        (op { obj := V₁, property := (_ : ↑{ val := ↑x, property := hxV₁ } ∈ V₁) }))
      ((f.val.app (op V₁)) s₁) =
    (germ (Sheaf.presheaf G) x) t
⊢ ∃ V, ∃ (_ : ↑x ∈ V), ∃ iVU s, (f.val.app (op V)) s = (G.val.map iVU.op) t

Next tactic:
obtain ⟨V₂, hxV₂, iV₂V₁, iV₂U, heq⟩ := G.presheaf.germ_eq x.1 hxV₁ x.2 _ _ hs₁
theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) :
    Function.Surjective (f.1.app (op U)) := by
  refine' app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => _
  -- Now we need to prove our initial claim: That we can find preimages of `t` locally.
  -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x`
  obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t)
  -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁`
  obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀
  subst hs₁; rename' hs₀ => hs₁
  erw [stalkFunctor_map_germ_apply V₁ ⟨x.1, hxV₁⟩ f.1 s₁] at hs₁
  -- Now, the germ of `f.app (op V₁) s₁` equals the germ of `t`, hence they must coincide on
  -- some open neighborhood `V₂`.
  obtain ⟨V₂, hxV₂, iV₂V₁, iV₂U, heq⟩ := G.presheaf.germ_eq x.1 hxV₁ x.2 _ _ hs₁
  -- The restriction of `s₁` to that neighborhood is our desired local preimage.
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : HasColimits C
X Y Z : TopCat
inst✝⁴ : ConcreteCategory C
inst✝³ : PreservesFilteredColimits (forget C)
inst✝² : HasLimits C
inst✝¹ : PreservesLimits (forget C)
inst✝ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
h : ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)
t : (forget C).obj (G.val.obj (op U))
x : ↥U
V₁ : Opens ↑X
hxV₁ : ↑x ∈ V₁
s₁ : (forget C).obj ((Sheaf.presheaf F).obj (op V₁))
hs₁ :
  (colimit.ι ((OpenNhds.inclusion ↑{ val := ↑x, property := hxV₁ }).op ⋙ G.val)
        (op { obj := V₁, property := (_ : ↑{ val := ↑x, property := hxV₁ } ∈ V₁) }))
      ((f.val.app (op V₁)) s₁) =
    (germ (Sheaf.presheaf G) x) t
V₂ : Opens ↑X
hxV₂ : ↑x ∈ V₂
iV₂V₁ : V₂ ⟶ V₁
iV₂U : V₂ ⟶ U
heq : ((Sheaf.presheaf G).map iV₂V₁.op) ((f.val.app (op V₁)) s₁) = ((Sheaf.presheaf G).map iV₂U.op) t
⊢ ∃ V, ∃ (_ : ↑x ∈ V), ∃ iVU s, (f.val.app (op V)) s = (G.val.map iVU.op) t

Next tactic:
use V₂, hxV₂, iV₂U, F.1.map iV₂V₁.op s₁
theorem app_surjective_of_stalkFunctor_map_bijective {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    (h : ∀ x : U, Function.Bijective ((stalkFunctor C x.val).map f.1)) :
    Function.Surjective (f.1.app (op U)) := by
  refine' app_surjective_of_injective_of_locally_surjective f U (fun x => (h x).1) fun t x => _
  -- Now we need to prove our initial claim: That we can find preimages of `t` locally.
  -- Since `f` is surjective on stalks, we can find a preimage `s₀` of the germ of `t` at `x`
  obtain ⟨s₀, hs₀⟩ := (h x).2 (G.presheaf.germ x t)
  -- ... and this preimage must come from some section `s₁` defined on some open neighborhood `V₁`
  obtain ⟨V₁, hxV₁, s₁, hs₁⟩ := F.presheaf.germ_exist x.1 s₀
  subst hs₁; rename' hs₀ => hs₁
  erw [stalkFunctor_map_germ_apply V₁ ⟨x.1, hxV₁⟩ f.1 s₁] at hs₁
  -- Now, the germ of `f.app (op V₁) s₁` equals the germ of `t`, hence they must coincide on
  -- some open neighborhood `V₂`.
  obtain ⟨V₂, hxV₂, iV₂V₁, iV₂U, heq⟩ := G.presheaf.germ_eq x.1 hxV₁ x.2 _ _ hs₁
  -- The restriction of `s₁` to that neighborhood is our desired local preimage.
  use V₂, hxV₂, iV₂U, F.1.map iV₂V₁.op s₁
  

Proof state:
case h
C : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : HasColimits C
X Y Z : TopCat
inst✝⁴ : ConcreteCategory C
inst✝³ : PreservesFilteredColimits (forget C)
inst✝² : HasLimits C
inst✝¹ : PreservesLimits (forget C)
inst✝ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
h : ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)
t : (forget C).obj (G.val.obj (op U))
x : ↥U
V₁ : Opens ↑X
hxV₁ : ↑x ∈ V₁
s₁ : (forget C).obj ((Sheaf.presheaf F).obj (op V₁))
hs₁ :
  (colimit.ι ((OpenNhds.inclusion ↑{ val := ↑x, property := hxV₁ }).op ⋙ G.val)
        (op { obj := V₁, property := (_ : ↑{ val := ↑x, property := hxV₁ } ∈ V₁) }))
      ((f.val.app (op V₁)) s₁) =
    (germ (Sheaf.presheaf G) x) t
V₂ : Opens ↑X
hxV₂ : ↑x ∈ V₂
iV₂V₁ : V₂ ⟶ V₁
iV₂U : V₂ ⟶ U
heq : ((Sheaf.presheaf G).map iV₂V₁.op) ((f.val.app (op V₁)) s₁) = ((Sheaf.presheaf G).map iV₂U.op) t
⊢ (f.val.app (op V₂)) ((F.val.map iV₂V₁.op) s₁) = (G.val.map iV₂U.op) t

Next tactic:
rw [← comp_apply, f.1.naturality, comp_apply, heq]
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
⊢ IsIso (f.val.app (op U))

Next tactic:
suffices IsIso ((forget C).map (f.1.app (op U))) by
    exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  suffices IsIso ((forget C).map (f.1.app (op U))) by
    

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
this : IsIso ((forget C).map (f.val.app (op U)))
⊢ IsIso (f.val.app (op U))

Next tactic:
exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  suffices IsIso ((forget C).map (f.1.app (op U))) by
    exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
⊢ IsIso ((forget C).map (f.val.app (op U)))

Next tactic:
rw [isIso_iff_bijective]
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  suffices IsIso ((forget C).map (f.1.app (op U))) by
    exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
  rw [isIso_iff_bijective]
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
⊢ Function.Bijective ((forget C).map (f.val.app (op U)))

Next tactic:
apply app_bijective_of_stalkFunctor_map_bijective
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  suffices IsIso ((forget C).map (f.1.app (op U))) by
    exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
  rw [isIso_iff_bijective]
  apply app_bijective_of_stalkFunctor_map_bijective
  

Proof state:
case h
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
⊢ ∀ (x : ↥U), Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)

Next tactic:
intro x
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  suffices IsIso ((forget C).map (f.1.app (op U))) by
    exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
  rw [isIso_iff_bijective]
  apply app_bijective_of_stalkFunctor_map_bijective
  intro x
  

Proof state:
case h
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
x : ↥U
⊢ Function.Bijective ⇑((stalkFunctor C ↑x).map f.val)

Next tactic:
apply (isIso_iff_bijective _).mp
theorem app_isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G) (U : Opens X)
    [∀ x : U, IsIso ((stalkFunctor C x.val).map f.1)] : IsIso (f.1.app (op U)) := by
  -- Since the forgetful functor of `C` reflects isomorphisms, it suffices to see that the
  -- underlying map between types is an isomorphism, i.e. bijective.
  suffices IsIso ((forget C).map (f.1.app (op U))) by
    exact isIso_of_reflects_iso (f.1.app (op U)) (forget C)
  rw [isIso_iff_bijective]
  apply app_bijective_of_stalkFunctor_map_bijective
  intro x
  apply (isIso_iff_bijective _).mp
  

Proof state:
case h
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
U : Opens ↑X
inst✝ : ∀ (x : ↥U), IsIso ((stalkFunctor C ↑x).map f.val)
x : ↥U
⊢ IsIso ⇑((stalkFunctor C ↑x).map f.val)

Next tactic:
exact Functor.map_isIso (forget C) ((stalkFunctor C x.1).map f.1)
/-- Let `F` and `G` be sheaves valued in a concrete category, whose forgetful functor reflects
isomorphisms, preserves limits and filtered colimits. Then if the stalk maps of a morphism
`f : F ⟶ G` are all isomorphisms, `f` must be an isomorphism.
-/
theorem isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G)
    [∀ x : X, IsIso ((stalkFunctor C x).map f.1)] : IsIso f := by
  -- Since the inclusion functor from sheaves to presheaves is fully faithful, it suffices to
  -- show that `f`, as a morphism between _presheaves_, is an isomorphism.
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
inst✝ : ∀ (x : ↑X), IsIso ((stalkFunctor C x).map f.val)
⊢ IsIso f

Next tactic:
suffices IsIso ((Sheaf.forget C X).map f) by exact isIso_of_fully_faithful (Sheaf.forget C X) f
/-- Let `F` and `G` be sheaves valued in a concrete category, whose forgetful functor reflects
isomorphisms, preserves limits and filtered colimits. Then if the stalk maps of a morphism
`f : F ⟶ G` are all isomorphisms, `f` must be an isomorphism.
-/
theorem isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G)
    [∀ x : X, IsIso ((stalkFunctor C x).map f.1)] : IsIso f := by
  -- Since the inclusion functor from sheaves to presheaves is fully faithful, it suffices to
  -- show that `f`, as a morphism between _presheaves_, is an isomorphism.
  suffices IsIso ((Sheaf.forget C X).map f) by 

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
inst✝ : ∀ (x : ↑X), IsIso ((stalkFunctor C x).map f.val)
this : IsIso ((Sheaf.forget C X).map f)
⊢ IsIso f

Next tactic:
exact isIso_of_fully_faithful (Sheaf.forget C X) f
/-- Let `F` and `G` be sheaves valued in a concrete category, whose forgetful functor reflects
isomorphisms, preserves limits and filtered colimits. Then if the stalk maps of a morphism
`f : F ⟶ G` are all isomorphisms, `f` must be an isomorphism.
-/
theorem isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G)
    [∀ x : X, IsIso ((stalkFunctor C x).map f.1)] : IsIso f := by
  -- Since the inclusion functor from sheaves to presheaves is fully faithful, it suffices to
  -- show that `f`, as a morphism between _presheaves_, is an isomorphism.
  suffices IsIso ((Sheaf.forget C X).map f) by exact isIso_of_fully_faithful (Sheaf.forget C X) f
  -- We show that all components of `f` are isomorphisms.
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
inst✝ : ∀ (x : ↑X), IsIso ((stalkFunctor C x).map f.val)
⊢ IsIso ((Sheaf.forget C X).map f)

Next tactic:
suffices ∀ U : (Opens X)ᵒᵖ, IsIso (f.1.app U) by
    exact @NatIso.isIso_of_isIso_app _ _ _ _ F.1 G.1 f.1 this
/-- Let `F` and `G` be sheaves valued in a concrete category, whose forgetful functor reflects
isomorphisms, preserves limits and filtered colimits. Then if the stalk maps of a morphism
`f : F ⟶ G` are all isomorphisms, `f` must be an isomorphism.
-/
theorem isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G)
    [∀ x : X, IsIso ((stalkFunctor C x).map f.1)] : IsIso f := by
  -- Since the inclusion functor from sheaves to presheaves is fully faithful, it suffices to
  -- show that `f`, as a morphism between _presheaves_, is an isomorphism.
  suffices IsIso ((Sheaf.forget C X).map f) by exact isIso_of_fully_faithful (Sheaf.forget C X) f
  -- We show that all components of `f` are isomorphisms.
  suffices ∀ U : (Opens X)ᵒᵖ, IsIso (f.1.app U) by
    

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
inst✝ : ∀ (x : ↑X), IsIso ((stalkFunctor C x).map f.val)
this : ∀ (U : (Opens ↑X)ᵒᵖ), IsIso (f.val.app U)
⊢ IsIso ((Sheaf.forget C X).map f)

Next tactic:
exact @NatIso.isIso_of_isIso_app _ _ _ _ F.1 G.1 f.1 this
/-- Let `F` and `G` be sheaves valued in a concrete category, whose forgetful functor reflects
isomorphisms, preserves limits and filtered colimits. Then if the stalk maps of a morphism
`f : F ⟶ G` are all isomorphisms, `f` must be an isomorphism.
-/
theorem isIso_of_stalkFunctor_map_iso {F G : Sheaf C X} (f : F ⟶ G)
    [∀ x : X, IsIso ((stalkFunctor C x).map f.1)] : IsIso f := by
  -- Since the inclusion functor from sheaves to presheaves is fully faithful, it suffices to
  -- show that `f`, as a morphism between _presheaves_, is an isomorphism.
  suffices IsIso ((Sheaf.forget C X).map f) by exact isIso_of_fully_faithful (Sheaf.forget C X) f
  -- We show that all components of `f` are isomorphisms.
  suffices ∀ U : (Opens X)ᵒᵖ, IsIso (f.1.app U) by
    exact @NatIso.isIso_of_isIso_app _ _ _ _ F.1 G.1 f.1 this
  

Proof state:
C : Type u
inst✝⁷ : Category.{v, u} C
inst✝⁶ : HasColimits C
X Y Z : TopCat
inst✝⁵ : ConcreteCategory C
inst✝⁴ : PreservesFilteredColimits (forget C)
inst✝³ : HasLimits C
inst✝² : PreservesLimits (forget C)
inst✝¹ : ReflectsIsomorphisms (forget C)
F G : Sheaf C X
f : F ⟶ G
inst✝ : ∀ (x : ↑X), IsIso ((stalkFunctor C x).map f.val)
⊢ ∀ (U : (Opens ↑X)ᵒᵖ), IsIso (f.val.app U)

Next tactic:
intro U