/
InjectiveResolution.lean
366 lines (300 loc) · 17.5 KB
/
InjectiveResolution.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/-
Copyright (c) 2022 Jujian Zhang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jujian Zhang, Scott Morrison
-/
import Mathlib.CategoryTheory.Preadditive.InjectiveResolution
import Mathlib.Algebra.Homology.HomotopyCategory
#align_import category_theory.abelian.injective_resolution from "leanprover-community/mathlib"@"f0c8bf9245297a541f468be517f1bde6195105e9"
/-!
# Abelian categories with enough injectives have injective resolutions
## Main results
When the underlying category is abelian:
* `CategoryTheory.InjectiveResolution.desc`: Given `I : InjectiveResolution X` and
`J : InjectiveResolution Y`, any morphism `X ⟶ Y` admits a descent to a chain map
`J.cocomplex ⟶ I.cocomplex`. It is a descent in the sense that `I.ι` intertwines the descent and
the original morphism, see `CategoryTheory.InjectiveResolution.desc_commutes`.
* `CategoryTheory.InjectiveResolution.descHomotopy`: Any two such descents are homotopic.
* `CategoryTheory.InjectiveResolution.homotopyEquiv`: Any two injective resolutions of the same
object are homotopy equivalent.
* `CategoryTheory.injectiveResolutions`: If every object admits an injective resolution, we can
construct a functor `injectiveResolutions C : C ⥤ HomotopyCategory C`.
* `CategoryTheory.exact_f_d`: `f` and `Injective.d f` are exact.
* `CategoryTheory.InjectiveResolution.of`: Hence, starting from a monomorphism `X ⟶ J`, where `J`
is injective, we can apply `Injective.d` repeatedly to obtain an injective resolution of `X`.
-/
noncomputable section
open CategoryTheory Category Limits
universe v u
namespace CategoryTheory
variable {C : Type u} [Category.{v} C]
open Injective
namespace InjectiveResolution
set_option linter.uppercaseLean3 false -- `InjectiveResolution`
section
variable [HasZeroObject C] [HasZeroMorphisms C]
/-- Auxiliary construction for `desc`. -/
def descFZero {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y) (J : InjectiveResolution Z) :
J.cocomplex.X 0 ⟶ I.cocomplex.X 0 :=
factorThru (f ≫ I.ι.f 0) (J.ι.f 0)
#align category_theory.InjectiveResolution.desc_f_zero CategoryTheory.InjectiveResolution.descFZero
end
section Abelian
variable [Abelian C]
lemma exact₀ {Z : C} (I : InjectiveResolution Z) :
(ShortComplex.mk _ _ I.ι_f_zero_comp_complex_d).Exact :=
ShortComplex.exact_of_f_is_kernel _ I.isLimitKernelFork
/-- Auxiliary construction for `desc`. -/
def descFOne {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y) (J : InjectiveResolution Z) :
J.cocomplex.X 1 ⟶ I.cocomplex.X 1 :=
J.exact₀.descToInjective (descFZero f I J ≫ I.cocomplex.d 0 1)
(by dsimp; simp [← assoc, descFZero])
#align category_theory.InjectiveResolution.desc_f_one CategoryTheory.InjectiveResolution.descFOne
@[simp]
theorem descFOne_zero_comm {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y)
(J : InjectiveResolution Z) :
J.cocomplex.d 0 1 ≫ descFOne f I J = descFZero f I J ≫ I.cocomplex.d 0 1 := by
apply J.exact₀.comp_descToInjective
#align category_theory.InjectiveResolution.desc_f_one_zero_comm CategoryTheory.InjectiveResolution.descFOne_zero_comm
/-- Auxiliary construction for `desc`. -/
def descFSucc {Y Z : C} (I : InjectiveResolution Y) (J : InjectiveResolution Z) (n : ℕ)
(g : J.cocomplex.X n ⟶ I.cocomplex.X n) (g' : J.cocomplex.X (n + 1) ⟶ I.cocomplex.X (n + 1))
(w : J.cocomplex.d n (n + 1) ≫ g' = g ≫ I.cocomplex.d n (n + 1)) :
Σ'g'' : J.cocomplex.X (n + 2) ⟶ I.cocomplex.X (n + 2),
J.cocomplex.d (n + 1) (n + 2) ≫ g'' = g' ≫ I.cocomplex.d (n + 1) (n + 2) :=
⟨(J.exact_succ n).descToInjective
(g' ≫ I.cocomplex.d (n + 1) (n + 2)) (by simp [reassoc_of% w]),
(J.exact_succ n).comp_descToInjective _ _⟩
#align category_theory.InjectiveResolution.desc_f_succ CategoryTheory.InjectiveResolution.descFSucc
/-- A morphism in `C` descends to a chain map between injective resolutions. -/
def desc {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y) (J : InjectiveResolution Z) :
J.cocomplex ⟶ I.cocomplex :=
CochainComplex.mkHom _ _ (descFZero f _ _) (descFOne f _ _) (descFOne_zero_comm f I J).symm
fun n ⟨g, g', w⟩ => ⟨(descFSucc I J n g g' w.symm).1, (descFSucc I J n g g' w.symm).2.symm⟩
#align category_theory.InjectiveResolution.desc CategoryTheory.InjectiveResolution.desc
/-- The resolution maps intertwine the descent of a morphism and that morphism. -/
@[reassoc (attr := simp)]
theorem desc_commutes {Y Z : C} (f : Z ⟶ Y) (I : InjectiveResolution Y)
(J : InjectiveResolution Z) : J.ι ≫ desc f I J = (CochainComplex.single₀ C).map f ≫ I.ι := by
ext
simp [desc, descFOne, descFZero]
#align category_theory.InjectiveResolution.desc_commutes CategoryTheory.InjectiveResolution.desc_commutes
@[reassoc (attr := simp)]
lemma desc_commutes_zero {Y Z : C} (f : Z ⟶ Y)
(I : InjectiveResolution Y) (J : InjectiveResolution Z) :
J.ι.f 0 ≫ (desc f I J).f 0 = f ≫ I.ι.f 0 :=
(HomologicalComplex.congr_hom (desc_commutes f I J) 0).trans (by simp)
-- Now that we've checked this property of the descent, we can seal away the actual definition.
/-- An auxiliary definition for `descHomotopyZero`. -/
def descHomotopyZeroZero {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = 0) : I.cocomplex.X 1 ⟶ J.cocomplex.X 0 :=
I.exact₀.descToInjective (f.f 0) (congr_fun (congr_arg HomologicalComplex.Hom.f comm) 0)
#align category_theory.InjectiveResolution.desc_homotopy_zero_zero CategoryTheory.InjectiveResolution.descHomotopyZeroZero
@[reassoc (attr := simp)]
lemma comp_descHomotopyZeroZero {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = 0) :
I.cocomplex.d 0 1 ≫ descHomotopyZeroZero f comm = f.f 0 :=
I.exact₀.comp_descToInjective _ _
/-- An auxiliary definition for `descHomotopyZero`. -/
def descHomotopyZeroOne {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = (0 : _ ⟶ J.cocomplex)) :
I.cocomplex.X 2 ⟶ J.cocomplex.X 1 :=
(I.exact_succ 0).descToInjective (f.f 1 - descHomotopyZeroZero f comm ≫ J.cocomplex.d 0 1)
(by rw [Preadditive.comp_sub, comp_descHomotopyZeroZero_assoc f comm,
HomologicalComplex.Hom.comm, sub_self])
#align category_theory.InjectiveResolution.desc_homotopy_zero_one CategoryTheory.InjectiveResolution.descHomotopyZeroOne
@[reassoc (attr := simp)]
lemma comp_descHomotopyZeroOne {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = (0 : _ ⟶ J.cocomplex)) :
I.cocomplex.d 1 2 ≫ descHomotopyZeroOne f comm =
f.f 1 - descHomotopyZeroZero f comm ≫ J.cocomplex.d 0 1 :=
(I.exact_succ 0).comp_descToInjective _ _
/-- An auxiliary definition for `descHomotopyZero`. -/
def descHomotopyZeroSucc {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (n : ℕ) (g : I.cocomplex.X (n + 1) ⟶ J.cocomplex.X n)
(g' : I.cocomplex.X (n + 2) ⟶ J.cocomplex.X (n + 1))
(w : f.f (n + 1) = I.cocomplex.d (n + 1) (n + 2) ≫ g' + g ≫ J.cocomplex.d n (n + 1)) :
I.cocomplex.X (n + 3) ⟶ J.cocomplex.X (n + 2) :=
(I.exact_succ (n + 1)).descToInjective (f.f (n + 2) - g' ≫ J.cocomplex.d _ _) (by
dsimp
rw [Preadditive.comp_sub, ← HomologicalComplex.Hom.comm, w, Preadditive.add_comp,
Category.assoc, Category.assoc, HomologicalComplex.d_comp_d, comp_zero,
add_zero, sub_self])
#align category_theory.InjectiveResolution.desc_homotopy_zero_succ CategoryTheory.InjectiveResolution.descHomotopyZeroSucc
@[reassoc (attr := simp)]
lemma comp_descHomotopyZeroSucc {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (n : ℕ) (g : I.cocomplex.X (n + 1) ⟶ J.cocomplex.X n)
(g' : I.cocomplex.X (n + 2) ⟶ J.cocomplex.X (n + 1))
(w : f.f (n + 1) = I.cocomplex.d (n + 1) (n + 2) ≫ g' + g ≫ J.cocomplex.d n (n + 1)) :
I.cocomplex.d (n+2) (n+3) ≫ descHomotopyZeroSucc f n g g' w =
f.f (n + 2) - g' ≫ J.cocomplex.d _ _ :=
(I.exact_succ (n+1)).comp_descToInjective _ _
/-- Any descent of the zero morphism is homotopic to zero. -/
def descHomotopyZero {Y Z : C} {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(f : I.cocomplex ⟶ J.cocomplex) (comm : I.ι ≫ f = 0) : Homotopy f 0 :=
Homotopy.mkCoinductive _ (descHomotopyZeroZero f comm) (by simp)
(descHomotopyZeroOne f comm) (by simp) (fun n ⟨g, g', w⟩ =>
⟨descHomotopyZeroSucc f n g g' (by simp only [w, add_comm]), by simp⟩)
#align category_theory.InjectiveResolution.desc_homotopy_zero CategoryTheory.InjectiveResolution.descHomotopyZero
/-- Two descents of the same morphism are homotopic. -/
def descHomotopy {Y Z : C} (f : Y ⟶ Z) {I : InjectiveResolution Y} {J : InjectiveResolution Z}
(g h : I.cocomplex ⟶ J.cocomplex) (g_comm : I.ι ≫ g = (CochainComplex.single₀ C).map f ≫ J.ι)
(h_comm : I.ι ≫ h = (CochainComplex.single₀ C).map f ≫ J.ι) : Homotopy g h :=
Homotopy.equivSubZero.invFun (descHomotopyZero _ (by simp [g_comm, h_comm]))
#align category_theory.InjectiveResolution.desc_homotopy CategoryTheory.InjectiveResolution.descHomotopy
/-- The descent of the identity morphism is homotopic to the identity cochain map. -/
def descIdHomotopy (X : C) (I : InjectiveResolution X) :
Homotopy (desc (𝟙 X) I I) (𝟙 I.cocomplex) := by
apply descHomotopy (𝟙 X) <;> simp
#align category_theory.InjectiveResolution.desc_id_homotopy CategoryTheory.InjectiveResolution.descIdHomotopy
/-- The descent of a composition is homotopic to the composition of the descents. -/
def descCompHomotopy {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (I : InjectiveResolution X)
(J : InjectiveResolution Y) (K : InjectiveResolution Z) :
Homotopy (desc (f ≫ g) K I) (desc f J I ≫ desc g K J) := by
apply descHomotopy (f ≫ g) <;> simp
#align category_theory.InjectiveResolution.desc_comp_homotopy CategoryTheory.InjectiveResolution.descCompHomotopy
-- We don't care about the actual definitions of these homotopies.
/-- Any two injective resolutions are homotopy equivalent. -/
def homotopyEquiv {X : C} (I J : InjectiveResolution X) :
HomotopyEquiv I.cocomplex J.cocomplex where
hom := desc (𝟙 X) J I
inv := desc (𝟙 X) I J
homotopyHomInvId := (descCompHomotopy (𝟙 X) (𝟙 X) I J I).symm.trans <| by
simpa [id_comp] using descIdHomotopy _ _
homotopyInvHomId := (descCompHomotopy (𝟙 X) (𝟙 X) J I J).symm.trans <| by
simpa [id_comp] using descIdHomotopy _ _
#align category_theory.InjectiveResolution.homotopy_equiv CategoryTheory.InjectiveResolution.homotopyEquiv
@[reassoc (attr := simp)] -- Porting note: Originally `@[simp, reassoc.1]`
theorem homotopyEquiv_hom_ι {X : C} (I J : InjectiveResolution X) :
I.ι ≫ (homotopyEquiv I J).hom = J.ι := by simp [homotopyEquiv]
#align category_theory.InjectiveResolution.homotopy_equiv_hom_ι CategoryTheory.InjectiveResolution.homotopyEquiv_hom_ι
@[reassoc (attr := simp)] -- Porting note: Originally `@[simp, reassoc.1]`
theorem homotopyEquiv_inv_ι {X : C} (I J : InjectiveResolution X) :
J.ι ≫ (homotopyEquiv I J).inv = I.ι := by simp [homotopyEquiv]
#align category_theory.InjectiveResolution.homotopy_equiv_inv_ι CategoryTheory.InjectiveResolution.homotopyEquiv_inv_ι
end Abelian
end InjectiveResolution
section
variable [Abelian C]
/-- An arbitrarily chosen injective resolution of an object. -/
abbrev injectiveResolution (Z : C) [HasInjectiveResolution Z] : InjectiveResolution Z :=
(HasInjectiveResolution.out (Z := Z)).some
#align category_theory.injective_resolution CategoryTheory.injectiveResolution
variable (C)
variable [HasInjectiveResolutions C]
/-- Taking injective resolutions is functorial,
if considered with target the homotopy category
(`ℕ`-indexed cochain complexes and chain maps up to homotopy).
-/
def injectiveResolutions : C ⥤ HomotopyCategory C (ComplexShape.up ℕ) where
obj X := (HomotopyCategory.quotient _ _).obj (injectiveResolution X).cocomplex
map f := (HomotopyCategory.quotient _ _).map (InjectiveResolution.desc f _ _)
map_id X := by
rw [← (HomotopyCategory.quotient _ _).map_id]
apply HomotopyCategory.eq_of_homotopy
apply InjectiveResolution.descIdHomotopy
map_comp f g := by
rw [← (HomotopyCategory.quotient _ _).map_comp]
apply HomotopyCategory.eq_of_homotopy
apply InjectiveResolution.descCompHomotopy
#align category_theory.injective_resolutions CategoryTheory.injectiveResolutions
variable {C}
/-- If `I : InjectiveResolution X`, then the chosen `(injectiveResolutions C).obj X`
is isomorphic (in the homotopy category) to `I.cocomplex`. -/
def InjectiveResolution.iso {X : C} (I : InjectiveResolution X) :
(injectiveResolutions C).obj X ≅
(HomotopyCategory.quotient _ _).obj I.cocomplex :=
HomotopyCategory.isoOfHomotopyEquiv (homotopyEquiv _ _)
@[reassoc]
lemma InjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
(I : InjectiveResolution X) (J : InjectiveResolution Y)
(φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
(injectiveResolutions C).map f ≫ J.iso.hom =
I.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
apply HomotopyCategory.eq_of_homotopy
apply descHomotopy f
all_goals aesop_cat
@[reassoc]
lemma InjectiveResolution.iso_inv_naturality {X Y : C} (f : X ⟶ Y)
(I : InjectiveResolution X) (J : InjectiveResolution Y)
(φ : I.cocomplex ⟶ J.cocomplex) (comm : I.ι.f 0 ≫ φ.f 0 = f ≫ J.ι.f 0) :
I.iso.inv ≫ (injectiveResolutions C).map f =
(HomotopyCategory.quotient _ _).map φ ≫ J.iso.inv := by
rw [← cancel_mono (J.iso).hom, Category.assoc, iso_hom_naturality f I J φ comm,
Iso.inv_hom_id_assoc, Category.assoc, Iso.inv_hom_id, Category.comp_id]
end
section
variable [Abelian C] [EnoughInjectives C]
theorem exact_f_d {X Y : C} (f : X ⟶ Y) :
(ShortComplex.mk f (d f) (by simp)).Exact := by
let α : ShortComplex.mk f (cokernel.π f) (by simp) ⟶ ShortComplex.mk f (d f) (by simp) :=
{ τ₁ := 𝟙 _
τ₂ := 𝟙 _
τ₃ := Injective.ι _ }
have : Epi α.τ₁ := by dsimp; infer_instance
have : IsIso α.τ₂ := by dsimp; infer_instance
have : Mono α.τ₃ := by dsimp; infer_instance
rw [← ShortComplex.exact_iff_of_epi_of_isIso_of_mono α]
apply ShortComplex.exact_of_g_is_cokernel
apply cokernelIsCokernel
#align category_theory.exact_f_d CategoryTheory.exact_f_d
end
namespace InjectiveResolution
/-!
Our goal is to define `InjectiveResolution.of Z : InjectiveResolution Z`.
The `0`-th object in this resolution will just be `Injective.under Z`,
i.e. an arbitrarily chosen injective object with a map from `Z`.
After that, we build the `n+1`-st object as `Injective.syzygies`
applied to the previously constructed morphism,
and the map from the `n`-th object as `Injective.d`.
-/
variable [Abelian C] [EnoughInjectives C] (Z : C)
-- The construction of the injective resolution `of` would be very, very slow
-- if it were not broken into separate definitions and lemmas
/-- Auxiliary definition for `InjectiveResolution.of`. -/
def ofCocomplex : CochainComplex C ℕ :=
CochainComplex.mk' (Injective.under Z) (Injective.syzygies (Injective.ι Z))
(Injective.d (Injective.ι Z)) fun f => ⟨_, Injective.d f, by simp⟩
set_option linter.uppercaseLean3 false in
#align category_theory.InjectiveResolution.of_cocomplex CategoryTheory.InjectiveResolution.ofCocomplex
lemma ofCocomplex_d_0_1 :
(ofCocomplex Z).d 0 1 = d (Injective.ι Z) := by
simp [ofCocomplex]
--Adaptation note: nightly-2024-03-11. This takes takes forever now
lemma ofCocomplex_exactAt_succ (n : ℕ) :
(ofCocomplex Z).ExactAt (n + 1) := by
rw [HomologicalComplex.exactAt_iff' _ n (n + 1) (n + 1 + 1) (by simp) (by simp)]
dsimp [ofCocomplex, CochainComplex.mk', CochainComplex.mk, HomologicalComplex.sc',
HomologicalComplex.shortComplexFunctor']
simp only [CochainComplex.of_d]
match n with
| 0 => apply exact_f_d ((CochainComplex.mkAux _ _ _
(d (Injective.ι Z)) (d (d (Injective.ι Z))) _ _ 0).f)
| n+1 => apply exact_f_d ((CochainComplex.mkAux _ _ _
(d (Injective.ι Z)) (d (d (Injective.ι Z))) _ _ (n+1)).f)
instance (n : ℕ) : Injective ((ofCocomplex Z).X n) := by
obtain (_ | _ | _ | n) := n <;> apply Injective.injective_under
/-- In any abelian category with enough injectives,
`InjectiveResolution.of Z` constructs an injective resolution of the object `Z`.
-/
irreducible_def of : InjectiveResolution Z where
cocomplex := ofCocomplex Z
ι := (CochainComplex.fromSingle₀Equiv _ _).symm ⟨Injective.ι Z,
by rw [ofCocomplex_d_0_1, cokernel.condition_assoc, zero_comp]⟩
quasiIso := ⟨fun n => by
cases n
· rw [CochainComplex.quasiIsoAt₀_iff, ShortComplex.quasiIso_iff_of_zeros]
· refine' (ShortComplex.exact_and_mono_f_iff_of_iso _).2
⟨exact_f_d (Injective.ι Z), by dsimp; infer_instance⟩
exact ShortComplex.isoMk (Iso.refl _) (Iso.refl _) (Iso.refl _) (by simp)
(by simp [ofCocomplex])
all_goals rfl
· rw [quasiIsoAt_iff_exactAt]
· apply ofCocomplex_exactAt_succ
· apply CochainComplex.exactAt_succ_single_obj⟩
set_option linter.uppercaseLean3 false in
#align category_theory.InjectiveResolution.of CategoryTheory.InjectiveResolution.of
instance (priority := 100) (Z : C) : HasInjectiveResolution Z where out := ⟨of Z⟩
instance (priority := 100) : HasInjectiveResolutions C where out _ := inferInstance
end InjectiveResolution
end CategoryTheory