l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem isLimitEquivSections_symm_apply {c : Cone F} (t : IsLimit c)
    (x : F.sections) (j : J) :
    c.π.app j ((isLimitEquivSections t).symm x) = (x : ∀ j, F.obj j) j := by
  conv_rhs => 

Proof state:
J : Type v
inst✝ : Category.{u_1, v} J
F : J ⥤ Type u
c : Cone F
t : IsLimit c
x : ↑(Functor.sections F)
j : J
| ↑x j

Next tactic:
rw [← (isLimitEquivSections t).right_inv x]
/-- (internal implementation) the limit cone of a functor,
implemented as flat sections of a pi type
-/
@[simps]
noncomputable def limitCone (F : J ⥤ Type u) : Cone F where
  pt := Shrink F.sections
  π :=
    { app := fun j u => ((equivShrink F.sections).symm u).val j
      naturality := fun j j' f => by
        

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
j j' : J
f : j ⟶ j'
⊢ ((Functor.const J).obj (Shrink.{u, max u v} ↑(Functor.sections F))).map f ≫
      (fun j u => ↑((equivShrink ↑(Functor.sections F)).symm u) j) j' =
    (fun j u => ↑((equivShrink ↑(Functor.sections F)).symm u) j) j ≫ F.map f

Next tactic:
funext x
/-- (internal implementation) the limit cone of a functor,
implemented as flat sections of a pi type
-/
@[simps]
noncomputable def limitCone (F : J ⥤ Type u) : Cone F where
  pt := Shrink F.sections
  π :=
    { app := fun j u => ((equivShrink F.sections).symm u).val j
      naturality := fun j j' f => by
        funext x
        

Proof state:
case h
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
j j' : J
f : j ⟶ j'
x : ((Functor.const J).obj (Shrink.{u, max u v} ↑(Functor.sections F))).obj j
⊢ (((Functor.const J).obj (Shrink.{u, max u v} ↑(Functor.sections F))).map f ≫
        (fun j u => ↑((equivShrink ↑(Functor.sections F)).symm u) j) j')
      x =
    ((fun j u => ↑((equivShrink ↑(Functor.sections F)).symm u) j) j ≫ F.map f) x

Next tactic:
simp
@[ext]
lemma limitCone_pt_ext (F : J ⥤ Type u) {x y : (limitCone F).pt}
    (w : (equivShrink F.sections).symm x = (equivShrink F.sections).symm y) : x = y := by
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x y : (limitCone F).pt
w : (equivShrink ↑(Functor.sections F)).symm x = (equivShrink ↑(Functor.sections F)).symm y
⊢ x = y

Next tactic:
aesop
/-- (internal implementation) the fact that the proposed limit cone is the limit -/
@[simps]
noncomputable def limitConeIsLimit (F : J ⥤ Type u) : IsLimit (limitCone.{v, u} F) where
  lift s v := equivShrink F.sections
    { val := fun j => s.π.app j v
      property := fun f => congr_fun (Cone.w s f) _ }
  uniq := fun _ _ w => by
    

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x✝¹ : Cone F
x✝ : x✝¹.pt ⟶ (limitCone F).pt
w : ∀ (j : J), x✝ ≫ (limitCone F).π.app j = x✝¹.π.app j
⊢ x✝ =
    (fun s v =>
        (equivShrink ↑(Functor.sections F))
          { val := fun j => s.π.app j v,
            property := (_ : ∀ {j j' : J} (f : j ⟶ j'), (s.π.app j ≫ F.map f) v = s.π.app j' v) })
      x✝¹

Next tactic:
ext x j
/-- (internal implementation) the fact that the proposed limit cone is the limit -/
@[simps]
noncomputable def limitConeIsLimit (F : J ⥤ Type u) : IsLimit (limitCone.{v, u} F) where
  lift s v := equivShrink F.sections
    { val := fun j => s.π.app j v
      property := fun f => congr_fun (Cone.w s f) _ }
  uniq := fun _ _ w => by
    ext x j
    

Proof state:
case h.w.a.h
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x✝¹ : Cone F
x✝ : x✝¹.pt ⟶ (limitCone F).pt
w : ∀ (j : J), x✝ ≫ (limitCone F).π.app j = x✝¹.π.app j
x : x✝¹.pt
j : J
⊢ ↑((equivShrink ↑(Functor.sections F)).symm (x✝ x)) j =
    ↑((equivShrink ↑(Functor.sections F)).symm
          ((fun s v =>
              (equivShrink ↑(Functor.sections F))
                { val := fun j => s.π.app j v,
                  property := (_ : ∀ {j j' : J} (f : j ⟶ j'), (s.π.app j ≫ F.map f) v = s.π.app j' v) })
            x✝¹ x))
      j

Next tactic:
simpa using congr_fun (w j) x
/-- (internal implementation) the limit cone of a functor,
implemented as flat sections of a pi type
-/
@[simps]
noncomputable def limitCone (F : J ⥤ TypeMax.{v, u}) : Cone F where
  pt := F.sections
  π :=
    { app := fun j u => u.val j
      naturality := fun j j' f => by
        

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
f : j ⟶ j'
⊢ ((Functor.const J).obj ↑(Functor.sections F)).map f ≫ (fun j u => ↑u j) j' = (fun j u => ↑u j) j ≫ F.map f

Next tactic:
funext x
/-- (internal implementation) the limit cone of a functor,
implemented as flat sections of a pi type
-/
@[simps]
noncomputable def limitCone (F : J ⥤ TypeMax.{v, u}) : Cone F where
  pt := F.sections
  π :=
    { app := fun j u => u.val j
      naturality := fun j j' f => by
        funext x
        

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
f : j ⟶ j'
x : ((Functor.const J).obj ↑(Functor.sections F)).obj j
⊢ (((Functor.const J).obj ↑(Functor.sections F)).map f ≫ (fun j u => ↑u j) j') x = ((fun j u => ↑u j) j ≫ F.map f) x

Next tactic:
simp
/-- (internal implementation) the fact that the proposed limit cone is the limit -/
@[simps]
noncomputable def limitConeIsLimit (F : J ⥤ TypeMax.{v, u}) : IsLimit (limitCone.{v, u} F) where
  lift s v :=
    { val := fun j => s.π.app j v
      property := fun f => congr_fun (Cone.w s f) _ }
  uniq := fun _ _ w => by
    

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x✝¹ : Cone F
x✝ : x✝¹.pt ⟶ (limitCone F).pt
w : ∀ (j : J), x✝ ≫ (limitCone F).π.app j = x✝¹.π.app j
⊢ x✝ =
    (fun s v =>
        { val := fun j => s.π.app j v,
          property := (_ : ∀ {j j' : J} (f : j ⟶ j'), (s.π.app j ≫ F.map f) v = s.π.app j' v) })
      x✝¹

Next tactic:
funext x
/-- (internal implementation) the fact that the proposed limit cone is the limit -/
@[simps]
noncomputable def limitConeIsLimit (F : J ⥤ TypeMax.{v, u}) : IsLimit (limitCone.{v, u} F) where
  lift s v :=
    { val := fun j => s.π.app j v
      property := fun f => congr_fun (Cone.w s f) _ }
  uniq := fun _ _ w => by
    funext x
    

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x✝¹ : Cone F
x✝ : x✝¹.pt ⟶ (limitCone F).pt
w : ∀ (j : J), x✝ ≫ (limitCone F).π.app j = x✝¹.π.app j
x : x✝¹.pt
⊢ x✝ x =
    (fun s v =>
        { val := fun j => s.π.app j v,
          property := (_ : ∀ {j j' : J} (f : j ⟶ j'), (s.π.app j ≫ F.map f) v = s.π.app j' v) })
      x✝¹ x

Next tactic:
apply Subtype.ext
/-- (internal implementation) the fact that the proposed limit cone is the limit -/
@[simps]
noncomputable def limitConeIsLimit (F : J ⥤ TypeMax.{v, u}) : IsLimit (limitCone.{v, u} F) where
  lift s v :=
    { val := fun j => s.π.app j v
      property := fun f => congr_fun (Cone.w s f) _ }
  uniq := fun _ _ w => by
    funext x
    apply Subtype.ext
    

Proof state:
case h.a
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x✝¹ : Cone F
x✝ : x✝¹.pt ⟶ (limitCone F).pt
w : ∀ (j : J), x✝ ≫ (limitCone F).π.app j = x✝¹.π.app j
x : x✝¹.pt
⊢ ↑(x✝ x) =
    ↑((fun s v =>
          { val := fun j => s.π.app j v,
            property := (_ : ∀ {j j' : J} (f : j ⟶ j'), (s.π.app j ≫ F.map f) v = s.π.app j' v) })
        x✝¹ x)

Next tactic:
funext j
/-- (internal implementation) the fact that the proposed limit cone is the limit -/
@[simps]
noncomputable def limitConeIsLimit (F : J ⥤ TypeMax.{v, u}) : IsLimit (limitCone.{v, u} F) where
  lift s v :=
    { val := fun j => s.π.app j v
      property := fun f => congr_fun (Cone.w s f) _ }
  uniq := fun _ _ w => by
    funext x
    apply Subtype.ext
    funext j
    

Proof state:
case h.a.h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x✝¹ : Cone F
x✝ : x✝¹.pt ⟶ (limitCone F).pt
w : ∀ (j : J), x✝ ≫ (limitCone F).π.app j = x✝¹.π.app j
x : x✝¹.pt
j : J
⊢ ↑(x✝ x) j =
    ↑((fun s v =>
            { val := fun j => s.π.app j v,
              property := (_ : ∀ {j j' : J} (f : j ⟶ j'), (s.π.app j ≫ F.map f) v = s.π.app j' v) })
          x✝¹ x)
      j

Next tactic:
exact congr_fun (w j) x
@[simp]
theorem Limit.π_mk (F : J ⥤ Type u) (x : ∀ j, F.obj j)
    (h : ∀ (j j') (f : j ⟶ j'), F.map f (x j) = x j') (j) :
      limit.π F j (Limit.mk.{v, u} F x h) = x j := by
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x : (j : J) → F.obj j
h : ∀ (j j' : J) (f : j ⟶ j'), F.map f (x j) = x j'
j : J
⊢ limit.π F j (mk F x h) = x j

Next tactic:
dsimp [Limit.mk]
@[simp]
theorem Limit.π_mk (F : J ⥤ Type u) (x : ∀ j, F.obj j)
    (h : ∀ (j j') (f : j ⟶ j'), F.map f (x j) = x j') (j) :
      limit.π F j (Limit.mk.{v, u} F x h) = x j := by
  dsimp [Limit.mk]
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x : (j : J) → F.obj j
h : ∀ (j j' : J) (f : j ⟶ j'), F.map f (x j) = x j'
j : J
⊢ limit.π F j
      ((limitEquivSections F).symm { val := x, property := (_ : ∀ {j j' : J} (f : j ⟶ j'), F.map f (x j) = x j') }) =
    x j

Next tactic:
simp
@[ext]
theorem limit_ext (F : J ⥤ Type u) (x y : limit F)
    (w : ∀ j, limit.π F j x = limit.π F j y) : x = y := by
  

Proof state:
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x y : limit F
w : ∀ (j : J), limit.π F j x = limit.π F j y
⊢ x = y

Next tactic:
apply (limitEquivSections.{v, u} F).injective
@[ext]
theorem limit_ext (F : J ⥤ Type u) (x y : limit F)
    (w : ∀ j, limit.π F j x = limit.π F j y) : x = y := by
  apply (limitEquivSections.{v, u} F).injective
  

Proof state:
case a
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x y : limit F
w : ∀ (j : J), limit.π F j x = limit.π F j y
⊢ (limitEquivSections F) x = (limitEquivSections F) y

Next tactic:
ext j
@[ext]
theorem limit_ext (F : J ⥤ Type u) (x y : limit F)
    (w : ∀ j, limit.π F j x = limit.π F j y) : x = y := by
  apply (limitEquivSections.{v, u} F).injective
  ext j
  

Proof state:
case a.a.h
J : Type v
inst✝¹ : SmallCategory J
inst✝ : Small.{u, v} J
F : J ⥤ Type u
x y : limit F
w : ∀ (j : J), limit.π F j x = limit.π F j y
j : J
⊢ ↑((limitEquivSections F) x) j = ↑((limitEquivSections F) y) j

Next tactic:
simp [w j]
/-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/
def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where
  desc s :=
    Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by
      

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
s : Cocone F
x✝² x✝¹ : (j : J) × F.obj j
j : J
x : F.obj j
j' : J
x' : F.obj j'
x✝ : Quot.Rel F { fst := j, snd := x } { fst := j', snd := x' }
f : { fst := j, snd := x }.fst ⟶ { fst := j', snd := x' }.fst
hf : { fst := j', snd := x' }.snd = F.map f { fst := j, snd := x }.snd
⊢ (fun p => s.ι.app p.fst p.snd) { fst := j, snd := x } = (fun p => s.ι.app p.fst p.snd) { fst := j', snd := x' }

Next tactic:
dsimp at hf
/-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/
def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where
  desc s :=
    Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by
      dsimp at hf
      

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
s : Cocone F
x✝² x✝¹ : (j : J) × F.obj j
j : J
x : F.obj j
j' : J
x' : F.obj j'
x✝ : Quot.Rel F { fst := j, snd := x } { fst := j', snd := x' }
f : { fst := j, snd := x }.fst ⟶ { fst := j', snd := x' }.fst
hf : x' = F.map f x
⊢ (fun p => s.ι.app p.fst p.snd) { fst := j, snd := x } = (fun p => s.ι.app p.fst p.snd) { fst := j', snd := x' }

Next tactic:
rw [hf]
/-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/
def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where
  desc s :=
    Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by
      dsimp at hf
      rw [hf]
      

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
s : Cocone F
x✝² x✝¹ : (j : J) × F.obj j
j : J
x : F.obj j
j' : J
x' : F.obj j'
x✝ : Quot.Rel F { fst := j, snd := x } { fst := j', snd := x' }
f : { fst := j, snd := x }.fst ⟶ { fst := j', snd := x' }.fst
hf : x' = F.map f x
⊢ (fun p => s.ι.app p.fst p.snd) { fst := j, snd := x } = (fun p => s.ι.app p.fst p.snd) { fst := j', snd := F.map f x }

Next tactic:
exact (congr_fun (Cocone.w s f) x).symm
/-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/
def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where
  desc s :=
    Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by
      dsimp at hf
      rw [hf]
      exact (congr_fun (Cocone.w s f) x).symm
  uniq s m hm := by
    

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
s : Cocone F
m : (colimitCocone F).pt ⟶ s.pt
hm : ∀ (j : J), (colimitCocone F).ι.app j ≫ m = s.ι.app j
⊢ m =
    (fun s =>
        Quot.lift (fun p => s.ι.app p.fst p.snd)
          (_ :
            ∀ (x x_1 : (j : J) × F.obj j),
              Quot.Rel F x x_1 → (fun p => s.ι.app p.fst p.snd) x = (fun p => s.ι.app p.fst p.snd) x_1))
      s

Next tactic:
funext x
/-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/
def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where
  desc s :=
    Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by
      dsimp at hf
      rw [hf]
      exact (congr_fun (Cocone.w s f) x).symm
  uniq s m hm := by
    funext x
    

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
s : Cocone F
m : (colimitCocone F).pt ⟶ s.pt
hm : ∀ (j : J), (colimitCocone F).ι.app j ≫ m = s.ι.app j
x : (colimitCocone F).pt
⊢ m x =
    (fun s =>
        Quot.lift (fun p => s.ι.app p.fst p.snd)
          (_ :
            ∀ (x x_1 : (j : J) × F.obj j),
              Quot.Rel F x x_1 → (fun p => s.ι.app p.fst p.snd) x = (fun p => s.ι.app p.fst p.snd) x_1))
      s x

Next tactic:
induction' x using Quot.ind with x
/-- (internal implementation) the fact that the proposed colimit cocone is the colimit -/
def colimitCoconeIsColimit (F : J ⥤ TypeMax.{v, u}) : IsColimit (colimitCocone.{v, u} F) where
  desc s :=
    Quot.lift (fun p : Σj, F.obj j => s.ι.app p.1 p.2) fun ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩ => by
      dsimp at hf
      rw [hf]
      exact (congr_fun (Cocone.w s f) x).symm
  uniq s m hm := by
    funext x
    induction' x using Quot.ind with x
    

Proof state:
case h.mk
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
s : Cocone F
m : (colimitCocone F).pt ⟶ s.pt
hm : ∀ (j : J), (colimitCocone F).ι.app j ≫ m = s.ι.app j
x : (j : J) × F.obj j
⊢ m (Quot.mk (Quot.Rel F) x) =
    (fun s =>
        Quot.lift (fun p => s.ι.app p.fst p.snd)
          (_ :
            ∀ (x x_1 : (j : J) × F.obj j),
              Quot.Rel F x x_1 → (fun p => s.ι.app p.fst p.snd) x = (fun p => s.ι.app p.fst p.snd) x_1))
      s (Quot.mk (Quot.Rel F) x)

Next tactic:
exact congr_fun (hm x.1) x.2
@[simp]
theorem colimitEquivQuot_apply (F : J ⥤ TypeMax.{v, u}) (j : J) (x : F.obj j) :
    (colimitEquivQuot.{v, u} F) (colimit.ι F j x) = Quot.mk _ ⟨j, x⟩ := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j : J
x : F.obj j
⊢ (colimitEquivQuot F) (colimit.ι F j x) = Quot.mk (Quot.Rel F) { fst := j, snd := x }

Next tactic:
apply (colimitEquivQuot F).symm.injective
@[simp]
theorem colimitEquivQuot_apply (F : J ⥤ TypeMax.{v, u}) (j : J) (x : F.obj j) :
    (colimitEquivQuot.{v, u} F) (colimit.ι F j x) = Quot.mk _ ⟨j, x⟩ := by
  apply (colimitEquivQuot F).symm.injective
  

Proof state:
case a
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j : J
x : F.obj j
⊢ (colimitEquivQuot F).symm ((colimitEquivQuot F) (colimit.ι F j x)) =
    (colimitEquivQuot F).symm (Quot.mk (Quot.Rel F) { fst := j, snd := x })

Next tactic:
simp
theorem colimit_sound {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'} (f : j ⟶ j')
    (w : F.map f x = x') : colimit.ι F j x = colimit.ι F j' x' := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
x : F.obj j
x' : F.obj j'
f : j ⟶ j'
w : F.map f x = x'
⊢ colimit.ι F j x = colimit.ι F j' x'

Next tactic:
rw [← w, Colimit.w_apply.{v, u}]
theorem colimit_sound' {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'} {j'' : J}
    (f : j ⟶ j'') (f' : j' ⟶ j'') (w : F.map f x = F.map f' x') :
    colimit.ι F j x = colimit.ι F j' x' := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
x : F.obj j
x' : F.obj j'
j'' : J
f : j ⟶ j''
f' : j' ⟶ j''
w : F.map f x = F.map f' x'
⊢ colimit.ι F j x = colimit.ι F j' x'

Next tactic:
rw [← colimit.w _ f, ← colimit.w _ f']
theorem colimit_sound' {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'} {j'' : J}
    (f : j ⟶ j'') (f' : j' ⟶ j'') (w : F.map f x = F.map f' x') :
    colimit.ι F j x = colimit.ι F j' x' := by
  rw [← colimit.w _ f, ← colimit.w _ f']
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
x : F.obj j
x' : F.obj j'
j'' : J
f : j ⟶ j''
f' : j' ⟶ j''
w : F.map f x = F.map f' x'
⊢ (F.map f ≫ colimit.ι F j'') x = (F.map f' ≫ colimit.ι F j'') x'

Next tactic:
rw [types_comp_apply, types_comp_apply, w]
theorem colimit_eq {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'}
    (w : colimit.ι F j x = colimit.ι F j' x') :
      EqvGen (Quot.Rel.{v, u} F) ⟨j, x⟩ ⟨j', x'⟩ := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
x : F.obj j
x' : F.obj j'
w : colimit.ι F j x = colimit.ι F j' x'
⊢ EqvGen (Quot.Rel F) { fst := j, snd := x } { fst := j', snd := x' }

Next tactic:
apply Quot.eq.1
theorem colimit_eq {F : J ⥤ TypeMax.{v, u}} {j j' : J} {x : F.obj j} {x' : F.obj j'}
    (w : colimit.ι F j x = colimit.ι F j' x') :
      EqvGen (Quot.Rel.{v, u} F) ⟨j, x⟩ ⟨j', x'⟩ := by
  apply Quot.eq.1
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
j j' : J
x : F.obj j
x' : F.obj j'
w : colimit.ι F j x = colimit.ι F j' x'
⊢ Quot.mk (Quot.Rel F) { fst := j, snd := x } = Quot.mk (Quot.Rel F) { fst := j', snd := x' }

Next tactic:
simpa using congr_arg (colimitEquivQuot.{v, u} F) w
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
⊢ ∃ j y, t.ι.app j y = x

Next tactic:
suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    simpa using congr_arg ULift.down this
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
this : (fun x => { down := ∃ j y, t.ι.app j y = x }) = fun x => { down := True }
⊢ ∃ j y, t.ι.app j y = x

Next tactic:
have := congr_fun this x
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
this✝ : (fun x => { down := ∃ j y, t.ι.app j y = x }) = fun x => { down := True }
this : { down := ∃ j y, t.ι.app j y = x } = { down := True }
⊢ ∃ j y, t.ι.app j y = x

Next tactic:
simpa using congr_arg ULift.down this
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    simpa using congr_arg ULift.down this
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
⊢ (fun x => { down := ∃ j y, t.ι.app j y = x }) = fun x => { down := True }

Next tactic:
refine' h.hom_ext _
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    simpa using congr_arg ULift.down this
  refine' h.hom_ext _
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
⊢ ∀ (j : J), (t.ι.app j ≫ fun x => { down := ∃ j y, t.ι.app j y = x }) = t.ι.app j ≫ fun x => { down := True }

Next tactic:
intro j
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    simpa using congr_arg ULift.down this
  refine' h.hom_ext _
  intro j
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
j : J
⊢ (t.ι.app j ≫ fun x => { down := ∃ j y, t.ι.app j y = x }) = t.ι.app j ≫ fun x => { down := True }

Next tactic:
funext y
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    simpa using congr_arg ULift.down this
  refine' h.hom_ext _
  intro j
  funext y
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
j : J
y : F.obj j
⊢ (t.ι.app j ≫ fun x => { down := ∃ j y, t.ι.app j y = x }) y = (t.ι.app j ≫ fun x => { down := True }) y

Next tactic:
simp only [Functor.const_obj_obj, types_comp_apply, ULift.up_inj, eq_iff_iff, iff_true]
theorem jointly_surjective (F : J ⥤ TypeMax.{v, u}) {t : Cocone F} (h : IsColimit t) (x : t.pt) :
    ∃ j y, t.ι.app j y = x := by
  suffices (fun x : t.pt => ULift.up (∃ j y, t.ι.app j y = x)) = fun _ => ULift.up.{max v u} True by
    have := congr_fun this x
    simpa using congr_arg ULift.down this
  refine' h.hom_ext _
  intro j
  funext y
  simp only [Functor.const_obj_obj, types_comp_apply, ULift.up_inj, eq_iff_iff, iff_true]
  

Proof state:
case h
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
t : Cocone F
h : IsColimit t
x : t.pt
j : J
y : F.obj j
⊢ ∃ j_1 y_1, t.ι.app j_1 y_1 = t.ι.app j y

Next tactic:
exact ⟨j, y, rfl⟩
/-- A variant of `jointly_surjective` for `x : colimit F`. -/
theorem jointly_surjective' {F : J ⥤ TypeMax.{v, u}} (x : colimit F) :
    ∃ j y, colimit.ι F j y = x := by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x : colimit F
⊢ ∃ j y, colimit.ι F j y = x

Next tactic:
exact jointly_surjective.{v, u} F (colimit.isColimit F) x
theorem rel_of_quot_rel (x y : Σ j, F.obj j) :
    Quot.Rel.{v, u} F x y → FilteredColimit.Rel.{v, u} F x y :=
  fun ⟨f, h⟩ => ⟨y.1, f, 𝟙 y.1, by 

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x y : (j : J) × F.obj j
x✝ : Quot.Rel F x y
f : x.fst ⟶ y.fst
h : y.snd = F.map f x.snd
⊢ F.map f x.snd = F.map (𝟙 y.fst) y.snd

Next tactic:
rw [← h, FunctorToTypes.map_id_apply]
theorem eqvGen_quot_rel_of_rel (x y : Σ j, F.obj j) :
    FilteredColimit.Rel.{v, u} F x y → EqvGen (Quot.Rel.{v, u} F) x y := fun ⟨k, f, g, h⟩ => by
  

Proof state:
J : Type v
inst✝ : SmallCategory J
F : J ⥤ TypeMax
x y : (j : J) × F.obj j
x✝ : FilteredColimit.Rel F x y
k : J
f : x.fst ⟶ k
g : y.fst ⟶ k
h : F.map f x.snd = F.map g y.snd
⊢ EqvGen (Quot.Rel F) x y

Next tactic:
refine' EqvGen.trans _ ⟨k, F.map f x.2⟩ _ _ _