l3lab/ntp-mathlib huggingface dataset:
theorem natDegree_cancelLeads_lt_of_natDegree_le_natDegree_of_comm
    (comm : p.leadingCoeff * q.leadingCoeff = q.leadingCoeff * p.leadingCoeff)
    (h : p.natDegree ≤ q.natDegree) (hq : 0 < q.natDegree) :
    (p.cancelLeads q).natDegree < q.natDegree := by
  by_cases hp : p = 0
  · convert hq
    simp [hp, cancelLeads]
  rw [cancelLeads, sub_eq_add_neg, tsub_eq_zero_iff_le.mpr h, pow_zero, mul_one]
  by_cases h0 :
    C p.leadingCoeff * q + -(C q.leadingCoeff * X ^ (q.natDegree - p.natDegree) * p) = 0
  · exact (le_of_eq (by simp only [h0, natDegree_zero])).trans_lt hq
  apply lt_of_le_of_ne
  · compute_degree!
    rwa [Nat.sub_add_cancel]
  · contrapose! h0
    rw [← leadingCoeff_eq_zero, leadingCoeff, h0, mul_assoc, X_pow_mul, ← tsub_add_cancel_of_le h,
      add_comm _ p.natDegree]
    

Proof state:
case neg.a
R : Type u_1
inst✝ : Ring R
p q : R[X]
comm : leadingCoeff p * leadingCoeff q = leadingCoeff q * leadingCoeff p
h : natDegree p ≤ natDegree q
hq : 0 < natDegree q
hp : ¬p = 0
h0 : natDegree (C (leadingCoeff p) * q + -(C (leadingCoeff q) * X ^ (natDegree q - natDegree p) * p)) = natDegree q
⊢ coeff
      (C (leadingCoeff p) * q +
        -(C (leadingCoeff q) * (p * X ^ (natDegree p + (natDegree q - natDegree p) - natDegree p))))
      (natDegree p + (natDegree q - natDegree p)) =
    0

Next tactic:
simp only [coeff_mul_X_pow, coeff_neg, coeff_C_mul, add_tsub_cancel_left, coeff_add]
theorem natDegree_cancelLeads_lt_of_natDegree_le_natDegree_of_comm
    (comm : p.leadingCoeff * q.leadingCoeff = q.leadingCoeff * p.leadingCoeff)
    (h : p.natDegree ≤ q.natDegree) (hq : 0 < q.natDegree) :
    (p.cancelLeads q).natDegree < q.natDegree := by
  by_cases hp : p = 0
  · convert hq
    simp [hp, cancelLeads]
  rw [cancelLeads, sub_eq_add_neg, tsub_eq_zero_iff_le.mpr h, pow_zero, mul_one]
  by_cases h0 :
    C p.leadingCoeff * q + -(C q.leadingCoeff * X ^ (q.natDegree - p.natDegree) * p) = 0
  · exact (le_of_eq (by simp only [h0, natDegree_zero])).trans_lt hq
  apply lt_of_le_of_ne
  · compute_degree!
    rwa [Nat.sub_add_cancel]
  · contrapose! h0
    rw [← leadingCoeff_eq_zero, leadingCoeff, h0, mul_assoc, X_pow_mul, ← tsub_add_cancel_of_le h,
      add_comm _ p.natDegree]
    simp only [coeff_mul_X_pow, coeff_neg, coeff_C_mul, add_tsub_cancel_left, coeff_add]
    

Proof state:
case neg.a
R : Type u_1
inst✝ : Ring R
p q : R[X]
comm : leadingCoeff p * leadingCoeff q = leadingCoeff q * leadingCoeff p
h : natDegree p ≤ natDegree q
hq : 0 < natDegree q
hp : ¬p = 0
h0 : natDegree (C (leadingCoeff p) * q + -(C (leadingCoeff q) * X ^ (natDegree q - natDegree p) * p)) = natDegree q
⊢ leadingCoeff p * coeff q (natDegree p + (natDegree q - natDegree p)) + -(leadingCoeff q * coeff p (natDegree p)) = 0

Next tactic:
rw [add_comm p.natDegree, tsub_add_cancel_of_le h, ← leadingCoeff, ← leadingCoeff, comm,
      add_right_neg]
@[simp]
lemma factorsThruAlong_id {X : C} (S T : Presieve X) :
    S.FactorsThruAlong T (𝟙 X) ↔ S.FactorsThru T := by
  

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
⊢ FactorsThruAlong S T (𝟙 X) ↔ FactorsThru S T

Next tactic:
simp [FactorsThruAlong, FactorsThru]
lemma factorsThru_of_le {X : C} (S T : Presieve X) (h : S ≤ T) :
    S.FactorsThru T :=
  fun Y g hg => ⟨Y, 𝟙 _, g, h _ hg, by 

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
h : S ≤ T
Y : C
g : Y ⟶ X
hg : S g
⊢ 𝟙 Y ≫ g = g

Next tactic:
simp
lemma le_of_factorsThru_sieve {X : C} (S : Presieve X) (T : Sieve X) (h : S.FactorsThru T) :
    S ≤ T := by
  

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S : Presieve X
T : Sieve X
h : FactorsThru S T.arrows
⊢ S ≤ T.arrows

Next tactic:
rintro Y f hf
lemma le_of_factorsThru_sieve {X : C} (S : Presieve X) (T : Sieve X) (h : S.FactorsThru T) :
    S ≤ T := by
  rintro Y f hf
  

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S : Presieve X
T : Sieve X
h : FactorsThru S T.arrows
Y : C
f : Y ⟶ X
hf : f ∈ S
⊢ f ∈ T.arrows

Next tactic:
obtain ⟨W, i, e, h1, rfl⟩ := h hf
lemma le_of_factorsThru_sieve {X : C} (S : Presieve X) (T : Sieve X) (h : S.FactorsThru T) :
    S ≤ T := by
  rintro Y f hf
  obtain ⟨W, i, e, h1, rfl⟩ := h hf
  

Proof state:
case intro.intro.intro.intro
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S : Presieve X
T : Sieve X
h : FactorsThru S T.arrows
Y W : C
i : Y ⟶ W
e : W ⟶ X
h1 : T.arrows e
hf : i ≫ e ∈ S
⊢ i ≫ e ∈ T.arrows

Next tactic:
exact T.downward_closed h1 _
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
H : FactorsThru S T
hS : IsSheafFor P S
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
⊢ IsSheafFor P T

Next tactic:
simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
H : FactorsThru S T
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
⊢ IsSeparatedFor P T ∧
    ∀ (x : FamilyOfElements P T), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t

Next tactic:
choose W i e h1 h2 using H
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
⊢ IsSeparatedFor P T ∧
    ∀ (x : FamilyOfElements P T), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t

Next tactic:
refine ⟨?_, fun x hx => ?_⟩
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · 

Proof state:
case refine_1
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
⊢ IsSeparatedFor P T

Next tactic:
intro x y₁ y₂ h₁ h₂
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    

Proof state:
case refine_1
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
y₁ y₂ : P.obj (Opposite.op X)
h₁ : FamilyOfElements.IsAmalgamation x y₁
h₂ : FamilyOfElements.IsAmalgamation x y₂
⊢ y₁ = y₂

Next tactic:
refine hS.1.ext (fun Y g hg => ?_)
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    

Proof state:
case refine_1
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
y₁ y₂ : P.obj (Opposite.op X)
h₁ : FamilyOfElements.IsAmalgamation x y₁
h₂ : FamilyOfElements.IsAmalgamation x y₂
Y : C
g : Y ⟶ X
hg : S g
⊢ P.map g.op y₁ = P.map g.op y₂

Next tactic:
simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  

Proof state:
case refine_2
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
⊢ ∃ t, FamilyOfElements.IsAmalgamation x t

Next tactic:
let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  

Proof state:
case refine_2
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
⊢ ∃ t, FamilyOfElements.IsAmalgamation x t

Next tactic:
have hy : y.Compatible := by
    intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
    rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op),
      ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op),
      ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp]
    apply hx
    simp only [h2, h, Category.assoc]
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  have hy : y.Compatible := by
    

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
⊢ FamilyOfElements.Compatible y

Next tactic:
intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  have hy : y.Compatible := by
    intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
    

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h✝ : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
Y₁ Y₂ Z : C
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : S f₁
h₂ : S f₂
h : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ P.map g₁.op (y f₁ h₁) = P.map g₂.op (y f₂ h₂)

Next tactic:
rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op),
      ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op),
      ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp]
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  have hy : y.Compatible := by
    intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
    rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op),
      ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op),
      ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp]
    

Proof state:
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h✝ : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
Y₁ Y₂ Z : C
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : S f₁
h₂ : S f₂
h : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ P.map (g₁ ≫ i h₁).op (x (e h₁) (_ : T (e h₁))) = P.map (g₂ ≫ i h₂).op (x (e h₂) (_ : T (e h₂)))

Next tactic:
apply hx
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  have hy : y.Compatible := by
    intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
    rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op),
      ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op),
      ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp]
    apply hx
    

Proof state:
case a
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h✝ : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
Y₁ Y₂ Z : C
g₁ : Z ⟶ Y₁
g₂ : Z ⟶ Y₂
f₁ : Y₁ ⟶ X
f₂ : Y₂ ⟶ X
h₁ : S f₁
h₂ : S f₂
h : g₁ ≫ f₁ = g₂ ≫ f₂
⊢ (g₁ ≫ i h₁) ≫ e h₁ = (g₂ ≫ i h₂) ≫ e h₂

Next tactic:
simp only [h2, h, Category.assoc]
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  have hy : y.Compatible := by
    intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
    rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op),
      ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op),
      ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp]
    apply hx
    simp only [h2, h, Category.assoc]
  

Proof state:
case refine_2
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
hy : FamilyOfElements.Compatible y
⊢ ∃ t, FamilyOfElements.IsAmalgamation x t

Next tactic:
let ⟨_, h2'⟩ := hS
lemma isSheafFor_of_factorsThru
    {X : C} {S T : Presieve X}
    (P : Cᵒᵖ ⥤ Type w)
    (H : S.FactorsThru T) (hS : S.IsSheafFor P)
    (h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ (R : Presieve Y),
      R.IsSeparatedFor P ∧ R.FactorsThruAlong S f):
    T.IsSheafFor P := by
  simp only [← Presieve.isSeparatedFor_and_exists_isAmalgamation_iff_isSheafFor] at *
  choose W i e h1 h2 using H
  refine ⟨?_, fun x hx => ?_⟩
  · intro x y₁ y₂ h₁ h₂
    refine hS.1.ext (fun Y g hg => ?_)
    simp only [← h2 hg, op_comp, P.map_comp, types_comp_apply, h₁ _ (h1 _ ), h₂ _ (h1 _)]
  let y : S.FamilyOfElements P := fun Y g hg => P.map (i _).op (x (e hg) (h1 _))
  have hy : y.Compatible := by
    intro Y₁ Y₂ Z g₁ g₂ f₁ f₂ h₁ h₂ h
    rw [← types_comp_apply (P.map (i h₁).op) (P.map g₁.op),
      ← types_comp_apply (P.map (i h₂).op) (P.map g₂.op),
      ← P.map_comp, ← op_comp, ← P.map_comp, ← op_comp]
    apply hx
    simp only [h2, h, Category.assoc]
  let ⟨_, h2'⟩ := hS
  

Proof state:
case refine_2
C : Type u_2
inst✝ : Category.{u_1, u_2} C
X : C
S T : Presieve X
P : Cᵒᵖ ⥤ Type w
h : ∀ ⦃Y : C⦄ ⦃f : Y ⟶ X⦄, T f → ∃ R, IsSeparatedFor P R ∧ FactorsThruAlong R S f
hS :
  IsSeparatedFor P S ∧
    ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
W : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → S g → C
i : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → Z ⟶ W a
e : ⦃Z : C⦄ → ⦃g : Z ⟶ X⦄ → (a : S g) → W a ⟶ X
h1 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), T (e a)
h2 : ∀ ⦃Z : C⦄ ⦃g : Z ⟶ X⦄ (a : S g), i a ≫ e a = g
x : FamilyOfElements P T
hx : FamilyOfElements.Compatible x
y : FamilyOfElements P S := fun Y g hg => P.map (i hg).op (x (e hg) (_ : T (e hg)))
hy : FamilyOfElements.Compatible y
left✝ : IsSeparatedFor P S
h2' : ∀ (x : FamilyOfElements P S), FamilyOfElements.Compatible x → ∃ t, FamilyOfElements.IsAmalgamation x t
⊢ ∃ t, FamilyOfElements.IsAmalgamation x t

Next tactic:
obtain ⟨z, hz⟩ := h2' y hy