l3lab/ntp-mathlib huggingface dataset:
/-- The sections of the presheaf `presheafHom F G` identify to morphisms `F ⟶ G`. -/
def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where
  toFun s :=
    { app := fun X => (s.1 X).app ⟨Over.mk (𝟙 _)⟩
      naturality := by
        rintro ⟨X₁⟩ ⟨X₂⟩ ⟨f : X₂ ⟶ X₁⟩
        dsimp
        refine' Eq.trans _ ((s.1 ⟨X₁⟩).naturality
          (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op)
        erw [← s.2 f.op, presheafHom_map_app_op_mk_id]
        rfl }
  invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩
  left_inv s := 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
s : ↑(Functor.sections (presheafHom F G))
⊢ (fun f =>
        { val := fun X => whiskerLeft (Over.forget X.unop).op f,
          property :=
            (_ :
              ∀ {j j' : Cᵒᵖ} (x : j ⟶ j'),
                (presheafHom F G).map x ((fun X => whiskerLeft (Over.forget X.unop).op f) j) =
                  (presheafHom F G).map x ((fun X => whiskerLeft (Over.forget X.unop).op f) j)) })
      ((fun s => NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }) s) =
    s

Next tactic:
dsimp
/-- The sections of the presheaf `presheafHom F G` identify to morphisms `F ⟶ G`. -/
def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where
  toFun s :=
    { app := fun X => (s.1 X).app ⟨Over.mk (𝟙 _)⟩
      naturality := by
        rintro ⟨X₁⟩ ⟨X₂⟩ ⟨f : X₂ ⟶ X₁⟩
        dsimp
        refine' Eq.trans _ ((s.1 ⟨X₁⟩).naturality
          (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op)
        erw [← s.2 f.op, presheafHom_map_app_op_mk_id]
        rfl }
  invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩
  left_inv s := by
    dsimp
    

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
s : ↑(Functor.sections (presheafHom F G))
⊢ {
      val := fun X =>
        whiskerLeft (Over.forget X.unop).op (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }),
      property :=
        (_ :
          ∀ {j j' : Cᵒᵖ} (x : j ⟶ j'),
            (presheafHom F G).map x
                (whiskerLeft (Over.forget j.unop).op (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) })) =
              (presheafHom F G).map x
                (whiskerLeft (Over.forget j.unop).op
                  (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }))) } =
    s

Next tactic:
ext ⟨X⟩ ⟨Y : Over X⟩
/-- The sections of the presheaf `presheafHom F G` identify to morphisms `F ⟶ G`. -/
def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where
  toFun s :=
    { app := fun X => (s.1 X).app ⟨Over.mk (𝟙 _)⟩
      naturality := by
        rintro ⟨X₁⟩ ⟨X₂⟩ ⟨f : X₂ ⟶ X₁⟩
        dsimp
        refine' Eq.trans _ ((s.1 ⟨X₁⟩).naturality
          (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op)
        erw [← s.2 f.op, presheafHom_map_app_op_mk_id]
        rfl }
  invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩
  left_inv s := by
    dsimp
    ext ⟨X⟩ ⟨Y : Over X⟩
    

Proof state:
case a.h.mk.w.h.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
s : ↑(Functor.sections (presheafHom F G))
X : C
Y : Over X
⊢ (↑{
              val := fun X =>
                whiskerLeft (Over.forget X.unop).op (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }),
              property :=
                (_ :
                  ∀ {j j' : Cᵒᵖ} (x : j ⟶ j'),
                    (presheafHom F G).map x
                        (whiskerLeft (Over.forget j.unop).op
                          (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) })) =
                      (presheafHom F G).map x
                        (whiskerLeft (Over.forget j.unop).op
                          (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }))) }
          { unop := X }).app
      { unop := Y } =
    (↑s { unop := X }).app { unop := Y }

Next tactic:
have H := s.2 Y.hom.op
/-- The sections of the presheaf `presheafHom F G` identify to morphisms `F ⟶ G`. -/
def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where
  toFun s :=
    { app := fun X => (s.1 X).app ⟨Over.mk (𝟙 _)⟩
      naturality := by
        rintro ⟨X₁⟩ ⟨X₂⟩ ⟨f : X₂ ⟶ X₁⟩
        dsimp
        refine' Eq.trans _ ((s.1 ⟨X₁⟩).naturality
          (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op)
        erw [← s.2 f.op, presheafHom_map_app_op_mk_id]
        rfl }
  invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩
  left_inv s := by
    dsimp
    ext ⟨X⟩ ⟨Y : Over X⟩
    have H := s.2 Y.hom.op
    

Proof state:
case a.h.mk.w.h.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
s : ↑(Functor.sections (presheafHom F G))
X : C
Y : Over X
H : (presheafHom F G).map Y.hom.op (↑s (op ((Functor.fromPUnit X).obj Y.right))) = ↑s (op ((𝟭 C).obj Y.left))
⊢ (↑{
              val := fun X =>
                whiskerLeft (Over.forget X.unop).op (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }),
              property :=
                (_ :
                  ∀ {j j' : Cᵒᵖ} (x : j ⟶ j'),
                    (presheafHom F G).map x
                        (whiskerLeft (Over.forget j.unop).op
                          (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) })) =
                      (presheafHom F G).map x
                        (whiskerLeft (Over.forget j.unop).op
                          (NatTrans.mk fun X => (↑s X).app { unop := Over.mk (𝟙 X.unop) }))) }
          { unop := X }).app
      { unop := Y } =
    (↑s { unop := X }).app { unop := Y }

Next tactic:
dsimp at H ⊢
/-- The sections of the presheaf `presheafHom F G` identify to morphisms `F ⟶ G`. -/
def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where
  toFun s :=
    { app := fun X => (s.1 X).app ⟨Over.mk (𝟙 _)⟩
      naturality := by
        rintro ⟨X₁⟩ ⟨X₂⟩ ⟨f : X₂ ⟶ X₁⟩
        dsimp
        refine' Eq.trans _ ((s.1 ⟨X₁⟩).naturality
          (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op)
        erw [← s.2 f.op, presheafHom_map_app_op_mk_id]
        rfl }
  invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩
  left_inv s := by
    dsimp
    ext ⟨X⟩ ⟨Y : Over X⟩
    have H := s.2 Y.hom.op
    dsimp at H ⊢
    

Proof state:
case a.h.mk.w.h.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
s : ↑(Functor.sections (presheafHom F G))
X : C
Y : Over X
H : (presheafHom F G).map Y.hom.op (↑s (op X)) = ↑s (op Y.left)
⊢ (↑s (op Y.left)).app { unop := Over.mk (𝟙 Y.left) } = (↑s { unop := X }).app { unop := Y }

Next tactic:
rw [← H]
/-- The sections of the presheaf `presheafHom F G` identify to morphisms `F ⟶ G`. -/
def presheafHomSectionsEquiv : (presheafHom F G).sections ≃ (F ⟶ G) where
  toFun s :=
    { app := fun X => (s.1 X).app ⟨Over.mk (𝟙 _)⟩
      naturality := by
        rintro ⟨X₁⟩ ⟨X₂⟩ ⟨f : X₂ ⟶ X₁⟩
        dsimp
        refine' Eq.trans _ ((s.1 ⟨X₁⟩).naturality
          (Over.homMk f : Over.mk f ⟶ Over.mk (𝟙 X₁)).op)
        erw [← s.2 f.op, presheafHom_map_app_op_mk_id]
        rfl }
  invFun f := ⟨fun X => whiskerLeft _ f, fun _ => rfl⟩
  left_inv s := by
    dsimp
    ext ⟨X⟩ ⟨Y : Over X⟩
    have H := s.2 Y.hom.op
    dsimp at H ⊢
    rw [← H]
    

Proof state:
case a.h.mk.w.h.mk
C : Type u
inst✝¹ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u'
inst✝ : Category.{v', u'} A
F G : Cᵒᵖ ⥤ A
s : ↑(Functor.sections (presheafHom F G))
X : C
Y : Over X
H : (presheafHom F G).map Y.hom.op (↑s (op X)) = ↑s (op Y.left)
⊢ ((presheafHom F G).map Y.hom.op (↑s (op X))).app { unop := Over.mk (𝟙 Y.left) } = (↑s { unop := X }).app { unop := Y }

Next tactic:
apply presheafHom_map_app_op_mk_id
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := 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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
⊢ Presieve.FamilyOfElements.IsAmalgamation x y ↔
    ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
constructor
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · 

Proof state:
case mp
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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
⊢ Presieve.FamilyOfElements.IsAmalgamation x y →
    ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
intro h Y g hg
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    

Proof state:
case mp
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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : Presieve.FamilyOfElements.IsAmalgamation x y
Y : C
g : Y ⟶ X
hg : S.arrows g
⊢ y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))

Next tactic:
rw [← h g hg, presheafHom_map_app_op_mk_id]
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · 

Proof state:
case mpr
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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
⊢ (∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))) →
    Presieve.FamilyOfElements.IsAmalgamation x y

Next tactic:
intro h Y g hg
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    

Proof state:
case mpr
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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
⊢ (presheafHom F G).map g.op y = x g hg

Next tactic:
dsimp
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    

Proof state:
case mpr
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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
⊢ (presheafHom F G).map g.op y = x g hg

Next tactic:
ext ⟨W : Over Y⟩
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    

Proof state:
case mpr.w.h.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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
⊢ ((presheafHom F G).map g.op y).app { unop := W } = (x g hg).app { unop := W }

Next tactic:
refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
    

Proof state:
case mpr.w.h.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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
⊢ (x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g))).app (op (Over.mk (𝟙 W.left))) = (x g hg).app { unop := W }

Next tactic:
have H := hx (𝟙 _) W.hom (S.downward_closed hg W.hom) hg (by simp)
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
    have H := hx (𝟙 _) W.hom (S.downward_closed hg W.hom) hg (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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
⊢ 𝟙 ((𝟭 C).obj W.left) ≫ W.hom ≫ g = W.hom ≫ g

Next tactic:
simp
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
    have H := hx (𝟙 _) W.hom (S.downward_closed hg W.hom) hg (by simp)
    

Proof state:
case mpr.w.h.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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
H :
  (presheafHom F G).map (𝟙 ((𝟭 C).obj W.left)).op (x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g))) =
    (presheafHom F G).map W.hom.op (x g hg)
⊢ (x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g))).app (op (Over.mk (𝟙 W.left))) = (x g hg).app { unop := W }

Next tactic:
dsimp at H
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
    have H := hx (𝟙 _) W.hom (S.downward_closed hg W.hom) hg (by simp)
    dsimp at H
    

Proof state:
case mpr.w.h.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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
H :
  (presheafHom F G).map (𝟙 (op W.left)) (x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g))) =
    (presheafHom F G).map W.hom.op (x g hg)
⊢ (x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g))).app (op (Over.mk (𝟙 W.left))) = (x g hg).app { unop := W }

Next tactic:
simp only [Functor.map_id, FunctorToTypes.map_id_apply] at H
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
    have H := hx (𝟙 _) W.hom (S.downward_closed hg W.hom) hg (by simp)
    dsimp at H
    simp only [Functor.map_id, FunctorToTypes.map_id_apply] at H
    

Proof state:
case mpr.w.h.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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
H : x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g)) = (presheafHom F G).map W.hom.op (x g hg)
⊢ (x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g))).app (op (Over.mk (𝟙 W.left))) = (x g hg).app { unop := W }

Next tactic:
rw [H, presheafHom_map_app_op_mk_id]
lemma PresheafHom.isAmalgamation_iff {X : C} (S : Sieve X)
    (x : Presieve.FamilyOfElements (presheafHom F G) S.arrows)
    (hx : x.Compatible) (y : (presheafHom F G).obj (op X)) :
    x.IsAmalgamation y ↔ ∀ (Y : C) (g : Y ⟶ X) (hg : S g),
      y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y))) := by
  constructor
  · intro h Y g hg
    rw [← h g hg, presheafHom_map_app_op_mk_id]
  · intro h Y g hg
    dsimp
    ext ⟨W : Over Y⟩
    refine (h W.left (W.hom ≫ g) (S.downward_closed hg _)).trans ?_
    have H := hx (𝟙 _) W.hom (S.downward_closed hg W.hom) hg (by simp)
    dsimp at H
    simp only [Functor.map_id, FunctorToTypes.map_id_apply] at H
    rw [H, presheafHom_map_app_op_mk_id]
    

Proof state:
case mpr.w.h.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
x : Presieve.FamilyOfElements (presheafHom F G) S.arrows
hx : Presieve.FamilyOfElements.Compatible x
y : (presheafHom F G).obj (op X)
h : ∀ (Y : C) (g : Y ⟶ X) (hg : S.arrows g), y.app (op (Over.mk g)) = (x g hg).app (op (Over.mk (𝟙 Y)))
Y : C
g : Y ⟶ X
hg : S.arrows g
W : Over Y
H : x (W.hom ≫ g) (_ : S.arrows (W.hom ≫ g)) = (presheafHom F G).map W.hom.op (x g hg)
⊢ (x g hg).app (op (Over.mk W.hom)) = (x g hg).app { unop := W }

Next tactic:
rfl
lemma exists_app :
    ∃ (φ : F.obj (op Y) ⟶ G.obj (op Y)),
      ∀ {Z : C} (p : Z ⟶ Y) (hp : S (p ≫ g)), φ ≫ G.map p.op =
        F.map p.op ≫ (x (p ≫ g) hp).app ⟨Over.mk (𝟙 Z)⟩ := 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
⊢ ∃ φ,
    ∀ {Z : C} (p : Z ⟶ Y) (hp : S.arrows (p ≫ g)),
      φ ≫ G.map p.op = F.map p.op ≫ (x (p ≫ g) hp).app { unop := Over.mk (𝟙 Z) }

Next tactic:
let c : Cone ((Presieve.diagram (Sieve.pullback g S).arrows).op ⋙ G) :=
    { pt := F.obj (op Y)
      π :=
        { app := fun ⟨Z, hZ⟩ => F.map Z.hom.op ≫ (x _ hZ).app (op (Over.mk (𝟙 _)))
          naturality := by
            rintro ⟨Z₁, hZ₁⟩ ⟨Z₂, hZ₂⟩ ⟨f : Z₂ ⟶ Z₁⟩
            dsimp
            rw [id_comp, assoc]
            have H := hx f.left (𝟙 _) hZ₁ hZ₂ (by simp)
            simp only [presheafHom_obj, unop_op, Functor.id_obj, op_id,
              FunctorToTypes.map_id_apply] at H
            let φ : Over.mk f.left ⟶ Over.mk (𝟙 Z₁.left) := Over.homMk f.left
            have H' := (x (Z₁.hom ≫ g) hZ₁).naturality φ.op
            dsimp at H H' ⊢
            erw [← H, ← H', presheafHom_map_app_op_mk_id, ← F.map_comp_assoc,
              ← op_comp, Over.w f] } }