Theorem: CategoryTheory.Limits.Types.isColimit_iff_bijective_desc
File: Mathlib/CategoryTheory/Limits/Types.lean

tactic: refine ⟨?_, ?_⟩
state_before: J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
⊢ Nonempty (IsColimit c) ↔ Function.Bijective (Quot.desc c)
state_after: case refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
⊢ Nonempty (IsColimit c) → Function.Bijective (Quot.desc c)

case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
⊢ Function.Bijective (Quot.desc c) → Nonempty (IsColimit c)

tactic: refine fun ⟨hc⟩ => ⟨fun x y h => ?_, fun x => ?_⟩
state_before: case refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
⊢ Nonempty (IsColimit c) → Function.Bijective (Quot.desc c)
state_after: case refine_1.refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
⊢ x = y

case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
⊢ ∃ a, Quot.desc c a = x

tactic: let f : Quot F → ULift.{u} Bool := fun z => ULift.up (x = z)
state_before: case refine_1.refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
⊢ x = y
state_after: case refine_1.refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
f : Quot F → ULift.{u, 0} Bool := fun z => { down := decide (x = z) }
⊢ x = y

tactic: suffices f x = f y by simpa [f] using this
state_before: case refine_1.refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
f : Quot F → ULift.{u, 0} Bool := fun z => { down := decide (x = z) }
⊢ x = y
state_after: case refine_1.refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
f : Quot F → ULift.{u, 0} Bool := fun z => { down := decide (x = z) }
⊢ f x = f y

tactic: rw [← Quot.desc_toCocone_desc c f hc x, h, Quot.desc_toCocone_desc]
state_before: case refine_1.refine_1
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
f : Quot F → ULift.{u, 0} Bool := fun z => { down := decide (x = z) }
⊢ f x = f y
state_after: no goals

tactic: simpa [f] using this
state_before: J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x y : Quot F
h : Quot.desc c x = Quot.desc c y
f : Quot F → ULift.{u, 0} Bool := fun z => { down := decide (x = z) }
this : f x = f y
⊢ x = y
state_after: no goals

tactic: let f₁ : c.pt ⟶ ULift.{u} Bool := fun _ => ULift.up true
state_before: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
⊢ ∃ a, Quot.desc c a = x
state_after: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
⊢ ∃ a, Quot.desc c a = x

tactic: let f₂ : c.pt ⟶ ULift.{u} Bool := fun x => ULift.up (∃ a, Quot.desc c a = x)
state_before: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
⊢ ∃ a, Quot.desc c a = x
state_after: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
⊢ ∃ a, Quot.desc c a = x

tactic: suffices f₁ = f₂ by simpa [f₁, f₂] using congrFun this x
state_before: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
⊢ ∃ a, Quot.desc c a = x
state_after: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
⊢ f₁ = f₂

tactic: refine hc.hom_ext fun j => funext fun x => ?_
state_before: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
⊢ f₁ = f₂
state_after: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝¹ : Nonempty (IsColimit c)
hc : IsColimit c
x✝ : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
j : J
x : F.obj j
⊢ (c.ι.app j ≫ f₁) x = (c.ι.app j ≫ f₂) x

tactic: simpa [f₁, f₂] using ⟨Quot.ι F j x, by simp⟩
state_before: case refine_1.refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝¹ : Nonempty (IsColimit c)
hc : IsColimit c
x✝ : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
j : J
x : F.obj j
⊢ (c.ι.app j ≫ f₁) x = (c.ι.app j ≫ f₂) x
state_after: no goals

tactic: simpa [f₁, f₂] using congrFun this x
state_before: J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝ : Nonempty (IsColimit c)
hc : IsColimit c
x : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
this : f₁ = f₂
⊢ ∃ a, Quot.desc c a = x
state_after: no goals

tactic: simp
state_before: J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
x✝¹ : Nonempty (IsColimit c)
hc : IsColimit c
x✝ : c.pt
f₁ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := true }
f₂ : c.pt ⟶ ULift.{u, 0} Bool := fun x => { down := decide (∃ a, Quot.desc c a = x) }
j : J
x : F.obj j
⊢ Quot.desc c (Quot.ι F j x) = c.ι.app j x
state_after: no goals

tactic: refine fun h => ⟨?_⟩
state_before: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
⊢ Function.Bijective (Quot.desc c) → Nonempty (IsColimit c)
state_after: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h : Function.Bijective (Quot.desc c)
⊢ IsColimit c

tactic: let e := Equiv.ofBijective _ h
state_before: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h : Function.Bijective (Quot.desc c)
⊢ IsColimit c
state_after: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h
⊢ IsColimit c

tactic: have h : ∀ j x, e.symm (c.ι.app j x) = Quot.ι F j x :=
  fun j x => e.injective (Equiv.ofBijective_apply_symm_apply _ _ _)
state_before: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h
⊢ IsColimit c
state_after: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
⊢ IsColimit c

tactic: exact
  { desc := fun s => Quot.desc s ∘ e.symm
    fac := fun s j => by
      ext x
      simp [h]
    uniq := fun s m hm => by
      ext x
      obtain ⟨x, rfl⟩ := e.surjective x
      obtain ⟨j, x, rfl⟩ := Quot.jointly_surjective x
      rw [← h, Equiv.apply_symm_apply]
      simpa [h] using congrFun (hm j) x }
state_before: case refine_2
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
⊢ IsColimit c
state_after: no goals

tactic: ext x
state_before: J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
j : J
⊢ c.ι.app j ≫ (fun s => Quot.desc s ∘ ⇑e.symm) s = s.ι.app j
state_after: case h
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
j : J
x : F.obj j
⊢ (c.ι.app j ≫ (fun s => Quot.desc s ∘ ⇑e.symm) s) x = s.ι.app j x

tactic: simp [h]
state_before: case h
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
j : J
x : F.obj j
⊢ (c.ι.app j ≫ (fun s => Quot.desc s ∘ ⇑e.symm) s) x = s.ι.app j x
state_after: no goals

tactic: ext x
state_before: J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
⊢ m = (fun s => Quot.desc s ∘ ⇑e.symm) s
state_after: case h
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
x : c.pt
⊢ m x = (fun s => Quot.desc s ∘ ⇑e.symm) s x

tactic: obtain ⟨x, rfl⟩ := e.surjective x
state_before: case h
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
x : c.pt
⊢ m x = (fun s => Quot.desc s ∘ ⇑e.symm) s x
state_after: case h.intro
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
x : Quot F
⊢ m (e x) = (fun s => Quot.desc s ∘ ⇑e.symm) s (e x)

tactic: obtain ⟨j, x, rfl⟩ := Quot.jointly_surjective x
state_before: case h.intro
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
x : Quot F
⊢ m (e x) = (fun s => Quot.desc s ∘ ⇑e.symm) s (e x)
state_after: case h.intro.intro.intro
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
j : J
x : F.obj j
⊢ m (e (Quot.ι F j x)) = (fun s => Quot.desc s ∘ ⇑e.symm) s (e (Quot.ι F j x))

tactic: rw [← h, Equiv.apply_symm_apply]
state_before: case h.intro.intro.intro
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
j : J
x : F.obj j
⊢ m (e (Quot.ι F j x)) = (fun s => Quot.desc s ∘ ⇑e.symm) s (e (Quot.ι F j x))
state_after: case h.intro.intro.intro
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
j : J
x : F.obj j
⊢ m (c.ι.app j x) = (fun s => Quot.desc s ∘ ⇑e.symm) s (c.ι.app j x)

tactic: simpa [h] using congrFun (hm j) x
state_before: case h.intro.intro.intro
J : Type v
inst✝ : Category.{w, v} J
F : J ⥤ Type u
c : Cocone F
h✝ : Function.Bijective (Quot.desc c)
e : Quot F ≃ c.pt := Equiv.ofBijective (Quot.desc c) h✝
h : ∀ (j : J) (x : F.obj j), e.symm (c.ι.app j x) = Quot.ι F j x
s : Cocone F
m : c.pt ⟶ s.pt
hm : ∀ (j : J), c.ι.app j ≫ m = s.ι.app j
j : J
x : F.obj j
⊢ m (c.ι.app j x) = (fun s => Quot.desc s ∘ ⇑e.symm) s (c.ι.app j x)
state_after: no goals