/
ProjectiveResolution.lean
353 lines (293 loc) · 16.7 KB
/
ProjectiveResolution.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
/-
Copyright (c) 2022 Jujian Zhang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Markus Himmel, Scott Morrison, Jakob von Raumer, Joël Riou
-/
import Mathlib.CategoryTheory.Preadditive.ProjectiveResolution
import Mathlib.Algebra.Homology.HomotopyCategory
import Mathlib.Tactic.SuppressCompilation
/-!
# Abelian categories with enough projectives have projective resolutions
## Main results
When the underlying category is abelian:
* `CategoryTheory.ProjectiveResolution.lift`: Given `P : ProjectiveResolution X` and
`Q : ProjectiveResolution Y`, any morphism `X ⟶ Y` admits a lifting to a chain map
`P.complex ⟶ Q.complex`. It is a lifting in the sense that `P.ι` intertwines the lift and
the original morphism, see `CategoryTheory.ProjectiveResolution.lift_commutes`.
* `CategoryTheory.ProjectiveResolution.liftHomotopy`: Any two such descents are homotopic.
* `CategoryTheory.ProjectiveResolution.homotopyEquiv`: Any two projective resolutions of the same
object are homotopy equivalent.
* `CategoryTheory.projectiveResolutions`: If every object admits a projective resolution, we can
construct a functor `projectiveResolutions C : C ⥤ HomotopyCategory C (ComplexShape.down ℕ)`.
* `CategoryTheory.exact_d_f`: `Projective.d f` and `f` are exact.
* `CategoryTheory.ProjectiveResolution.of`: Hence, starting from an epimorphism `P ⟶ X`, where `P`
is projective, we can apply `Projective.d` repeatedly to obtain a projective resolution of `X`.
-/
suppress_compilation
noncomputable section
universe v u
namespace CategoryTheory
variable {C : Type u} [Category.{v} C]
open Category Limits Projective
set_option linter.uppercaseLean3 false -- `ProjectiveResolution`
namespace ProjectiveResolution
section
variable [HasZeroObject C] [HasZeroMorphisms C]
/-- Auxiliary construction for `lift`. -/
def liftFZero {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y) (Q : ProjectiveResolution Z) :
P.complex.X 0 ⟶ Q.complex.X 0 :=
Projective.factorThru (P.π.f 0 ≫ f) (Q.π.f 0)
#align category_theory.ProjectiveResolution.lift_f_zero CategoryTheory.ProjectiveResolution.liftFZero
end
section Abelian
variable [Abelian C]
lemma exact₀ {Z : C} (P : ProjectiveResolution Z) :
(ShortComplex.mk _ _ P.complex_d_comp_π_f_zero).Exact :=
ShortComplex.exact_of_g_is_cokernel _ P.isColimitCokernelCofork
/-- Auxiliary construction for `lift`. -/
def liftFOne {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y) (Q : ProjectiveResolution Z) :
P.complex.X 1 ⟶ Q.complex.X 1 :=
Q.exact₀.liftFromProjective (P.complex.d 1 0 ≫ liftFZero f P Q) (by simp [liftFZero])
#align category_theory.ProjectiveResolution.lift_f_one CategoryTheory.ProjectiveResolution.liftFOne
@[simp]
theorem liftFOne_zero_comm {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y)
(Q : ProjectiveResolution Z) :
liftFOne f P Q ≫ Q.complex.d 1 0 = P.complex.d 1 0 ≫ liftFZero f P Q := by
apply Q.exact₀.liftFromProjective_comp
#align category_theory.ProjectiveResolution.lift_f_one_zero_comm CategoryTheory.ProjectiveResolution.liftFOne_zero_comm
/-- Auxiliary construction for `lift`. -/
def liftFSucc {Y Z : C} (P : ProjectiveResolution Y) (Q : ProjectiveResolution Z) (n : ℕ)
(g : P.complex.X n ⟶ Q.complex.X n) (g' : P.complex.X (n + 1) ⟶ Q.complex.X (n + 1))
(w : g' ≫ Q.complex.d (n + 1) n = P.complex.d (n + 1) n ≫ g) :
Σ'g'' : P.complex.X (n + 2) ⟶ Q.complex.X (n + 2),
g'' ≫ Q.complex.d (n + 2) (n + 1) = P.complex.d (n + 2) (n + 1) ≫ g' :=
⟨(Q.exact_succ n).liftFromProjective
(P.complex.d (n + 2) (n + 1) ≫ g') (by simp [w]),
(Q.exact_succ n).liftFromProjective_comp _ _⟩
#align category_theory.ProjectiveResolution.lift_f_succ CategoryTheory.ProjectiveResolution.liftFSucc
/-- A morphism in `C` lift to a chain map between projective resolutions. -/
def lift {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y) (Q : ProjectiveResolution Z) :
P.complex ⟶ Q.complex :=
ChainComplex.mkHom _ _ (liftFZero f _ _) (liftFOne f _ _) (liftFOne_zero_comm f P Q)
fun n ⟨g, g', w⟩ => ⟨(liftFSucc P Q n g g' w).1, (liftFSucc P Q n g g' w).2⟩
#align category_theory.ProjectiveResolution.lift CategoryTheory.ProjectiveResolution.lift
/-- The resolution maps intertwine the lift of a morphism and that morphism. -/
@[reassoc (attr := simp)]
theorem lift_commutes {Y Z : C} (f : Y ⟶ Z) (P : ProjectiveResolution Y)
(Q : ProjectiveResolution Z) : lift f P Q ≫ Q.π = P.π ≫ (ChainComplex.single₀ C).map f := by
ext
simp [lift, liftFZero, liftFOne]
#align category_theory.ProjectiveResolution.lift_commutes CategoryTheory.ProjectiveResolution.lift_commutes
@[reassoc (attr := simp)]
lemma lift_commutes_zero {Y Z : C} (f : Y ⟶ Z)
(P : ProjectiveResolution Y) (Q : ProjectiveResolution Z) :
(lift f P Q).f 0 ≫ Q.π.f 0 = P.π.f 0 ≫ f :=
(HomologicalComplex.congr_hom (lift_commutes f P Q) 0).trans (by simp)
/-- An auxiliary definition for `liftHomotopyZero`. -/
def liftHomotopyZeroZero {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (comm : f ≫ Q.π = 0) : P.complex.X 0 ⟶ Q.complex.X 1 :=
Q.exact₀.liftFromProjective (f.f 0) (congr_fun (congr_arg HomologicalComplex.Hom.f comm) 0)
#align category_theory.ProjectiveResolution.lift_homotopy_zero_zero CategoryTheory.ProjectiveResolution.liftHomotopyZeroZero
@[reassoc (attr := simp)]
lemma liftHomotopyZeroZero_comp {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (comm : f ≫ Q.π = 0) :
liftHomotopyZeroZero f comm ≫ Q.complex.d 1 0 = f.f 0 :=
Q.exact₀.liftFromProjective_comp _ _
/-- An auxiliary definition for `liftHomotopyZero`. -/
def liftHomotopyZeroOne {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (comm : f ≫ Q.π = 0) :
P.complex.X 1 ⟶ Q.complex.X 2 :=
(Q.exact_succ 0).liftFromProjective (f.f 1 - P.complex.d 1 0 ≫ liftHomotopyZeroZero f comm)
(by rw [Preadditive.sub_comp, assoc, HomologicalComplex.Hom.comm,
liftHomotopyZeroZero_comp, sub_self])
#align category_theory.ProjectiveResolution.lift_homotopy_zero_one CategoryTheory.ProjectiveResolution.liftHomotopyZeroOne
@[reassoc (attr := simp)]
lemma liftHomotopyZeroOne_comp {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (comm : f ≫ Q.π = 0) :
liftHomotopyZeroOne f comm ≫ Q.complex.d 2 1 =
f.f 1 - P.complex.d 1 0 ≫ liftHomotopyZeroZero f comm :=
(Q.exact_succ 0).liftFromProjective_comp _ _
/-- An auxiliary definition for `liftHomotopyZero`. -/
def liftHomotopyZeroSucc {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (n : ℕ) (g : P.complex.X n ⟶ Q.complex.X (n + 1))
(g' : P.complex.X (n + 1) ⟶ Q.complex.X (n + 2))
(w : f.f (n + 1) = P.complex.d (n + 1) n ≫ g + g' ≫ Q.complex.d (n + 2) (n + 1)) :
P.complex.X (n + 2) ⟶ Q.complex.X (n + 3) :=
(Q.exact_succ (n + 1)).liftFromProjective (f.f (n + 2) - P.complex.d _ _ ≫ g') (by simp [w])
#align category_theory.ProjectiveResolution.lift_homotopy_zero_succ CategoryTheory.ProjectiveResolution.liftHomotopyZeroSucc
@[reassoc (attr := simp)]
lemma liftHomotopyZeroSucc_comp {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (n : ℕ) (g : P.complex.X n ⟶ Q.complex.X (n + 1))
(g' : P.complex.X (n + 1) ⟶ Q.complex.X (n + 2))
(w : f.f (n + 1) = P.complex.d (n + 1) n ≫ g + g' ≫ Q.complex.d (n + 2) (n + 1)) :
liftHomotopyZeroSucc f n g g' w ≫ Q.complex.d (n + 3) (n + 2) =
f.f (n + 2) - P.complex.d _ _ ≫ g' :=
(Q.exact_succ (n+1)).liftFromProjective_comp _ _
/-- Any lift of the zero morphism is homotopic to zero. -/
def liftHomotopyZero {Y Z : C} {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(f : P.complex ⟶ Q.complex) (comm : f ≫ Q.π = 0) : Homotopy f 0 :=
Homotopy.mkInductive _ (liftHomotopyZeroZero f comm) (by simp )
(liftHomotopyZeroOne f comm) (by simp) fun n ⟨g, g', w⟩ =>
⟨liftHomotopyZeroSucc f n g g' w, by simp⟩
#align category_theory.ProjectiveResolution.lift_homotopy_zero CategoryTheory.ProjectiveResolution.liftHomotopyZero
/-- Two lifts of the same morphism are homotopic. -/
def liftHomotopy {Y Z : C} (f : Y ⟶ Z) {P : ProjectiveResolution Y} {Q : ProjectiveResolution Z}
(g h : P.complex ⟶ Q.complex) (g_comm : g ≫ Q.π = P.π ≫ (ChainComplex.single₀ C).map f)
(h_comm : h ≫ Q.π = P.π ≫ (ChainComplex.single₀ C).map f) : Homotopy g h :=
Homotopy.equivSubZero.invFun (liftHomotopyZero _ (by simp [g_comm, h_comm]))
#align category_theory.ProjectiveResolution.lift_homotopy CategoryTheory.ProjectiveResolution.liftHomotopy
/-- The lift of the identity morphism is homotopic to the identity chain map. -/
def liftIdHomotopy (X : C) (P : ProjectiveResolution X) :
Homotopy (lift (𝟙 X) P P) (𝟙 P.complex) := by
apply liftHomotopy (𝟙 X) <;> simp
#align category_theory.ProjectiveResolution.lift_id_homotopy CategoryTheory.ProjectiveResolution.liftIdHomotopy
/-- The lift of a composition is homotopic to the composition of the lifts. -/
def liftCompHomotopy {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) (P : ProjectiveResolution X)
(Q : ProjectiveResolution Y) (R : ProjectiveResolution Z) :
Homotopy (lift (f ≫ g) P R) (lift f P Q ≫ lift g Q R) := by
apply liftHomotopy (f ≫ g) <;> simp
#align category_theory.ProjectiveResolution.lift_comp_homotopy CategoryTheory.ProjectiveResolution.liftCompHomotopy
-- We don't care about the actual definitions of these homotopies.
/-- Any two projective resolutions are homotopy equivalent. -/
def homotopyEquiv {X : C} (P Q : ProjectiveResolution X) :
HomotopyEquiv P.complex Q.complex where
hom := lift (𝟙 X) P Q
inv := lift (𝟙 X) Q P
homotopyHomInvId := (liftCompHomotopy (𝟙 X) (𝟙 X) P Q P).symm.trans <| by
simpa [id_comp] using liftIdHomotopy _ _
homotopyInvHomId := (liftCompHomotopy (𝟙 X) (𝟙 X) Q P Q).symm.trans <| by
simpa [id_comp] using liftIdHomotopy _ _
#align category_theory.ProjectiveResolution.homotopy_equiv CategoryTheory.ProjectiveResolution.homotopyEquiv
@[reassoc (attr := simp)]
theorem homotopyEquiv_hom_π {X : C} (P Q : ProjectiveResolution X) :
(homotopyEquiv P Q).hom ≫ Q.π = P.π := by simp [homotopyEquiv]
#align category_theory.ProjectiveResolution.homotopy_equiv_hom_π CategoryTheory.ProjectiveResolution.homotopyEquiv_hom_π
@[reassoc (attr := simp)]
theorem homotopyEquiv_inv_π {X : C} (P Q : ProjectiveResolution X) :
(homotopyEquiv P Q).inv ≫ P.π = Q.π := by simp [homotopyEquiv]
#align category_theory.ProjectiveResolution.homotopy_equiv_inv_π CategoryTheory.ProjectiveResolution.homotopyEquiv_inv_π
end Abelian
end ProjectiveResolution
/-- An arbitrarily chosen projective resolution of an object. -/
abbrev projectiveResolution (Z : C) [HasZeroObject C]
[HasZeroMorphisms C] [HasProjectiveResolution Z] :
ProjectiveResolution Z :=
(HasProjectiveResolution.out (Z := Z)).some
#align category_theory.projective_resolution CategoryTheory.projectiveResolution
variable (C)
variable [Abelian C] [HasProjectiveResolutions C]
/-- Taking projective resolutions is functorial,
if considered with target the homotopy category
(`ℕ`-indexed chain complexes and chain maps up to homotopy).
-/
def projectiveResolutions : C ⥤ HomotopyCategory C (ComplexShape.down ℕ) where
obj X := (HomotopyCategory.quotient _ _).obj (projectiveResolution X).complex
map f := (HomotopyCategory.quotient _ _).map (ProjectiveResolution.lift f _ _)
map_id X := by
rw [← (HomotopyCategory.quotient _ _).map_id]
apply HomotopyCategory.eq_of_homotopy
apply ProjectiveResolution.liftIdHomotopy
map_comp f g := by
rw [← (HomotopyCategory.quotient _ _).map_comp]
apply HomotopyCategory.eq_of_homotopy
apply ProjectiveResolution.liftCompHomotopy
#align category_theory.projective_resolutions CategoryTheory.projectiveResolutions
variable {C}
/-- If `P : ProjectiveResolution X`, then the chosen `(projectiveResolutions C).obj X`
is isomorphic (in the homotopy category) to `P.complex`. -/
def ProjectiveResolution.iso {X : C} (P : ProjectiveResolution X) :
(projectiveResolutions C).obj X ≅
(HomotopyCategory.quotient _ _).obj P.complex :=
HomotopyCategory.isoOfHomotopyEquiv (homotopyEquiv _ _)
@[reassoc]
lemma ProjectiveResolution.iso_inv_naturality {X Y : C} (f : X ⟶ Y)
(P : ProjectiveResolution X) (Q : ProjectiveResolution Y)
(φ : P.complex ⟶ Q.complex) (comm : φ.f 0 ≫ Q.π.f 0 = P.π.f 0 ≫ f) :
P.iso.inv ≫ (projectiveResolutions C).map f =
(HomotopyCategory.quotient _ _).map φ ≫ Q.iso.inv := by
apply HomotopyCategory.eq_of_homotopy
apply liftHomotopy f
all_goals
aesop_cat
@[reassoc]
lemma ProjectiveResolution.iso_hom_naturality {X Y : C} (f : X ⟶ Y)
(P : ProjectiveResolution X) (Q : ProjectiveResolution Y)
(φ : P.complex ⟶ Q.complex) (comm : φ.f 0 ≫ Q.π.f 0 = P.π.f 0 ≫ f) :
(projectiveResolutions C).map f ≫ Q.iso.hom =
P.iso.hom ≫ (HomotopyCategory.quotient _ _).map φ := by
rw [← cancel_epi (P.iso).inv, iso_inv_naturality_assoc f P Q φ comm,
Iso.inv_hom_id_assoc, Iso.inv_hom_id, comp_id]
variable [EnoughProjectives C]
theorem exact_d_f {X Y : C} (f : X ⟶ Y) :
(ShortComplex.mk (d f) f (by simp)).Exact := by
let α : ShortComplex.mk (d f) f (by simp) ⟶ ShortComplex.mk (kernel.ι f) f (by simp) :=
{ τ₁ := Projective.π _
τ₂ := 𝟙 _
τ₃ := 𝟙 _ }
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_f_is_kernel
apply kernelIsKernel
#align category_theory.exact_d_f CategoryTheory.exact_d_f
namespace ProjectiveResolution
/-!
Our goal is to define `ProjectiveResolution.of Z : ProjectiveResolution Z`.
The `0`-th object in this resolution will just be `Projective.over Z`,
i.e. an arbitrarily chosen projective object with a map to `Z`.
After that, we build the `n+1`-st object as `Projective.syzygies`
applied to the previously constructed morphism,
and the map from the `n`-th object as `Projective.d`.
-/
variable (Z : C)
-- The construction of the projective resolution `of` would be very, very slow
-- if it were not broken into separate definitions and lemmas
/-- Auxiliary definition for `ProjectiveResolution.of`. -/
def ofComplex : ChainComplex C ℕ :=
ChainComplex.mk' (Projective.over Z) (Projective.syzygies (Projective.π Z))
(Projective.d (Projective.π Z)) (fun f => ⟨_, Projective.d f, by simp⟩)
#align category_theory.ProjectiveResolution.of_complex CategoryTheory.ProjectiveResolution.ofComplex
lemma ofComplex_d_1_0 :
(ofComplex Z).d 1 0 = d (Projective.π Z) := by
simp [ofComplex]
lemma ofComplex_exactAt_succ (n : ℕ) :
(ofComplex Z).ExactAt (n + 1) := by
rw [HomologicalComplex.exactAt_iff' _ (n + 1 + 1) (n + 1) n (by simp) (by simp)]
dsimp [ofComplex, HomologicalComplex.sc', HomologicalComplex.shortComplexFunctor',
ChainComplex.mk', ChainComplex.mk]
simp only [ChainComplex.of_d]
-- TODO: this should just be apply exact_d_f so something is missing
match n with
| 0 =>
apply exact_d_f ((ChainComplex.mkAux _ _ _ (d (Projective.π Z)) (d (d (Projective.π Z))) _ _
0).g)
| n+1 =>
apply exact_d_f ((ChainComplex.mkAux _ _ _ (d (Projective.π Z)) (d (d (Projective.π Z))) _ _
(n+1)).g)
instance (n : ℕ) : Projective ((ofComplex Z).X n) := by
obtain (_ | _ | _ | n) := n <;> apply Projective.projective_over
/-- In any abelian category with enough projectives,
`ProjectiveResolution.of Z` constructs an projective resolution of the object `Z`.
-/
irreducible_def of : ProjectiveResolution Z where
complex := ofComplex Z
π := (ChainComplex.toSingle₀Equiv _ _).symm ⟨Projective.π Z, by
rw [ofComplex_d_1_0, assoc, kernel.condition, comp_zero]⟩
quasiIso := ⟨fun n => by
cases n
· rw [ChainComplex.quasiIsoAt₀_iff, ShortComplex.quasiIso_iff_of_zeros']
· dsimp
refine' (ShortComplex.exact_and_epi_g_iff_of_iso _).2
⟨exact_d_f (Projective.π Z), by dsimp; infer_instance⟩
exact ShortComplex.isoMk (Iso.refl _) (Iso.refl _) (Iso.refl _)
(by simp [ofComplex]) (by simp)
all_goals rfl
· rw [quasiIsoAt_iff_exactAt']
· apply ofComplex_exactAt_succ
· apply ChainComplex.exactAt_succ_single_obj⟩
#align category_theory.ProjectiveResolution.of CategoryTheory.ProjectiveResolution.of
instance (priority := 100) (Z : C) : HasProjectiveResolution Z where out := ⟨of Z⟩
instance (priority := 100) : HasProjectiveResolutions C where out _ := inferInstance
end ProjectiveResolution
end CategoryTheory