Theorem: CategoryTheory.Presheaf.isLimit_iff_isSheafFor
File: Mathlib/CategoryTheory/Sites/Sheaf.lean

tactic: dsimp [IsSheafFor]
state_before: C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ Nonempty (IsLimit (P.mapCone (Cocone.op (cocone S.arrows)))) ↔ ∀ (E : Aᵒᵖ), IsSheafFor (P ⋙ coyoneda.obj E) S.arrows

tactic: simp_rw [compatible_iff_sieveCompatible]
state_before: C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ Nonempty (IsLimit (P.mapCone (Cocone.op (cocone S.arrows)))) ↔
    ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), Compatible x → ∃! t, IsAmalgamation x t

tactic: rw [((Cone.isLimitEquivIsTerminal _).trans (isTerminalEquivUnique _ _)).nonempty_congr]
state_before: C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ Nonempty (IsLimit (P.mapCone (Cocone.op (cocone S.arrows)))) ↔
    ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t

tactic: rw [Classical.nonempty_pi]
state_before: C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ Nonempty ((X_1 : Cone (Functor.op (diagram S.arrows) ⋙ P)) → Unique (X_1 ⟶ P.mapCone (Cocone.op (cocone S.arrows)))) ↔
    ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t

tactic: constructor
state_before: C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ (∀ (i : Cone (Functor.op (diagram S.arrows) ⋙ P)), Nonempty (Unique (i ⟶ P.mapCone (Cocone.op (cocone S.arrows))))) ↔
    ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t

tactic: intro hu E x hx
state_before: case mp
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ (∀ (i : Cone (Functor.op (diagram S.arrows) ⋙ P)), Nonempty (Unique (i ⟶ P.mapCone (Cocone.op (cocone S.arrows))))) →
    ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t

tactic: specialize hu hx.cone
state_before: case mp
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : SieveCompatible x✝
hu : ∀ (i : Cone (Functor.op (diagram S.arrows) ⋙ P)), Nonempty (Unique (i ⟶ P.mapCone (Cocone.op (cocone S.arrows))))
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ ∃! t, IsAmalgamation x t

tactic: erw [(homEquivAmalgamation hx).uniqueCongr.nonempty_congr] at hu
state_before: case mp
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : SieveCompatible x✝
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
hu : Nonempty (Unique (SieveCompatible.cone hx ⟶ P.mapCone (Cocone.op (cocone S.arrows))))
⊢ ∃! t, IsAmalgamation x t

tactic: exact (unique_subtype_iff_exists_unique _).1 hu
state_before: case mp
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : SieveCompatible x✝
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
hu : Nonempty (Unique { t // IsAmalgamation x t })
⊢ ∃! t, IsAmalgamation x t

tactic: rintro h ⟨E, π⟩
state_before: case mpr
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : SieveCompatible x
⊢ (∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t) →
    ∀ (i : Cone (Functor.op (diagram S.arrows) ⋙ P)), Nonempty (Unique (i ⟶ P.mapCone (Cocone.op (cocone S.arrows))))

tactic: let eqv := conesEquivSieveCompatibleFamily P S (op E)
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : SieveCompatible x
h : ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t
E : A
π : (Functor.const (FullSubcategory fun f => S.arrows f.hom)ᵒᵖ).obj E ⟶ Functor.op (diagram S.arrows) ⋙ P
⊢ Nonempty (Unique ({ pt := E, π := π } ⟶ P.mapCone (Cocone.op (cocone S.arrows))))

tactic: rw [← eqv.left_inv π]
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : SieveCompatible x
h : ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t
E : A
π : (Functor.const (FullSubcategory fun f => S.arrows f.hom)ᵒᵖ).obj E ⟶ Functor.op (diagram S.arrows) ⋙ P
eqv : (Functor.cones (Functor.op (diagram S.arrows) ⋙ P)).obj E.op ≃ { x // SieveCompatible x } :=
  conesEquivSieveCompatibleFamily P S E.op
⊢ Nonempty (Unique ({ pt := E, π := π } ⟶ P.mapCone (Cocone.op (cocone S.arrows))))

tactic: erw [(homEquivAmalgamation (eqv π).2).uniqueCongr.nonempty_congr]
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : SieveCompatible x
h : ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t
E : A
π : (Functor.const (FullSubcategory fun f => S.arrows f.hom)ᵒᵖ).obj E ⟶ Functor.op (diagram S.arrows) ⋙ P
eqv : (Functor.cones (Functor.op (diagram S.arrows) ⋙ P)).obj E.op ≃ { x // SieveCompatible x } :=
  conesEquivSieveCompatibleFamily P S E.op
⊢ Nonempty (Unique ({ pt := E, π := Equiv.invFun eqv (Equiv.toFun eqv π) } ⟶ P.mapCone (Cocone.op (cocone S.arrows))))

tactic: rw [unique_subtype_iff_exists_unique]
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : SieveCompatible x
h : ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t
E : A
π : (Functor.const (FullSubcategory fun f => S.arrows f.hom)ᵒᵖ).obj E ⟶ Functor.op (diagram S.arrows) ⋙ P
eqv : (Functor.cones (Functor.op (diagram S.arrows) ⋙ P)).obj E.op ≃ { x // SieveCompatible x } :=
  conesEquivSieveCompatibleFamily P S E.op
⊢ Nonempty (Unique { t // IsAmalgamation (↑(↑eqv π)) t })

tactic: exact h _ _ (eqv π).2
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category C
A : Type u₂
inst✝ : Category A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : SieveCompatible x
h : ∀ (E : Aᵒᵖ) (x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows), SieveCompatible x → ∃! t, IsAmalgamation x t
E : A
π : (Functor.const (FullSubcategory fun f => S.arrows f.hom)ᵒᵖ).obj E ⟶ Functor.op (diagram S.arrows) ⋙ P
eqv : (Functor.cones (Functor.op (diagram S.arrows) ⋙ P)).obj E.op ≃ { x // SieveCompatible x } :=
  conesEquivSieveCompatibleFamily P S E.op
⊢ ∃! a, IsAmalgamation (↑(↑eqv π)) a