Skip to content

Commit 95ba50f

Browse files
kim-emint-y1Scott Morrisonmattrobball
committed
feat: port/CategoryTheory.Abelian.Homology (#3882)
Co-authored-by: int-y1 <jason_yuen2007@hotmail.com> Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au> Co-authored-by: Matthew Ballard <matt@mrb.email>
1 parent 956490f commit 95ba50f

File tree

2 files changed

+382
-0
lines changed

2 files changed

+382
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ import Mathlib.CategoryTheory.Abelian.DiagramLemmas.Four
427427
import Mathlib.CategoryTheory.Abelian.Exact
428428
import Mathlib.CategoryTheory.Abelian.FunctorCategory
429429
import Mathlib.CategoryTheory.Abelian.Generator
430+
import Mathlib.CategoryTheory.Abelian.Homology
430431
import Mathlib.CategoryTheory.Abelian.Images
431432
import Mathlib.CategoryTheory.Abelian.NonPreadditive
432433
import Mathlib.CategoryTheory.Abelian.Opposite
Lines changed: 381 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,381 @@
1+
/-
2+
Copyright (c) 2022 Adam Topaz. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Adam Topaz, Amelia Livingston
5+
6+
! This file was ported from Lean 3 source module category_theory.abelian.homology
7+
! leanprover-community/mathlib commit 956af7c76589f444f2e1313911bad16366ea476d
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Algebra.Homology.Additive
12+
import Mathlib.CategoryTheory.Abelian.Pseudoelements
13+
import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Kernels
14+
import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Images
15+
import Mathlib.Tactic.RSuffices
16+
import Mathlib.Tactic.FailIfNoProgress
17+
18+
/-!
19+
20+
The object `homology f g w`, where `w : f ≫ g = 0`, can be identified with either a
21+
cokernel or a kernel. The isomorphism with a cokernel is `homologyIsoCokernelLift`, which
22+
was obtained elsewhere. In the case of an abelian category, this file shows the isomorphism
23+
with a kernel as well.
24+
25+
We use these isomorphisms to obtain the analogous api for `homology`:
26+
- `homology.ι` is the map from `homology f g w` into the cokernel of `f`.
27+
- `homology.π'` is the map from `kernel g` to `homology f g w`.
28+
- `homology.desc'` constructs a morphism from `homology f g w`, when it is viewed as a cokernel.
29+
- `homology.lift` constructs a morphism to `homology f g w`, when it is viewed as a kernel.
30+
- Various small lemmas are proved as well, mimicking the API for (co)kernels.
31+
With these definitions and lemmas, the isomorphisms between homology and a (co)kernel need not
32+
be used directly.
33+
-/
34+
35+
36+
open CategoryTheory.Limits
37+
38+
open CategoryTheory
39+
40+
noncomputable section
41+
42+
universe v u
43+
44+
variable {A : Type u} [Category.{v} A] [Abelian A]
45+
46+
variable {X Y Z : A} (f : X ⟶ Y) (g : Y ⟶ Z) (w : f ≫ g = 0)
47+
48+
namespace CategoryTheory.Abelian
49+
50+
/-- The cokernel of `kernel.lift g f w`. This is isomorphic to `homology f g w`.
51+
See `homologyIsoCokernelLift`. -/
52+
abbrev homologyC : A :=
53+
cokernel (kernel.lift g f w)
54+
#align category_theory.abelian.homology_c CategoryTheory.Abelian.homologyC
55+
56+
/-- The kernel of `cokernel.desc f g w`. This is isomorphic to `homology f g w`.
57+
See `homologyIsoKernelDesc`. -/
58+
abbrev homologyK : A :=
59+
kernel (cokernel.desc f g w)
60+
#align category_theory.abelian.homology_k CategoryTheory.Abelian.homologyK
61+
62+
/-- The canonical map from `homologyC` to `homologyK`.
63+
This is an isomorphism, and it is used in obtaining the API for `homology f g w`
64+
in the bottom of this file. -/
65+
abbrev homologyCToK : homologyC f g w ⟶ homologyK f g w :=
66+
cokernel.desc _ (kernel.lift _ (kernel.ι _ ≫ cokernel.π _) (by simp))
67+
(by
68+
apply Limits.equalizer.hom_ext
69+
simp)
70+
#align category_theory.abelian.homology_c_to_k CategoryTheory.Abelian.homologyCToK
71+
72+
attribute [local instance] Pseudoelement.homToFun Pseudoelement.hasZero
73+
74+
instance : Mono (homologyCToK f g w) := by
75+
apply Pseudoelement.mono_of_zero_of_map_zero
76+
intro a ha
77+
obtain ⟨a, rfl⟩ := Pseudoelement.pseudo_surjective_of_epi (cokernel.π (kernel.lift g f w)) a
78+
apply_fun kernel.ι (cokernel.desc f g w) at ha
79+
simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι,
80+
Pseudoelement.apply_zero] at ha
81+
simp only [Pseudoelement.comp_apply] at ha
82+
obtain ⟨b, hb⟩ : ∃ b, f b = _ := (Pseudoelement.pseudo_exact_of_exact (exact_cokernel f)).2 _ ha
83+
rsuffices ⟨c, rfl⟩ : ∃ c, kernel.lift g f w c = a
84+
· simp [← Pseudoelement.comp_apply]
85+
use b
86+
apply_fun kernel.ι g
87+
swap; · apply Pseudoelement.pseudo_injective_of_mono
88+
simpa [← Pseudoelement.comp_apply]
89+
90+
instance : Epi (homologyCToK f g w) := by
91+
apply Pseudoelement.epi_of_pseudo_surjective
92+
intro a
93+
let b := kernel.ι (cokernel.desc f g w) a
94+
obtain ⟨c, hc⟩ : ∃ c, cokernel.π f c = b
95+
apply Pseudoelement.pseudo_surjective_of_epi (cokernel.π f)
96+
have : g c = 0 := by
97+
rw [show g = cokernel.π f ≫ cokernel.desc f g w by simp, Pseudoelement.comp_apply, hc]
98+
simp [← Pseudoelement.comp_apply]
99+
obtain ⟨d, hd⟩ : ∃ d, kernel.ι g d = c := by
100+
apply (Pseudoelement.pseudo_exact_of_exact exact_kernel_ι).2 _ this
101+
use cokernel.π (kernel.lift g f w) d
102+
apply_fun kernel.ι (cokernel.desc f g w)
103+
swap
104+
· apply Pseudoelement.pseudo_injective_of_mono
105+
simp only [← Pseudoelement.comp_apply, cokernel.π_desc, kernel.lift_ι]
106+
simp only [Pseudoelement.comp_apply, hd, hc]
107+
108+
instance (w : f ≫ g = 0) : IsIso (homologyCToK f g w) :=
109+
isIso_of_mono_of_epi _
110+
111+
end CategoryTheory.Abelian
112+
113+
/-- The homology associated to `f` and `g` is isomorphic to a kernel. -/
114+
def homologyIsoKernelDesc : homology f g w ≅ kernel (cokernel.desc f g w) :=
115+
homologyIsoCokernelLift _ _ _ ≪≫ asIso (CategoryTheory.Abelian.homologyCToK _ _ _)
116+
#align homology_iso_kernel_desc homologyIsoKernelDesc
117+
118+
namespace homology
119+
120+
-- `homology.π` is taken
121+
/-- The canonical map from the kernel of `g` to the homology of `f` and `g`. -/
122+
def π' : kernel g ⟶ homology f g w :=
123+
cokernel.π _ ≫ (homologyIsoCokernelLift _ _ _).inv
124+
#align homology.π' homology.π'
125+
126+
/-- The canonical map from the homology of `f` and `g` to the cokernel of `f`. -/
127+
def ι : homology f g w ⟶ cokernel f :=
128+
(homologyIsoKernelDesc _ _ _).hom ≫ kernel.ι _
129+
#align homology.ι homology.ι
130+
131+
/-- Obtain a morphism from the homology, given a morphism from the kernel. -/
132+
def desc' {W : A} (e : kernel g ⟶ W) (he : kernel.lift g f w ≫ e = 0) : homology f g w ⟶ W :=
133+
(homologyIsoCokernelLift _ _ _).hom ≫ cokernel.desc _ e he
134+
#align homology.desc' homology.desc'
135+
136+
/-- Obtain a moprhism to the homology, given a morphism to the kernel. -/
137+
def lift {W : A} (e : W ⟶ cokernel f) (he : e ≫ cokernel.desc f g w = 0) : W ⟶ homology f g w :=
138+
kernel.lift _ e he ≫ (homologyIsoKernelDesc _ _ _).inv
139+
#align homology.lift homology.lift
140+
141+
@[reassoc (attr := simp)]
142+
theorem π'_desc' {W : A} (e : kernel g ⟶ W) (he : kernel.lift g f w ≫ e = 0) :
143+
π' f g w ≫ desc' f g w e he = e := by
144+
dsimp [π', desc']
145+
simp
146+
#align homology.π'_desc' homology.π'_desc'
147+
148+
@[reassoc (attr := simp)]
149+
theorem lift_ι {W : A} (e : W ⟶ cokernel f) (he : e ≫ cokernel.desc f g w = 0) :
150+
lift f g w e he ≫ ι _ _ _ = e := by
151+
dsimp [ι, lift]
152+
simp
153+
#align homology.lift_ι homology.lift_ι
154+
155+
@[reassoc (attr := simp)]
156+
theorem condition_π' : kernel.lift g f w ≫ π' f g w = 0 := by
157+
dsimp [π']
158+
simp
159+
#align homology.condition_π' homology.condition_π'
160+
161+
@[reassoc (attr := simp)]
162+
theorem condition_ι : ι f g w ≫ cokernel.desc f g w = 0 := by
163+
dsimp [ι]
164+
simp
165+
#align homology.condition_ι homology.condition_ι
166+
167+
@[ext]
168+
theorem hom_from_ext {W : A} (a b : homology f g w ⟶ W)
169+
(h : π' f g w ≫ a = π' f g w ≫ b) : a = b := by
170+
dsimp [π'] at h
171+
apply_fun fun e => (homologyIsoCokernelLift f g w).inv ≫ e
172+
swap
173+
· intro i j hh
174+
apply_fun fun e => (homologyIsoCokernelLift f g w).hom ≫ e at hh
175+
simpa using hh
176+
simp only [Category.assoc] at h
177+
exact coequalizer.hom_ext h
178+
#align homology.hom_from_ext homology.hom_from_ext
179+
180+
@[ext]
181+
theorem hom_to_ext {W : A} (a b : W ⟶ homology f g w) (h : a ≫ ι f g w = b ≫ ι f g w) : a = b := by
182+
dsimp [ι] at h
183+
apply_fun fun e => e ≫ (homologyIsoKernelDesc f g w).hom
184+
swap
185+
· intro i j hh
186+
apply_fun fun e => e ≫ (homologyIsoKernelDesc f g w).inv at hh
187+
simpa using hh
188+
simp only [← Category.assoc] at h
189+
exact equalizer.hom_ext h
190+
#align homology.hom_to_ext homology.hom_to_ext
191+
192+
@[reassoc (attr := simp)]
193+
theorem π' : π' f g w ≫ ι f g w = kernel.ι _ ≫ cokernel.π _ := by
194+
dsimp [π', ι, homologyIsoKernelDesc]
195+
simp
196+
#align homology.π'_ι homology.π'_ι
197+
198+
@[reassoc (attr := simp)]
199+
theorem π'_eq_π : (kernelSubobjectIso _).hom ≫ π' f g w = π _ _ _ := by
200+
dsimp [π', homologyIsoCokernelLift]
201+
simp only [← Category.assoc]
202+
rw [Iso.comp_inv_eq]
203+
dsimp [π, homologyIsoCokernelImageToKernel']
204+
simp
205+
#align homology.π'_eq_π homology.π'_eq_π
206+
207+
section
208+
209+
variable {X' Y' Z' : A} (f' : X' ⟶ Y') (g' : Y' ⟶ Z') (w' : f' ≫ g' = 0)
210+
211+
@[reassoc (attr := simp)]
212+
theorem π'_map (α β h) : π' _ _ _ ≫ map w w' α β h =
213+
kernel.map _ _ α.right β.right (by simp [h, β.w.symm]) ≫ π' _ _ _ := by
214+
apply_fun fun e => (kernelSubobjectIso _).hom ≫ e
215+
swap
216+
· intro i j hh
217+
apply_fun fun e => (kernelSubobjectIso _).inv ≫ e at hh
218+
simpa using hh
219+
dsimp [map]
220+
simp only [π'_eq_π_assoc]
221+
dsimp [π]
222+
simp only [cokernel.π_desc]
223+
rw [← Iso.inv_comp_eq, ← Category.assoc]
224+
have :
225+
(kernelSubobjectIso g).inv ≫ kernelSubobjectMap β =
226+
kernel.map _ _ β.left β.right β.w.symm ≫ (kernelSubobjectIso _).inv := by
227+
rw [Iso.inv_comp_eq, ← Category.assoc, Iso.eq_comp_inv]
228+
refine Limits.equalizer.hom_ext ?_
229+
dsimp
230+
simp
231+
rw [this]
232+
simp only [Category.assoc]
233+
dsimp [π', homologyIsoCokernelLift]
234+
simp only [cokernelIsoOfEq_inv_comp_desc, cokernel.π_desc_assoc]
235+
congr 1
236+
· congr
237+
exact h.symm
238+
· rw [Iso.inv_comp_eq, ← Category.assoc, Iso.eq_comp_inv]
239+
dsimp [homologyIsoCokernelImageToKernel']
240+
simp
241+
#align homology.π'_map homology.π'_map
242+
243+
-- Porting note: need to fill in f,g,f',g' in the next few results or time out
244+
theorem map_eq_desc'_lift_left (α β h) :
245+
map w w' α β h =
246+
homology.desc' f g _ (homology.lift f' g' _ (kernel.ι _ ≫ β.left ≫ cokernel.π _)
247+
(by simp)) (by
248+
ext
249+
simp only [← h, Category.assoc, zero_comp, lift_ι, kernel.lift_ι_assoc]
250+
erw [← reassoc_of% α.w]
251+
simp) := by
252+
apply homology.hom_from_ext
253+
simp only [π'_map, π'_desc']
254+
dsimp [π', lift]
255+
rw [Iso.eq_comp_inv]
256+
dsimp [homologyIsoKernelDesc]
257+
-- Porting note: previously ext
258+
apply Limits.equalizer.hom_ext
259+
simp [h]
260+
#align homology.map_eq_desc'_lift_left homology.map_eq_desc'_lift_left
261+
262+
theorem map_eq_lift_desc'_left (α β h) :
263+
map w w' α β h =
264+
homology.lift f' g' _
265+
(homology.desc' f g _ (kernel.ι _ ≫ β.left ≫ cokernel.π _)
266+
(by
267+
simp only [kernel.lift_ι_assoc, ← h]
268+
erw [← reassoc_of% α.w]
269+
simp))
270+
(by
271+
-- Porting note: used to be ext
272+
apply homology.hom_from_ext
273+
simp) := by
274+
rw [map_eq_desc'_lift_left]
275+
-- Porting note: once was known as ext
276+
apply homology.hom_to_ext
277+
apply homology.hom_from_ext
278+
simp
279+
#align homology.map_eq_lift_desc'_left homology.map_eq_lift_desc'_left
280+
281+
theorem map_eq_desc'_lift_right (α β h) :
282+
map w w' α β h =
283+
homology.desc' f g _ (homology.lift f' g' _ (kernel.ι _ ≫ α.right ≫ cokernel.π _)
284+
(by simp [h]))
285+
(by
286+
ext
287+
simp only [Category.assoc, zero_comp, lift_ι, kernel.lift_ι_assoc]
288+
erw [← reassoc_of% α.w]
289+
simp) := by
290+
rw [map_eq_desc'_lift_left]
291+
ext
292+
simp [h]
293+
#align homology.map_eq_desc'_lift_right homology.map_eq_desc'_lift_right
294+
295+
theorem map_eq_lift_desc'_right (α β h) :
296+
map w w' α β h =
297+
homology.lift f' g' _
298+
(homology.desc' f g _ (kernel.ι _ ≫ α.right ≫ cokernel.π _)
299+
(by
300+
simp only [kernel.lift_ι_assoc]
301+
erw [← reassoc_of% α.w]
302+
simp))
303+
(by
304+
-- Porting note: once was known as ext
305+
apply homology.hom_from_ext
306+
simp [h]) := by
307+
rw [map_eq_desc'_lift_right]
308+
-- Porting note: once was known as ext
309+
apply homology.hom_to_ext
310+
apply homology.hom_from_ext
311+
simp
312+
#align homology.map_eq_lift_desc'_right homology.map_eq_lift_desc'_right
313+
314+
@[reassoc (attr := simp)]
315+
theorem map_ι (α β h) :
316+
map w w' α β h ≫ ι f' g' w' =
317+
ι f g w ≫ cokernel.map f f' α.left β.left (by simp [h, β.w.symm]) := by
318+
rw [map_eq_lift_desc'_left, lift_ι]
319+
-- Porting note: once was known as ext
320+
apply homology.hom_from_ext
321+
simp only [← Category.assoc]
322+
rw [π'_ι, π'_desc', Category.assoc, Category.assoc, cokernel.π_desc]
323+
#align homology.map_ι homology.map_ι
324+
325+
end
326+
327+
end homology
328+
329+
namespace CategoryTheory.Functor
330+
331+
variable {ι : Type _} {c : ComplexShape ι} {B : Type _} [Category B] [Abelian B] (F : A ⥤ B)
332+
[Functor.Additive F] [PreservesFiniteLimits F] [PreservesFiniteColimits F]
333+
334+
-- Porting note: not needed on reenableeta branch
335+
set_option maxHeartbeats 400000 in
336+
/-- When `F` is an exact additive functor, `F(Hᵢ(X)) ≅ Hᵢ(F(X))` for `X` a complex. -/
337+
noncomputable def homologyIso (C : HomologicalComplex A c) (j : ι) :
338+
F.obj (C.homology j) ≅ ((F.mapHomologicalComplex c).obj C).homology j :=
339+
(PreservesCokernel.iso F _).trans
340+
(cokernel.mapIso _ _
341+
((F.mapIso (imageSubobjectIso _)).trans
342+
((PreservesImage.iso F _).symm.trans (imageSubobjectIso _).symm))
343+
((F.mapIso (kernelSubobjectIso _)).trans
344+
((PreservesKernel.iso F _).trans (kernelSubobjectIso _).symm))
345+
(by
346+
dsimp
347+
ext
348+
simp only [Category.assoc, imageToKernel_arrow]
349+
erw [kernelSubobject_arrow', imageSubobject_arrow']
350+
simp [← F.map_comp]))
351+
#align category_theory.functor.homology_iso CategoryTheory.Functor.homologyIso
352+
353+
-- Porting note: not needed on reenableeta branch
354+
set_option maxHeartbeats 400000 in
355+
/-- If `F` is an exact additive functor, then `F` commutes with `Hᵢ` (up to natural isomorphism). -/
356+
noncomputable def homologyFunctorIso (i : ι) :
357+
homologyFunctor A c i ⋙ F ≅ F.mapHomologicalComplex c ⋙ homologyFunctor B c i :=
358+
NatIso.ofComponents (fun X => homologyIso F X i) (by
359+
intro X Y f
360+
dsimp
361+
rw [← Iso.inv_comp_eq, ← Category.assoc, ← Iso.eq_comp_inv]
362+
refine' coequalizer.hom_ext _
363+
dsimp [homologyIso]
364+
simp only [PreservesCokernel.iso_inv]
365+
dsimp [homology.map]
366+
simp only [← Category.assoc, cokernel.π_desc]
367+
simp only [Category.assoc, cokernelComparison_map_desc, cokernel.π_desc]
368+
simp only [π_comp_cokernelComparison, ← F.map_comp]
369+
erw [← kernelSubobjectIso_comp_kernel_map_assoc]
370+
simp only [HomologicalComplex.Hom.sqFrom_right, HomologicalComplex.Hom.sqFrom_left,
371+
F.mapHomologicalComplex_map_f, F.map_comp]
372+
dsimp [HomologicalComplex.dFrom, HomologicalComplex.Hom.next]
373+
rw [kernel_map_comp_preserves_kernel_iso_inv_assoc]
374+
conv_lhs => erw [← F.map_comp_assoc]
375+
rotate_right; simp
376+
rw [← kernel_map_comp_kernelSubobjectIso_inv]
377+
any_goals simp)
378+
#align category_theory.functor.homology_functor_iso CategoryTheory.Functor.homologyFunctorIso
379+
380+
end CategoryTheory.Functor
381+

0 commit comments

Comments
 (0)