l3lab/ntp-mathlib huggingface dataset:
/--
Implementation: This is a construction which will be used in the proof that
the sieve generated by a family of arrows is effective epimorphic if and only if
the family is an effective epi.
-/
noncomputable
def effectiveEpiFamilyStructOfIsColimit {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B))
    (H : IsColimit (Sieve.generateFamily X π : Presieve B).cocone) :
    EffectiveEpiFamilyStruct X π :=
  let aux {W : C} (e : (a : α) → (X a ⟶ W))
    (h : ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
      g₁ ≫ π _ = g₂ ≫ π _ → g₁ ≫ e _ = g₂ ≫ e _) :
    Cocone (Sieve.generateFamily X π).arrows.diagram := {
      pt := W
      ι := {
        app := fun ⟨T,hT⟩ => hT.choose_spec.choose ≫ e hT.choose
        naturality := by
          intro ⟨A,a,(g₁ : A.left ⟶ _),ha⟩ ⟨B,b,(g₂ : B.left ⟶ _),hb⟩ (q : A ⟶ B)
          dsimp; rw [Category.comp_id, ← Category.assoc]
          apply h; rw [Category.assoc]
          generalize_proofs h1 h2 h3 h4
          rw [h2.choose_spec, h4.choose_spec, Over.w] } }
  { desc := fun {W} e h => H.desc (aux e h)
    fac := by
      intro W e h a
      dsimp
      have := H.fac (aux e h) ⟨Over.mk (π a), a, 𝟙 _, by simp⟩
      dsimp at this; rw [this]; clear this
      conv_rhs => rw [← Category.id_comp (e a)]
      apply h
      generalize_proofs h1 h2
      rw [h2.choose_spec, Category.id_comp]
    uniq := by
      intro W e h m hm
      apply H.uniq (aux e h)
      rintro ⟨T, a, (g : T.left ⟶ _), ha⟩
      dsimp
      nth_rewrite 1 [← ha, Category.assoc, hm]
      

Proof state:
case x.mk.intro.intro
C : Type u_1
inst✝ : Category.{?u.76591, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
H : IsColimit (Presieve.cocone (Sieve.generateFamily X π).arrows)
aux : {W : C} →
  (e : (a : α) → X a ⟶ W) →
    (∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ e a₁ = g₂ ≫ e a₂) →
      Cocone (Presieve.diagram (Sieve.generateFamily X π).arrows) :=
  fun {W} e h =>
    { pt := W,
      ι :=
        NatTrans.mk fun x =>
          match x with
          | { obj := T, property := hT } =>
            Exists.choose (_ : ∃ g, g ≫ π (Exists.choose hT) = T.hom) ≫ e (Exists.choose hT) }
W : C
e : (a : α) → X a ⟶ W
h : ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ e a₁ = g₂ ≫ e a₂
m : B ⟶ W
hm : ∀ (a : α), π a ≫ m = e a
T : Over B
a : α
g : T.left ⟶ X a
ha : g ≫ π a = T.hom
⊢ g ≫ e a =
    Exists.choose (_ : ∃ g_1, g_1 ≫ π (Exists.choose (_ : ∃ a g, g ≫ π a = T.hom)) = T.hom) ≫
      e (Exists.choose (_ : ∃ a g, g ≫ π a = T.hom))

Next tactic:
apply h
/--
Implementation: This is a construction which will be used in the proof that
the sieve generated by a family of arrows is effective epimorphic if and only if
the family is an effective epi.
-/
noncomputable
def effectiveEpiFamilyStructOfIsColimit {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B))
    (H : IsColimit (Sieve.generateFamily X π : Presieve B).cocone) :
    EffectiveEpiFamilyStruct X π :=
  let aux {W : C} (e : (a : α) → (X a ⟶ W))
    (h : ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
      g₁ ≫ π _ = g₂ ≫ π _ → g₁ ≫ e _ = g₂ ≫ e _) :
    Cocone (Sieve.generateFamily X π).arrows.diagram := {
      pt := W
      ι := {
        app := fun ⟨T,hT⟩ => hT.choose_spec.choose ≫ e hT.choose
        naturality := by
          intro ⟨A,a,(g₁ : A.left ⟶ _),ha⟩ ⟨B,b,(g₂ : B.left ⟶ _),hb⟩ (q : A ⟶ B)
          dsimp; rw [Category.comp_id, ← Category.assoc]
          apply h; rw [Category.assoc]
          generalize_proofs h1 h2 h3 h4
          rw [h2.choose_spec, h4.choose_spec, Over.w] } }
  { desc := fun {W} e h => H.desc (aux e h)
    fac := by
      intro W e h a
      dsimp
      have := H.fac (aux e h) ⟨Over.mk (π a), a, 𝟙 _, by simp⟩
      dsimp at this; rw [this]; clear this
      conv_rhs => rw [← Category.id_comp (e a)]
      apply h
      generalize_proofs h1 h2
      rw [h2.choose_spec, Category.id_comp]
    uniq := by
      intro W e h m hm
      apply H.uniq (aux e h)
      rintro ⟨T, a, (g : T.left ⟶ _), ha⟩
      dsimp
      nth_rewrite 1 [← ha, Category.assoc, hm]
      apply h
      

Proof state:
case x.mk.intro.intro.a
C : Type u_1
inst✝ : Category.{?u.76591, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
H : IsColimit (Presieve.cocone (Sieve.generateFamily X π).arrows)
aux : {W : C} →
  (e : (a : α) → X a ⟶ W) →
    (∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ e a₁ = g₂ ≫ e a₂) →
      Cocone (Presieve.diagram (Sieve.generateFamily X π).arrows) :=
  fun {W} e h =>
    { pt := W,
      ι :=
        NatTrans.mk fun x =>
          match x with
          | { obj := T, property := hT } =>
            Exists.choose (_ : ∃ g, g ≫ π (Exists.choose hT) = T.hom) ≫ e (Exists.choose hT) }
W : C
e : (a : α) → X a ⟶ W
h : ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ e a₁ = g₂ ≫ e a₂
m : B ⟶ W
hm : ∀ (a : α), π a ≫ m = e a
T : Over B
a : α
g : T.left ⟶ X a
ha : g ≫ π a = T.hom
⊢ g ≫ π a =
    Exists.choose (_ : ∃ g_1, g_1 ≫ π (Exists.choose (_ : ∃ a g, g ≫ π a = T.hom)) = T.hom) ≫
      π (Exists.choose (_ : ∃ a g, g ≫ π a = T.hom))

Next tactic:
generalize_proofs h1 h2
/--
Implementation: This is a construction which will be used in the proof that
the sieve generated by a family of arrows is effective epimorphic if and only if
the family is an effective epi.
-/
noncomputable
def effectiveEpiFamilyStructOfIsColimit {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B))
    (H : IsColimit (Sieve.generateFamily X π : Presieve B).cocone) :
    EffectiveEpiFamilyStruct X π :=
  let aux {W : C} (e : (a : α) → (X a ⟶ W))
    (h : ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
      g₁ ≫ π _ = g₂ ≫ π _ → g₁ ≫ e _ = g₂ ≫ e _) :
    Cocone (Sieve.generateFamily X π).arrows.diagram := {
      pt := W
      ι := {
        app := fun ⟨T,hT⟩ => hT.choose_spec.choose ≫ e hT.choose
        naturality := by
          intro ⟨A,a,(g₁ : A.left ⟶ _),ha⟩ ⟨B,b,(g₂ : B.left ⟶ _),hb⟩ (q : A ⟶ B)
          dsimp; rw [Category.comp_id, ← Category.assoc]
          apply h; rw [Category.assoc]
          generalize_proofs h1 h2 h3 h4
          rw [h2.choose_spec, h4.choose_spec, Over.w] } }
  { desc := fun {W} e h => H.desc (aux e h)
    fac := by
      intro W e h a
      dsimp
      have := H.fac (aux e h) ⟨Over.mk (π a), a, 𝟙 _, by simp⟩
      dsimp at this; rw [this]; clear this
      conv_rhs => rw [← Category.id_comp (e a)]
      apply h
      generalize_proofs h1 h2
      rw [h2.choose_spec, Category.id_comp]
    uniq := by
      intro W e h m hm
      apply H.uniq (aux e h)
      rintro ⟨T, a, (g : T.left ⟶ _), ha⟩
      dsimp
      nth_rewrite 1 [← ha, Category.assoc, hm]
      apply h
      generalize_proofs h1 h2
      

Proof state:
case x.mk.intro.intro.a
C : Type u_1
inst✝ : Category.{?u.76591, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
H : IsColimit (Presieve.cocone (Sieve.generateFamily X π).arrows)
aux : {W : C} →
  (e : (a : α) → X a ⟶ W) →
    (∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ e a₁ = g₂ ≫ e a₂) →
      Cocone (Presieve.diagram (Sieve.generateFamily X π).arrows) :=
  fun {W} e h =>
    { pt := W,
      ι :=
        NatTrans.mk fun x =>
          match x with
          | { obj := T, property := hT } =>
            Exists.choose (_ : ∃ g, g ≫ π (Exists.choose hT) = T.hom) ≫ e (Exists.choose hT) }
W : C
e : (a : α) → X a ⟶ W
h : ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂), g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ e a₁ = g₂ ≫ e a₂
m : B ⟶ W
hm : ∀ (a : α), π a ≫ m = e a
T : Over B
a : α
g : T.left ⟶ X a
ha : g ≫ π a = T.hom
h1 : ∃ a g, g ≫ π a = T.hom
h2 : ∃ g, g ≫ π (Exists.choose h1) = T.hom
⊢ g ≫ π a = Exists.choose h2 ≫ π (Exists.choose h1)

Next tactic:
rwa [h2.choose_spec]
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  

Proof state:
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
⊢ Presieve.EffectiveEpimorphic (Presieve.ofArrows X π) ↔ EffectiveEpiFamily X π

Next tactic:
constructor
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · 

Proof state:
case mp
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
⊢ Presieve.EffectiveEpimorphic (Presieve.ofArrows X π) → EffectiveEpiFamily X π

Next tactic:
intro (h : Nonempty _)
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    

Proof state:
case mp
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
h : Nonempty (IsColimit (Presieve.cocone (generate (Presieve.ofArrows X π)).arrows))
⊢ EffectiveEpiFamily X π

Next tactic:
rw [Sieve.generateFamily_eq] at h
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    rw [Sieve.generateFamily_eq] at h
    

Proof state:
case mp
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
h : Nonempty (IsColimit (Presieve.cocone (generateFamily X π).arrows))
⊢ EffectiveEpiFamily X π

Next tactic:
constructor
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    rw [Sieve.generateFamily_eq] at h
    constructor
    

Proof state:
case mp.effectiveEpiFamily
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
h : Nonempty (IsColimit (Presieve.cocone (generateFamily X π).arrows))
⊢ Nonempty (EffectiveEpiFamilyStruct X π)

Next tactic:
apply Nonempty.map (effectiveEpiFamilyStructOfIsColimit _ _) h
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    rw [Sieve.generateFamily_eq] at h
    constructor
    apply Nonempty.map (effectiveEpiFamilyStructOfIsColimit _ _) h
  · 

Proof state:
case mpr
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
⊢ EffectiveEpiFamily X π → Presieve.EffectiveEpimorphic (Presieve.ofArrows X π)

Next tactic:
rintro ⟨h⟩
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    rw [Sieve.generateFamily_eq] at h
    constructor
    apply Nonempty.map (effectiveEpiFamilyStructOfIsColimit _ _) h
  · rintro ⟨h⟩
    

Proof state:
case mpr.mk
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
h : Nonempty (EffectiveEpiFamilyStruct X π)
⊢ Presieve.EffectiveEpimorphic (Presieve.ofArrows X π)

Next tactic:
show Nonempty _
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    rw [Sieve.generateFamily_eq] at h
    constructor
    apply Nonempty.map (effectiveEpiFamilyStructOfIsColimit _ _) h
  · rintro ⟨h⟩
    show Nonempty _
    

Proof state:
case mpr.mk
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
h : Nonempty (EffectiveEpiFamilyStruct X π)
⊢ Nonempty (IsColimit (Presieve.cocone (generate (Presieve.ofArrows X π)).arrows))

Next tactic:
rw [Sieve.generateFamily_eq]
theorem Sieve.effectiveEpimorphic_family {B : C} {α : Type*}
    (X : α → C) (π : (a : α) → (X a ⟶ B)) :
    (Presieve.ofArrows X π).EffectiveEpimorphic ↔ EffectiveEpiFamily X π := by
  constructor
  · intro (h : Nonempty _)
    rw [Sieve.generateFamily_eq] at h
    constructor
    apply Nonempty.map (effectiveEpiFamilyStructOfIsColimit _ _) h
  · rintro ⟨h⟩
    show Nonempty _
    rw [Sieve.generateFamily_eq]
    

Proof state:
case mpr.mk
C : Type u_1
inst✝ : Category.{u_3, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
h : Nonempty (EffectiveEpiFamilyStruct X π)
⊢ Nonempty (IsColimit (Presieve.cocone (generateFamily X π).arrows))

Next tactic:
apply Nonempty.map (isColimitOfEffectiveEpiFamilyStruct _ _) h
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    

Proof state:
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
h : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
Z✝ : C
a₁ a₂ : α
g₁ : Z✝ ⟶ X a₁
g₂ : Z✝ ⟶ X a₂
hg : g₁ ≫ π a₁ = g₂ ≫ π a₂
⊢ g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂

Next tactic:
simp only [← Category.assoc]
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    

Proof state:
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
h : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
Z✝ : C
a₁ a₂ : α
g₁ : Z✝ ⟶ X a₁
g₂ : Z✝ ⟶ X a₂
hg : g₁ ≫ π a₁ = g₂ ≫ π a₂
⊢ (g₁ ≫ Sigma.ι X a₁) ≫ e = (g₂ ≫ Sigma.ι X a₂) ≫ e

Next tactic:
apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
    

Proof state:
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
h : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
Z✝ : C
a₁ a₂ : α
g₁ : Z✝ ⟶ X a₁
g₂ : Z✝ ⟶ X a₂
hg : g₁ ≫ π a₁ = g₂ ≫ π a₂
⊢ (g₁ ≫ Sigma.ι X a₁) ≫ Sigma.desc π = (g₂ ≫ Sigma.ι X a₂) ≫ Sigma.desc π

Next tactic:
simpa only [Category.assoc, colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app]
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
    simpa only [Category.assoc, colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app])
  fac e h := by
    

Proof state:
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
h : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
⊢ Sigma.desc π ≫
      (fun {W} e h =>
          EffectiveEpiFamily.desc X π (fun a => Sigma.ι X a ≫ e)
            (_ :
              ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
                g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂))
        e (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e) =
    e

Next tactic:
ext a
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
    simpa only [Category.assoc, colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app])
  fac e h := by
    ext a
    

Proof state:
case h
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
h : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
a : α
⊢ Sigma.ι (fun b => X b) a ≫
      Sigma.desc π ≫
        (fun {W} e h =>
            EffectiveEpiFamily.desc X π (fun a => Sigma.ι X a ≫ e)
              (_ :
                ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
                  g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂))
          e (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e) =
    Sigma.ι (fun b => X b) a ≫ e

Next tactic:
simp only [colimit.ι_desc_assoc, Discrete.functor_obj, Cofan.mk_pt, Cofan.mk_ι_app,
      EffectiveEpiFamily.fac]
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
    simpa only [Category.assoc, colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app])
  fac e h := by
    ext a
    simp only [colimit.ι_desc_assoc, Discrete.functor_obj, Cofan.mk_pt, Cofan.mk_ι_app,
      EffectiveEpiFamily.fac]
  uniq e _ m hm := by
    

Proof state:
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
x✝ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
m : B ⟶ W✝
hm : Sigma.desc π ≫ m = e
⊢ m =
    (fun {W} e h =>
        EffectiveEpiFamily.desc X π (fun a => Sigma.ι X a ≫ e)
          (_ :
            ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
              g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂))
      e (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e)

Next tactic:
have := EffectiveEpiFamily.uniq X π (fun a ↦ Sigma.ι X a ≫ e) ?_ m
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
    simpa only [Category.assoc, colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app])
  fac e h := by
    ext a
    simp only [colimit.ι_desc_assoc, Discrete.functor_obj, Cofan.mk_pt, Cofan.mk_ι_app,
      EffectiveEpiFamily.fac]
  uniq e _ m hm := by
    have := EffectiveEpiFamily.uniq X π (fun a ↦ Sigma.ι X a ≫ e) ?_ m
    · 

Proof state:
case refine_2
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
x✝ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
m : B ⟶ W✝
hm : Sigma.desc π ≫ m = e
this :
  (∀ (a : α), π a ≫ m = Sigma.ι X a ≫ e) →
    m =
      EffectiveEpiFamily.desc X π (fun a => Sigma.ι X a ≫ e)
        (_ :
          ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
            g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂)
⊢ m =
    (fun {W} e h =>
        EffectiveEpiFamily.desc X π (fun a => Sigma.ι X a ≫ e)
          (_ :
            ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
              g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂))
      e (_ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e)

Next tactic:
apply this
/--
Given an `EffectiveEpiFamily X π` such that the coproduct of `X` exists, `Sigma.desc π` is an
`EffectiveEpi`.
-/
noncomputable
def effectiveEpiStructDescOfEffectiveEpiFamily {B : C} {α : Type*} (X : α → C)
    (π : (a : α) → (X a ⟶ B)) [HasCoproduct X] [EffectiveEpiFamily X π] :
    EffectiveEpiStruct (Sigma.desc π) where
  desc e h := EffectiveEpiFamily.desc X π (fun a ↦ Sigma.ι X a ≫ e) (fun a₁ a₂ g₁ g₂ hg ↦ by
    simp only [← Category.assoc]
    apply h (g₁ ≫ Sigma.ι X a₁) (g₂ ≫ Sigma.ι X a₂)
    simpa only [Category.assoc, colimit.ι_desc, Cofan.mk_pt, Cofan.mk_ι_app])
  fac e h := by
    ext a
    simp only [colimit.ι_desc_assoc, Discrete.functor_obj, Cofan.mk_pt, Cofan.mk_ι_app,
      EffectiveEpiFamily.fac]
  uniq e _ m hm := by
    have := EffectiveEpiFamily.uniq X π (fun a ↦ Sigma.ι X a ≫ e) ?_ m
    · apply this
      

Proof state:
case refine_2
C : Type u_1
inst✝² : Category.{?u.93370, u_1} C
B : C
α : Type u_2
X : α → C
π : (a : α) → X a ⟶ B
inst✝¹ : HasCoproduct X
inst✝ : EffectiveEpiFamily X π
W✝ : C
e : (∐ fun b => X b) ⟶ W✝
x✝ : ∀ {Z : C} (g₁ g₂ : Z ⟶ ∐ fun b => X b), g₁ ≫ Sigma.desc π = g₂ ≫ Sigma.desc π → g₁ ≫ e = g₂ ≫ e
m : B ⟶ W✝
hm : Sigma.desc π ≫ m = e
this :
  (∀ (a : α), π a ≫ m = Sigma.ι X a ≫ e) →
    m =
      EffectiveEpiFamily.desc X π (fun a => Sigma.ι X a ≫ e)
        (_ :
          ∀ {Z : C} (a₁ a₂ : α) (g₁ : Z ⟶ X a₁) (g₂ : Z ⟶ X a₂),
            g₁ ≫ π a₁ = g₂ ≫ π a₂ → g₁ ≫ (fun a => Sigma.ι X a ≫ e) a₁ = g₂ ≫ (fun a => Sigma.ι X a ≫ e) a₂)
⊢ ∀ (a : α), π a ≫ m = Sigma.ι X a ≫ e

Next tactic:
intro a