Theorem: TopCat.Presheaf.isSheaf_iff_isSheaf_comp
File: Mathlib/Topology/Sheaves/Forget.lean

tactic: rw [Presheaf.isSheaf_iff_isSheafEqualizerProducts,
  Presheaf.isSheaf_iff_isSheafEqualizerProducts]
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
⊢ IsSheaf F ↔ IsSheaf (F ⋙ G)

tactic: constructor
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
⊢ IsSheafEqualizerProducts F ↔ IsSheafEqualizerProducts (F ⋙ G)

tactic: intro S ι U
state_before: case mp
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
⊢ IsSheafEqualizerProducts F → IsSheafEqualizerProducts (F ⋙ G)

tactic: obtain ⟨t₁⟩ := S U
state_before: case mp
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts F
ι : Type v
U : ι → Opens ↑X
⊢ Nonempty (IsLimit (fork (F ⋙ G) U))

tactic: letI := preservesSmallestLimitsOfPreservesLimits G
state_before: case mp.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts F
ι : Type v
U : ι → Opens ↑X
t₁ : IsLimit (fork F U)
⊢ Nonempty (IsLimit (fork (F ⋙ G) U))

tactic: have t₂ := @PreservesLimit.preserves _ _ _ _ _ _ _ G _ _ t₁
state_before: case mp.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts F
ι : Type v
U : ι → Opens ↑X
t₁ : IsLimit (fork F U)
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
⊢ Nonempty (IsLimit (fork (F ⋙ G) U))

tactic: have t₃ := IsLimit.ofIsoLimit t₂ (mapConeFork G F U)
state_before: case mp.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts F
ι : Type v
U : ι → Opens ↑X
t₁ : IsLimit (fork F U)
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
t₂ : IsLimit (G.mapCone (fork F U))
⊢ Nonempty (IsLimit (fork (F ⋙ G) U))

tactic: have t₄ := IsLimit.postcomposeInvEquiv _ _ t₃
state_before: case mp.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts F
ι : Type v
U : ι → Opens ↑X
t₁ : IsLimit (fork F U)
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
t₂ : IsLimit (G.mapCone (fork F U))
t₃ : IsLimit ((Cones.postcompose (diagramCompPreservesLimits G F U).inv).obj (fork (F ⋙ G) U))
⊢ Nonempty (IsLimit (fork (F ⋙ G) U))

tactic: exact ⟨t₄⟩
state_before: case mp.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts F
ι : Type v
U : ι → Opens ↑X
t₁ : IsLimit (fork F U)
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
t₂ : IsLimit (G.mapCone (fork F U))
t₃ : IsLimit ((Cones.postcompose (diagramCompPreservesLimits G F U).inv).obj (fork (F ⋙ G) U))
t₄ : (fun x => IsLimit (fork (F ⋙ G) U)) t₃
⊢ Nonempty (IsLimit (fork (F ⋙ G) U))

tactic: intro S ι U
state_before: case mpr
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
⊢ IsSheafEqualizerProducts (F ⋙ G) → IsSheafEqualizerProducts F

tactic: refine' ⟨_⟩
state_before: case mpr
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
⊢ Nonempty (IsLimit (fork F U))

tactic: let f := equalizer.lift _ (w F U)
state_before: case mpr
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
⊢ IsLimit (fork F U)

tactic: skip
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this : IsIso (G.map f)
⊢ IsLimit (fork F U)

tactic: haveI : IsIso f := isIso_of_reflects_iso f G
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this : IsIso (G.map f)
⊢ IsLimit (fork F U)

tactic: apply IsLimit.ofIsoLimit (limit.isLimit _)
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this✝ : IsIso (G.map f)
this : IsIso f
⊢ IsLimit (fork F U)

tactic: apply Iso.symm
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this✝ : IsIso (G.map f)
this : IsIso f
⊢ limit.cone (parallelPair (leftRes F U) (rightRes F U)) ≅ fork F U

tactic: fapply Cones.ext
state_before: case I
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this✝ : IsIso (G.map f)
this : IsIso f
⊢ fork F U ≅ limit.cone (parallelPair (leftRes F U) (rightRes F U))

tactic: exact asIso f
state_before: case I.φ
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this✝ : IsIso (G.map f)
this : IsIso f
⊢ (fork F U).pt ≅ (limit.cone (parallelPair (leftRes F U) (rightRes F U))).pt

case I.w
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this✝ : IsIso (G.map f)
this : IsIso f
⊢ autoParam
    (∀ (j : WalkingParallelPair),
      (fork F U).π.app j = ?I.φ.hom ≫ (limit.cone (parallelPair (leftRes F U) (rightRes F U))).π.app j)
    _auto✝

tactic: simp
state_before: case I.w.one
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
this✝ : IsIso (G.map f)
this : IsIso f
⊢ (fork F U).π.app WalkingParallelPair.one =
    (asIso f).hom ≫ (limit.cone (parallelPair (leftRes F U) (rightRes F U))).π.app WalkingParallelPair.one

tactic: let c := fork (F ⋙ G) U
state_before: case mpr
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
⊢ IsIso (G.map f)

tactic: obtain ⟨hc⟩ := S U
state_before: case mpr
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
⊢ IsIso (G.map f)

tactic: let d := G.mapCone (equalizer.fork (leftRes.{v} F U) (rightRes F U))
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
⊢ IsIso (G.map f)

tactic: letI := preservesSmallestLimitsOfPreservesLimits G
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
⊢ IsIso (G.map f)

tactic: have hd : IsLimit d := PreservesLimit.preserves (limit.isLimit _)
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
⊢ IsIso (G.map f)

tactic: let d' := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
⊢ IsIso (G.map f)

tactic: have hd' : IsLimit d' :=
  (IsLimit.postcomposeHomEquiv (diagramCompPreservesLimits G F U : _) d).symm hd
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
⊢ IsIso (G.map f)

tactic: let f' : c ⟶ d' := Fork.mkHom (G.map f) (by
  dsimp only [diagramCompPreservesLimits, res]
  dsimp only [Fork.ι]
  refine limit.hom_ext fun j => ?_
  dsimp
  simp only [Category.assoc, ← Functor.map_comp_assoc, equalizer.lift_ι,
    map_lift_piComparison_assoc]
  dsimp [res])
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
⊢ IsIso (G.map f)

tactic: haveI : IsIso f' := IsLimit.hom_isIso hc hd' f'
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
f' : c ⟶ d' := Fork.mkHom (G.map f) (_ : G.map f ≫ Fork.ι d' = Fork.ι c)
⊢ IsIso (G.map f)

tactic: exact IsIso.of_iso ((Cones.forget _).mapIso (asIso f'))
state_before: case mpr.intro
C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this✝ : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
f' : c ⟶ d' := Fork.mkHom (G.map f) (_ : G.map f ≫ Fork.ι d' = Fork.ι c)
this : IsIso f'
⊢ IsIso (G.map f)

tactic: dsimp only [diagramCompPreservesLimits, res]
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
⊢ G.map f ≫ Fork.ι d' = Fork.ι c

tactic: dsimp only [Fork.ι]
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
⊢ G.map
        (equalizer.lift (Pi.lift fun i => F.map (Opens.leSupr U i).op)
          (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)) ≫
      Fork.ι
        ((Cones.postcompose
              (NatIso.ofComponents fun X_1 =>
                  WalkingParallelPair.rec (PreservesProduct.iso G fun i => F.obj (U i).op)
                    (PreservesProduct.iso G fun p => F.obj (U p.fst ⊓ U p.snd).op) X_1).hom).obj
          (G.mapCone (equalizer.fork (leftRes F U) (rightRes F U)))) =
    Fork.ι (fork (F ⋙ G) U)

tactic: refine limit.hom_ext fun j => ?_
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
⊢ G.map
        (equalizer.lift (Pi.lift fun i => F.map (Opens.leSupr U i).op)
          (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)) ≫
      ((Cones.postcompose
                  (NatIso.ofComponents fun X_1 =>
                      WalkingParallelPair.rec (PreservesProduct.iso G fun i => F.obj (U i).op)
                        (PreservesProduct.iso G fun p => F.obj (U p.fst ⊓ U p.snd).op) X_1).hom).obj
              (G.mapCone (equalizer.fork (leftRes F U) (rightRes F U)))).π.app
        WalkingParallelPair.zero =
    (fork (F ⋙ G) U).π.app WalkingParallelPair.zero

tactic: dsimp
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
j : Discrete ι
⊢ (G.map
          (equalizer.lift (Pi.lift fun i => F.map (Opens.leSupr U i).op)
            (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)) ≫
        ((Cones.postcompose
                    (NatIso.ofComponents fun X_1 =>
                        WalkingParallelPair.rec (PreservesProduct.iso G fun i => F.obj (U i).op)
                          (PreservesProduct.iso G fun p => F.obj (U p.fst ⊓ U p.snd).op) X_1).hom).obj
                (G.mapCone (equalizer.fork (leftRes F U) (rightRes F U)))).π.app
          WalkingParallelPair.zero) ≫
      limit.π (Discrete.functor fun i => (F ⋙ G).obj (U i).op) j =
    (fork (F ⋙ G) U).π.app WalkingParallelPair.zero ≫ limit.π (Discrete.functor fun i => (F ⋙ G).obj (U i).op) j

tactic: simp only [Category.assoc, ← Functor.map_comp_assoc, equalizer.lift_ι,
  map_lift_piComparison_assoc]
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
j : Discrete ι
⊢ (G.map
          (equalizer.lift (Pi.lift fun i => F.map (Opens.leSupr U i).op)
            (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)) ≫
        G.map (equalizer.ι (leftRes F U) (rightRes F U)) ≫ piComparison G fun i => F.obj (U i).op) ≫
      limit.π (Discrete.functor fun i => G.obj (F.obj (U i).op)) j =
    res (F ⋙ G) U ≫ limit.π (Discrete.functor fun i => G.obj (F.obj (U i).op)) j

tactic: dsimp [res]
state_before: C : Type u₁
inst✝⁵ : Category C
D : Type u₂
inst✝⁴ : Category D
G : C ⥤ D
inst✝³ : ReflectsIsomorphisms G
inst✝² : HasLimits C
inst✝¹ : HasLimits D
inst✝ : PreservesLimits G
X : TopCat
F : Presheaf C X
S : IsSheafEqualizerProducts (F ⋙ G)
ι : Type v
U : ι → Opens ↑X
f : F.obj (iSup U).op ⟶ equalizer (leftRes F U) (rightRes F U) :=
  equalizer.lift (res F U) (_ : res F U ≫ leftRes F U = res F U ≫ rightRes F U)
c : Fork (leftRes (F ⋙ G) U) (rightRes (F ⋙ G) U) := fork (F ⋙ G) U
hc : IsLimit (fork (F ⋙ G) U)
d : Cone (parallelPair (leftRes F U) (rightRes F U) ⋙ G) := G.mapCone (equalizer.fork (leftRes F U) (rightRes F U))
this : PreservesLimitsOfSize G := preservesSmallestLimitsOfPreservesLimits G
hd : IsLimit d
d' : Cone (diagram (F ⋙ G) U) := (Cones.postcompose (diagramCompPreservesLimits G F U).hom).obj d
hd' : IsLimit d'
j : Discrete ι
⊢ (Pi.lift fun j => G.map (F.map (Opens.leSupr U j).op)) ≫
      limit.π (Discrete.functor fun i => G.obj (F.obj (U i).op)) j =
    res (F ⋙ G) U ≫ limit.π (Discrete.functor fun i => G.obj (F.obj (U i).op)) j