Theorem: CategoryTheory.Sieve.forallYonedaIsSheaf_iff_colimit
File: Mathlib/CategoryTheory/Sites/SheafOfTypes.lean

tactic: constructor
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
⊢ (∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows) ↔ Nonempty (IsColimit S.arrows.cocone)
state_after: case mp
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
⊢ (∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows) → Nonempty (IsColimit S.arrows.cocone)

case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
⊢ Nonempty (IsColimit S.arrows.cocone) → ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows

tactic: intro H
state_before: case mp
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
⊢ (∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows) → Nonempty (IsColimit S.arrows.cocone)
state_after: case mp
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
⊢ Nonempty (IsColimit S.arrows.cocone)

tactic: refine Nonempty.intro ?_
state_before: case mp
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
⊢ Nonempty (IsColimit S.arrows.cocone)
state_after: case mp
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
⊢ IsColimit S.arrows.cocone

tactic: exact
{ desc := fun s => H s.pt (yonedaFamilyOfElements_fromCocone S.arrows s)
    (yonedaFamily_fromCocone_compatible S s) |>.choose
  fac := by
    intro s f
    replace H := H s.pt (yonedaFamilyOfElements_fromCocone S.arrows s)
      (yonedaFamily_fromCocone_compatible S s)
    have ht := H.choose_spec.1 f.obj.hom f.property
    aesop_cat
  uniq := by
    intro s Fs HFs
    replace H := H s.pt (yonedaFamilyOfElements_fromCocone S.arrows s)
      (yonedaFamily_fromCocone_compatible S s)
    apply H.choose_spec.2 Fs
    exact fun _ f hf => HFs ⟨Over.mk f, hf⟩ }
state_before: case mp
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
⊢ IsColimit S.arrows.cocone
state_after: no goals

tactic: intro s f
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
⊢ ∀ (s : Cocone S.arrows.diagram) (j : S.arrows.category),
    S.arrows.cocone.ι.app j ≫ (fun s => Exists.choose ⋯) s = s.ι.app j
state_after: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
f : S.arrows.category
⊢ S.arrows.cocone.ι.app f ≫ (fun s => Exists.choose ⋯) s = s.ι.app f

tactic: replace H := H s.pt (yonedaFamilyOfElements_fromCocone S.arrows s)
  (yonedaFamily_fromCocone_compatible S s)
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
f : S.arrows.category
⊢ S.arrows.cocone.ι.app f ≫ (fun s => Exists.choose ⋯) s = s.ι.app f
state_after: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
f : S.arrows.category
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
⊢ S.arrows.cocone.ι.app f ≫ (fun s => Exists.choose ⋯) s = s.ι.app f

tactic: have ht := H.choose_spec.1 f.obj.hom f.property
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
f : S.arrows.category
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
⊢ S.arrows.cocone.ι.app f ≫ (fun s => Exists.choose ⋯) s = s.ι.app f
state_after: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
f : S.arrows.category
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
ht : (yoneda.obj s.pt).map f.obj.hom.op (Exists.choose H) = S.arrows.yonedaFamilyOfElements_fromCocone s f.obj.hom ⋯
⊢ S.arrows.cocone.ι.app f ≫ (fun s => Exists.choose ⋯) s = s.ι.app f

tactic: aesop_cat
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
f : S.arrows.category
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
ht : (yoneda.obj s.pt).map f.obj.hom.op (Exists.choose H) = S.arrows.yonedaFamilyOfElements_fromCocone s f.obj.hom ⋯
⊢ S.arrows.cocone.ι.app f ≫ (fun s => Exists.choose ⋯) s = s.ι.app f
state_after: no goals

tactic: intro s Fs HFs
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
⊢ ∀ (s : Cocone S.arrows.diagram) (m : S.arrows.cocone.pt ⟶ s.pt),
    (∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ m = s.ι.app j) → m = (fun s => Exists.choose ⋯) s
state_after: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
Fs : S.arrows.cocone.pt ⟶ s.pt
HFs : ∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ Fs = s.ι.app j
⊢ Fs = (fun s => Exists.choose ⋯) s

tactic: replace H := H s.pt (yonedaFamilyOfElements_fromCocone S.arrows s)
  (yonedaFamily_fromCocone_compatible S s)
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
Fs : S.arrows.cocone.pt ⟶ s.pt
HFs : ∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ Fs = s.ι.app j
⊢ Fs = (fun s => Exists.choose ⋯) s
state_after: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
Fs : S.arrows.cocone.pt ⟶ s.pt
HFs : ∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ Fs = s.ι.app j
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
⊢ Fs = (fun s => Exists.choose ⋯) s

tactic: apply H.choose_spec.2 Fs
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
Fs : S.arrows.cocone.pt ⟶ s.pt
HFs : ∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ Fs = s.ι.app j
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
⊢ Fs = (fun s => Exists.choose ⋯) s
state_after: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
Fs : S.arrows.cocone.pt ⟶ s.pt
HFs : ∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ Fs = s.ι.app j
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
⊢ (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation Fs

tactic: exact fun _ f hf => HFs ⟨Over.mk f, hf⟩
state_before: C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H✝ : ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
s : Cocone S.arrows.diagram
Fs : S.arrows.cocone.pt ⟶ s.pt
HFs : ∀ (j : S.arrows.category), S.arrows.cocone.ι.app j ≫ Fs = s.ι.app j
H : ∃! t, (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation t
⊢ (S.arrows.yonedaFamilyOfElements_fromCocone s).IsAmalgamation Fs
state_after: no goals

tactic: intro H W x hx
state_before: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
⊢ Nonempty (IsColimit S.arrows.cocone) → ∀ (W : C), IsSheafFor (yoneda.obj W) S.arrows
state_after: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : Nonempty (IsColimit S.arrows.cocone)
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
⊢ ∃! t, x.IsAmalgamation t

tactic: replace H := Classical.choice H
state_before: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
H : Nonempty (IsColimit S.arrows.cocone)
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
⊢ ∃! t, x.IsAmalgamation t
state_after: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
⊢ ∃! t, x.IsAmalgamation t

tactic: let s := compatibleYonedaFamily_toCocone S W x hx
state_before: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
⊢ ∃! t, x.IsAmalgamation t
state_after: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ ∃! t, x.IsAmalgamation t

tactic: use H.desc s
state_before: case mpr
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ ∃! t, x.IsAmalgamation t
state_after: case h
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ (fun t => x.IsAmalgamation t) (H.desc s) ∧
    ∀ (y : (yoneda.obj W).obj { unop := X }), (fun t => x.IsAmalgamation t) y → y = H.desc s

tactic: constructor
state_before: case h
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ (fun t => x.IsAmalgamation t) (H.desc s) ∧
    ∀ (y : (yoneda.obj W).obj { unop := X }), (fun t => x.IsAmalgamation t) y → y = H.desc s
state_after: case h.left
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ (fun t => x.IsAmalgamation t) (H.desc s)

case h.right
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ ∀ (y : (yoneda.obj W).obj { unop := X }), (fun t => x.IsAmalgamation t) y → y = H.desc s

tactic: exact fun _ f hf => (H.fac s) ⟨Over.mk f, hf⟩
state_before: case h.left
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ (fun t => x.IsAmalgamation t) (H.desc s)
state_after: no goals

tactic: exact fun g hg => H.uniq s g (fun ⟨⟨f, _, hom⟩, hf⟩ => hg hom hf)
state_before: case h.right
C : Type u
inst✝ : Category.{v, u} C
X : C
S : Sieve X
W : C
x : FamilyOfElements (yoneda.obj W) S.arrows
hx : x.Compatible
H : IsColimit S.arrows.cocone
s : Cocone S.arrows.diagram := S.arrows.compatibleYonedaFamily_toCocone W x hx
⊢ ∀ (y : (yoneda.obj W).obj { unop := X }), (fun t => x.IsAmalgamation t) y → y = H.desc s
state_after: no goals