Skip to content

Commit f4520b4

Browse files
int-y1mattrobball
andcommitted
feat: port CategoryTheory.Abelian.InjectiveResolution (#4059)
Co-authored-by: Matthew Ballard <matt@mrb.email>
1 parent ff68ab1 commit f4520b4

File tree

2 files changed

+349
-0
lines changed

2 files changed

+349
-0
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ import Mathlib.CategoryTheory.Abelian.FunctorCategory
540540
import Mathlib.CategoryTheory.Abelian.Generator
541541
import Mathlib.CategoryTheory.Abelian.Homology
542542
import Mathlib.CategoryTheory.Abelian.Images
543+
import Mathlib.CategoryTheory.Abelian.InjectiveResolution
543544
import Mathlib.CategoryTheory.Abelian.NonPreadditive
544545
import Mathlib.CategoryTheory.Abelian.Opposite
545546
import Mathlib.CategoryTheory.Abelian.Pseudoelements
Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
/-
2+
Copyright (c) 2022 Jujian Zhang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Jujian Zhang, Scott Morrison
5+
6+
! This file was ported from Lean 3 source module category_theory.abelian.injective_resolution
7+
! leanprover-community/mathlib commit f0c8bf9245297a541f468be517f1bde6195105e9
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.QuasiIso
12+
import Mathlib.CategoryTheory.Preadditive.InjectiveResolution
13+
import Mathlib.Algebra.Homology.HomotopyCategory
14+
15+
/-!
16+
# Main result
17+
18+
When the underlying category is abelian:
19+
* `CategoryTheory.InjectiveResolution.desc`: Given `I : InjectiveResolution X` and
20+
`J : InjectiveResolution Y`, any morphism `X ⟶ Y` admits a descent to a chain map
21+
`J.cocomplex ⟶ I.cocomplex`. It is a descent in the sense that `I.ι` intertwines the descent and
22+
the original morphism, see `CategoryTheory.InjectiveResolution.desc_commutes`.
23+
* `CategoryTheory.InjectiveResolution.descHomotopy`: Any two such descents are homotopic.
24+
* `CategoryTheory.InjectiveResolution.homotopyEquiv`: Any two injective resolutions of the same
25+
object are homotopy equivalent.
26+
* `CategoryTheory.injectiveResolutions`: If every object admits an injective resolution, we can
27+
construct a functor `injectiveResolutions C : C ⥤ HomotopyCategory C`.
28+
29+
* `CategoryTheory.exact_f_d`: `f` and `Injective.d f` are exact.
30+
* `CategoryTheory.InjectiveResolution.of`: Hence, starting from a monomorphism `X ⟶ J`, where `J`
31+
is injective, we can apply `Injective.d` repeatedly to obtain an injective resolution of `X`.
32+
-/
33+
34+
35+
noncomputable section
36+
37+
open CategoryTheory
38+
39+
open CategoryTheory.Limits
40+
41+
universe v u
42+
43+
namespace CategoryTheory
44+
45+
variable {C : Type u} [Category.{v} C]
46+
47+
open Injective
48+
49+
namespace InjectiveResolution
50+
set_option linter.uppercaseLean3 false -- `InjectiveResolution`
51+
52+
section
53+
54+
variable [HasZeroMorphisms C] [HasZeroObject C] [HasEqualizers C] [HasImages C]
55+
56+
/-- Auxiliary construction for `desc`. -/
57+
def descFZero {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y) (J : InjectiveResolution Z) :
58+
J.cocomplex.X 0 ⟶ I.cocomplex.X 0 :=
59+
factorThru (f ≫ I.ι.f 0) (J.ι.f 0)
60+
#align category_theory.InjectiveResolution.desc_f_zero CategoryTheory.InjectiveResolution.descFZero
61+
62+
end
63+
64+
section Abelian
65+
66+
variable [Abelian C]
67+
68+
/-- Auxiliary construction for `desc`. -/
69+
def descFOne {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y) (J : InjectiveResolution Z) :
70+
J.cocomplex.X 1 ⟶ I.cocomplex.X 1 :=
71+
Exact.desc (descFZero f I J ≫ I.cocomplex.d 0 1) (J.ι.f 0) (J.cocomplex.d 0 1)
72+
(Abelian.Exact.op _ _ J.exact₀) (by simp [← Category.assoc, descFZero])
73+
#align category_theory.InjectiveResolution.desc_f_one CategoryTheory.InjectiveResolution.descFOne
74+
75+
@[simp]
76+
theorem descFOne_zero_comm {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y)
77+
(J : InjectiveResolution Z) :
78+
J.cocomplex.d 0 1 ≫ descFOne f I J = descFZero f I J ≫ I.cocomplex.d 0 1 := by
79+
simp [descFZero, descFOne]
80+
#align category_theory.InjectiveResolution.desc_f_one_zero_comm CategoryTheory.InjectiveResolution.descFOne_zero_comm
81+
82+
/-- Auxiliary construction for `desc`. -/
83+
def descFSucc {Y Z : C} (I : InjectiveResolution Y) (J : InjectiveResolution Z) (n : ℕ)
84+
(g : J.cocomplex.X n ⟶ I.cocomplex.X n) (g' : J.cocomplex.X (n + 1) ⟶ I.cocomplex.X (n + 1))
85+
(w : J.cocomplex.d n (n + 1) ≫ g' = g ≫ I.cocomplex.d n (n + 1)) :
86+
Σ'g'' : J.cocomplex.X (n + 2) ⟶ I.cocomplex.X (n + 2),
87+
J.cocomplex.d (n + 1) (n + 2) ≫ g'' = g' ≫ I.cocomplex.d (n + 1) (n + 2) :=
88+
⟨@Exact.desc C _ _ _ _ _ _ _ _ _ (g' ≫ I.cocomplex.d (n + 1) (n + 2)) (J.cocomplex.d n (n + 1))
89+
(J.cocomplex.d (n + 1) (n + 2)) (Abelian.Exact.op _ _ (J.exact _))
90+
(by simp [← Category.assoc, w]),
91+
by simp⟩
92+
#align category_theory.InjectiveResolution.desc_f_succ CategoryTheory.InjectiveResolution.descFSucc
93+
94+
/-- A morphism in `C` descends to a chain map between injective resolutions. -/
95+
def desc {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y) (J : InjectiveResolution Z) :
96+
J.cocomplex ⟶ I.cocomplex :=
97+
CochainComplex.mkHom _ _ (descFZero f _ _) (descFOne f _ _) (descFOne_zero_comm f I J).symm
98+
fun n ⟨g, g', w⟩ => ⟨(descFSucc I J n g g' w.symm).1, (descFSucc I J n g g' w.symm).2.symm⟩
99+
#align category_theory.InjectiveResolution.desc CategoryTheory.InjectiveResolution.desc
100+
101+
/-- The resolution maps intertwine the descent of a morphism and that morphism. -/
102+
@[reassoc (attr := simp)] -- Porting note: Originally `@[simp, reassoc.1]`
103+
theorem desc_commutes {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y)
104+
(J : InjectiveResolution Z) : J.ι ≫ desc f I J = (CochainComplex.single₀ C).map f ≫ I.ι := by
105+
ext n
106+
rcases n with (_ | _ | n) <;>
107+
· dsimp [desc, descFOne, descFZero]
108+
simp
109+
#align category_theory.InjectiveResolution.desc_commutes CategoryTheory.InjectiveResolution.desc_commutes
110+
111+
-- Now that we've checked this property of the descent, we can seal away the actual definition.
112+
/-- An auxiliary definition for `descHomotopyZero`. -/
113+
def descHomotopyZeroZero {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
114+
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = 0) : I.cocomplex.X 1 ⟶ J.cocomplex.X 0 :=
115+
Exact.desc (f.f 0) (I.ι.f 0) (I.cocomplex.d 0 1) (Abelian.Exact.op _ _ I.exact₀)
116+
(congr_fun (congr_arg HomologicalComplex.Hom.f comm) 0)
117+
#align category_theory.InjectiveResolution.desc_homotopy_zero_zero CategoryTheory.InjectiveResolution.descHomotopyZeroZero
118+
119+
/-- An auxiliary definition for `descHomotopyZero`. -/
120+
def descHomotopyZeroOne {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
121+
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = (0 : _ ⟶ J.cocomplex)) :
122+
I.cocomplex.X 2 ⟶ J.cocomplex.X 1 :=
123+
Exact.desc (f.f 1 - descHomotopyZeroZero f comm ≫ J.cocomplex.d 0 1) (I.cocomplex.d 0 1)
124+
(I.cocomplex.d 1 2) (Abelian.Exact.op _ _ (I.exact _))
125+
(by simp [descHomotopyZeroZero, ← Category.assoc])
126+
#align category_theory.InjectiveResolution.desc_homotopy_zero_one CategoryTheory.InjectiveResolution.descHomotopyZeroOne
127+
128+
/-- An auxiliary definition for `descHomotopyZero`. -/
129+
def descHomotopyZeroSucc {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
130+
(f : I.cocomplex ⟶ J.cocomplex) (n : ℕ) (g : I.cocomplex.X (n + 1) ⟶ J.cocomplex.X n)
131+
(g' : I.cocomplex.X (n + 2) ⟶ J.cocomplex.X (n + 1))
132+
(w : f.f (n + 1) = I.cocomplex.d (n + 1) (n + 2) ≫ g' + g ≫ J.cocomplex.d n (n + 1)) :
133+
I.cocomplex.X (n + 3) ⟶ J.cocomplex.X (n + 2) :=
134+
Exact.desc (f.f (n + 2) - g' ≫ J.cocomplex.d _ _) (I.cocomplex.d (n + 1) (n + 2))
135+
(I.cocomplex.d (n + 2) (n + 3)) (Abelian.Exact.op _ _ (I.exact _))
136+
(by
137+
simp [Preadditive.comp_sub, ← Category.assoc, Preadditive.sub_comp,
138+
show I.cocomplex.d (n + 1) (n + 2) ≫ g' = f.f (n + 1) - g ≫ J.cocomplex.d n (n + 1) by
139+
rw [w]
140+
simp only [add_sub_cancel]])
141+
#align category_theory.InjectiveResolution.desc_homotopy_zero_succ CategoryTheory.InjectiveResolution.descHomotopyZeroSucc
142+
143+
/-- Any descent of the zero morphism is homotopic to zero. -/
144+
def descHomotopyZero {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
145+
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = 0) : Homotopy f 0 :=
146+
Homotopy.mkCoinductive _ (descHomotopyZeroZero f comm) (by simp [descHomotopyZeroZero])
147+
(descHomotopyZeroOne f comm) (by simp [descHomotopyZeroOne]) fun n ⟨g, g', w⟩ =>
148+
⟨descHomotopyZeroSucc f n g g' (by simp only [w, add_comm]), by simp [descHomotopyZeroSucc, w]⟩
149+
#align category_theory.InjectiveResolution.desc_homotopy_zero CategoryTheory.InjectiveResolution.descHomotopyZero
150+
151+
/-- Two descents of the same morphism are homotopic. -/
152+
def descHomotopy {Y Z : C} (f : Y ⟶ Z) {I : InjectiveResolution Y} {J : InjectiveResolution Z}
153+
(g h : I.cocomplex ⟶ J.cocomplex) (g_comm : I.ι ≫ g = (CochainComplex.single₀ C).map f ≫ J.ι)
154+
(h_comm : I.ι ≫ h = (CochainComplex.single₀ C).map f ≫ J.ι) : Homotopy g h :=
155+
Homotopy.equivSubZero.invFun (descHomotopyZero _ (by simp [g_comm, h_comm]))
156+
#align category_theory.InjectiveResolution.desc_homotopy CategoryTheory.InjectiveResolution.descHomotopy
157+
158+
/-- The descent of the identity morphism is homotopic to the identity cochain map. -/
159+
def descIdHomotopy (X : C) (I : InjectiveResolution X) :
160+
Homotopy (desc (𝟙 X) I I) (𝟙 I.cocomplex) := by
161+
apply descHomotopy (𝟙 X) <;> simp
162+
#align category_theory.InjectiveResolution.desc_id_homotopy CategoryTheory.InjectiveResolution.descIdHomotopy
163+
164+
/-- The descent of a composition is homotopic to the composition of the descents. -/
165+
def descCompHomotopy {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (I : InjectiveResolution X)
166+
(J : InjectiveResolution Y) (K : InjectiveResolution Z) :
167+
Homotopy (desc (f ≫ g) K I) (desc f J I ≫ desc g K J) := by
168+
apply descHomotopy (f ≫ g) <;> simp
169+
#align category_theory.InjectiveResolution.desc_comp_homotopy CategoryTheory.InjectiveResolution.descCompHomotopy
170+
171+
-- We don't care about the actual definitions of these homotopies.
172+
/-- Any two injective resolutions are homotopy equivalent. -/
173+
def homotopyEquiv {X : C} (I J : InjectiveResolution X) :
174+
HomotopyEquiv I.cocomplex J.cocomplex where
175+
hom := desc (𝟙 X) J I
176+
inv := desc (𝟙 X) I J
177+
homotopyHomInvId := (descCompHomotopy (𝟙 X) (𝟙 X) I J I).symm.trans <| by
178+
simpa [Category.id_comp] using descIdHomotopy _ _
179+
homotopyInvHomId := (descCompHomotopy (𝟙 X) (𝟙 X) J I J).symm.trans <| by
180+
simpa [Category.id_comp] using descIdHomotopy _ _
181+
#align category_theory.InjectiveResolution.homotopy_equiv CategoryTheory.InjectiveResolution.homotopyEquiv
182+
183+
@[reassoc (attr := simp)] -- Porting note: Originally `@[simp, reassoc.1]`
184+
theorem homotopyEquiv_hom_ι {X : C} (I J : InjectiveResolution X) :
185+
I.ι ≫ (homotopyEquiv I J).hom = J.ι := by simp [homotopyEquiv]
186+
#align category_theory.InjectiveResolution.homotopy_equiv_hom_ι CategoryTheory.InjectiveResolution.homotopyEquiv_hom_ι
187+
188+
@[reassoc (attr := simp)] -- Porting note: Originally `@[simp, reassoc.1]`
189+
theorem homotopyEquiv_inv_ι {X : C} (I J : InjectiveResolution X) :
190+
J.ι ≫ (homotopyEquiv I J).inv = I.ι := by simp [homotopyEquiv]
191+
#align category_theory.InjectiveResolution.homotopy_equiv_inv_ι CategoryTheory.InjectiveResolution.homotopyEquiv_inv_ι
192+
193+
end Abelian
194+
195+
end InjectiveResolution
196+
197+
section
198+
199+
variable [Abelian C]
200+
201+
/-- An arbitrarily chosen injective resolution of an object. -/
202+
abbrev injectiveResolution (Z : C) [HasInjectiveResolution Z] : CochainComplex C ℕ :=
203+
(HasInjectiveResolution.out (Z := Z)).some.cocomplex
204+
#align category_theory.injective_resolution CategoryTheory.injectiveResolution
205+
206+
/-- The cochain map from cochain complex consisting of `Z` supported in degree `0`
207+
back to the arbitrarily chosen injective resolution `injectiveResolution Z`. -/
208+
abbrev injectiveResolution.ι (Z : C) [HasInjectiveResolution Z] :
209+
(CochainComplex.single₀ C).obj Z ⟶ injectiveResolution Z :=
210+
(HasInjectiveResolution.out (Z := Z)).some.ι
211+
#align category_theory.injective_resolution.ι CategoryTheory.injectiveResolution.ι
212+
213+
/-- The descent of a morphism to a cochain map between the arbitrarily chosen injective resolutions.
214+
-/
215+
abbrev injectiveResolution.desc {X Y : C} (f : X ⟶ Y) [HasInjectiveResolution X]
216+
[HasInjectiveResolution Y] : injectiveResolution X ⟶ injectiveResolution Y :=
217+
InjectiveResolution.desc f _ _
218+
#align category_theory.injective_resolution.desc CategoryTheory.injectiveResolution.desc
219+
220+
variable (C)
221+
variable [HasInjectiveResolutions C]
222+
223+
/-- Taking injective resolutions is functorial,
224+
if considered with target the homotopy category
225+
(`ℕ`-indexed cochain complexes and chain maps up to homotopy).
226+
-/
227+
def injectiveResolutions : C ⥤ HomotopyCategory C (ComplexShape.up ℕ) where
228+
obj X := (HomotopyCategory.quotient _ _).obj (injectiveResolution X)
229+
map f := (HomotopyCategory.quotient _ _).map (injectiveResolution.desc f)
230+
map_id X := by
231+
rw [← (HomotopyCategory.quotient _ _).map_id]
232+
apply HomotopyCategory.eq_of_homotopy
233+
apply InjectiveResolution.descIdHomotopy
234+
map_comp f g := by
235+
rw [← (HomotopyCategory.quotient _ _).map_comp]
236+
apply HomotopyCategory.eq_of_homotopy
237+
apply InjectiveResolution.descCompHomotopy
238+
#align category_theory.injective_resolutions CategoryTheory.injectiveResolutions
239+
240+
end
241+
242+
section
243+
244+
variable [Abelian C] [EnoughInjectives C]
245+
246+
theorem exact_f_d {X Y : C} (f : X ⟶ Y) : Exact f (d f) :=
247+
(Abelian.exact_iff _ _).2 <|
248+
by simp, zero_of_comp_mono (ι _) <| by rw [Category.assoc, kernel.condition]⟩
249+
#align category_theory.exact_f_d CategoryTheory.exact_f_d
250+
251+
end
252+
253+
namespace InjectiveResolution
254+
255+
/-!
256+
Our goal is to define `InjectiveResolution.of Z : InjectiveResolution Z`.
257+
The `0`-th object in this resolution will just be `Injective.under Z`,
258+
i.e. an arbitrarily chosen injective object with a map from `Z`.
259+
After that, we build the `n+1`-st object as `Injective.syzygies`
260+
applied to the previously constructed morphism,
261+
and the map from the `n`-th object as `Injective.d`.
262+
-/
263+
264+
265+
variable [Abelian C] [EnoughInjectives C]
266+
267+
/-- Auxiliary definition for `InjectiveResolution.of`. -/
268+
@[simps!]
269+
def ofCocomplex (Z : C) : CochainComplex C ℕ :=
270+
CochainComplex.mk' (Injective.under Z) (Injective.syzygies (Injective.ι Z))
271+
(Injective.d (Injective.ι Z)) fun ⟨_, _, f⟩ =>
272+
⟨Injective.syzygies f, Injective.d f, (exact_f_d f).w⟩
273+
set_option linter.uppercaseLean3 false in
274+
#align category_theory.InjectiveResolution.of_cocomplex CategoryTheory.InjectiveResolution.ofCocomplex
275+
276+
-- Porting note: the ι field in `of` was very, very slow. To assist,
277+
-- implicit arguments were filled in and this particular proof was broken
278+
-- out into a separate result
279+
theorem ofCocomplex_sq_01_comm (Z : C) :
280+
Injective.ι Z ≫ HomologicalComplex.d (ofCocomplex Z) 0 1 =
281+
HomologicalComplex.d ((CochainComplex.single₀ C).obj Z) 0 10 := by
282+
simp only [ofCocomplex_d, eq_self_iff_true, eqToHom_refl, Category.comp_id,
283+
dite_eq_ite, if_true, comp_zero]
284+
exact (exact_f_d (Injective.ι Z)).w
285+
286+
-- Porting note: the `exact` in `of` was very, very slow. To assist,
287+
-- the whole proof was broken out into a separate result
288+
theorem exact_ofCocomplex (Z : C) (n : ℕ) :
289+
Exact (HomologicalComplex.d (ofCocomplex Z) n (n + 1))
290+
(HomologicalComplex.d (ofCocomplex Z) (n + 1) (n + 2)) :=
291+
match n with
292+
-- Porting note: used to be simp; apply exact_f_d on both branches
293+
| 0 => by simp; apply exact_f_d
294+
| m+1 => by
295+
simp only [ofCocomplex_X, ComplexShape.up_Rel, not_true, ofCocomplex_d,
296+
eqToHom_refl, Category.comp_id, dite_eq_ite, ite_true]
297+
erw [if_pos (c := m + 1 + 1 + 1 = m + 2 + 1) rfl]
298+
apply exact_f_d
299+
300+
-- Porting note: still very slow but with `ofCocomplex_sq_01_comm` and
301+
-- `exact_ofCocomplex` as separate results it is more reasonable
302+
/-- In any abelian category with enough injectives,
303+
`InjectiveResolution.of Z` constructs an injective resolution of the object `Z`.
304+
-/
305+
irreducible_def of (Z : C) : InjectiveResolution Z :=
306+
{ cocomplex := ofCocomplex Z
307+
ι :=
308+
CochainComplex.mkHom
309+
((CochainComplex.single₀ C).obj Z) (ofCocomplex Z) (Injective.ι Z) 0
310+
(ofCocomplex_sq_01_comm Z) fun n _ => by
311+
-- Porting note: used to be ⟨0, by ext⟩
312+
use 0
313+
apply HasZeroObject.from_zero_ext
314+
injective := by rintro (_ | _ | _ | n) <;> · apply Injective.injective_under
315+
exact₀ := by simpa using exact_f_d (Injective.ι Z)
316+
exact := exact_ofCocomplex Z
317+
mono := Injective.ι_mono Z }
318+
set_option linter.uppercaseLean3 false in
319+
#align category_theory.InjectiveResolution.of CategoryTheory.InjectiveResolution.of
320+
321+
322+
instance (priority := 100) (Z : C) : HasInjectiveResolution Z where out := ⟨of Z⟩
323+
324+
instance (priority := 100) : HasInjectiveResolutions C where out _ := inferInstance
325+
326+
end InjectiveResolution
327+
328+
end CategoryTheory
329+
330+
namespace HomologicalComplex.Hom
331+
332+
variable {C : Type u} [Category.{v} C] [Abelian C]
333+
334+
/-- If `X` is a cochain complex of injective objects and we have a quasi-isomorphism
335+
`f : Y[0] ⟶ X`, then `X` is an injective resolution of `Y`. -/
336+
def HomologicalComplex.Hom.fromSingle₀InjectiveResolution (X : CochainComplex C ℕ) (Y : C)
337+
(f : (CochainComplex.single₀ C).obj Y ⟶ X) [QuasiIso f] (H : ∀ n, Injective (X.X n)) :
338+
InjectiveResolution Y where
339+
cocomplex := X
340+
ι := f
341+
injective := H
342+
exact₀ := from_single₀_exact_f_d_at_zero f
343+
exact := from_single₀_exact_at_succ f
344+
mono := from_single₀_mono_at_zero f
345+
set_option linter.uppercaseLean3 false in
346+
#align homological_complex.hom.homological_complex.hom.from_single₀_InjectiveResolution HomologicalComplex.Hom.HomologicalComplex.Hom.fromSingle₀InjectiveResolution
347+
348+
end HomologicalComplex.Hom

0 commit comments

Comments
 (0)