l3lab/ntp-mathlib huggingface dataset:
/--
Effective epi families in a precoherent category are transitive, in the sense that an
`EffectiveEpiFamily` and an `EffectiveEpiFamily` over each member, the composition is an
`EffectiveEpiFamily`.
Note: The finiteness condition is an artifact of the proof and is probably unnecessary.
-/
theorem EffectiveEpiFamily.transitive_of_finite {α : Type} [Fintype α] {Y : α → C}
    (π : (a : α) → (Y a ⟶ X)) (h : EffectiveEpiFamily Y π) {β : α → Type} [∀ (a: α), Fintype (β a)]
    {Y_n : (a : α) → β a → C} (π_n : (a : α) → (b : β a) → (Y_n a b ⟶ Y a))
    (H : ∀ a, EffectiveEpiFamily (Y_n a) (π_n a)) :
    EffectiveEpiFamily
      (fun (c : Σ a, β a) => Y_n c.fst c.snd) (fun c => π_n c.fst c.snd ≫ π c.fst) := by
  rw [← Sieve.effectiveEpimorphic_family]
  suffices h₂ : (Sieve.generate (Presieve.ofArrows (fun (⟨a, b⟩ : Σ _, β _) => Y_n a b)
        (fun ⟨a,b⟩ => π_n a b ≫ π a))) ∈ GrothendieckTopology.sieves (coherentTopology C) X by
    change Nonempty _
    rw [← Sieve.forallYonedaIsSheaf_iff_colimit]
    exact fun W => coherentTopology.isSheaf_yoneda_obj W _ h₂
  let h' := h
  rw [← Sieve.effectiveEpimorphic_family] at h'
  let H' := H
  conv at H' =>
    intro a
    rw [← Sieve.effectiveEpimorphic_family]
  -- Show that a covering sieve is a colimit, which implies the original set of arrows is regular
  -- epimorphic. We use the transitivity property of saturation
  apply Coverage.saturate.transitive X (Sieve.generate (Presieve.ofArrows Y π))
  · apply Coverage.saturate.of
    use α, inferInstance, Y, π
  · intro V f ⟨Y₁, h, g, ⟨hY, hf⟩⟩
    rw [← hf, Sieve.pullback_comp]
    apply (coherentTopology C).pullback_stable'
    apply coherentTopology.mem_sieves_of_hasEffectiveEpiFamily
    -- Need to show that the pullback of the family `π_n` to a given `Y i` is effective epimorphic
    rcases hY with ⟨i⟩
    use β i, inferInstance, Y_n i, π_n i, H i
    intro b
    use Y_n i b, (𝟙 _), π_n i b ≫ π i, ⟨(⟨i, b⟩ : Σ (i : α), β i)⟩
    

Proof state:
case right
C✝ : Type u_1
inst✝⁴ : Category.{?u.13173, u_1} C✝
C : Type u_2
inst✝³ : Category.{u_3, u_2} C
inst✝² : Precoherent C
X : C
α : Type
inst✝¹ : Fintype α
Y✝ : α → C
π : (a : α) → Y✝ a ⟶ X
h✝ : EffectiveEpiFamily Y✝ π
β : α → Type
inst✝ : (a : α) → Fintype (β a)
Y_n : (a : α) → β a → C
π_n : (a : α) → (b : β a) → Y_n a b ⟶ Y✝ a
H : ∀ (a : α), EffectiveEpiFamily (Y_n a) (π_n a)
h' : Presieve.EffectiveEpimorphic (Presieve.ofArrows Y✝ π)
H' : ∀ (a : α), Presieve.EffectiveEpimorphic (Presieve.ofArrows (Y_n a) (π_n a))
V : C
f : V ⟶ X
Y : C
i : α
h : V ⟶ Y✝ i
hf : h ≫ π i = f
b : β i
⊢ 𝟙 (Y_n i b) ≫ π_n i b ≫ π i = π_n i b ≫ π i

Next tactic:
exact Category.id_comp (π_n i b ≫ π i)
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  

Proof state:
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
⊢ S ∈ GrothendieckTopology.sieves (coherentTopology C) X ↔ ∃ α x Y π, EffectiveEpiFamily Y π ∧ ∀ (a : α), S.arrows (π a)

Next tactic:
constructor
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · 

Proof state:
case mp
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
⊢ S ∈ GrothendieckTopology.sieves (coherentTopology C) X → ∃ α x Y π, EffectiveEpiFamily Y π ∧ ∀ (a : α), S.arrows (π a)

Next tactic:
intro h
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    

Proof state:
case mp
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
h : S ∈ GrothendieckTopology.sieves (coherentTopology C) X
⊢ ∃ α x Y π, EffectiveEpiFamily Y π ∧ ∀ (a : α), S.arrows (π a)

Next tactic:
induction' h with Y T hS Y Y R S _ _ a b
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · 

Proof state:
case mp.of
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
T : Presieve Y
hS : T ∈ Coverage.covering (coherentCoverage C) Y
⊢ ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), (Sieve.generate T).arrows (π a)

Next tactic:
rcases hS with ⟨a, h, Y', π, h'⟩
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      

Proof state:
case mp.of.intro.intro.intro.intro
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
T : Presieve Y
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
h' : T = Presieve.ofArrows Y' π ∧ EffectiveEpiFamily Y' π
⊢ ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), (Sieve.generate T).arrows (π a)

Next tactic:
use a, h, Y', π, by tauto
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by 

Proof state:
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
T : Presieve Y
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
h' : T = Presieve.ofArrows Y' π ∧ EffectiveEpiFamily Y' π
⊢ EffectiveEpiFamily Y' π

Next tactic:
tauto
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      

Proof state:
case right
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
T : Presieve Y
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
h' : T = Presieve.ofArrows Y' π ∧ EffectiveEpiFamily Y' π
⊢ ∀ (a : a), (Sieve.generate T).arrows (π a)

Next tactic:
intro a'
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      

Proof state:
case right
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
T : Presieve Y
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
h' : T = Presieve.ofArrows Y' π ∧ EffectiveEpiFamily Y' π
a' : a
⊢ (Sieve.generate T).arrows (π a')

Next tactic:
rcases h' with ⟨rfl, _⟩
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      

Proof state:
case right.intro
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
a' : a
right✝ : EffectiveEpiFamily Y' π
⊢ (Sieve.generate (Presieve.ofArrows Y' π)).arrows (π a')

Next tactic:
simp only [Sieve.generate_apply]
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      

Proof state:
case right.intro
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
a' : a
right✝ : EffectiveEpiFamily Y' π
⊢ ∃ Y_1 h g, Presieve.ofArrows Y' π g ∧ h ≫ g = π a'

Next tactic:
use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      

Proof state:
case right
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
a : Type
h : Fintype a
Y' : a → C
π : (a : a) → Y' a ⟶ Y
a' : a
right✝ : EffectiveEpiFamily Y' π
⊢ 𝟙 Y' a' ≫ π a' = π a'

Next tactic:
apply Category.id_comp
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · 

Proof state:
case mp.top
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
⊢ ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), ⊤.arrows (π a)

Next tactic:
use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      

Proof state:
case h
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S : Sieve X
Y : C
⊢ (EffectiveEpiFamily (fun x => Y) fun x => 𝟙 Y) ∧ (Unit → ⊤.arrows (𝟙 Y))

Next tactic:
cases' S with arrows downward_closed
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      cases' S with arrows downward_closed
      

Proof state:
case h.mk
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X Y : C
arrows : Presieve X
downward_closed : ∀ {Y Z : C} {f : Y ⟶ X}, arrows f → ∀ (g : Z ⟶ Y), arrows (g ≫ f)
⊢ (EffectiveEpiFamily (fun x => Y) fun x => 𝟙 Y) ∧ ∀ (a : Unit), ⊤.arrows ((fun x => 𝟙 Y) a)

Next tactic:
exact ⟨inferInstance, by simp only [Sieve.top_apply, forall_const]⟩
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      cases' S with arrows downward_closed
      exact ⟨inferInstance, by 

Proof state:
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X Y : C
arrows : Presieve X
downward_closed : ∀ {Y Z : C} {f : Y ⟶ X}, arrows f → ∀ (g : Z ⟶ Y), arrows (g ≫ f)
⊢ ∀ (a : Unit), ⊤.arrows ((fun x => 𝟙 Y) a)

Next tactic:
simp only [Sieve.top_apply, forall_const]
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      cases' S with arrows downward_closed
      exact ⟨inferInstance, by simp only [Sieve.top_apply, forall_const]⟩
    · 

Proof state:
case mp.transitive
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S✝ : Sieve X
Y : C
R S : Sieve Y
a✝¹ : Coverage.saturate (coherentCoverage C) Y R
a✝ : ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄, R.arrows f → Coverage.saturate (coherentCoverage C) Y_1 (Sieve.pullback f S)
a : ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), R.arrows (π a)
b :
  ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄,
    R.arrows f → ∃ α x Y_2 π, EffectiveEpiFamily Y_2 π ∧ ∀ (a : α), (Sieve.pullback f S).arrows (π a)
⊢ ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), S.arrows (π a)

Next tactic:
rcases a with ⟨α, w, Y₁, π, ⟨h₁,h₂⟩⟩
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      cases' S with arrows downward_closed
      exact ⟨inferInstance, by simp only [Sieve.top_apply, forall_const]⟩
    · rcases a with ⟨α, w, Y₁, π, ⟨h₁,h₂⟩⟩
      

Proof state:
case mp.transitive.intro.intro.intro.intro.intro
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S✝ : Sieve X
Y : C
R S : Sieve Y
a✝¹ : Coverage.saturate (coherentCoverage C) Y R
a✝ : ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄, R.arrows f → Coverage.saturate (coherentCoverage C) Y_1 (Sieve.pullback f S)
b :
  ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄,
    R.arrows f → ∃ α x Y_2 π, EffectiveEpiFamily Y_2 π ∧ ∀ (a : α), (Sieve.pullback f S).arrows (π a)
α : Type
w : Fintype α
Y₁ : α → C
π : (a : α) → Y₁ a ⟶ Y
h₁ : EffectiveEpiFamily Y₁ π
h₂ : ∀ (a : α), R.arrows (π a)
⊢ ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), S.arrows (π a)

Next tactic:
choose β _ Y_n π_n H using fun a => b (h₂ a)
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      cases' S with arrows downward_closed
      exact ⟨inferInstance, by simp only [Sieve.top_apply, forall_const]⟩
    · rcases a with ⟨α, w, Y₁, π, ⟨h₁,h₂⟩⟩
      choose β _ Y_n π_n H using fun a => b (h₂ a)
      

Proof state:
case mp.transitive.intro.intro.intro.intro.intro
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S✝ : Sieve X
Y : C
R S : Sieve Y
a✝¹ : Coverage.saturate (coherentCoverage C) Y R
a✝ : ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄, R.arrows f → Coverage.saturate (coherentCoverage C) Y_1 (Sieve.pullback f S)
b :
  ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄,
    R.arrows f → ∃ α x Y_2 π, EffectiveEpiFamily Y_2 π ∧ ∀ (a : α), (Sieve.pullback f S).arrows (π a)
α : Type
w : Fintype α
Y₁ : α → C
π : (a : α) → Y₁ a ⟶ Y
h₁ : EffectiveEpiFamily Y₁ π
h₂ : ∀ (a : α), R.arrows (π a)
β : α → Type
x✝ : (a : α) → Fintype (β a)
Y_n : (a : α) → β a → C
π_n : (a : α) → (a_1 : β a) → Y_n a a_1 ⟶ Y₁ a
H : ∀ (a : α), EffectiveEpiFamily (Y_n a) (π_n a) ∧ ∀ (a_1 : β a), (Sieve.pullback (π a) S).arrows (π_n a a_1)
⊢ ∃ α x Y_1 π, EffectiveEpiFamily Y_1 π ∧ ∀ (a : α), S.arrows (π a)

Next tactic:
use (Σ a, β a), inferInstance, fun ⟨a,b⟩ => Y_n a b, fun ⟨a, b⟩ => (π_n a b) ≫ (π a)
/--
A sieve belongs to the coherent topology if and only if it contains a finite
`EffectiveEpiFamily`.
-/
theorem coherentTopology.mem_sieves_iff_hasEffectiveEpiFamily (S : Sieve X) :
    (S ∈ GrothendieckTopology.sieves (coherentTopology C) X) ↔
    (∃ (α : Type) (_ : Fintype α) (Y : α → C) (π : (a : α) → (Y a ⟶ X)),
        EffectiveEpiFamily Y π ∧ (∀ a : α, (S.arrows) (π a)) )  := by
  constructor
  · intro h
    induction' h with Y T hS Y Y R S _ _ a b
    · rcases hS with ⟨a, h, Y', π, h'⟩
      use a, h, Y', π, by tauto
      intro a'
      rcases h' with ⟨rfl, _⟩
      simp only [Sieve.generate_apply]
      use Y' a', 𝟙 Y' a', π a', Presieve.ofArrows.mk a'
      apply Category.id_comp
    · use Unit, Unit.fintype, fun _ => Y, fun _ => (𝟙 Y)
      cases' S with arrows downward_closed
      exact ⟨inferInstance, by simp only [Sieve.top_apply, forall_const]⟩
    · rcases a with ⟨α, w, Y₁, π, ⟨h₁,h₂⟩⟩
      choose β _ Y_n π_n H using fun a => b (h₂ a)
      use (Σ a, β a), inferInstance, fun ⟨a,b⟩ => Y_n a b, fun ⟨a, b⟩ => (π_n a b) ≫ (π a)
      

Proof state:
case h
C✝ : Type u_1
inst✝² : Category.{?u.18231, u_1} C✝
C : Type u_2
inst✝¹ : Category.{u_3, u_2} C
inst✝ : Precoherent C
X : C
S✝ : Sieve X
Y : C
R S : Sieve Y
a✝¹ : Coverage.saturate (coherentCoverage C) Y R
a✝ : ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄, R.arrows f → Coverage.saturate (coherentCoverage C) Y_1 (Sieve.pullback f S)
b :
  ∀ ⦃Y_1 : C⦄ ⦃f : Y_1 ⟶ Y⦄,
    R.arrows f → ∃ α x Y_2 π, EffectiveEpiFamily Y_2 π ∧ ∀ (a : α), (Sieve.pullback f S).arrows (π a)
α : Type
w : Fintype α
Y₁ : α → C
π : (a : α) → Y₁ a ⟶ Y
h₁ : EffectiveEpiFamily Y₁ π
h₂ : ∀ (a : α), R.arrows (π a)
β : α → Type
x✝ : (a : α) → Fintype (β a)
Y_n : (a : α) → β a → C
π_n : (a : α) → (a_1 : β a) → Y_n a a_1 ⟶ Y₁ a
H : ∀ (a : α), EffectiveEpiFamily (Y_n a) (π_n a) ∧ ∀ (a_1 : β a), (Sieve.pullback (π a) S).arrows (π_n a a_1)
⊢ (EffectiveEpiFamily
      (fun x =>
        match x with
        | { fst := a, snd := b } => Y_n a b)
      fun x =>
      match x with
      | { fst := a, snd := b } => π_n a b ≫ π a) ∧
    ∀ (a : (a : α) × β a),
      S.arrows
        (match a with
        | { fst := a, snd := b } => π_n a b ≫ π a)

Next tactic:
constructor