Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 7bb1081

Browse files
committed
feat(category_theory): turn a split mono with cokernel into a biproduct (#13184)
1 parent 2693ab5 commit 7bb1081

File tree

4 files changed

+155
-20
lines changed

4 files changed

+155
-20
lines changed

src/category_theory/limits/shapes/biproducts.lean

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/-
22
Copyright (c) 2019 Scott Morrison. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Scott Morrison
4+
Authors: Scott Morrison, Jakob von Raumer
55
-/
66
import algebra.group.ext
77
import category_theory.limits.shapes.finite_products
@@ -1539,6 +1539,106 @@ lemma biprod.map_eq [has_binary_biproducts C] {W X Y Z : C} {f : W ⟶ Y} {g : X
15391539
biprod.map f g = biprod.fst ≫ f ≫ biprod.inl + biprod.snd ≫ g ≫ biprod.inr :=
15401540
by apply biprod.hom_ext; apply biprod.hom_ext'; simp
15411541

1542+
/--
1543+
Every split mono `f` with a cokernel induces a binary bicone with `f` as its `inl` and
1544+
the cokernel map as its `snd`.
1545+
We will show in `is_bilimit_binary_bicone_of_split_mono_of_cokernel` that this binary bicone is in
1546+
fact already a biproduct. -/
1547+
@[simps]
1548+
def binary_bicone_of_split_mono_of_cokernel {X Y : C} {f : X ⟶ Y} [split_mono f]
1549+
{c : cokernel_cofork f} (i : is_colimit c) : binary_bicone X c.X :=
1550+
{ X := Y,
1551+
fst := retraction f,
1552+
snd := c.π,
1553+
inl := f,
1554+
inr :=
1555+
let c' : cokernel_cofork (𝟙 Y - (𝟙 Y - retraction f ≫ f)) :=
1556+
cokernel_cofork.of_π (cofork.π c) (by simp) in
1557+
let i' : is_colimit c' := is_cokernel_epi_comp i (retraction f) (by simp) in
1558+
let i'' := is_colimit_cofork_of_cokernel_cofork i' in
1559+
(split_epi_of_idempotent_of_is_colimit_cofork C (by simp) i'').section_,
1560+
inl_fst' := by simp,
1561+
inl_snd' := by simp,
1562+
inr_fst' :=
1563+
begin
1564+
dsimp only,
1565+
rw [split_epi_of_idempotent_of_is_colimit_cofork_section_,
1566+
is_colimit_cofork_of_cokernel_cofork_desc, is_cokernel_epi_comp_desc],
1567+
dsimp only [cokernel_cofork_of_cofork_of_π],
1568+
letI := epi_of_is_colimit_parallel_pair i,
1569+
apply zero_of_epi_comp c.π,
1570+
simp only [sub_comp, category.comp_id, category.assoc, split_mono.id, is_colimit.fac_assoc,
1571+
cofork.of_π_ι_app, category.id_comp, cofork.π_of_π],
1572+
apply sub_eq_zero_of_eq,
1573+
apply category.id_comp
1574+
end,
1575+
inr_snd' := by apply split_epi.id }
1576+
1577+
/-- The bicone constructed in `binary_bicone_of_split_mono_of_cokernel` is a bilimit.
1578+
This is a version of the splitting lemma that holds in all preadditive categories. -/
1579+
def is_bilimit_binary_bicone_of_split_mono_of_cokernel {X Y : C} {f : X ⟶ Y} [split_mono f]
1580+
{c : cokernel_cofork f} (i : is_colimit c) :
1581+
(binary_bicone_of_split_mono_of_cokernel i).is_bilimit :=
1582+
is_binary_bilimit_of_total _
1583+
begin
1584+
simp only [binary_bicone_of_split_mono_of_cokernel_fst,
1585+
binary_bicone_of_split_mono_of_cokernel_inr, binary_bicone_of_split_mono_of_cokernel_snd,
1586+
split_epi_of_idempotent_of_is_colimit_cofork_section_],
1587+
dsimp only [binary_bicone_of_split_mono_of_cokernel_X],
1588+
rw [is_colimit_cofork_of_cokernel_cofork_desc, is_cokernel_epi_comp_desc],
1589+
simp only [cofork.is_colimit.π_desc_of_π, cokernel_cofork_of_cofork_π,
1590+
cofork.π_of_π, binary_bicone_of_split_mono_of_cokernel_inl, add_sub_cancel'_right],
1591+
end
1592+
1593+
/--
1594+
Every split epi `f` with a kernel induces a binary bicone with `f` as its `snd` and
1595+
the kernel map as its `inl`.
1596+
We will show in `binary_bicone_of_split_mono_of_cokernel` that this binary bicone is in fact
1597+
already a biproduct. -/
1598+
@[simps]
1599+
def binary_bicone_of_split_epi_of_kernel {X Y : C} {f : X ⟶ Y} [split_epi f]
1600+
{c : kernel_fork f} (i : is_limit c) : binary_bicone c.X Y :=
1601+
{ X := X,
1602+
fst :=
1603+
let c' : kernel_fork (𝟙 X - (𝟙 X - f ≫ section_ f)) :=
1604+
kernel_fork.of_ι (fork.ι c) (by simp) in
1605+
let i' : is_limit c' := is_kernel_comp_mono i (section_ f) (by simp) in
1606+
let i'' := is_limit_fork_of_kernel_fork i' in
1607+
(split_mono_of_idempotent_of_is_limit_fork C (by simp) i'').retraction,
1608+
snd := f,
1609+
inl := c.ι,
1610+
inr := section_ f,
1611+
inl_fst' := by apply split_mono.id,
1612+
inl_snd' := by simp,
1613+
inr_fst' :=
1614+
begin
1615+
dsimp only,
1616+
rw [split_mono_of_idempotent_of_is_limit_fork_retraction,
1617+
is_limit_fork_of_kernel_fork_lift, is_kernel_comp_mono_lift],
1618+
dsimp only [kernel_fork_of_fork_ι],
1619+
letI := mono_of_is_limit_parallel_pair i,
1620+
apply zero_of_comp_mono c.ι,
1621+
simp only [comp_sub, category.comp_id, category.assoc, sub_self, fork.ι_eq_app_zero,
1622+
fork.is_limit.lift_of_ι_ι, fork.of_ι_π_app, split_epi.id_assoc]
1623+
end,
1624+
inr_snd' := by simp }
1625+
1626+
/-- The bicone constructed in `binary_bicone_of_split_epi_of_kernel` is a bilimit.
1627+
This is a version of the splitting lemma that holds in all preadditive categories. -/
1628+
def is_bilimit_binary_bicone_of_split_epi_of_kernel {X Y : C} {f : X ⟶ Y} [split_epi f]
1629+
{c : kernel_fork f} (i : is_limit c) :
1630+
(binary_bicone_of_split_epi_of_kernel i).is_bilimit :=
1631+
is_binary_bilimit_of_total _
1632+
begin
1633+
simp only [binary_bicone_of_split_epi_of_kernel_fst, binary_bicone_of_split_epi_of_kernel_inl,
1634+
binary_bicone_of_split_epi_of_kernel_inr, binary_bicone_of_split_epi_of_kernel_snd,
1635+
split_mono_of_idempotent_of_is_limit_fork_retraction],
1636+
dsimp only [binary_bicone_of_split_epi_of_kernel_X],
1637+
rw [is_limit_fork_of_kernel_fork_lift, is_kernel_comp_mono_lift],
1638+
simp only [fork.ι_eq_app_zero, kernel_fork.condition, comp_zero, zero_comp, eq_self_iff_true,
1639+
fork.is_limit.lift_of_ι_ι, kernel_fork_of_fork_ι, fork.of_ι_π_app, sub_add_cancel]
1640+
end
1641+
15421642
end
15431643

15441644
section

src/category_theory/limits/shapes/equalizers.lean

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ fork.is_limit.mk t
359359

360360
/-- This is a slightly more convenient method to verify that a cofork is a colimit cocone. It
361361
only asks for a proof of facts that carry any mathematical content -/
362+
@[simps]
362363
def cofork.is_colimit.mk (t : cofork f g)
363364
(desc : Π (s : cofork f g), t.X ⟶ s.X)
364365
(fac : ∀ (s : cofork f g), cofork.π t ≫ desc s = cofork.π s)
@@ -940,19 +941,20 @@ lemma has_equalizer_comp_mono [has_equalizer f g] {Z : C} (h : Y ⟶ Z) [mono h]
940941
⟨⟨{ cone := _, is_limit := is_equalizer_comp_mono (limit.is_limit _) h }⟩⟩
941942

942943
/-- An equalizer of an idempotent morphism and the identity is split mono. -/
944+
@[simps]
943945
def split_mono_of_idempotent_of_is_limit_fork {X : C} {f : X ⟶ X} (hf : f ≫ f = f)
944-
{c : fork f (𝟙 X)} (i : is_limit c) : split_mono c.ι :=
946+
{c : fork (𝟙 X) f} (i : is_limit c) : split_mono c.ι :=
945947
{ retraction := i.lift (fork.of_ι f (by simp [hf])),
946948
id' :=
947949
begin
948950
letI := mono_of_is_limit_parallel_pair i,
949-
rw [← cancel_mono_id c.ι, category.assoc, fork.is_limit.lift_of_ι_ι, c.condition],
951+
rw [←cancel_mono_id c.ι, category.assoc, fork.is_limit.lift_of_ι_ι, c.condition],
950952
exact category.comp_id c.ι
951953
end }
952954

953955
/-- The equalizer of an idempotent morphism and the identity is split mono. -/
954956
def split_mono_of_idempotent_equalizer {X : C} {f : X ⟶ X} (hf : f ≫ f = f)
955-
[has_equalizer f (𝟙 X)] : split_mono (equalizer.ι f (𝟙 X)) :=
957+
[has_equalizer (𝟙 X) f] : split_mono (equalizer.ι (𝟙 X) f) :=
956958
split_mono_of_idempotent_of_is_limit_fork _ hf (limit.is_limit _)
957959

958960
section
@@ -990,12 +992,12 @@ def split_epi_of_coequalizer {X Y : C} {f : X ⟶ Y} {s : Y ⟶ X} (hs : f ≫ s
990992

991993
variables {C f g}
992994

993-
/-- The cofork obtained by precomposing a coequalizer cofork with an epimorphism is
995+
/-- The cofork obtained by precomposing a coequalizer cofork with an epimorphism is
994996
a coequalizer. -/
995997
def is_coequalizer_epi_comp {c : cofork f g} (i : is_colimit c) {W : C} (h : W ⟶ X) [hm : epi h] :
996998
is_colimit (cofork.of_π c.π (by simp) : cofork (h ≫ f) (h ≫ g)) :=
997999
cofork.is_colimit.mk' _ $ λ s,
998-
let s' : cofork f g := cofork.of_π s.π
1000+
let s' : cofork f g := cofork.of_π s.π
9991001
(by apply hm.left_cancellation; simp_rw [←category.assoc, s.condition]) in
10001002
let l := cofork.is_colimit.desc' i s'.π s'.condition in
10011003
⟨l.1, l.2,
@@ -1008,19 +1010,20 @@ lemma has_coequalizer_epi_comp [has_coequalizer f g] {W : C} (h : W ⟶ X) [hm :
10081010
variables (C f g)
10091011

10101012
/-- A coequalizer of an idempotent morphism and the identity is split epi. -/
1013+
@[simps]
10111014
def split_epi_of_idempotent_of_is_colimit_cofork {X : C} {f : X ⟶ X} (hf : f ≫ f = f)
1012-
{c : cofork f (𝟙 X)} (i : is_colimit c) : split_epi c.π :=
1015+
{c : cofork (𝟙 X) f} (i : is_colimit c) : split_epi c.π :=
10131016
{ section_ := i.desc (cofork.of_π f (by simp [hf])),
10141017
id' :=
10151018
begin
10161019
letI := epi_of_is_colimit_parallel_pair i,
1017-
rw [← cancel_epi_id c.π, ← category.assoc, cofork.is_colimit.π_desc_of_π, c.condition],
1020+
rw [← cancel_epi_id c.π, ← category.assoc, cofork.is_colimit.π_desc_of_π, c.condition],
10181021
exact category.id_comp _,
10191022
end }
10201023

10211024
/-- The coequalizer of an idempotent morphism and the identity is split epi. -/
10221025
def split_epi_of_idempotent_coequalizer {X : C} {f : X ⟶ X} (hf : f ≫ f = f)
1023-
[has_coequalizer f (𝟙 X)] : split_epi (coequalizer.π f (𝟙 X)) :=
1026+
[has_coequalizer (𝟙 X) f] : split_epi (coequalizer.π (𝟙 X) f) :=
10241027
split_epi_of_idempotent_of_is_colimit_cofork _ hf (colimit.is_colimit _)
10251028

10261029
end category_theory.limits

src/category_theory/limits/shapes/kernels.lean

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,19 @@ def is_limit.of_ι {W : C} (g : W ⟶ X) (eq : g ≫ f = 0)
136136
is_limit_aux _ (λ s, lift s.ι s.condition) (λ s, fac s.ι s.condition) (λ s, uniq s.ι s.condition)
137137

138138
/-- Every kernel of `f` induces a kernel of `f ≫ g` if `g` is mono. -/
139-
def is_kernel_comp_mono {c : kernel_fork f} (i : is_limit c) {Z} (g : Y ⟶ Z) [hg : mono g] :
140-
is_limit (kernel_fork.of_ι c.ι (by simp) : kernel_fork (f ≫ g)) :=
139+
def is_kernel_comp_mono {c : kernel_fork f} (i : is_limit c) {Z} (g : Y ⟶ Z) [hg : mono g]
140+
{h : X ⟶ Z} (hh : h = f ≫ g) :
141+
is_limit (kernel_fork.of_ι c.ι (by simp [hh]) : kernel_fork h) :=
141142
fork.is_limit.mk' _ $ λ s,
142-
let s' : kernel_fork f := fork.of_ι s.ι (by apply hg.right_cancellation; simp [s.condition]) in
143+
let s' : kernel_fork f := fork.of_ι s.ι (by rw [←cancel_mono g]; simp [←hh, s.condition]) in
143144
let l := kernel_fork.is_limit.lift' i s'.ι s'.condition in
144145
⟨l.1, l.2, λ m hm, by apply fork.is_limit.hom_ext i; rw fork.ι_of_ι at hm; rw hm; exact l.2.symm⟩
145146

147+
lemma is_kernel_comp_mono_lift {c : kernel_fork f} (i : is_limit c) {Z} (g : Y ⟶ Z) [hg : mono g]
148+
{h : X ⟶ Z} (hh : h = f ≫ g) (s : kernel_fork h) :
149+
(is_kernel_comp_mono i g hh).lift s
150+
= i.lift (fork.of_ι s.ι (by { rw [←cancel_mono g, category.assoc, ←hh], simp })) := rfl
151+
146152
end
147153

148154
section
@@ -283,7 +289,7 @@ lemma kernel_not_iso_of_nonzero (w : f ≠ 0) : (is_iso (kernel.ι f)) → false
283289

284290
instance has_kernel_comp_mono {X Y Z : C} (f : X ⟶ Y) [has_kernel f] (g : Y ⟶ Z) [mono g] :
285291
has_kernel (f ≫ g) :=
286-
⟨⟨{ cone := _, is_limit := is_kernel_comp_mono (limit.is_limit _) g }⟩⟩
292+
⟨⟨{ cone := _, is_limit := is_kernel_comp_mono (limit.is_limit _) g rfl }⟩⟩
287293

288294
/--
289295
When `g` is a monomorphism, the kernel of `f ≫ g` is isomorphic to the kernel of `f`.
@@ -452,15 +458,22 @@ def is_colimit.of_π {Z : C} (g : Y ⟶ Z) (eq : f ≫ g = 0)
452458
is_colimit_aux _ (λ s, desc s.π s.condition) (λ s, fac s.π s.condition) (λ s, uniq s.π s.condition)
453459

454460
/-- Every cokernel of `f` induces a cokernel of `g ≫ f` if `g` is epi. -/
455-
def is_cokernel_epi_comp {c : cokernel_cofork f} (i : is_colimit c) {W} (g : W ⟶ X) [hg : epi g] :
456-
is_colimit (cokernel_cofork.of_π c.π (by simp) : cokernel_cofork (g ≫ f)) :=
461+
def is_cokernel_epi_comp {c : cokernel_cofork f} (i : is_colimit c) {W} (g : W ⟶ X) [hg : epi g]
462+
{h : W ⟶ Y} (hh : h = g ≫ f) :
463+
is_colimit (cokernel_cofork.of_π c.π (by rw [hh]; simp) : cokernel_cofork h) :=
457464
cofork.is_colimit.mk' _ $ λ s,
458465
let s' : cokernel_cofork f := cofork.of_π s.π
459-
(by apply hg.left_cancellation; simp [←category.assoc, s.condition]) in
466+
(by { apply hg.left_cancellation, rw [←category.assoc, ←hh, s.condition], simp }) in
460467
let l := cokernel_cofork.is_colimit.desc' i s'.π s'.condition in
461468
⟨l.1, l.2,
462469
λ m hm, by apply cofork.is_colimit.hom_ext i; rw cofork.π_of_π at hm; rw hm; exact l.2.symm⟩
463470

471+
@[simp]
472+
lemma is_cokernel_epi_comp_desc {c : cokernel_cofork f} (i : is_colimit c) {W}
473+
(g : W ⟶ X) [hg : epi g] {h : W ⟶ Y} (hh : h = g ≫ f) (s : cokernel_cofork h) :
474+
(is_cokernel_epi_comp i g hh).desc s
475+
= i.desc (cofork.of_π s.π (by { rw [←cancel_epi g, ←category.assoc, ←hh], simp })) := rfl
476+
464477
end
465478

466479
section
@@ -625,14 +638,13 @@ def cokernel_comp_is_iso {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [has_cokernel f
625638

626639
instance has_cokernel_epi_comp {X Y : C} (f : X ⟶ Y) [has_cokernel f] {W} (g : W ⟶ X) [epi g] :
627640
has_cokernel (g ≫ f) :=
628-
⟨⟨{ cocone := _, is_colimit := is_cokernel_epi_comp (colimit.is_colimit _) g }⟩⟩
641+
⟨⟨{ cocone := _, is_colimit := is_cokernel_epi_comp (colimit.is_colimit _) g rfl }⟩⟩
629642

630643
/--
631644
When `f` is an epimorphism, the cokernel of `f ≫ g` is isomorphic to the cokernel of `g`.
632645
-/
633646
@[simps]
634-
def cokernel_epi_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z)
635-
[epi f] [has_cokernel g] :
647+
def cokernel_epi_comp {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) [epi f] [has_cokernel g] :
636648
cokernel (f ≫ g) ≅ cokernel g :=
637649
{ hom := cokernel.desc _ (cokernel.π g) (by simp),
638650
inv := cokernel.desc _ (cokernel.π (f ≫ g)) (by { rw [←cancel_epi f, ←category.assoc], simp, }), }

src/category_theory/preadditive/default.lean

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/-
22
Copyright (c) 2020 Markus Himmel. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Markus Himmel
4+
Authors: Markus Himmel, Jakob von Raumer
55
-/
66
import algebra.big_operators.basic
77
import algebra.hom.group
@@ -233,13 +233,22 @@ fork.of_ι c.ι $ by rw [← sub_eq_zero, ← comp_sub, c.condition]
233233
def kernel_fork_of_fork (c : fork f g) : kernel_fork (f - g) :=
234234
fork.of_ι c.ι $ by rw [comp_sub, comp_zero, sub_eq_zero, c.condition]
235235

236+
@[simp] lemma kernel_fork_of_fork_ι (c : fork f g) : (kernel_fork_of_fork c).ι = c.ι := rfl
237+
238+
@[simp] lemma kernel_fork_of_fork_of_ι {P : C} (ι : P ⟶ X) (w : ι ≫ f = ι ≫ g) :
239+
(kernel_fork_of_fork (fork.of_ι ι w)) = kernel_fork.of_ι ι (by simp [w]) := rfl
240+
236241
/-- A kernel of `f - g` is an equalizer of `f` and `g`. -/
237242
def is_limit_fork_of_kernel_fork {c : kernel_fork (f - g)} (i : is_limit c) :
238243
is_limit (fork_of_kernel_fork c) :=
239244
fork.is_limit.mk' _ $ λ s,
240245
⟨i.lift (kernel_fork_of_fork s), i.fac _ _,
241246
λ m h, by { apply fork.is_limit.hom_ext i, rw [i.fac], exact h }⟩
242247

248+
@[simp]
249+
lemma is_limit_fork_of_kernel_fork_lift {c : kernel_fork (f - g)} (i : is_limit c) (s : fork f g) :
250+
(is_limit_fork_of_kernel_fork i).lift s = i.lift (kernel_fork_of_fork s) := rfl
251+
243252
/-- An equalizer of `f` and `g` is a kernel of `f - g`. -/
244253
def is_limit_kernel_fork_of_fork {c : fork f g} (i : is_limit c) :
245254
is_limit (kernel_fork_of_fork c) :=
@@ -269,13 +278,24 @@ cofork.of_π c.π $ by rw [← sub_eq_zero, ← sub_comp, c.condition]
269278
def cokernel_cofork_of_cofork (c : cofork f g) : cokernel_cofork (f - g) :=
270279
cofork.of_π c.π $ by rw [sub_comp, zero_comp, sub_eq_zero, c.condition]
271280

281+
@[simp] lemma cokernel_cofork_of_cofork_π (c : cofork f g) :
282+
(cokernel_cofork_of_cofork c).π = c.π := rfl
283+
284+
@[simp] lemma cokernel_cofork_of_cofork_of_π {P : C} (π : Y ⟶ P) (w : f ≫ π = g ≫ π) :
285+
(cokernel_cofork_of_cofork (cofork.of_π π w)) = cokernel_cofork.of_π π (by simp [w]) := rfl
286+
272287
/-- A cokernel of `f - g` is a coequalizer of `f` and `g`. -/
273288
def is_colimit_cofork_of_cokernel_cofork {c : cokernel_cofork (f - g)} (i : is_colimit c) :
274289
is_colimit (cofork_of_cokernel_cofork c) :=
275290
cofork.is_colimit.mk' _ $ λ s,
276291
⟨i.desc (cokernel_cofork_of_cofork s), i.fac _ _,
277292
λ m h, by { apply cofork.is_colimit.hom_ext i, rw [i.fac], exact h }⟩
278293

294+
@[simp]
295+
lemma is_colimit_cofork_of_cokernel_cofork_desc {c : cokernel_cofork (f - g)}
296+
(i : is_colimit c) (s : cofork f g) :
297+
(is_colimit_cofork_of_cokernel_cofork i).desc s = i.desc (cokernel_cofork_of_cofork s) := rfl
298+
279299
/-- A coequalizer of `f` and `g` is a cokernel of `f - g`. -/
280300
def is_colimit_cokernel_cofork_of_cofork {c : cofork f g} (i : is_colimit c) :
281301
is_colimit (cokernel_cofork_of_cofork c) :=

0 commit comments

Comments
 (0)