l3lab/ntp-mathlib huggingface dataset:
/-- Recognizing filtered colimits of types. -/
noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x = t.ι.app i xi)
    (hinj :
      ∀ i j xi xj,
        t.ι.app i xi = t.ι.app j xj → ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj) :
    IsColimit t := by
  -- Strategy: Prove that the map from "the" colimit of F (defined above) to t.X
  -- is a bijection.
  apply IsColimit.ofIsoColimit (colimit.isColimit F)
  refine' Cocones.ext (Equiv.toIso (Equiv.ofBijective _ _)) _
  · exact colimit.desc F t
  · constructor
    · show Function.Injective _
      intro a b h
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) a with ⟨i, xi, rfl⟩
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) b with ⟨j, xj, rfl⟩
      replace h : (colimit.ι F i ≫ colimit.desc F t) xi = (colimit.ι F j ≫ colimit.desc F t) xj := h
      rw [colimit.ι_desc, colimit.ι_desc] at h
      rcases hinj i j xi xj h with ⟨k, f, g, h'⟩
      change colimit.ι F i xi = colimit.ι F j xj
      rw [← colimit.w F f, ← colimit.w F g]
      change colimit.ι F k (F.map f xi) = colimit.ι F k (F.map g xj)
      rw [h']
    · show Function.Surjective _
      intro x
      rcases hsurj x with ⟨i, xi, rfl⟩
      

Proof state:
case refine'_2.right.intro.intro
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
hsurj : ∀ (x : t.pt), ∃ i xi, x = t.ι.app i xi
hinj : ∀ (i j : J) (xi : F.obj i) (xj : F.obj j), t.ι.app i xi = t.ι.app j xj → ∃ k f g, F.map f xi = F.map g xj
i : J
xi : F.obj i
⊢ ∃ a, colimit.desc F t a = t.ι.app i xi

Next tactic:
use colimit.ι F i xi
/-- Recognizing filtered colimits of types. -/
noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x = t.ι.app i xi)
    (hinj :
      ∀ i j xi xj,
        t.ι.app i xi = t.ι.app j xj → ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj) :
    IsColimit t := by
  -- Strategy: Prove that the map from "the" colimit of F (defined above) to t.X
  -- is a bijection.
  apply IsColimit.ofIsoColimit (colimit.isColimit F)
  refine' Cocones.ext (Equiv.toIso (Equiv.ofBijective _ _)) _
  · exact colimit.desc F t
  · constructor
    · show Function.Injective _
      intro a b h
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) a with ⟨i, xi, rfl⟩
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) b with ⟨j, xj, rfl⟩
      replace h : (colimit.ι F i ≫ colimit.desc F t) xi = (colimit.ι F j ≫ colimit.desc F t) xj := h
      rw [colimit.ι_desc, colimit.ι_desc] at h
      rcases hinj i j xi xj h with ⟨k, f, g, h'⟩
      change colimit.ι F i xi = colimit.ι F j xj
      rw [← colimit.w F f, ← colimit.w F g]
      change colimit.ι F k (F.map f xi) = colimit.ι F k (F.map g xj)
      rw [h']
    · show Function.Surjective _
      intro x
      rcases hsurj x with ⟨i, xi, rfl⟩
      use colimit.ι F i xi
      

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
hsurj : ∀ (x : t.pt), ∃ i xi, x = t.ι.app i xi
hinj : ∀ (i j : J) (xi : F.obj i) (xj : F.obj j), t.ι.app i xi = t.ι.app j xj → ∃ k f g, F.map f xi = F.map g xj
i : J
xi : F.obj i
⊢ colimit.desc F t (colimit.ι F i xi) = t.ι.app i xi

Next tactic:
apply Colimit.ι_desc_apply.{v, u}
/-- Recognizing filtered colimits of types. -/
noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x = t.ι.app i xi)
    (hinj :
      ∀ i j xi xj,
        t.ι.app i xi = t.ι.app j xj → ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj) :
    IsColimit t := by
  -- Strategy: Prove that the map from "the" colimit of F (defined above) to t.X
  -- is a bijection.
  apply IsColimit.ofIsoColimit (colimit.isColimit F)
  refine' Cocones.ext (Equiv.toIso (Equiv.ofBijective _ _)) _
  · exact colimit.desc F t
  · constructor
    · show Function.Injective _
      intro a b h
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) a with ⟨i, xi, rfl⟩
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) b with ⟨j, xj, rfl⟩
      replace h : (colimit.ι F i ≫ colimit.desc F t) xi = (colimit.ι F j ≫ colimit.desc F t) xj := h
      rw [colimit.ι_desc, colimit.ι_desc] at h
      rcases hinj i j xi xj h with ⟨k, f, g, h'⟩
      change colimit.ι F i xi = colimit.ι F j xj
      rw [← colimit.w F f, ← colimit.w F g]
      change colimit.ι F k (F.map f xi) = colimit.ι F k (F.map g xj)
      rw [h']
    · show Function.Surjective _
      intro x
      rcases hsurj x with ⟨i, xi, rfl⟩
      use colimit.ι F i xi
      apply Colimit.ι_desc_apply.{v, u}
  · 

Proof state:
case refine'_3
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
hsurj : ∀ (x : t.pt), ∃ i xi, x = t.ι.app i xi
hinj : ∀ (i j : J) (xi : F.obj i) (xj : F.obj j), t.ι.app i xi = t.ι.app j xj → ∃ k f g, F.map f xi = F.map g xj
⊢ ∀ (j : J),
    (colimit.cocone F).ι.app j ≫
        (Equiv.toIso
            (Equiv.ofBijective (colimit.desc F t)
              (_ : Function.Injective (colimit.desc F t) ∧ Function.Surjective (colimit.desc F t)))).hom =
      t.ι.app j

Next tactic:
intro j
/-- Recognizing filtered colimits of types. -/
noncomputable def isColimitOf (t : Cocone F) (hsurj : ∀ x : t.pt, ∃ i xi, x = t.ι.app i xi)
    (hinj :
      ∀ i j xi xj,
        t.ι.app i xi = t.ι.app j xj → ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj) :
    IsColimit t := by
  -- Strategy: Prove that the map from "the" colimit of F (defined above) to t.X
  -- is a bijection.
  apply IsColimit.ofIsoColimit (colimit.isColimit F)
  refine' Cocones.ext (Equiv.toIso (Equiv.ofBijective _ _)) _
  · exact colimit.desc F t
  · constructor
    · show Function.Injective _
      intro a b h
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) a with ⟨i, xi, rfl⟩
      rcases jointly_surjective.{v, u} F (colimit.isColimit F) b with ⟨j, xj, rfl⟩
      replace h : (colimit.ι F i ≫ colimit.desc F t) xi = (colimit.ι F j ≫ colimit.desc F t) xj := h
      rw [colimit.ι_desc, colimit.ι_desc] at h
      rcases hinj i j xi xj h with ⟨k, f, g, h'⟩
      change colimit.ι F i xi = colimit.ι F j xj
      rw [← colimit.w F f, ← colimit.w F g]
      change colimit.ι F k (F.map f xi) = colimit.ι F k (F.map g xj)
      rw [h']
    · show Function.Surjective _
      intro x
      rcases hsurj x with ⟨i, xi, rfl⟩
      use colimit.ι F i xi
      apply Colimit.ι_desc_apply.{v, u}
  · intro j
    

Proof state:
case refine'_3
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
hsurj : ∀ (x : t.pt), ∃ i xi, x = t.ι.app i xi
hinj : ∀ (i j : J) (xi : F.obj i) (xj : F.obj j), t.ι.app i xi = t.ι.app j xj → ∃ k f g, F.map f xi = F.map g xj
j : J
⊢ (colimit.cocone F).ι.app j ≫
      (Equiv.toIso
          (Equiv.ofBijective (colimit.desc F t)
            (_ : Function.Injective (colimit.desc F t) ∧ Function.Surjective (colimit.desc F t)))).hom =
    t.ι.app j

Next tactic:
apply colimit.ι_desc
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map (f ≫ fl ≫ n) x.snd = F.map (fl ≫ n) (F.map f x.snd)

Next tactic:
simp
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by simp
        _ = F.map (fl ≫ n) (F.map g y.2) := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map (fl ≫ n) (F.map f x.snd) = F.map (fl ≫ n) (F.map g y.snd)

Next tactic:
rw [h]
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by simp
        _ = F.map (fl ≫ n) (F.map g y.2) := by rw [h]
        _ = F.map ((g ≫ fl) ≫ n) y.2 := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map (fl ≫ n) (F.map g y.snd) = F.map ((g ≫ fl) ≫ n) y.snd

Next tactic:
simp
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by simp
        _ = F.map (fl ≫ n) (F.map g y.2) := by rw [h]
        _ = F.map ((g ≫ fl) ≫ n) y.2 := by simp
        _ = F.map ((f' ≫ gl) ≫ n) y.2 := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map ((g ≫ fl) ≫ n) y.snd = F.map ((f' ≫ gl) ≫ n) y.snd

Next tactic:
rw [hn]
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by simp
        _ = F.map (fl ≫ n) (F.map g y.2) := by rw [h]
        _ = F.map ((g ≫ fl) ≫ n) y.2 := by simp
        _ = F.map ((f' ≫ gl) ≫ n) y.2 := by rw [hn]
        _ = F.map (gl ≫ n) (F.map f' y.2) := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map ((f' ≫ gl) ≫ n) y.snd = F.map (gl ≫ n) (F.map f' y.snd)

Next tactic:
simp
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by simp
        _ = F.map (fl ≫ n) (F.map g y.2) := by rw [h]
        _ = F.map ((g ≫ fl) ≫ n) y.2 := by simp
        _ = F.map ((f' ≫ gl) ≫ n) y.2 := by rw [hn]
        _ = F.map (gl ≫ n) (F.map f' y.2) := by simp
        _ = F.map (gl ≫ n) (F.map g' z.2) := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map (gl ≫ n) (F.map f' y.snd) = F.map (gl ≫ n) (F.map g' z.snd)

Next tactic:
rw [h']
protected theorem rel_equiv : _root_.Equivalence (FilteredColimit.Rel.{v, u} F) where
  refl x := ⟨x.1, 𝟙 x.1, 𝟙 x.1, rfl⟩
  symm := fun ⟨k, f, g, h⟩ => ⟨k, g, f, h.symm⟩
  trans {x y z} := fun ⟨k, f, g, h⟩ ⟨k', f', g', h'⟩ =>
    let ⟨l, fl, gl, _⟩ := IsFilteredOrEmpty.cocone_objs k k'
    let ⟨m, n, hn⟩ := IsFilteredOrEmpty.cocone_maps (g ≫ fl) (f' ≫ gl)
    ⟨m, f ≫ fl ≫ n, g' ≫ gl ≫ n,
      calc
        F.map (f ≫ fl ≫ n) x.2 = F.map (fl ≫ n) (F.map f x.2) := by simp
        _ = F.map (fl ≫ n) (F.map g y.2) := by rw [h]
        _ = F.map ((g ≫ fl) ≫ n) y.2 := by simp
        _ = F.map ((f' ≫ gl) ≫ n) y.2 := by rw [hn]
        _ = F.map (gl ≫ n) (F.map f' y.2) := by simp
        _ = F.map (gl ≫ n) (F.map g' z.2) := by rw [h']
        _ = F.map (g' ≫ gl ≫ n) z.2 := by 

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
x y z : (j : J) × F.obj j
x✝¹ : FilteredColimit.Rel F x y
x✝ : FilteredColimit.Rel F y z
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
k' : J
f' : y.fst ⟶ k'
g' : z.fst ⟶ k'
h' : F.map f' y.snd = F.map g' z.snd
l : J
fl : k ⟶ l
gl : k' ⟶ l
h✝ : True
m : J
n : l ⟶ m
hn : (g ≫ fl) ≫ n = (f' ≫ gl) ≫ n
⊢ F.map (gl ≫ n) (F.map g' z.snd) = F.map (g' ≫ gl ≫ n) z.snd

Next tactic:
simp
protected theorem rel_eq_eqvGen_quot_rel :
    FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel.{v, u} F) := by
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
⊢ FilteredColimit.Rel F = EqvGen (Quot.Rel F)

Next tactic:
ext ⟨j, x⟩ ⟨j', y⟩
protected theorem rel_eq_eqvGen_quot_rel :
    FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel.{v, u} F) := by
  ext ⟨j, x⟩ ⟨j', y⟩
  

Proof state:
case h.mk.h.mk.a
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
j : J
x : F.obj j
j' : J
y : F.obj j'
⊢ FilteredColimit.Rel F { fst := j, snd := x } { fst := j', snd := y } ↔
    EqvGen (Quot.Rel F) { fst := j, snd := x } { fst := j', snd := y }

Next tactic:
constructor
protected theorem rel_eq_eqvGen_quot_rel :
    FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel.{v, u} F) := by
  ext ⟨j, x⟩ ⟨j', y⟩
  constructor
  · 

Proof state:
case h.mk.h.mk.a.mp
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
j : J
x : F.obj j
j' : J
y : F.obj j'
⊢ FilteredColimit.Rel F { fst := j, snd := x } { fst := j', snd := y } →
    EqvGen (Quot.Rel F) { fst := j, snd := x } { fst := j', snd := y }

Next tactic:
apply eqvGen_quot_rel_of_rel
protected theorem rel_eq_eqvGen_quot_rel :
    FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel.{v, u} F) := by
  ext ⟨j, x⟩ ⟨j', y⟩
  constructor
  · apply eqvGen_quot_rel_of_rel
  · 

Proof state:
case h.mk.h.mk.a.mpr
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
j : J
x : F.obj j
j' : J
y : F.obj j'
⊢ EqvGen (Quot.Rel F) { fst := j, snd := x } { fst := j', snd := y } →
    FilteredColimit.Rel F { fst := j, snd := x } { fst := j', snd := y }

Next tactic:
rw [← (FilteredColimit.rel_equiv F).eqvGen_iff]
protected theorem rel_eq_eqvGen_quot_rel :
    FilteredColimit.Rel.{v, u} F = EqvGen (Quot.Rel.{v, u} F) := by
  ext ⟨j, x⟩ ⟨j', y⟩
  constructor
  · apply eqvGen_quot_rel_of_rel
  · rw [← (FilteredColimit.rel_equiv F).eqvGen_iff]
    

Proof state:
case h.mk.h.mk.a.mpr
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
j : J
x : F.obj j
j' : J
y : F.obj j'
⊢ EqvGen (Quot.Rel F) { fst := j, snd := x } { fst := j', snd := y } →
    EqvGen (FilteredColimit.Rel F) { fst := j, snd := x } { fst := j', snd := y }

Next tactic:
exact EqvGen.mono (rel_of_quot_rel F)
theorem colimit_eq_iff_aux {i j : J} {xi : F.obj i} {xj : F.obj j} :
    (colimitCocone.{v, u} F).ι.app i xi = (colimitCocone.{v, u} F).ι.app j xj ↔
      FilteredColimit.Rel.{v, u} F ⟨i, xi⟩ ⟨j, xj⟩ := by
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
i j : J
xi : F.obj i
xj : F.obj j
⊢ (colimitCocone F).ι.app i xi = (colimitCocone F).ι.app j xj ↔
    FilteredColimit.Rel F { fst := i, snd := xi } { fst := j, snd := xj }

Next tactic:
change Quot.mk _ _ = Quot.mk _ _ ↔ _
theorem colimit_eq_iff_aux {i j : J} {xi : F.obj i} {xj : F.obj j} :
    (colimitCocone.{v, u} F).ι.app i xi = (colimitCocone.{v, u} F).ι.app j xj ↔
      FilteredColimit.Rel.{v, u} F ⟨i, xi⟩ ⟨j, xj⟩ := by
  change Quot.mk _ _ = Quot.mk _ _ ↔ _
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
i j : J
xi : F.obj i
xj : F.obj j
⊢ Quot.mk (Quot.Rel F) { fst := i, snd := xi } = Quot.mk (Quot.Rel F) { fst := j, snd := xj } ↔
    FilteredColimit.Rel F { fst := i, snd := xi } { fst := j, snd := xj }

Next tactic:
rw [Quot.eq, FilteredColimit.rel_eq_eqvGen_quot_rel]
theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj i} {xj : F.obj j} :
    t.ι.app i xi = t.ι.app j xj ↔ ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj := by
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
t : Cocone F
ht : IsColimit t
i j : J
xi : F.obj i
xj : F.obj j
⊢ t.ι.app i xi = t.ι.app j xj ↔ ∃ k f g, F.map f xi = F.map g xj

Next tactic:
let t' := colimitCocone.{v, u} F
theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj i} {xj : F.obj j} :
    t.ι.app i xi = t.ι.app j xj ↔ ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj := by
  let t' := colimitCocone.{v, u} F
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
t : Cocone F
ht : IsColimit t
i j : J
xi : F.obj i
xj : F.obj j
t' : Cocone F := colimitCocone F
⊢ t.ι.app i xi = t.ι.app j xj ↔ ∃ k f g, F.map f xi = F.map g xj

Next tactic:
let e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj i} {xj : F.obj j} :
    t.ι.app i xi = t.ι.app j xj ↔ ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj := by
  let t' := colimitCocone.{v, u} F
  let e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
t : Cocone F
ht : IsColimit t
i j : J
xi : F.obj i
xj : F.obj j
t' : Cocone F := colimitCocone F
e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
⊢ t.ι.app i xi = t.ι.app j xj ↔ ∃ k f g, F.map f xi = F.map g xj

Next tactic:
let e' : t'.pt ≅ t.pt := (Cocones.forget _).mapIso e
theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj i} {xj : F.obj j} :
    t.ι.app i xi = t.ι.app j xj ↔ ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj := by
  let t' := colimitCocone.{v, u} F
  let e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
  let e' : t'.pt ≅ t.pt := (Cocones.forget _).mapIso e
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
t : Cocone F
ht : IsColimit t
i j : J
xi : F.obj i
xj : F.obj j
t' : Cocone F := colimitCocone F
e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
e' : t'.pt ≅ t.pt := (Cocones.forget F).mapIso e
⊢ t.ι.app i xi = t.ι.app j xj ↔ ∃ k f g, F.map f xi = F.map g xj

Next tactic:
refine' Iff.trans _ (colimit_eq_iff_aux.{v, u} F)
theorem isColimit_eq_iff {t : Cocone F} (ht : IsColimit t) {i j : J} {xi : F.obj i} {xj : F.obj j} :
    t.ι.app i xi = t.ι.app j xj ↔ ∃ (k : _) (f : i ⟶ k) (g : j ⟶ k), F.map f xi = F.map g xj := by
  let t' := colimitCocone.{v, u} F
  let e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
  let e' : t'.pt ≅ t.pt := (Cocones.forget _).mapIso e
  refine' Iff.trans _ (colimit_eq_iff_aux.{v, u} F)
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
F : J ⥤ TypeMax
inst✝ : IsFilteredOrEmpty J
t : Cocone F
ht : IsColimit t
i j : J
xi : F.obj i
xj : F.obj j
t' : Cocone F := colimitCocone F
e : t' ≅ t := IsColimit.uniqueUpToIso (colimitCoconeIsColimit F) ht
e' : t'.pt ≅ t.pt := (Cocones.forget F).mapIso e
⊢ t.ι.app i xi = t.ι.app j xj ↔ (colimitCocone F).ι.app i xi = (colimitCocone F).ι.app j xj

Next tactic:
exact @Equiv.apply_eq_iff_eq _ _ e'.toEquiv ((colimitCocone.{v, u} F).ι.app i xi)
    ((colimitCocone.{v, u} F).ι.app j xj)
theorem Image.lift_fac (F' : MonoFactorisation f) : Image.lift F' ≫ F'.m = Image.ι f := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
α β : Type u
f : α ⟶ β
F' : MonoFactorisation f
⊢ lift F' ≫ F'.m = ι f

Next tactic:
funext x
theorem Image.lift_fac (F' : MonoFactorisation f) : Image.lift F' ≫ F'.m = Image.ι f := by
  funext x
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
α β : Type u
f : α ⟶ β
F' : MonoFactorisation f
x : Image f
⊢ (lift F' ≫ F'.m) x = ι f x

Next tactic:
change (F'.e ≫ F'.m) _ = _
theorem Image.lift_fac (F' : MonoFactorisation f) : Image.lift F' ≫ F'.m = Image.ι f := by
  funext x
  change (F'.e ≫ F'.m) _ = _
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
α β : Type u
f : α ⟶ β
F' : MonoFactorisation f
x : Image f
⊢ (F'.e ≫ F'.m) ↑(Classical.indefiniteDescription (fun x_1 => f x_1 = ↑x) (_ : ↑x ∈ Set.range f)) = ι f x

Next tactic:
rw [F'.fac, (Classical.indefiniteDescription _ x.2).2]
theorem Image.lift_fac (F' : MonoFactorisation f) : Image.lift F' ≫ F'.m = Image.ι f := by
  funext x
  change (F'.e ≫ F'.m) _ = _
  rw [F'.fac, (Classical.indefiniteDescription _ x.2).2]
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
α β : Type u
f : α ⟶ β
F' : MonoFactorisation f
x : Image f
⊢ ↑x = ι f x

Next tactic:
rfl
instance : HasImages (Type u) where
  has_image := by 

Proof state:
J : Type v
inst✝ : SmallCategory J
α β : Type u
f : α ⟶ β
⊢ ∀ {X Y : Type u} (f : X ⟶ Y), HasImage f

Next tactic:
infer_instance
instance : HasImageMaps (Type u) where
  has_image_map {f g} st :=
    HasImageMap.transport st (monoFactorisation f.hom) (isImage g.hom)
      (fun x => ⟨st.right x.1, ⟨st.left (Classical.choose x.2), by
        

Proof state:
J : Type v
inst✝ : SmallCategory J
α β : Type u
f✝ : α ⟶ β
f g : Arrow (Type u)
st : f ⟶ g
x : (monoFactorisation f.hom).I
⊢ Comma.hom g (CommaMorphism.left st (Classical.choose (_ : ↑x ∈ Set.range f.hom))) = CommaMorphism.right st ↑x

Next tactic:
have p := st.w
instance : HasImageMaps (Type u) where
  has_image_map {f g} st :=
    HasImageMap.transport st (monoFactorisation f.hom) (isImage g.hom)
      (fun x => ⟨st.right x.1, ⟨st.left (Classical.choose x.2), by
        have p := st.w
        

Proof state:
J : Type v
inst✝ : SmallCategory J
α β : Type u
f✝ : α ⟶ β
f g : Arrow (Type u)
st : f ⟶ g
x : (monoFactorisation f.hom).I
p : (𝟭 (Type u)).map st.left ≫ g.hom = f.hom ≫ (𝟭 (Type u)).map st.right
⊢ Comma.hom g (CommaMorphism.left st (Classical.choose (_ : ↑x ∈ Set.range f.hom))) = CommaMorphism.right st ↑x

Next tactic:
replace p := congr_fun p (Classical.choose x.2)