|
| 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