l3lab/ntp-mathlib huggingface dataset:
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          

Proof state:
case mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
⊢ ((Over.forget (op X).unop).op ⋙ F).map { unop := φ } ≫ (fun Y => app hG x hx Y.unop.hom) { unop := Y₂ } =
    (fun Y => app hG x hx Y.unop.hom) { unop := Y₁ } ≫ ((Over.forget (op X).unop).op ⋙ G).map { unop := φ }

Next tactic:
apply (hG Y₂.hom).hom_ext
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          

Proof state:
case mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
⊢ ∀ (j : (FullSubcategory fun f => (Sieve.pullback Y₂.hom S).arrows f.hom)ᵒᵖ),
    (((Over.forget (op X).unop).op ⋙ F).map { unop := φ } ≫ (fun Y => app hG x hx Y.unop.hom) { unop := Y₂ }) ≫
        (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback Y₂.hom S).arrows))).π.app j =
      ((fun Y => app hG x hx Y.unop.hom) { unop := Y₁ } ≫ ((Over.forget (op X).unop).op ⋙ G).map { unop := φ }) ≫
        (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback Y₂.hom S).arrows))).π.app j

Next tactic:
rintro ⟨Z : Over Y₂.left, hZ⟩
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          

Proof state:
case mk.mk.mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
Z : Over Y₂.left
hZ : (Sieve.pullback Y₂.hom S).arrows Z.hom
⊢ (((Over.forget (op X).unop).op ⋙ F).map { unop := φ } ≫ (fun Y => app hG x hx Y.unop.hom) { unop := Y₂ }) ≫
      (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback Y₂.hom S).arrows))).π.app
        { unop := { obj := Z, property := hZ } } =
    ((fun Y => app hG x hx Y.unop.hom) { unop := Y₁ } ≫ ((Over.forget (op X).unop).op ⋙ G).map { unop := φ }) ≫
      (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback Y₂.hom S).arrows))).π.app
        { unop := { obj := Z, property := hZ } }

Next tactic:
dsimp
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          

Proof state:
case mk.mk.mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
Z : Over Y₂.left
hZ : (Sieve.pullback Y₂.hom S).arrows Z.hom
⊢ (F.map { unop := φ }.unop.left.op ≫ app hG x hx Y₂.hom) ≫ G.map Z.hom.op =
    (app hG x hx Y₁.hom ≫ G.map { unop := φ }.unop.left.op) ≫ G.map Z.hom.op

Next tactic:
rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          

Proof state:
case mk.mk.mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
Z : Over Y₂.left
hZ : (Sieve.pullback Y₂.hom S).arrows Z.hom
⊢ F.map { unop := φ }.unop.left.op ≫
      F.map Z.hom.op ≫ (x (Z.hom ≫ Y₂.hom) hZ).app { unop := Over.mk (𝟙 ((𝟭 C).obj Z.left)) } =
    app hG x hx Y₁.hom ≫ G.map (Z.hom ≫ { unop := φ }.unop.left).op

Next tactic:
erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
Z : Over Y₂.left
hZ : (Sieve.pullback Y₂.hom S).arrows Z.hom
⊢ S.arrows ((Z.hom ≫ φ.left) ≫ Y₁.hom)

Next tactic:
simpa using hZ
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          

Proof state:
case mk.mk.mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
Z : Over Y₂.left
hZ : (Sieve.pullback Y₂.hom S).arrows Z.hom
⊢ F.map ({ unop := φ }.unop.left.op ≫ Z.hom.op) ≫
      (x (Z.hom ≫ Y₂.hom) hZ).app { unop := Over.mk (𝟙 ((𝟭 C).obj Z.left)) } =
    F.map (φ.left.op ≫ Z.hom.op) ≫
      (x ((Z.hom ≫ φ.left) ≫ Y₁.hom) (_ : S.arrows ((Z.hom ≫ φ.left) ≫ Y₁.hom))).app
        { unop := Over.mk (𝟙 ((𝟭 C).obj Z.left)) }

Next tactic:
congr 3
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          

Proof state:
case mk.mk.mk.mk.mk.e_a.e_self.e_f
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y₁ Y₂ : Over X
φ : Y₂ ⟶ Y₁
Z : Over Y₂.left
hZ : (Sieve.pullback Y₂.hom S).arrows Z.hom
⊢ Z.hom ≫ Y₂.hom = (Z.hom ≫ φ.left) ≫ Y₁.hom

Next tactic:
simp
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    

Proof state:
case hex
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
⊢ Presieve.FamilyOfElements.IsAmalgamation x (NatTrans.mk fun Y => app hG x hx Y.unop.hom)

Next tactic:
rw [PresheafHom.isAmalgamation_iff _ _ hx]
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    

Proof state:
case hex
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
⊢ ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g),
    (NatTrans.mk fun Y => app hG x hx Y.unop.hom).app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
intro Y g hg
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    

Proof state:
case hex
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
⊢ (NatTrans.mk fun Y => app hG x hx Y.unop.hom).app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
dsimp
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    

Proof state:
case hex
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
⊢ app hG x hx g = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
have H := app_cond hG x hx g (𝟙 _) (by simpa using hg)
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    have H := app_cond hG x hx g (𝟙 _) (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
⊢ S.arrows (𝟙 Y ≫ g)

Next tactic:
simpa using hg
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    have H := app_cond hG x hx g (𝟙 _) (by simpa using hg)
    

Proof state:
case hex
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
H :
  app hG x hx g ≫ G.map (𝟙 Y).op = F.map (𝟙 Y).op ≫ (x (𝟙 Y ≫ g) (_ : S.arrows (𝟙 Y ≫ g))).app { unop := Over.mk (𝟙 Y) }
⊢ app hG x hx g = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
rw [op_id, G.map_id, comp_id, F.map_id, id_comp] at H
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    have H := app_cond hG x hx g (𝟙 _) (by simpa using hg)
    rw [op_id, G.map_id, comp_id, F.map_id, id_comp] at H
    

Proof state:
case hex
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
H : app hG x hx g = (x (𝟙 Y ≫ g) (_ : S.arrows (𝟙 Y ≫ g))).app { unop := Over.mk (𝟙 Y) }
⊢ app hG x hx g = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
exact H.trans (by congr; simp)
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    have H := app_cond hG x hx g (𝟙 _) (by simpa using hg)
    rw [op_id, G.map_id, comp_id, F.map_id, id_comp] at H
    exact H.trans (by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
H : app hG x hx g = (x (𝟙 Y ≫ g) (_ : S.arrows (𝟙 Y ≫ g))).app { unop := Over.mk (𝟙 Y) }
⊢ (x (𝟙 Y ≫ g) (_ : S.arrows (𝟙 Y ≫ g))).app { unop := Over.mk (𝟙 Y) } = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
congr
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    have H := app_cond hG x hx g (𝟙 _) (by simpa using hg)
    rw [op_id, G.map_id, comp_id, F.map_id, id_comp] at H
    exact H.trans (by congr; 

Proof state:
case e_self.e_f
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
Y : C
g : Y ⟶ X
hg : S.arrows g
H : app hG x hx g = (x (𝟙 Y ≫ g) (_ : S.arrows (𝟙 Y ≫ g))).app { unop := Over.mk (𝟙 Y) }
⊢ 𝟙 Y ≫ g = g

Next tactic:
simp
open PresheafHom.IsSheafFor in
lemma presheafHom_isSheafFor  :
    Presieve.IsSheafFor (presheafHom F G) S.arrows := by
  intro x hx
  apply exists_unique_of_exists_of_unique
  · refine' ⟨
      { app := fun Y => app hG x hx Y.unop.hom
        naturality := by
          rintro ⟨Y₁ : Over X⟩ ⟨Y₂ : Over X⟩ ⟨φ : Y₂ ⟶ Y₁⟩
          apply (hG Y₂.hom).hom_ext
          rintro ⟨Z : Over Y₂.left, hZ⟩
          dsimp
          rw [assoc, assoc, app_cond hG x hx Y₂.hom Z.hom hZ, ← G.map_comp, ← op_comp]
          erw [app_cond hG x hx Y₁.hom (Z.hom ≫ φ.left) (by simpa using hZ),
            ← F.map_comp_assoc, op_comp]
          congr 3
          simp }, _⟩
    rw [PresheafHom.isAmalgamation_iff _ _ hx]
    intro Y g hg
    dsimp
    have H := app_cond hG x hx g (𝟙 _) (by simpa using hg)
    rw [op_id, G.map_id, comp_id, F.map_id, id_comp] at H
    exact H.trans (by congr; simp)
  · 

Proof state:
case hunique
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
X : C
S : Sieve X
hG : ⦃Y : C⦄ → (f : Y ⟶ X) → IsLimit (G.mapCone (Cocone.op (Presieve.cocone (Sieve.pullback f S).arrows)))
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
⊢ ∀ (y₁ y₂ : (presheafHom F G).obj (op X)),
    Presieve.FamilyOfElements.IsAmalgamation x y₁ → Presieve.FamilyOfElements.IsAmalgamation x y₂ → y₁ = y₂

Next tactic:
intro y₁ y₂ hy₁ hy₂