diff --git a/Mathlib.lean b/Mathlib.lean index cd72d6d36a5d31..ff28b3c64aa186 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -657,6 +657,17 @@ public import Mathlib.Algebra.Homology.ShortComplex.ShortExact public import Mathlib.Algebra.Homology.ShortComplex.SnakeLemma public import Mathlib.Algebra.Homology.Single public import Mathlib.Algebra.Homology.SingleHomology +public import Mathlib.Algebra.Homology.SpectralObject.Basic +public import Mathlib.Algebra.Homology.SpectralObject.Cycles +public import Mathlib.Algebra.Homology.SpectralObject.Differentials +public import Mathlib.Algebra.Homology.SpectralObject.EpiMono +public import Mathlib.Algebra.Homology.SpectralObject.FirstPage +public import Mathlib.Algebra.Homology.SpectralObject.HasSpectralSequence +public import Mathlib.Algebra.Homology.SpectralObject.Homology +public import Mathlib.Algebra.Homology.SpectralObject.Page +public import Mathlib.Algebra.Homology.SpectralObject.SpectralSequence +public import Mathlib.Algebra.Homology.SpectralSequence.Basic +public import Mathlib.Algebra.Homology.SpectralSequence.ComplexShape public import Mathlib.Algebra.Homology.Square public import Mathlib.Algebra.Homology.TotalComplex public import Mathlib.Algebra.Homology.TotalComplexShift @@ -3235,6 +3246,10 @@ public import Mathlib.CategoryTheory.Triangulated.Rotate public import Mathlib.CategoryTheory.Triangulated.SpectralObject public import Mathlib.CategoryTheory.Triangulated.Subcategory public import Mathlib.CategoryTheory.Triangulated.TStructure.Basic +public import Mathlib.CategoryTheory.Triangulated.TStructure.ETrunc +public import Mathlib.CategoryTheory.Triangulated.TStructure.Induced +public import Mathlib.CategoryTheory.Triangulated.TStructure.SpectralObject +public import Mathlib.CategoryTheory.Triangulated.TStructure.TruncLEGT public import Mathlib.CategoryTheory.Triangulated.TStructure.TruncLTGE public import Mathlib.CategoryTheory.Triangulated.TriangleShift public import Mathlib.CategoryTheory.Triangulated.Triangulated @@ -5658,6 +5673,7 @@ public import Mathlib.Order.Filter.Ultrafilter.Basic public import Mathlib.Order.Filter.Ultrafilter.Defs public import Mathlib.Order.Filter.ZeroAndBoundedAtFilter public import Mathlib.Order.Fin.Basic +public import Mathlib.Order.Fin.Clamp public import Mathlib.Order.Fin.Finset public import Mathlib.Order.Fin.SuccAboveOrderIso public import Mathlib.Order.Fin.Tuple diff --git a/Mathlib/Algebra/Homology/SpectralObject/Basic.lean b/Mathlib/Algebra/Homology/SpectralObject/Basic.lean new file mode 100644 index 00000000000000..ac796f96615664 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/Basic.lean @@ -0,0 +1,235 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.ExactSequence +public import Mathlib.CategoryTheory.ComposableArrows.One +public import Mathlib.CategoryTheory.ComposableArrows.Two + +/-! +# Spectral objects in abelian categories + +In this file, we introduce the category `SpectralObject C ι` of spectral +objects in an abelian category `C` indexed by the category `ι`. + +## References +* [Jean-Louis Verdier, *Des catégories dérivées des catégories abéliennes*, II.4][verdier1996] + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category Limits + +namespace Abelian + +variable (C ι : Type*) [Category C] [Category ι] [Abelian C] + +open ComposableArrows + +/-- A spectral object in an abelian category category `C` indexed by a category `` +consists of a functor `H : ComposableArrows ι 1 ⥤ C`, and a +functorial long exact sequence +`⋯ ⟶ (H n₀).obj (mk₁ f) ⟶ (H n₀).obj (mk₁ (f ≫ g)) ⟶ (H n₀).obj (mk₁ g) ⟶ (H n₁).obj (mk₁ f) ⟶ ⋯` +when `n₀ + 1 = n₁` and `f` and `g` are composable morphisms in `ι`. (This will be +shortened as `H^n₀(f) ⟶ H^n₀(f ≫ g) ⟶ H^n₀(g) ⟶ H^n₁(f)` in the documentation.) -/ +structure SpectralObject where + /-- A sequence of functors from `ComposableArrows ι 1` to the abelian category. + The image of `mk₁ f` will be referred to as `H^n(f)` in the documentation. -/ + H (n : ℤ) : ComposableArrows ι 1 ⥤ C + /-- The connecting homomorphism of the spectral object. (Use `δ` instead.) -/ + δ' (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) : + functorArrows ι 1 2 2 ⋙ H n₀ ⟶ functorArrows ι 0 1 2 ⋙ H n₁ + exact₁' (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (D : ComposableArrows ι 2) : + (mk₂ ((δ' n₀ n₁ h).app D) ((H n₁).map ((mapFunctorArrows ι 0 1 0 2 2).app D))).Exact + exact₂' (n : ℤ) (D : ComposableArrows ι 2) : + (mk₂ ((H n).map ((mapFunctorArrows ι 0 1 0 2 2).app D)) + ((H n).map ((mapFunctorArrows ι 0 2 1 2 2).app D))).Exact + exact₃' (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (D : ComposableArrows ι 2) : + (mk₂ ((H n₀).map ((mapFunctorArrows ι 0 2 1 2 2).app D)) ((δ' n₀ n₁ h).app D)).Exact + +namespace SpectralObject + +variable {C ι} (X : SpectralObject C ι) + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) + +/-- The connecting homomorphism of the spectral object. -/ +def δ : (X.H n₀).obj (mk₁ g) ⟶ (X.H n₁).obj (mk₁ f) := + (X.δ' n₀ n₁ hn₁).app (mk₂ f g) + +@[reassoc] +lemma δ_naturality {i' j' k' : ι} (f' : i' ⟶ j') (g' : j' ⟶ k') + (α : mk₁ f ⟶ mk₁ f') (β : mk₁ g ⟶ mk₁ g') (hαβ : α.app 1 = β.app 0 := by cat_disch) : + (X.H n₀).map β ≫ X.δ n₀ n₁ hn₁ f' g' = X.δ n₀ n₁ hn₁ f g ≫ (X.H n₁).map α := by + have h := (X.δ' n₀ n₁ hn₁).naturality + (homMk₂ (α.app 0) (α.app 1) (β.app 1) (naturality' α 0 1) + (by simpa only [hαβ] using naturality' β 0 1) : mk₂ f g ⟶ mk₂ f' g') + dsimp at h + convert h <;> cat_disch + +end + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) + (fg : i ⟶ k) (h : f ≫ g = fg) + +@[reassoc (attr := simp)] +lemma zero₁ : + X.δ n₀ n₁ hn₁ f g ≫ (X.H n₁).map (twoδ₂Toδ₁ f g fg h) = 0 := by + subst h + exact (X.exact₁' n₀ n₁ hn₁ (mk₂ f g)).zero 0 + +@[reassoc (attr := simp)] +lemma zero₂ (fg : i ⟶ k) (h : f ≫ g = fg) : + (X.H n₀).map (twoδ₂Toδ₁ f g fg h) ≫ (X.H n₀).map (twoδ₁Toδ₀ f g fg h) = 0 := by + subst h + exact (X.exact₂' n₀ (mk₂ f g)).zero 0 + +@[reassoc (attr := simp)] +lemma zero₃ : + (X.H n₀).map (twoδ₁Toδ₀ f g fg h) ≫ X.δ n₀ n₁ hn₁ f g = 0 := by + subst h + exact (X.exact₃' n₀ n₁ hn₁ (mk₂ f g)).zero 0 + +/-- The (exact) short complex `H^n₀(g) ⟶ H^n₁(f) ⟶ H^n₁(fg)` of a +spectral object, when `f ≫ g = fg` and `n₀ + 1 = n₁`. -/ +@[simps] +def sc₁ : ShortComplex C := + ShortComplex.mk _ _ (X.zero₁ n₀ n₁ hn₁ f g fg h) + +/-- The (exact) short complex `H^n₀(f) ⟶ H^n₀(fg) ⟶ H^n₀(g)` of a +spectral object, when `f ≫ g = fg`. -/ +@[simps] +def sc₂ : ShortComplex C := + ShortComplex.mk _ _ (X.zero₂ n₀ f g fg h) + +/-- The (exact) short complex `H^n₀(fg) ⟶ H^n₀(g) ⟶ H^n₁(f)` +of a spectral object, when `f ≫ g = fg` and `n₀ + 1 = n₁`. -/ +@[simps] +def sc₃ : ShortComplex C := + ShortComplex.mk _ _ (X.zero₃ n₀ n₁ hn₁ f g fg h) + +lemma exact₁ : (X.sc₁ n₀ n₁ hn₁ f g fg h).Exact := by + subst h + exact (X.exact₁' n₀ n₁ hn₁ (mk₂ f g)).exact 0 + +lemma exact₂ : (X.sc₂ n₀ f g fg h).Exact := by + subst h + exact (X.exact₂' n₀ (mk₂ f g)).exact 0 + +lemma exact₃ : (X.sc₃ n₀ n₁ hn₁ f g fg h).Exact := by + subst h + exact ((X.exact₃' n₀ n₁ hn₁ (mk₂ f g))).exact 0 + +/-- The (exact) sequence +`H^n₀(f) ⟶ H^n₀(fg) ⟶ H^n₀(g) ⟶ H^n₁(f) ⟶ H^n₁(fg) ⟶ H^n₁(g)` +of a spectral object, when `f ≫ g = fg` and `n₀ + 1 = n₁`. -/ +abbrev composableArrows₅ : ComposableArrows C 5 := + mk₅ ((X.H n₀).map (twoδ₂Toδ₁ f g fg h)) ((X.H n₀).map (twoδ₁Toδ₀ f g fg h)) + (X.δ n₀ n₁ hn₁ f g) ((X.H n₁).map (twoδ₂Toδ₁ f g fg h)) + ((X.H n₁).map (twoδ₁Toδ₀ f g fg h)) + +lemma composableArrows₅_exact : + (X.composableArrows₅ n₀ n₁ hn₁ f g fg h).Exact := + exact_of_δ₀ (X.exact₂ n₀ _ _ _ h).exact_toComposableArrows + (exact_of_δ₀ (X.exact₃ n₀ n₁ hn₁ _ _ _ h).exact_toComposableArrows + (exact_of_δ₀ (X.exact₁ n₀ n₁ hn₁ _ _ _ h).exact_toComposableArrows + ((X.exact₂ n₁ _ _ _ h).exact_toComposableArrows))) + +end + +@[reassoc (attr := simp)] +lemma δ_δ (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i j k l : ι} (f : i ⟶ j) (g : j ⟶ k) (h : k ⟶ l) : + X.δ n₀ n₁ hn₁ g h ≫ X.δ n₁ n₂ hn₂ f g = 0 := by + have eq := X.δ_naturality n₁ n₂ hn₂ f g f (g ≫ h) (𝟙 _) (twoδ₂Toδ₁ g h _ rfl) + rw [Functor.map_id, comp_id] at eq + rw [← eq, X.zero₁_assoc n₀ n₁ hn₁ g h _ rfl, zero_comp] + +/-- The type of morphisms between spectral objects in abelian categories. -/ +@[ext] +structure Hom (X' : SpectralObject C ι) where + /-- The natural transformation that is part of a morphism between spectral objects. -/ + hom (n : ℤ) : X.H n ⟶ X'.H n + comm (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) : + X.δ n₀ n₁ hn₁ f g ≫ (hom n₁).app (mk₁ f) = + (hom n₀).app (mk₁ g) ≫ X'.δ n₀ n₁ hn₁ f g := by cat_disch + +attribute [reassoc (attr := simp)] Hom.comm + +@[simps] +instance : Category (SpectralObject C ι) where + Hom := Hom + id X := { hom _ := 𝟙 _ } + comp f g := { hom n := f.hom n ≫ g.hom n } + +attribute [simp] id_hom +attribute [reassoc, simp] comp_hom + +lemma isZero_H_map_mk₁_of_isIso (n : ℤ) {i₀ i₁ : ι} (f : i₀ ⟶ i₁) [IsIso f] : + IsZero ((X.H n).obj (mk₁ f)) := by + let φ := twoδ₂Toδ₁ f (inv f) (𝟙 i₀) (by simp) ≫ twoδ₁Toδ₀ f (inv f) (𝟙 i₀) + have : IsIso φ := by + rw [isIso_iff₁] + constructor <;> dsimp <;> infer_instance + rw [IsZero.iff_id_eq_zero] + rw [← cancel_mono ((X.H n).map φ), Category.id_comp, zero_comp, + ← X.zero₂ n f (inv f) (𝟙 _) (by simp), ← Functor.map_comp] + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) {i₀ i₁ i₂ : ι} + (f : i₀ ⟶ i₁) (g : i₁ ⟶ i₂) (fg : i₀ ⟶ i₂) (hfg : f ≫ g = fg) + (h₁ : IsZero ((X.H n₀).obj (mk₁ f))) (h₂ : IsZero ((X.H n₁).obj (mk₁ f))) + +include h₁ in +lemma mono_H_map_twoδ₁Toδ₀ : Mono ((X.H n₀).map (twoδ₁Toδ₀ f g fg hfg)) := + (X.exact₂ n₀ f g fg hfg).mono_g (h₁.eq_of_src _ _) + +include h₂ hn₁ in +lemma epi_H_map_twoδ₁Toδ₀ : Epi ((X.H n₀).map (twoδ₁Toδ₀ f g fg hfg)) := + (X.exact₃ n₀ n₁ hn₁ f g fg hfg).epi_f (h₂.eq_of_tgt _ _) + +include h₁ h₂ hn₁ in +lemma isIso_H_map_twoδ₁Toδ₀ : IsIso ((X.H n₀).map (twoδ₁Toδ₀ f g fg hfg)) := by + have := X.mono_H_map_twoδ₁Toδ₀ n₀ f g fg hfg h₁ + have := X.epi_H_map_twoδ₁Toδ₀ n₀ n₁ hn₁ f g fg hfg h₂ + apply isIso_of_mono_of_epi + +end + +section + +variable {ι' : Type*} [Preorder ι'] (X' : SpectralObject C ι') + (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) (i₀ i₁ i₂ : ι') (h₀₁ : i₀ ≤ i₁) (h₁₂ : i₁ ≤ i₂) + (h₁ : IsZero ((X'.H n₀).obj (mk₁ (homOfLE h₀₁)))) + (h₂ : IsZero ((X'.H n₁).obj (mk₁ (homOfLE h₀₁)))) + +include h₁ in +lemma mono_H_map_twoδ₁Toδ₀' : Mono ((X'.H n₀).map (twoδ₁Toδ₀' i₀ i₁ i₂ h₀₁ h₁₂)) := + X'.mono_H_map_twoδ₁Toδ₀ _ _ _ _ _ h₁ + +include h₂ hn₁ in +lemma epi_H_map_twoδ₁Toδ₀' : Epi ((X'.H n₀).map (twoδ₁Toδ₀' i₀ i₁ i₂ h₀₁ h₁₂)) := + X'.epi_H_map_twoδ₁Toδ₀ _ _ hn₁ _ _ _ _ h₂ + +include h₁ h₂ hn₁ in +lemma isIso_H_map_twoδ₁Toδ₀' : IsIso ((X'.H n₀).map (twoδ₁Toδ₀' i₀ i₁ i₂ h₀₁ h₁₂)) := + X'.isIso_H_map_twoδ₁Toδ₀ _ _ hn₁ _ _ _ _ h₁ h₂ + +end + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/Cycles.lean b/Mathlib/Algebra/Homology/SpectralObject/Cycles.lean new file mode 100644 index 00000000000000..a9d2d011e6a29a --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/Cycles.lean @@ -0,0 +1,501 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.Basic +public import Mathlib.Algebra.Homology.ExactSequenceFour +public import Mathlib.CategoryTheory.Abelian.Exact + +/-! +# Kernel and cokernel of the differentiel of a spectral object + +Let `X` be a spectral object index by the category `ι` +in the abelian category `C`. In this file, we introduce +the kernel `X.cycles` and the cokernel `X.opcycles` of `X.δ`. +These are defined when `f` and `g` are composable morphisms +in `ι` and for any integer `n`. +In the documentation, the kernel `X.cycles n f g` of +`δ : H^n(g) ⟶ H^{n+1}(f)` shall be denoted `Z^n(f, g)`, +and the cokernel `X.opcycles n f g` of `δ : H^{n-1}(g) ⟶ H^n(f)` +shall be denoted `opZ^n(f, g)`. +The definitions `cyclesMap` and `opcyclesMap` give the +functoriality of these definitions with respect +to morphisms in `ComposableArrows ι 2`. + +We record that `Z^n(f, g)` is a kernel by the lemma +`kernelSequenceCycles_exact` and that `opZ^n(f, g)` is +a cokernel by the lemma `cokernelSequenceOpcycles_exact`. +We also provide a constructor `X.liftCycles` for morphisms +to cycles and `X.descOpcycles` for morphisms from opcycles. + +The fact that the morphisms `δ` are part of a long exact sequence allow +to show that `X.cycles` also identify to a cokernel (`cokernelIsoCycles`) +and `X.opcycles` to a kernel (`opcyclesIsoKernel`). +More precisely, the exactness of `H^n(f) ⟶ H^n(f ≫ g) ⟶ Z^n(f, g) ⟶ 0` +is `cokernelSequenceCycles_exact` and the exactness of +`0 ⟶ opZ^n(f, g) ⟶ H^n(f ≫ g) ⟶ H^n(g)` is +`kernelSequenceOpcycles_exact`. In particular, we also +get constructors `descCycles` and `liftOpcycles` for morphisms +from cycles and to opcycles. + +When `f₁`, `f₂` and `f₃` are composable morphisms, we introduce +morphisms `δToCycles : H^n(f₃) ⟶ Z^{n+1}(f₁, f₂)` and . +`δFromOpcycles : opZ^n(f₂, f₃) ⟶ H^{n+1}(f₁)`. + +## References +* [Jean-Louis Verdier, *Des catégories dérivées des catégories abéliennes*, II.4][verdier1996] +-/ + +@[expose] public section + +namespace CategoryTheory + +open Limits ComposableArrows + +namespace Abelian + +variable {C ι : Type*} [Category C] [Category ι] [Abelian C] + +namespace SpectralObject + +variable (X : SpectralObject C ι) + +section + +variable (n : ℤ) {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) + +/-- The kernel of `δ : H^n(g) ⟶ H^{n+1}(f)`. In the documentation, +this may be shortened as `Z^n(f, g)` -/ +noncomputable def cycles : C := kernel (X.δ n (n + 1) rfl f g) + +/-- The cokernel of `δ : H^{n-1}(g) ⟶ H^n(g)`. In the documentation, +this may be shortened as `opZ^n₁(f, g)`. -/ +noncomputable def opcycles : C := cokernel (X.δ (n - 1) n (by lia) f g) + +/-- The inclusion `Z^n(f, g) ⟶ H^n(g)` of the kernel of `δ`. -/ +noncomputable def iCycles : + X.cycles n f g ⟶ (X.H n).obj (mk₁ g) := + kernel.ι _ + +/-- The projection `H^n(f) ⟶ opZ^n(f, g)` to the cokernel of `δ`. -/ +noncomputable def pOpcycles : + (X.H n).obj (mk₁ f) ⟶ X.opcycles n f g := + cokernel.π _ + +instance : Mono (X.iCycles n f g) := by + dsimp [iCycles] + infer_instance + +instance : Epi (X.pOpcycles n f g) := by + dsimp [pOpcycles] + infer_instance + +lemma isZero_opcycles (h : IsZero ((X.H n).obj (mk₁ f))) : + IsZero (X.opcycles n f g) := by + rw [IsZero.iff_id_eq_zero, ← cancel_epi (X.pOpcycles ..)] + apply h.eq_of_src + +lemma isZero_cycles (h : IsZero ((X.H n).obj (mk₁ g))) : + IsZero (X.cycles n f g) := by + rw [IsZero.iff_id_eq_zero, ← cancel_mono (X.iCycles ..)] + apply h.eq_of_tgt + +end + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) + +@[reassoc (attr := simp)] +lemma iCycles_δ : X.iCycles n₀ f g ≫ X.δ n₀ n₁ hn₁ f g = 0 := by + subst hn₁ + simp [iCycles] + +@[reassoc (attr := simp)] +lemma δ_pOpcycles : X.δ n₀ n₁ hn₁ f g ≫ X.pOpcycles n₁ f g = 0 := by + obtain rfl : n₀ = n₁ - 1 := by lia + simp [pOpcycles] + +/-- The short complex which expresses `X.cycles` as the kernel of `X.δ`. -/ +@[simps] +noncomputable def kernelSequenceCycles : ShortComplex C := + ShortComplex.mk _ _ (X.iCycles_δ n₀ n₁ hn₁ f g) + +/-- The short complex which expresses `X.opcycles` as the cokernel of `X.δ`. -/ +@[simps] +noncomputable def cokernelSequenceOpcycles : ShortComplex C := + ShortComplex.mk _ _ (X.δ_pOpcycles n₀ n₁ hn₁ f g) + +instance : Mono (X.kernelSequenceCycles n₀ n₁ hn₁ f g).f := by + dsimp + infer_instance + +instance : Epi (X.cokernelSequenceOpcycles n₀ n₁ hn₁ f g).g := by + dsimp + infer_instance + +lemma kernelSequenceCycles_exact : + (X.kernelSequenceCycles n₀ n₁ hn₁ f g).Exact := by + subst hn₁ + apply ShortComplex.exact_kernel + +lemma cokernelSequenceOpcycles_exact : + (X.cokernelSequenceOpcycles n₀ n₁ hn₁ f g).Exact := by + obtain rfl : n₀ = n₁ - 1 := by lia + apply ShortComplex.exact_cokernel + +section + +variable {A : C} (x : A ⟶ (X.H n₀).obj (mk₁ g)) (hx : x ≫ X.δ n₀ n₁ hn₁ f g = 0) + +/-- Constructor for morphisms to `X.cycles`. -/ +noncomputable def liftCycles : + A ⟶ X.cycles n₀ f g := + kernel.lift _ x (by subst hn₁; exact hx) + +@[reassoc (attr := simp)] +lemma liftCycles_i : X.liftCycles n₀ n₁ hn₁ f g x hx ≫ X.iCycles n₀ f g = x := by + apply kernel.lift_ι + +end + +section + +variable {A : C} (x : (X.H n₁).obj (mk₁ f) ⟶ A) (hx : X.δ n₀ n₁ hn₁ f g ≫ x = 0) + +/-- Constructor for morphisms from `X.opcycles`. -/ +noncomputable def descOpcycles : + X.opcycles n₁ f g ⟶ A := + cokernel.desc _ x (by + obtain rfl : n₀ = n₁ -1 := by lia + exact hx) + +@[reassoc (attr := simp)] +lemma p_descOpcycles : X.pOpcycles n₁ f g ≫ X.descOpcycles n₀ n₁ hn₁ f g x hx = x := by + apply cokernel.π_desc + +end + +end + +section + +variable (n : ℤ) {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) + {i' j' k' : ι} (f' : i' ⟶ j') (g' : j' ⟶ k') + {i'' j'' k'' : ι} (f'' : i'' ⟶ j'') (g'' : j'' ⟶ k'') + +/-- The functoriality of `X.cycles` with respect to morphisms in +`ComposableArrows ι 2`. -/ +noncomputable def cyclesMap (α : mk₂ f g ⟶ mk₂ f' g') : + X.cycles n f g ⟶ X.cycles n f' g' := + X.liftCycles _ _ rfl _ _ + (X.iCycles n f g ≫ (X.H n).map (homMk₁ (α.app 1) (α.app 2) + (naturality' α 1 2))) (by + rw [Category.assoc, X.δ_naturality n _ rfl f g f' g' + (homMk₁ (α.app 0) (α.app 1) (naturality' α 0 1)) + (homMk₁ (α.app 1) (α.app 2) (naturality' α 1 2)) rfl, + iCycles_δ_assoc, zero_comp]) + +@[reassoc] +lemma cyclesMap_i (α : mk₂ f g ⟶ mk₂ f' g') (β : mk₁ g ⟶ mk₁ g') + (hβ : β = homMk₁ (α.app 1) (α.app 2) (naturality' α 1 2)) : + X.cyclesMap n f g f' g' α ≫ X.iCycles n f' g' = + X.iCycles n f g ≫ (X.H n).map β := by + subst hβ + simp [cyclesMap] + +@[simp] +lemma cyclesMap_id : + X.cyclesMap n f g f g (𝟙 _) = 𝟙 _ := by + rw [← cancel_mono (X.iCycles n f g), + X.cyclesMap_i n f g f g (𝟙 _) (𝟙 _) (by cat_disch), + Functor.map_id, Category.comp_id, Category.id_comp] + +@[reassoc] +lemma cyclesMap_comp (α : mk₂ f g ⟶ mk₂ f' g') (α' : mk₂ f' g' ⟶ mk₂ f'' g'') + (α'' : mk₂ f g ⟶ mk₂ f'' g'') (h : α ≫ α' = α'') : + X.cyclesMap n f g f' g' α ≫ X.cyclesMap n f' g' f'' g'' α' = + X.cyclesMap n f g f'' g'' α'' := by + subst h + rw [← cancel_mono (X.iCycles n f'' g''), Category.assoc, + X.cyclesMap_i n f' g' f'' g'' α' _ rfl, + X.cyclesMap_i_assoc n f g f' g' α _ rfl, + ← Functor.map_comp] + symm + apply X.cyclesMap_i + cat_disch + +/-- The functoriality of `X.opcycles` with respect to morphisms in +`ComposableArrows ι 2`. -/ +noncomputable def opcyclesMap (α : mk₂ f g ⟶ mk₂ f' g') : + X.opcycles n f g ⟶ X.opcycles n f' g' := + X.descOpcycles (n - 1) n (by lia) _ _ + ((X.H n).map (homMk₁ (by exact α.app 0) (by exact α.app 1) + (naturality' α 0 1)) ≫ X.pOpcycles n f' g') (by + rw [← X.δ_naturality_assoc (n - 1) n (by lia) f g f' g' + (homMk₁ (α.app 0) (α.app 1) (naturality' α 0 1)) + (homMk₁ (α.app 1) (α.app 2) (naturality' α 1 2)) rfl, + δ_pOpcycles, comp_zero]) + +@[reassoc] +lemma p_opcyclesMap (α : mk₂ f g ⟶ mk₂ f' g') (β : mk₁ f ⟶ mk₁ f') + (hβ : β = homMk₁ (α.app 0) (α.app 1) (naturality' α 0 1)) : + X.pOpcycles n f g ≫ X.opcyclesMap n f g f' g' α = + (X.H n).map β ≫ X.pOpcycles n f' g' := by + subst hβ + simp [opcyclesMap] + +@[simp] +lemma opcyclesMap_id : + X.opcyclesMap n f g f g (𝟙 _) = 𝟙 _ := by + rw [← cancel_epi (X.pOpcycles n f g), + X.p_opcyclesMap n f g f g (𝟙 _) (𝟙 _) (by cat_disch), + Functor.map_id, Category.comp_id, Category.id_comp] + +lemma opcyclesMap_comp (α : mk₂ f g ⟶ mk₂ f' g') (α' : mk₂ f' g' ⟶ mk₂ f'' g'') + (α'' : mk₂ f g ⟶ mk₂ f'' g'') (h : α ≫ α' = α'') : + X.opcyclesMap n f g f' g' α ≫ X.opcyclesMap n f' g' f'' g'' α' = + X.opcyclesMap n f g f'' g'' α'' := by + subst h + rw [← cancel_epi (X.pOpcycles n f g), + X.p_opcyclesMap_assoc n f g f' g' α _ rfl, + X.p_opcyclesMap n f' g' f'' g'' α' _ rfl, + ← Functor.map_comp_assoc] + symm + apply X.p_opcyclesMap + aesop_cat + +variable (fg : i ⟶ k) (h : f ≫ g = fg) (fg' : i' ⟶ k') (h' : f' ≫ g' = fg') + +/-- `X.cycles` also identifies to a cokernel. More precisely, +`Z^n(f, g)` identifies to the cokernel of `H^n(f) ⟶ H^n(f ≫ g)` -/ +noncomputable def cokernelIsoCycles : + cokernel ((X.H n).map (twoδ₂Toδ₁ f g fg h)) ≅ X.cycles n f g := + (X.composableArrows₅_exact n _ rfl f g fg h).cokerIsoKer 0 + +@[reassoc (attr := simp)] +lemma cokernelIsoCycles_hom_fac : + cokernel.π _ ≫ (X.cokernelIsoCycles n f g fg h).hom ≫ + X.iCycles n f g = (X.H n).map (twoδ₁Toδ₀ f g fg h) := + (X.composableArrows₅_exact n _ rfl f g fg h).cokerIsoKer_hom_fac 0 + +/-- `X.opcycles` also identifies to a kernel. More precisely, +`opZ(f, g)` identifies to the kernel of `H^n(f ≫ g) ⟶ H^n(g)` -/ +noncomputable def opcyclesIsoKernel : + X.opcycles n f g ≅ kernel ((X.H n).map (twoδ₁Toδ₀ f g fg h)) := + (X.composableArrows₅_exact (n - 1) n (by lia) f g fg h).cokerIsoKer 2 + +@[reassoc (attr := simp)] +lemma opcyclesIsoKernel_hom_fac : + X.pOpcycles n f g ≫ (X.opcyclesIsoKernel n f g fg h).hom ≫ + kernel.ι _ = (X.H n).map (twoδ₂Toδ₁ f g fg h) := + (X.composableArrows₅_exact (n - 1) n (by lia) f g fg h).cokerIsoKer_hom_fac 2 + +/-- The map `H^n(fg) ⟶ H^n(g)` factors through `Z^n(f, g)`. -/ +noncomputable def toCycles : (X.H n).obj (mk₁ fg) ⟶ X.cycles n f g := + kernel.lift _ ((X.H n).map (twoδ₁Toδ₀ f g fg h)) (by simp) + +instance : Epi (X.toCycles n f g fg h) := + (ShortComplex.exact_iff_epi_kernel_lift _).1 (X.exact₃ n _ rfl f g fg h) + +@[reassoc (attr := simp)] +lemma toCycles_i : + X.toCycles n f g fg h ≫ X.iCycles n f g = (X.H n).map (twoδ₁Toδ₀ f g fg h) := + kernel.lift_ι .. + +@[reassoc] +lemma toCycles_cyclesMap (α : mk₂ f g ⟶ mk₂ f' g') (β : mk₁ fg ⟶ mk₁ fg') + (hβ₀ : β.app 0 = α.app 0) (hβ₁ : β.app 1 = α.app 2) : + X.toCycles n f g fg h ≫ X.cyclesMap n f g f' g' α = + (X.H n).map β ≫ X.toCycles n f' g' fg' h' := by + rw [← cancel_mono (X.iCycles n f' g'), Category.assoc, Category.assoc, toCycles_i, + X.cyclesMap_i n f g f' g' α (homMk₁ (α.app 1) (α.app 2) (naturality' α 1 2)) rfl, + toCycles_i_assoc, ← Functor.map_comp, ← Functor.map_comp] + congr 1 + ext + · dsimp + rw [hβ₀] + exact naturality' α 0 1 + · dsimp + rw [hβ₁, Category.comp_id, Category.id_comp] + +/-- The map `H^n(f) ⟶ H^n(f ≫ g)` factors through `opZ^n(f, g)`. -/ +noncomputable def fromOpcycles : + X.opcycles n f g ⟶ (X.H n).obj (mk₁ fg) := + cokernel.desc _ ((X.H n).map (twoδ₂Toδ₁ f g fg h)) (by simp) + +instance : Mono (X.fromOpcycles n f g fg h) := + (ShortComplex.exact_iff_mono_cokernel_desc _).1 (X.exact₁ (n - 1) n (by lia) f g fg h) + +@[reassoc (attr := simp)] +lemma p_fromOpcycles : + X.pOpcycles n f g ≫ X.fromOpcycles n f g fg h = + (X.H n).map (twoδ₂Toδ₁ f g fg h) := + cokernel.π_desc .. + +@[reassoc] +lemma opcyclesMap_fromOpcycles (α : mk₂ f g ⟶ mk₂ f' g') (β : mk₁ fg ⟶ mk₁ fg') + (hβ₀ : β.app 0 = α.app 0) (hβ₁ : β.app 1 = α.app 2) : + X.opcyclesMap n f g f' g' α ≫ X.fromOpcycles n f' g' fg' h' = + X.fromOpcycles n f g fg h ≫ (X.H n).map β := by + rw [← cancel_epi (X.pOpcycles n f g), p_fromOpcycles_assoc, + X.p_opcyclesMap_assoc n f g f' g' α (homMk₁ (α.app 0) (α.app 1) + (naturality' α 0 1)) rfl, + p_fromOpcycles, ← Functor.map_comp, ← Functor.map_comp] + congr 1 + ext + · cat_disch + · dsimp + rw [hβ₁] + exact (naturality' α 1 2).symm + +@[reassoc (attr := simp)] +lemma H_map_twoδ₂Toδ₁_toCycles : + (X.H n).map (twoδ₂Toδ₁ f g fg h) ≫ X.toCycles n f g fg h = 0 := by + simp [← cancel_mono (X.iCycles n f g)] + +@[reassoc (attr := simp)] +lemma fromOpcycles_H_map_twoδ₁Toδ₀ : + X.fromOpcycles n f g fg h ≫ (X.H n).map (twoδ₁Toδ₀ f g fg h) = 0 := by + simp [← cancel_epi (X.pOpcycles n f g)] + +/-- The short complex expressing `Z^n(f, g)` as a cokernel of +the map `H^n(f) ⟶ H^n(f ≫ g)`. -/ +@[simps] +noncomputable def cokernelSequenceCycles : ShortComplex C := + ShortComplex.mk _ _ (X.H_map_twoδ₂Toδ₁_toCycles n f g fg h) + +/-- The short complex expressing `opZ^n(f, g)` as a kernel of +the map `H^n(f ≫ g) ⟶ H^n(g)`. -/ +@[simps] +noncomputable def kernelSequenceOpcycles : ShortComplex C := + ShortComplex.mk _ _ (X.fromOpcycles_H_map_twoδ₁Toδ₀ n f g fg h) + +instance : Epi (X.cokernelSequenceCycles n f g fg h).g := by + dsimp + infer_instance + +instance : Mono (X.kernelSequenceOpcycles n f g fg h).f := by + dsimp + infer_instance + +/-- `Z^n(f, g)` identifies to a cokernel of the `H^n(f) ⟶ H^n(f ≫ g)`. -/ +lemma cokernelSequenceCycles_exact : + (X.cokernelSequenceCycles n f g fg h).Exact := by + apply ShortComplex.exact_of_g_is_cokernel + exact IsColimit.ofIsoColimit (cokernelIsCokernel _) + (Cofork.ext (X.cokernelIsoCycles n f g fg h) (by + simp [← cancel_mono (X.iCycles n f g)])) + +/-- `opZ^n(f, g)` identifies to the kernel of `H^n(f ≫ g) ⟶ H^n(g)`. -/ +lemma kernelSequenceOpcycles_exact : + (X.kernelSequenceOpcycles n f g fg h).Exact := by + apply ShortComplex.exact_of_f_is_kernel + exact IsLimit.ofIsoLimit (kernelIsKernel _) + (Iso.symm (Fork.ext (X.opcyclesIsoKernel n f g fg h) (by + simp [← cancel_epi (X.pOpcycles n f g)]))) + +lemma isIso_toCycles (hf : IsZero ((X.H n).obj (mk₁ f))) : + IsIso (X.toCycles n f g fg h) := by + have : Mono (X.toCycles n f g fg h) := + (X.cokernelSequenceCycles_exact n f g fg h).mono_g (hf.eq_of_src _ _) + exact Balanced.isIso_of_mono_of_epi _ + +lemma isIso_fromOpcycles (hg : IsZero ((X.H n).obj (mk₁ g))) : + IsIso (X.fromOpcycles n f g fg h) := by + have : Epi (X.fromOpcycles n f g fg h) := + (X.kernelSequenceOpcycles_exact n f g fg h).epi_f (hg.eq_of_tgt _ _) + exact Balanced.isIso_of_mono_of_epi _ + +section + +variable {A : C} (x : (X.H n).obj (mk₁ fg) ⟶ A) + (hx : (X.H n).map (twoδ₂Toδ₁ f g fg h) ≫ x = 0) + +/-- Constructor for morphisms from `X.cycles`. -/ +noncomputable def descCycles : + X.cycles n f g ⟶ A := + (X.cokernelSequenceCycles_exact n f g fg h).desc x hx + +@[reassoc (attr := simp)] +lemma toCycles_descCycles : + X.toCycles n f g fg h ≫ X.descCycles n f g fg h x hx = x := + (X.cokernelSequenceCycles_exact n f g fg h).g_desc x hx + +end + +section + +variable {A : C} (x : A ⟶ (X.H n).obj (mk₁ fg)) + (hx : x ≫ (X.H n).map (twoδ₁Toδ₀ f g fg h) = 0) + +/-- Constructor for morphisms to `X.opcycles`. -/ +noncomputable def liftOpcycles : + A ⟶ X.opcycles n f g := + (X.kernelSequenceOpcycles_exact n f g fg h).lift x hx + +@[reassoc (attr := simp)] +lemma liftOpcycles_fromOpcycles : + X.liftOpcycles n f g fg h x hx ≫ X.fromOpcycles n f g fg h = x := + (X.kernelSequenceOpcycles_exact n f g fg h).lift_f x hx + +end + +end + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) + {i j k l : ι} (f₁ : i ⟶ j) (f₂ : j ⟶ k) (f₃ : k ⟶ l) + (f₁₂ : i ⟶ k) (h₁₂ : f₁ ≫ f₂ = f₁₂) (f₂₃ : j ⟶ l) (h₂₃ : f₂ ≫ f₃ = f₂₃) + +/-- The morphism `H^{n₀}(f₃) ⟶ Z^{n₁}(f₁, f₂)` induced by `δ` +when `f₁`, `f₂`, `f₃` are composable morphisms and `n₀ + 1 = n₁`. -/ +noncomputable def δToCycles : (X.H n₀).obj (mk₁ f₃) ⟶ X.cycles n₁ f₁ f₂ := + X.liftCycles n₁ _ rfl f₁ f₂ (X.δ n₀ n₁ hn₁ f₂ f₃) (by simp) + +@[reassoc (attr := simp)] +lemma δToCycles_iCycles : + X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃ ≫ X.iCycles n₁ f₁ f₂ = + X.δ n₀ n₁ hn₁ f₂ f₃ := by + simp only [δToCycles, liftCycles_i] + +@[reassoc (attr := simp)] +lemma δ_toCycles : + X.δ n₀ n₁ hn₁ f₁₂ f₃ ≫ X.toCycles n₁ f₁ f₂ f₁₂ h₁₂ = + X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃ := by + rw [← cancel_mono (X.iCycles n₁ f₁ f₂), Category.assoc, + toCycles_i, δToCycles_iCycles, + ← X.δ_naturality n₀ n₁ hn₁ f₁₂ f₃ f₂ f₃ (twoδ₁Toδ₀ f₁ f₂ f₁₂ h₁₂) (𝟙 _) rfl, + Functor.map_id, Category.id_comp] + +/-- The morphism `opZ^{n₀}(f₂, f₃) ⟶ H^{n₁}(f₁)` induced by `δ` +when `f₁`, `f₂`, `f₃` are composable morphisms and `n₀ + 1 = n₁`. -/ +noncomputable def δFromOpcycles : X.opcycles n₀ f₂ f₃ ⟶ (X.H n₁).obj (mk₁ f₁) := + X.descOpcycles (n₀ - 1) n₀ (by lia) f₂ f₃ (X.δ n₀ n₁ hn₁ f₁ f₂) (by simp) + +@[reassoc (attr := simp)] +lemma pOpcycles_δFromOpcycles : + X.pOpcycles n₀ f₂ f₃ ≫ X.δFromOpcycles n₀ n₁ hn₁ f₁ f₂ f₃ = + X.δ n₀ n₁ hn₁ f₁ f₂ := by + simp only [δFromOpcycles, p_descOpcycles] + +@[reassoc (attr := simp)] +lemma fromOpcyles_δ : + X.fromOpcycles n₀ f₂ f₃ f₂₃ h₂₃ ≫ X.δ n₀ n₁ hn₁ f₁ f₂₃ = + X.δFromOpcycles n₀ n₁ hn₁ f₁ f₂ f₃ := by + rw [← cancel_epi (X.pOpcycles n₀ f₂ f₃), + p_fromOpcycles_assoc, pOpcycles_δFromOpcycles, + X.δ_naturality n₀ n₁ hn₁ f₁ f₂ f₁ f₂₃ (𝟙 _) (twoδ₂Toδ₁ f₂ f₃ f₂₃ h₂₃) rfl, + Functor.map_id, Category.comp_id] + +end + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/Differentials.lean b/Mathlib/Algebra/Homology/SpectralObject/Differentials.lean new file mode 100644 index 00000000000000..af3ce320f85882 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/Differentials.lean @@ -0,0 +1,255 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.Page +public import Mathlib.CategoryTheory.ComposableArrows.Three + +/-! +# Differentials of a spectral object + +Let `X` be a spectral object in an abelian category `C` indexed by a category `ι`. +In this file, we construct the differentials `d : E^{n}(f₃, f₄, f₅) ⟶ E^{n+1}(f₁, f₂, f₃)` +that are attached to families of five composable morphisms `f₁`, `f₂`, `f₃`, `f₄`, `f₅` +in `ι`. We show that `d ≫ d = 0`. The homology of these differentials is computed in the +file `Mathlib/Algebra/Homology/SpectralObject/Homology.lean`. + +## References +* [Jean-Louis Verdier, *Des catégories dérivées des catégories abéliennes*, II.4][verdier1996] + +-/ + +@[expose] public section + +namespace CategoryTheory + +variable {C ι : Type*} [Category C] [Category ι] [Abelian C] + +open Category ComposableArrows Limits Preadditive + +namespace Abelian + +namespace SpectralObject + +variable (X : SpectralObject C ι) + +section + +variable (n₀ n₁ n₂ n₃ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ i₃ i₄ i₅ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) (f₁₂ : i₀ ⟶ i₂) (h₁₂ : f₁ ≫ f₂ = f₁₂) + (f₂₃ : i₁ ⟶ i₃) (h₂₃ : f₂ ≫ f₃ = f₂₃) + (f₃₄ : i₂ ⟶ i₄) (h₃₄ : f₃ ≫ f₄ = f₃₄) + (f₄₅ : i₃ ⟶ i₅) (h₄₅ : f₄ ≫ f₅ = f₄₅) + +/-- The differential `E^{n}(f₃, f₄, f₅) ⟶ E^{n+1}(f₁, f₂, f₃)` that is +attached to a family of five composable morphisms `f₁`, `f₂`, `f₃`, `f₄`, `f₅`. -/ +noncomputable def d : X.E n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅ ⟶ X.E n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ := + X.descE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅ _ rfl (X.δ n₁ n₂ hn₂ (f₁ ≫ f₂) (f₃ ≫ f₄) ≫ + X.toCycles n₂ f₁ f₂ _ rfl ≫ X.πE n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃) (by + rw [X.δ_naturality_assoc n₁ n₂ hn₂ (f₁ ≫ f₂) f₃ (f₁ ≫ f₂) (f₃ ≫ f₄) + (𝟙 _) (twoδ₂Toδ₁ f₃ f₄ _ rfl) rfl, Functor.map_id, id_comp, + δ_toCycles_assoc, δToCycles_πE]) (by rw [δ_δ_assoc, zero_comp]) + +@[reassoc] +lemma toCycles_πE_d : + X.toCycles n₁ f₃ f₄ f₃₄ h₃₄ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅ ≫ + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ = + X.δ n₁ n₂ hn₂ f₁₂ f₃₄ ≫ X.toCycles n₂ f₁ f₂ f₁₂ h₁₂ ≫ + X.πE n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ := by + subst h₁₂ h₃₄ + simp only [d, δ_toCycles_assoc, toCycles_πE_descE] + +include h₃₄ in +@[reassoc] +lemma d_ιE_fromOpcycles : + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ ≫ X.ιE n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ ≫ + X.fromOpcycles n₂ f₂ f₃ f₂₃ h₂₃ = + X.ιE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅ ≫ X.fromOpcycles n₁ f₄ f₅ f₄₅ h₄₅ ≫ + X.δ n₁ n₂ hn₂ f₂₃ f₄₅ := by + rw [← cancel_epi (X.πE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅), + ← cancel_epi (X.toCycles n₁ f₃ f₄ f₃₄ h₃₄), + X.toCycles_πE_d_assoc n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ _ rfl] + rw [πE_ιE_assoc, p_fromOpcycles, toCycles_i_assoc, fromOpcyles_δ, + πE_ιE_assoc, pOpcycles_δFromOpcycles, toCycles_i_assoc, ← Functor.map_comp] + symm + apply δ_naturality + simp + +end + +section + +variable (n₀ n₁ n₂ n₃ n₄ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) (hn₄ : n₃ + 1 = n₄) + {i₀ i₁ i₂ i₃ i₄ i₅ i₆ i₇ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) (f₆ : i₅ ⟶ i₆) (f₇ : i₆ ⟶ i₇) + +@[reassoc (attr := simp)] +lemma d_d : + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₃ f₄ f₅ f₆ f₇ ≫ + X.d n₁ n₂ n₃ n₄ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ = 0 := by + rw [← cancel_epi (X.πE n₀ n₁ n₂ hn₁ hn₂ f₅ f₆ f₇), + ← cancel_epi (X.toCycles n₁ f₅ f₆ _ rfl), comp_zero, comp_zero, + X.toCycles_πE_d_assoc n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₃ f₄ f₅ f₆ f₇ _ rfl _ rfl, + X.toCycles_πE_d n₁ n₂ n₃ n₄ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ _ rfl _ rfl, + δ_δ_assoc, zero_comp] + +end + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) + {i j k l : ι} (f₁ : i ⟶ j) (f₂ : j ⟶ k) (f₃ : k ⟶ l) + (f₁₂ : i ⟶ k) (h₁₂ : f₁ ≫ f₂ = f₁₂) (f₂₃ : j ⟶ l) (h₂₃ : f₂ ≫ f₃ = f₂₃) + +/-- When `f₁`, `f₂` and `f₃` are composable morphisms, this is the canonical +morphism `Z^n(f₂, f₃) ⟶ opZ^{n+1}(f₁, f₂)` that is induced both +by `δ : H^n(f₂ ≫ f₃) ⟶ H^{n+1}(f₁)` (see `toCycles_Ψ`) and +by `δ : H^n(f₃) ⟶ H^{n+1}(f₁ ≫ f₂)` (see `Ψ_fromOpcycles`). +See the lemma `πE_d_ιE` for the relation between this definition +and the differentials `d`. -/ +noncomputable def Ψ : X.cycles n₀ f₂ f₃ ⟶ X.opcycles n₁ f₁ f₂ := + X.descCycles n₀ f₂ f₃ _ rfl + (X.δ n₀ n₁ hn₁ f₁ (f₂ ≫ f₃) ≫ X.pOpcycles n₁ f₁ f₂) (by + rw [X.δ_naturality_assoc n₀ n₁ hn₁ f₁ f₂ f₁ (f₂ ≫ f₃) (𝟙 _) (twoδ₂Toδ₁ f₂ f₃ _ rfl) rfl, + Functor.map_id, id_comp, δ_pOpcycles]) + +@[reassoc (attr := simp)] +lemma toCycles_Ψ : + X.toCycles n₀ f₂ f₃ f₂₃ h₂₃ ≫ X.Ψ n₀ n₁ hn₁ f₁ f₂ f₃ = + X.δ n₀ n₁ hn₁ f₁ f₂₃ ≫ X.pOpcycles n₁ f₁ f₂ := by + subst h₂₃ + simp only [Ψ, toCycles_descCycles] + +@[reassoc (attr := simp)] +lemma Ψ_fromOpcycles : + X.Ψ n₀ n₁ hn₁ f₁ f₂ f₃ ≫ X.fromOpcycles n₁ f₁ f₂ f₁₂ h₁₂ = + X.iCycles n₀ f₂ f₃ ≫ X.δ n₀ n₁ hn₁ f₁₂ f₃ := by + rw [← cancel_epi (X.toCycles n₀ f₂ f₃ _ rfl), + toCycles_Ψ_assoc, p_fromOpcycles, toCycles_i_assoc] + exact (X.δ_naturality _ _ _ _ _ _ _ _ _ rfl).symm + +include h₂₃ in +lemma cyclesMap_Ψ : + X.cyclesMap n₀ _ _ _ _ (threeδ₁Toδ₀ f₁ f₂ f₃ f₁₂ h₁₂) ≫ + X.Ψ n₀ n₁ hn₁ f₁ f₂ f₃ = 0 := by + rw [← cancel_epi (X.toCycles n₀ f₁₂ f₃ (f₁ ≫ f₂ ≫ f₃) + (by rw [reassoc_of% h₁₂])), comp_zero, + X.toCycles_cyclesMap_assoc n₀ f₁₂ f₃ f₂ f₃ (f₁ ≫ f₂ ≫ f₃) + (by rw [reassoc_of% h₁₂]) f₂₃ h₂₃ (threeδ₁Toδ₀ f₁ f₂ f₃ f₁₂ h₁₂) + (twoδ₁Toδ₀ f₁ f₂₃ (f₁ ≫ f₂ ≫ f₃) (by rw [h₂₃])) rfl rfl, + toCycles_Ψ, zero₃_assoc, zero_comp] + +include h₁₂ in +lemma Ψ_opcyclesMap : + X.Ψ n₀ n₁ hn₁ f₁ f₂ f₃ ≫ + X.opcyclesMap n₁ _ _ _ _ (threeδ₃Toδ₂ f₁ f₂ f₃ f₂₃ h₂₃) = 0 := by + rw [← cancel_mono (X.fromOpcycles n₁ f₁ f₂₃ (f₁ ≫ f₂ ≫ f₃) (by rw [h₂₃])), + zero_comp, assoc, X.opcyclesMap_fromOpcycles n₁ f₁ f₂ f₁ f₂₃ f₁₂ h₁₂ + (f₁ ≫ f₂ ≫ f₃) (by rw [h₂₃]) (threeδ₃Toδ₂ f₁ f₂ f₃ f₂₃ h₂₃) + (twoδ₂Toδ₁ f₁₂ f₃ (f₁ ≫ f₂ ≫ f₃) (by rw [reassoc_of% h₁₂])) rfl rfl, + Ψ_fromOpcycles_assoc, zero₁, comp_zero] + +/-- When `f₁`, `f₂` and `f₃` are composable morphisms, this is the exact sequence +`Z^n(f₁ ≫ f₂, f₃) ⟶ Z^n(f₂, f₃) ⟶ opZ^{n+1}(f₁, f₂) ⟶ opZ^{n+1}(f₁, f₂ ≫ f₃)`. -/ +noncomputable def sequenceΨ : ComposableArrows C 3 := + mk₃ (X.cyclesMap n₀ _ _ _ _ (threeδ₁Toδ₀ f₁ f₂ f₃ f₁₂ h₁₂)) + (X.Ψ n₀ n₁ hn₁ f₁ f₂ f₃) + (X.opcyclesMap n₁ _ _ _ _ (threeδ₃Toδ₂ f₁ f₂ f₃ f₂₃ h₂₃)) + +lemma cyclesMap_Ψ_exact : + (ShortComplex.mk _ _ (X.cyclesMap_Ψ n₀ n₁ hn₁ f₁ f₂ f₃ f₁₂ h₁₂ f₂₃ h₂₃)).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A z hz + refine ⟨A, 𝟙 _, inferInstance, + X.liftCycles n₀ n₁ hn₁ f₁₂ f₃ (z ≫ X.iCycles n₀ f₂ f₃) ?_, ?_⟩ + · dsimp + rw [assoc, ← X.Ψ_fromOpcycles n₀ n₁ hn₁ f₁ f₂ f₃ f₁₂ h₁₂ , reassoc_of% hz, zero_comp] + · dsimp + rw [← cancel_mono (X.iCycles n₀ f₂ f₃), id_comp, assoc, + X.cyclesMap_i n₀ _ _ _ _ (threeδ₁Toδ₀ f₁ f₂ f₃ f₁₂ h₁₂) (𝟙 _) (by cat_disch), + Functor.map_id, comp_id, liftCycles_i] + +lemma Ψ_opcyclesMap_exact : + (ShortComplex.mk _ _ (X.Ψ_opcyclesMap n₀ n₁ hn₁ f₁ f₂ f₃ f₁₂ h₁₂ f₂₃ h₂₃)).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A z₀ hz₀ + dsimp at z₀ hz₀ + obtain ⟨A₁, π₁, _, z₁, hz₁⟩ := + surjective_up_to_refinements_of_epi (X.pOpcycles n₁ f₁ f₂) z₀ + obtain ⟨A₂, π₂, _, z₂, hz₂⟩ := + (X.cokernelSequenceOpcycles_exact n₀ n₁ hn₁ f₁ f₂₃).exact_up_to_refinements z₁ (by + dsimp + have H := X.p_opcyclesMap n₁ f₁ f₂ f₁ f₂₃ + (threeδ₃Toδ₂ f₁ f₂ f₃ f₂₃ h₂₃) (𝟙 _) (by cat_disch) + rw [Functor.map_id, id_comp] at H + rw [← H, ← reassoc_of% hz₁, hz₀, comp_zero]) + dsimp at z₂ hz₂ + refine ⟨A₂, π₂ ≫ π₁, inferInstance, z₂ ≫ X.toCycles n₀ f₂ f₃ f₂₃ h₂₃, ?_⟩ + dsimp + rw [← cancel_mono (X.fromOpcycles n₁ f₁ f₂ f₁₂ h₁₂), assoc, assoc, + assoc, assoc, toCycles_Ψ_assoc, p_fromOpcycles, ← reassoc_of% hz₂, + reassoc_of% hz₁, p_fromOpcycles] + +lemma sequenceΨ_exact : + (X.sequenceΨ n₀ n₁ hn₁ f₁ f₂ f₃ f₁₂ h₁₂ f₂₃ h₂₃).Exact := + exact_of_δ₀ + (X.cyclesMap_Ψ_exact n₀ n₁ hn₁ f₁ f₂ f₃ f₁₂ h₁₂ f₂₃ h₂₃).exact_toComposableArrows + (X.Ψ_opcyclesMap_exact n₀ n₁ hn₁ f₁ f₂ f₃ f₁₂ h₁₂ f₂₃ h₂₃).exact_toComposableArrows + +end + + +section + +variable (n₀ n₁ n₂ n₃ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ i₃ i₄ i₅ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) + +@[reassoc (attr := simp)] +lemma πE_d_ιE : + X.πE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅ ≫ X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ ≫ + X.ιE n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ = X.Ψ n₁ n₂ hn₂ f₂ f₃ f₄ := by + rw [← cancel_epi (X.toCycles n₁ f₃ f₄ _ rfl), toCycles_Ψ, + X.toCycles_πE_d_assoc n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ _ rfl, + πE_ιE, toCycles_i_assoc, ← X.δ_naturality_assoc n₁ n₂ hn₂ (f₁ ≫ f₂) (f₃ ≫ f₄) f₂ (f₃ ≫ f₄) + (twoδ₁Toδ₀ f₁ f₂ _ rfl) (𝟙 _) rfl, Functor.map_id, id_comp] + +end + +section + +variable (n₀ n₁ n₂ n₃ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ : ι} + (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) + +@[reassoc (attr := simp)] +lemma πE_EIsoH_hom : + X.πE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i₀) f₁ (𝟙 i₁) ≫ (X.EIsoH n₀ n₁ n₂ hn₁ hn₂ f₁).hom = + (X.cyclesIsoH n₁ n₂ hn₂ f₁).hom := by + obtain rfl : n₀ = n₁ - 1 := by lia + simp [πE, cyclesIsoH, EIsoH] + +@[reassoc] +lemma d_EIsoH_hom : + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ (𝟙 i₀) f₁ (𝟙 i₁) f₂ (𝟙 i₂) ≫ + (X.EIsoH n₁ n₂ n₃ hn₂ hn₃ f₁).hom = + (X.EIsoH n₀ n₁ n₂ hn₁ hn₂ f₂).hom ≫ X.δ n₁ n₂ hn₂ f₁ f₂ := by + rw [← cancel_epi (X.πE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i₁) f₂ (𝟙 i₂)), + ← cancel_epi (X.toCycles n₁ (𝟙 i₁) f₂ f₂ (by simp)), + X.toCycles_πE_d_assoc n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ (𝟙 i₀) f₁ (𝟙 i₁) f₂ (𝟙 i₂) f₁ (by simp), + πE_EIsoH_hom, πE_EIsoH_hom_assoc, cyclesIsoH_inv_hom_id, comp_id, + cyclesIsoH_inv_hom_id_assoc] + +end + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/EpiMono.lean b/Mathlib/Algebra/Homology/SpectralObject/EpiMono.lean new file mode 100644 index 00000000000000..ac8efa1e2f5da0 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/EpiMono.lean @@ -0,0 +1,261 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.Differentials +public import Mathlib.CategoryTheory.ComposableArrows.Four + +/-! +# Spectral objects in abelian categories + + +## References +* [Jean-Louis Verdier, *Des catégories dérivées des catégories abéliennes*, II.4][verdier1996] + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category Limits ComposableArrows + +namespace Abelian + +namespace SpectralObject + +variable {C ι ι' κ : Type*} [Category C] [Abelian C] [Category ι] [Preorder ι'] + (X : SpectralObject C ι) (X' : SpectralObject C ι') + +section + +variable (n₀ n₁ n₂ n₃ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i₀' i₀ i₁ i₂ i₃ i₃' : ι} (f₁ : i₀ ⟶ i₁) + (f₁' : i₀' ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) (f₃' : i₂ ⟶ i₃') + +lemma epi_EMap (α : mk₃ f₁ f₂ f₃ ⟶ mk₃ f₁ f₂ f₃') + (hα₀ : α.app 0 = 𝟙 _) (hα₁ : α.app 1 = 𝟙 _) (hα₂ : α.app 2 = 𝟙 _) : + Epi (X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁ f₂ f₃' α) := by + have := X.πE_EMap n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _ α (𝟙 _) (by cat_disch) + rw [cyclesMap_id, id_comp] at this + exact epi_of_epi_fac this + +lemma mono_EMap (α : mk₃ f₁ f₂ f₃ ⟶ mk₃ f₁' f₂ f₃) + (hα₁ : α.app 1 = 𝟙 _) (hα₂ : α.app 2 = 𝟙 _) (hα₃ : α.app 3 = 𝟙 _) : + Mono (X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂ f₃ α) := by + have := X.EMap_ιE n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _ α (𝟙 _) (by cat_disch) + rw [opcyclesMap_id, comp_id] at this + exact mono_of_mono_fac this + +end + +section + +variable (n₀ n₁ n₂ n₃ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ i₃ i₄ i₅ i₆ i₇ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) + (f₂₃ : i₁ ⟶ i₃) (h₂₃ : f₂ ≫ f₃ = f₂₃) + (f₃₄ : i₂ ⟶ i₄) (h₃₄ : f₃ ≫ f₄ = f₃₄) + +@[reassoc (attr := simp)] +lemma d_EMap_fourδ₄Toδ₃ : + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ ≫ + X.EMap n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ f₁ f₂ f₃₄ (fourδ₄Toδ₃ f₁ f₂ f₃ f₄ f₃₄ h₃₄) = 0 := by + rw [← cancel_epi (X.πE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅), + ← cancel_epi (X.toCycles n₁ f₃ f₄ f₃₄ h₃₄), comp_zero, comp_zero, + X.toCycles_πE_d_assoc n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ _ rfl f₃₄ h₃₄, + X.πE_EMap n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ f₁ f₂ f₃₄ + (fourδ₄Toδ₃ f₁ f₂ f₃ f₄ f₃₄ h₃₄) (𝟙 _) (by ext <;> simp; rfl), + cyclesMap_id, Category.id_comp, δ_toCycles_assoc, δToCycles_πE] + +instance : + Epi (X.EMap n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ f₁ f₂ f₃₄ (fourδ₄Toδ₃ f₁ f₂ f₃ f₄ f₃₄ h₃₄)) := + X.epi_EMap _ _ _ _ _ _ _ _ _ _ rfl rfl rfl + +lemma isIso_EMap_fourδ₄Toδ₃ (h : ((X.H n₁).map (twoδ₁Toδ₀ f₃ f₄ f₃₄ h₃₄) = 0)) : + IsIso (X.EMap n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ f₁ f₂ f₃₄ (fourδ₄Toδ₃ f₁ f₂ f₃ f₄ f₃₄ h₃₄)) := by + apply ShortComplex.isIso_homologyMap_of_epi_of_isIso_of_mono' + · exact (X.exact₂ _ f₃ f₄ f₃₄ h₃₄).epi_f h + · dsimp + convert inferInstanceAs (IsIso ((X.H n₂).map (𝟙 _))) + cat_disch + · dsimp + convert inferInstanceAs (Mono ((X.H n₃).map (𝟙 (mk₁ f₁)))) + cat_disch + +lemma isIso_EMap_fourδ₄Toδ₃_of_isZero (h : IsZero ((X.H n₁).obj (mk₁ f₄))) : + IsIso (X.EMap n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ f₁ f₂ f₃₄ (fourδ₄Toδ₃ f₁ f₂ f₃ f₄ f₃₄ h₃₄)) := by + apply X.isIso_EMap_fourδ₄Toδ₃ + apply h.eq_of_tgt + +@[reassoc (attr := simp)] +lemma EMap_fourδ₁Toδ₀_d : + X.EMap n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅ f₃ f₄ f₅ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃) ≫ + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ = 0 := by + rw [← cancel_mono (X.ιE n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃), + ← cancel_mono (X.fromOpcycles n₂ f₂ f₃ f₂₃ h₂₃), zero_comp, zero_comp, assoc, + assoc, X.d_ιE_fromOpcycles n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₂₃ h₂₃ _ rfl _ rfl] + rw [X.EMap_ιE_assoc n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅ f₃ f₄ f₅ + (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃) (𝟙 _) (by ext <;> simp <;> rfl), + opcyclesMap_id, fromOpcyles_δ, id_comp, ιE_δFromOpcycles] + +instance : + Mono (X.EMap n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅ f₃ f₄ f₅ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃)) := + X.mono_EMap _ _ _ _ _ _ _ _ _ _ rfl rfl rfl + +lemma isIso_EMap_fourδ₁Toδ₀ (h : ((X.H n₂).map (twoδ₂Toδ₁ f₂ f₃ f₂₃ h₂₃) = 0)) : + IsIso (X.EMap n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅ f₃ f₄ f₅ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃)) := by + apply ShortComplex.isIso_homologyMap_of_epi_of_isIso_of_mono' + · dsimp + convert inferInstanceAs (Epi ((X.H n₀).map (𝟙 _))) + cat_disch + · dsimp + convert inferInstanceAs (IsIso ((X.H n₁).map (𝟙 _))) + cat_disch + · exact (X.exact₂ n₂ f₂ f₃ f₂₃ h₂₃).mono_g h + +lemma isIso_EMap_fourδ₁Toδ₀_of_isZero (h : IsZero ((X.H n₂).obj (mk₁ f₂))) : + IsIso (X.EMap n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅ f₃ f₄ f₅ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃)) := by + apply X.isIso_EMap_fourδ₁Toδ₀ + apply h.eq_of_src + +end + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + (i₀ i₁ i₂ i₃ i₄ i₅ : ι') (hi₀₁ : i₀ ≤ i₁) + (hi₁₂ : i₁ ≤ i₂) (hi₂₃ : i₂ ≤ i₃) (hi₃₄ : i₃ ≤ i₄) (hi₄₅ : i₄ ≤ i₅) + +/-- EMapFourδ₁Toδ₀' -/ +noncomputable abbrev EMapFourδ₁Toδ₀' := + X'.EMap n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _ (fourδ₁Toδ₀' i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) + + +/-- EMapFourδ₄Toδ₃' -/ +noncomputable abbrev EMapFourδ₄Toδ₃' := + X'.EMap n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _ (fourδ₄Toδ₃' i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) + +@[reassoc] +lemma EMapFourδ₁Toδ₀'_comp : + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₃ i₄ i₅ hi₀₁ (hi₁₂.trans hi₂₃) hi₃₄ hi₄₅ ≫ + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₁ i₂ i₃ i₄ i₅ hi₁₂ hi₂₃ hi₃₄ hi₄₅ = + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₂ i₃ i₄ i₅ (hi₀₁.trans hi₁₂) hi₂₃ hi₃₄ hi₄₅ := by + rw [← EMap_comp] + rfl + +@[reassoc] +lemma EMapFourδ₄Toδ₃'_comp : + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ ≫ + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₄ i₅ hi₀₁ hi₁₂ (hi₂₃.trans hi₃₄) hi₄₅ = + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₅ hi₀₁ hi₁₂ hi₂₃ (hi₃₄.trans hi₄₅) := by + dsimp [EMapFourδ₄Toδ₃'] + rw [← EMap_comp] + rfl + +@[reassoc] +lemma EMapFourδ₁Toδ₀'_EMapFourδ₃Toδ₃' : + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ ≫ + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₁ i₂ i₃ i₄ i₅ hi₁₂ hi₂₃ hi₃₄ hi₄₅ = + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₂ i₃ i₄ i₅ _ _ _ hi₄₅ ≫ + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₅ hi₀₁ _ _ _ := by + dsimp [EMapFourδ₁Toδ₀', EMapFourδ₄Toδ₃'] + rw [← EMap_comp, ← EMap_comp] + rfl + +section + +variable (h : IsZero ((X'.H n₂).obj (mk₁ (homOfLE hi₀₁)))) + +include h in +lemma isIso_EMapFourδ₁Toδ₀' : + IsIso (X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) := by + apply X'.isIso_EMap_fourδ₁Toδ₀_of_isZero + exact h + +/-- isoEMapFourδ₁Toδ₀' -/ +@[simps! hom] +noncomputable def isoEMapFourδ₁Toδ₀' : + X'.E n₀ n₁ n₂ hn₁ hn₂ (homOfLE (hi₀₁.trans hi₁₂)) (homOfLE hi₂₃) (homOfLE hi₃₄) ≅ + X'.E n₀ n₁ n₂ hn₁ hn₂ (homOfLE hi₁₂) (homOfLE hi₂₃) (homOfLE hi₃₄) := + have := X'.isIso_EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h + asIso (X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) + +@[reassoc (attr := simp)] +lemma isoEMapFourδ₁Toδ₀'_hom_inv_id : + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ ≫ + (X'.isoEMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).inv = 𝟙 _ := + (X'.isoEMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).hom_inv_id + +@[reassoc (attr := simp)] +lemma isoEMapFourδ₁Toδ₀'_inv_hom_id : + (X'.isoEMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).inv ≫ + X'.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ = 𝟙 _ := + (X'.isoEMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).inv_hom_id + +end + +section + +variable (h : IsZero ((X'.H n₀).obj (mk₁ (homOfLE hi₃₄)))) + +include h in +lemma isIso_EMapFourδ₄Toδ₃' : + IsIso (X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) := by + apply X'.isIso_EMap_fourδ₄Toδ₃_of_isZero + exact h + +/-- isoEMapFourδ₄Toδ₃' -/ +@[simps! hom] +noncomputable def isoEMapFourδ₄Toδ₃' : + X'.E n₀ n₁ n₂ hn₁ hn₂ (homOfLE hi₀₁) (homOfLE hi₁₂) (homOfLE hi₂₃) ≅ + X'.E n₀ n₁ n₂ hn₁ hn₂ (homOfLE hi₀₁) (homOfLE hi₁₂) (homOfLE (hi₂₃.trans hi₃₄)) := + have := X'.isIso_EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h + asIso (X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) + +@[reassoc (attr := simp)] +lemma isoEMapFourδ₄Toδ₄'_hom_inv_id : + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ ≫ + (X'.isoEMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).inv = 𝟙 _ := + (X'.isoEMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).hom_inv_id + +@[reassoc (attr := simp)] +lemma isoEMapFourδ₄Toδ₄'_inv_hom_id : + (X'.isoEMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).inv ≫ + X'.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ = 𝟙 _ := + (X'.isoEMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄ h).inv_hom_id + +end + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + (i₀ i₁ i₂ i₃ i₄ i₅ : ι') (hi₀₁ : i₀ ≤ i₁) + (hi₁₂ : i₁ ≤ i₂) (hi₂₃ : i₂ ≤ i₃) (hi₃₄ : i₃ ≤ i₄) (hi₄₅ : i₄ ≤ i₅) + +/-- EMapFourδ₂Toδ₁' -/ +noncomputable abbrev EMapFourδ₂Toδ₁' := + X'.EMap n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _ (fourδ₂Toδ₁' i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) + +/-- isIso_EMapFourδ₂Toδ₁' -/ +lemma isIso_EMapFourδ₂Toδ₁' + (h₁ : IsIso ((X'.H n₁).map (twoδ₁Toδ₀' i₁ i₂ i₃ hi₁₂ hi₂₃))) + (h₂ : IsIso ((X'.H n₂).map (twoδ₂Toδ₁' i₀ i₁ i₂ hi₀₁ hi₁₂))) : + IsIso (X'.EMapFourδ₂Toδ₁' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₄ hi₀₁ hi₁₂ hi₂₃ hi₃₄) := + X'.isIso_EMap _ _ _ _ _ _ _ _ _ _ _ _ + (inferInstanceAs (IsIso ((X'.H n₀).map (𝟙 _)))) h₁ h₂ + +end + +end + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/FirstPage.lean b/Mathlib/Algebra/Homology/SpectralObject/FirstPage.lean new file mode 100644 index 00000000000000..34e37db497fd06 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/FirstPage.lean @@ -0,0 +1,134 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.SpectralSequence + +/-! +# The first page of the spectral sequence of a spectral object + +Let `ι` be a preordered type, `X` a spectral object in an abelian +category indexed by `ι`. Let `data : SpectralSequenceMkData ι c r₀`. +Assume that `X.HasSpectralSequence data` holds. In this file, +we introduce a property `data.HasFirstPageComputation` which allows +to "compute" the objects of the `r₀`th page of the spectral +sequence attached to `X` in terms of objects of the form `X.H`, +and we compute the differential on the first page in terms of `X.δ`. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category ComposableArrows + +namespace Abelian + +namespace SpectralObject + +variable {C ι κ : Type*} [Category C] [Abelian C] [Preorder ι] + (X : SpectralObject C ι) + {c : ℤ → ComplexShape κ} {r₀ : ℤ} + (data : SpectralSequenceMkData ι c r₀) + +namespace SpectralSequenceMkData + +/-- Given `data : SpectralSequenceMkData ι c r₀`, this is the property +that on the page `r₀`, indices `i₀` and `i₁` are equal, +and indices `i₂` and `i₃` are equal. This condition allows +to express the objects of the `r₀`th page of the spectral sequences +obtained using a spectral object `X` indexed by `ι` and `data` as objects +of the form `X.H`, see `SpectralObject.spectralSequenceFirstPageXIso`. -/ +class HasFirstPageComputation : Prop where + hi₀₁ (pq : κ) : data.i₀ r₀ pq = data.i₁ pq + hi₂₃ (pq : κ) : data.i₂ pq = data.i₃ r₀ pq + +export HasFirstPageComputation (hi₀₁ hi₂₃) + +instance : mkDataE₂Cohomological.HasFirstPageComputation where + hi₀₁ pq := by dsimp; congr 1; lia + hi₂₃ pq := by dsimp; congr 1; lia + +instance : mkDataE₂CohomologicalNat.HasFirstPageComputation where + hi₀₁ pq := by dsimp; congr 1; lia + hi₂₃ pq := by dsimp; congr 1; lia + +instance : mkDataE₂HomologicalNat.HasFirstPageComputation where + hi₀₁ pq := by dsimp; congr 1; lia + hi₂₃ pq := by dsimp; congr 1; lia + +end SpectralSequenceMkData + +variable [data.HasFirstPageComputation] [X.HasSpectralSequence data] + +/-- If `data : SpectralSequenceMkData ι c r₀` is such that +`data.HasFirstPageComputation` holds, this is an isomorphisms which +allows to "compute" the objects on the `r₀`th page of the spectral sequence +obtained from a spectral object `X` indexed by `i` using data as objects +of the form `X.H`. See also `spectralSequence_first_page_d_eq` for the relation +between the differentials of the first page of the spectral sequence and `X.δ`. +-/ +noncomputable def spectralSequenceFirstPageXIso (pq : κ) (n : ℤ) (hn : n = data.deg pq) + (i₁ i₂ : ι) (hi₁ : i₁ = data.i₁ pq) (hi₂ : i₂ = data.i₂ pq) : + ((X.spectralSequence data).page r₀).X pq ≅ + (X.H n).obj (mk₁ (homOfLE (by grind [data.le₁₂ pq]) : i₁ ⟶ i₂)) := + X.spectralSequencePageXIso data _ (by rfl) _ _ _ _ _ _ hn _ _ _ _ + (by rw [hi₁, ← data.hi₀₁]) hi₁ hi₂ (by rw [hi₂, data.hi₂₃]) ≪≫ + X.EIsoH (n - 1) n (n + 1) (by simp) rfl (homOfLE _) + +@[reassoc] +lemma spectralSequenceFirstPageXIso_hom (pq : κ) (n : ℤ) (hn : n = data.deg pq) + (i₁ i₂ : ι) (hi₁ : i₁ = data.i₁ pq) (hi₂ : i₂ = data.i₂ pq) + (n₀ n₂ : ℤ) (hn₀ : n₀ + 1 = n) (hn₂ : n + 1 = n₂) : + (X.spectralSequenceFirstPageXIso data pq n hn i₁ i₂ hi₁ hi₂).hom = + (X.spectralSequencePageXIso data r₀ (by rfl) _ _ _ _ _ _ hn _ _ _ _ + (by rw [hi₁, ← data.hi₀₁]) hi₁ hi₂ (by rw [hi₂, data.hi₂₃])).hom ≫ + (X.EIsoH n₀ n n₂ hn₀ hn₂ _).hom := by + obtain rfl : n₀ = n - 1 := by lia + obtain rfl := hn₂ + rfl + +@[reassoc] +lemma spectralSequenceFirstPageXIso_inv (pq : κ) (n : ℤ) (hn : n = data.deg pq) + (i₁ i₂ : ι) (hi₁ : i₁ = data.i₁ pq) (hi₂ : i₂ = data.i₂ pq) + (n₀ n₂ : ℤ) (hn₀ : n₀ + 1 = n) (hn₂ : n + 1 = n₂) : + (X.spectralSequenceFirstPageXIso data pq n hn i₁ i₂ hi₁ hi₂).inv = + (X.EIsoH n₀ n n₂ hn₀ hn₂ _).inv ≫ + (X.spectralSequencePageXIso data r₀ (by rfl) _ _ _ _ _ _ hn _ _ _ _ + (by rw [hi₁, ← data.hi₀₁]) hi₁ hi₂ (by rw [hi₂, data.hi₂₃])).inv := by + obtain rfl : n₀ = n - 1 := by lia + obtain rfl := hn₂ + rfl + +lemma spectralSequence_first_page_d_eq (pq pq' : κ) + (hpq : (c r₀).Rel pq pq') (n n' : ℤ) (hn : n = data.deg pq) + (hn' : n + 1 = n') (i j k : ι) + (hi : i = data.i₁ pq') (hj : j = data.i₁ pq) (hk : k = data.i₂ pq) : + ((X.spectralSequence data).page r₀).d pq pq' = + (X.spectralSequenceFirstPageXIso data pq n hn j k hj hk).hom ≫ + X.δ n n' hn' (homOfLE + (by simpa only [hi, hj, data.hc₁₃ r₀ pq pq' hpq, ← data.hi₂₃ pq'] + using data.le₁₂ pq') : i ⟶ j) + (homOfLE (by simpa only [hj, hk] using data.le₁₂ pq) : j ⟶ k) ≫ + (X.spectralSequenceFirstPageXIso data pq' n' + (by rw [← hn', hn, data.hc r₀ pq pq' hpq]) + i j hi (by rw [hj, ← data.hc₀₂ r₀ pq pq' hpq, data.hi₀₁ pq])).inv := by + simp only [assoc, X.spectralSequenceFirstPageXIso_hom data pq n hn + j k hj hk (n - 1) n' (by simp) hn', + ← X.d_EIsoH_hom_assoc (n - 1) n n' (n' + 1) (by simp) hn' rfl, + X.spectralSequenceFirstPageXIso_inv data pq' n' + (by rw [← hn', hn, data.hc r₀ pq pq' hpq]) i j hi + (by rw [hj, data.hi₂₃, data.hc₁₃ r₀ pq pq' hpq]) n (n' + 1) hn' rfl, + Iso.hom_inv_id_assoc] + apply spectralSequence_page_d_eq + exact hpq + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/HasSpectralSequence.lean b/Mathlib/Algebra/Homology/SpectralObject/HasSpectralSequence.lean new file mode 100644 index 00000000000000..07bcb9f64f75c6 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/HasSpectralSequence.lean @@ -0,0 +1,468 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.Basic +public import Mathlib.Algebra.Homology.SpectralSequence.ComplexShape +public import Mathlib.Order.Fin.Clamp +public import Mathlib.Order.WithBotTop + +/-! +# Shapes of spectral sequences obtained from a spectral object + +This file prepares for the construction of the spectral sequence +of a spectral object in an abelian category which shall be conducted +in the file `Mathlib/Algebra/Homology/SpectralObject/SpectralSequence.lean`. + +In this file, we introduce a structure `SpectralSequenceMkData` which +contains a recipe for the construction of the pages of the spectral sequence. +For example, from a spectral object `X` indexed by `EInt` the definition +`mkDataE₂Cohomological` will allow to construct an `E₂` cohomological +spectral sequence such that the object on position `(p, q)` on the `r`th +page is `E^{p + q}(q - r + 2 ≤ q ≤ q + 1 ≤ q + r - 1)`. +The data (and properties) in the structure `SpectralSequenceMkData` allow +to define the pages and the differentials directly from the `SpectralObject` +API from the files +`Mathlib/Algebra/Homology/SpectralObject/Page.lean` and +`Mathlib/Algebra/Homology/SpectralObject/Differentials.lean`. +However, the computation of the homology of the differentials in +`Mathlib/Algebra/Homology/SpectralObject/Homology.lean` may not directly +apply: we introduce a typeclass `HasSpectralSequence` which puts +additional conditions on the spectral object so that the homology of a +page identifies to the next page. These conditions are automatically +satisfied for `mkDataE₂Cohomological`, but this design allows +to obtain a spectral sequence with objects of the pages indexed +by `ℕ × ℕ` instead of `ℤ × ℤ` when suitable conditions are satisfied by +a spectral object indexed by `EInt` (see `mkDataE₂CohomologicalNat` +and the typeclass `IsFirstQuadrant`). + +-/ + +/-! +# The spectral sequence of a spectral object + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category Limits ComposableArrows + +namespace Abelian + +namespace SpectralObject + +variable {C ι κ : Type*} [Category C] [Abelian C] [Preorder ι] + {c : ℤ → ComplexShape κ} {r₀ : ℤ} + +variable (ι c r₀) in +/-- This data is a recipe in order to produce a spectral sequence starting on +page `r₀` (where the `r`th page is of shape `c r`) from a spectral object +indexed by `ι`. The object on page `r` at the position `pq : κ` shall be +`E^(deg pq)(i₀ ≤ i₁ ≤ i₂ ≤ i₃)`, where `i₀ ≤ i₁ ≤ i₂ ≤ i₃` are elements in the +index type `ι` of the spectral object and `deg pq : ℤ` is a cohomological degree. +The indices `i₀` and `i₃` depend on `r` and `pq`, but `i₁`, `i₂` only depend on `pq`. +Various conditions are added in order to construct the differentials on the pages +and show that the homology of a page identifies to the next page; in certain +cases, additional conditions may be required on the spectral object, +see the typeclass `HasSpectralSequence`. -/ +structure SpectralSequenceMkData where + /-- The cohomological degree of objects in the pages -/ + deg : κ → ℤ + /-- The zeroth index -/ + i₀ (r : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) : ι + /-- The first index -/ + i₁ (pq : κ) : ι + /-- The second index -/ + i₂ (pq : κ) : ι + /-- The third index -/ + i₃ (r : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) : ι + le₀₁ (r : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) : i₀ r pq ≤ i₁ pq + le₁₂ (pq : κ) : i₁ pq ≤ i₂ pq + le₂₃ (r : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) : i₂ pq ≤ i₃ r pq + hc (r : ℤ) (pq pq' : κ) (hpq : (c r).Rel pq pq') (hr : r₀ ≤ r := by lia) : deg pq + 1 = deg pq' + hc₀₂ (r : ℤ) (pq pq' : κ) (hpq : (c r).Rel pq pq') (hr : r₀ ≤ r := by lia) : i₀ r pq = i₂ pq' + hc₁₃ (r : ℤ) (pq pq' : κ) (hpq : (c r).Rel pq pq') (hr : r₀ ≤ r := by lia) : i₁ pq = i₃ r pq' + antitone_i₀ (r r' : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) (hrr' : r ≤ r' := by lia) : + i₀ r' pq ≤ i₀ r pq + monotone_i₃ (r r' : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) (hrr' : r ≤ r' := by lia) : + i₃ r pq ≤ i₃ r' pq + i₀_prev (r r' : ℤ) (pq pq' : κ) (hpq : (c r).Rel pq pq') (hrr' : r + 1 = r' := by lia) + (hr : r₀ ≤ r := by lia) : + i₀ r' pq = i₁ pq' + i₃_next (r r' : ℤ) (pq pq' : κ) (hpq : (c r).Rel pq pq') (hrr' : r + 1 = r' := by lia) + (hr : r₀ ≤ r := by lia) : + i₃ r' pq' = i₂ pq + +namespace SpectralSequenceMkData + +variable (data : SpectralSequenceMkData ι c r₀) + +lemma i₀_le (r r' : ℤ) (pq : κ) (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + data.i₀ r' pq ≤ data.i₀ r pq := + data.antitone_i₀ r r' pq + +lemma i₃_le (r r' : ℤ) (pq : κ) (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + data.i₃ r pq ≤ data.i₃ r' pq := + data.monotone_i₃ r r' pq + +lemma le₀'₀ {r r' : ℤ} (hrr' : r + 1 = r') (hr : r₀ ≤ r) (pq' : κ) + {i₀' i₀ : ι} (hi₀' : i₀' = data.i₀ r' pq') (hi₀ : i₀ = data.i₀ r pq') : + i₀' ≤ i₀ := by + rw [hi₀', hi₀] + exact data.antitone_i₀ r r' pq' + +lemma le₀₁' (r : ℤ) (hr : r₀ ≤ r) (pq' : κ) {i₀ i₁ : ι} + (hi₀ : i₀ = data.i₀ r pq') + (hi₁ : i₁ = data.i₁ pq') : + i₀ ≤ i₁ := by + have := data.le₀₁ r pq' + simpa only [hi₀, hi₁] using data.le₀₁ r pq' + +lemma le₁₂' (pq' : κ) {i₁ i₂ : ι} (hi₁ : i₁ = data.i₁ pq') (hi₂ : i₂ = data.i₂ pq') : + i₁ ≤ i₂ := by + simpa only [hi₁, hi₂] using data.le₁₂ pq' + +lemma le₂₃' (r : ℤ) (hr : r₀ ≤ r) (pq' : κ) + {i₂ i₃ : ι} + (hi₂ : i₂ = data.i₂ pq') + (hi₃ : i₃ = data.i₃ r pq') : + i₂ ≤ i₃ := by + simpa only [hi₂, hi₃] using data.le₂₃ r pq' + +lemma le₃₃' {r r' : ℤ} (hrr' : r + 1 = r') (hr : r₀ ≤ r) (pq' : κ) + {i₃ i₃' : ι} + (hi₃ : i₃ = data.i₃ r pq') + (hi₃' : i₃' = data.i₃ r' pq') : + i₃ ≤ i₃' := by + simpa only [hi₃, hi₃'] using data.monotone_i₃ r r' pq' + +end SpectralSequenceMkData + +/-- The data which allows to construct an `E₂`-cohomological spectral sequence +indexed by `ℤ × ℤ` from a spectral object indexed by `EInt`. -/ +@[simps!] +def mkDataE₂Cohomological : + SpectralSequenceMkData EInt (fun r ↦ ComplexShape.up' (⟨r, 1 - r⟩ : ℤ × ℤ)) 2 where + deg pq := pq.1 + pq.2 + i₀ r pq hr := (pq.2 - r + 2 :) + i₁ pq := pq.2 + i₂ pq := (pq.2 + 1 :) + i₃ r pq hr := (pq.2 + r - 1 :) + le₀₁ r pq hr := by simp; lia + le₁₂ pq := by simp + le₂₃ r pq hr := by simp; lia + hc := by rintro r pq _ rfl _; dsimp; lia + hc₀₂ := by rintro r pq hr rfl _; simp; lia + hc₁₃ := by rintro r pq hr rfl _; simp; lia + antitone_i₀ r r' pq hr hrr' := by simp; lia + monotone_i₃ r r' pq hr hrr' := by simp; lia + i₀_prev := by rintro r r' hr pq rfl _ _; dsimp; lia + i₃_next := by rintro r r' hr pq rfl _ _; dsimp; lia + +/-- The data which allows to construct an `E₂`-cohomological spectral sequence +indexed by `ℕ × ℕ` from a spectral object indexed by `EInt`. (Note: additional +assumptions on the spectral object are required.) -/ +@[simps!] +def mkDataE₂CohomologicalNat : + SpectralSequenceMkData EInt + (fun r ↦ ComplexShape.spectralSequenceNat ⟨r, 1 - r⟩) 2 where + deg pq := pq.1 + pq.2 + i₀ r pq hr := (pq.2 - r + 2 :) + i₁ pq := (pq.2 : ℤ) + i₂ pq := (pq.2 + 1 : ℤ) + i₃ r pq hr := (pq.2 + r - 1 : ℤ) + le₀₁ r pq hr := by simp; lia + le₁₂ pq := by simp + le₂₃ r pq hr := by simp; lia + hc r pq pq' hpq hr := by simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq; lia + hc₀₂ r pq pq' hpq hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + hc₁₃ r pq pq' hpq hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + antitone_i₀ r r' pq hr hrr' := by simp; lia + monotone_i₃ r r' pq hr hrr' := by simp; lia + i₀_prev r r' pq pq' hpq hrr' hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + i₃_next r r' pq pq' hpq hrr' hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + +/-- The data which allows to construct an `E₂`-cohomological spectral sequence +indexed by `ℤ × Fin l` from a spectral object indexed by `Fin (l + 1)`. -/ +@[simps deg i₀ i₁ i₂ i₃] +def mkDataE₂CohomologicalFin (l : ℕ) : + SpectralSequenceMkData (Fin (l + 1)) + (fun r ↦ ComplexShape.spectralSequenceFin l ⟨r, 1 - r⟩) 2 where + deg pq := pq.1 + pq.2.1 + i₀ r pq hr := ⟨(pq.2.1 - (r - 2)).toNat, by grind⟩ + i₁ pq := pq.2.castSucc + i₂ pq := pq.2.succ + i₃ r pq hr := Fin.clamp (pq.2.1 + (r - 1)).toNat _ + le₀₁ := by rintro r ⟨p, q, hq⟩ hr; simp; lia + le₁₂ pq := by simp [Fin.le_iff_val_le_val] + le₂₃ r pq hr := by + simp only [Fin.le_iff_val_le_val, Fin.val_succ, le_min_iff, Fin.clamp] + grind + hc _ _ _ := fun ⟨h₁, h₂⟩ ↦ by lia + hc₀₂ r := by + rintro ⟨a₁, ⟨a₂, _⟩⟩ ⟨b₁, ⟨b₂, _⟩⟩ ⟨h₁, h₂⟩ hr + ext + grind + hc₁₃ r := by + rintro ⟨a₁, ⟨a₂, _⟩⟩ ⟨b₁, ⟨b₂, _⟩⟩ ⟨h₁, h₂⟩ hr + rw [Fin.ext_iff] + dsimp at h₁ h₂ ⊢ + grind + antitone_i₀ := by + rintro r r' ⟨a, ⟨a', _⟩⟩ hr hrr' + dsimp + rw [Fin.mk_le_mk] + lia + monotone_i₃ := by + rintro r r' ⟨a, ⟨a', _⟩⟩ hr hrr' + dsimp + rw [Fin.mk_le_mk] + exact Fin.clamp_mono (by lia) + i₀_prev := by + rintro r r' ⟨a, ⟨a', _⟩⟩ ⟨b, ⟨b', _⟩⟩ ⟨h₁, h₂⟩ hrr' hr + ext + dsimp at h₁ h₂ ⊢ + lia + i₃_next := by + rintro r r' ⟨a, ⟨a', _⟩⟩ ⟨b, ⟨b', _⟩⟩ ⟨h₁, h₂⟩ hrr' hr + ext + dsimp at h₁ h₂ ⊢ + grind + +/-- The data which allows to construct an `E₂`-homological spectral sequence +indexed by `ℕ × ℕ` from a spectral object indexed by `EInt`. (Note: additional +assumptions on the spectral object are required.) -/ +@[simps!] +def mkDataE₂HomologicalNat : + SpectralSequenceMkData EInt + (fun r ↦ ComplexShape.spectralSequenceNat ⟨-r, r - 1⟩) 2 where + deg pq := - pq.1 - pq.2 + i₀ r pq hr := (-pq.2 - r + 2 :) + i₁ pq := (-pq.2 : ℤ) + i₂ pq := (-pq.2 + 1 : ℤ) + i₃ r pq hr := (-pq.2 + r - 1 :) + le₀₁ r pq hr := by simp; lia + le₁₂ pq := by simp + le₂₃ r pq hr := by simp; lia + hc r pq pq' hpq hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + hc₀₂ r pq pq' hpq hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + hc₁₃ r pq pq' hpq hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + antitone_i₀ r r' pq hr hrr' := by simp; lia + monotone_i₃ r r' pq hr hrr' := by simp; lia + i₀_prev r r' pq pq' hpq hrr' hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + i₃_next r r' pq pq' hpq hrr' hr := by + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + lia + +variable (X : SpectralObject C ι) (data : SpectralSequenceMkData ι c r₀) + +/-- Given `X : SpectralObject C ι` and `data : SpectralSequenceMkData ι c r₀`, this is +the property which allows to construct a spectral sequence by using the recipe given +by `data`. The conditions given allow to show that the homology of a page identifies +to the next page. -/ +class HasSpectralSequence : Prop where + isZero_H_obj_mk₁_i₀_le (r r' : ℤ) (pq : κ) + (hpq : ∀ (pq' : κ), ¬ ((c r).Rel pq pq')) + (n : ℤ) (hn : n = data.deg pq + 1 ) + (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + IsZero ((X.H n).obj (mk₁ (homOfLE (data.i₀_le r r' pq)))) + isZero_H_obj_mk₁_i₃_le (r r' : ℤ) (pq : κ) (hpq : ∀ (pq' : κ), ¬ ((c r).Rel pq' pq)) + (n : ℤ) (hn : n = data.deg pq - 1) + (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + IsZero ((X.H n).obj (mk₁ (homOfLE (data.i₃_le r r' pq)))) + +variable [X.HasSpectralSequence data] + +lemma isZero_H_obj_mk₁_i₀_le (r r' : ℤ) (hrr' : r + 1 = r') (hr : r₀ ≤ r) + (pq : κ) (hpq : ∀ (pq' : κ), ¬ ((c r).Rel pq pq')) + (n : ℤ) (hn : n = data.deg pq + 1) : + IsZero ((X.H n).obj (mk₁ (homOfLE (data.i₀_le r r' pq)))) := + HasSpectralSequence.isZero_H_obj_mk₁_i₀_le r r' pq hpq n hn + +lemma isZero_H_obj_mk₁_i₀_le' (r r' : ℤ) (hrr' : r + 1 = r') (hr : r₀ ≤ r) + (pq : κ) (hpq : ∀ (pq' : κ), ¬ ((c r).Rel pq pq')) + (n : ℤ) (hn : n = data.deg pq + 1) (i₀' i₀ : ι) + (hi₀' : i₀' = data.i₀ r' pq) + (hi₀ : i₀ = data.i₀ r pq) : + IsZero ((X.H n).obj (mk₁ (homOfLE (show i₀' ≤ i₀ by + simpa only [hi₀', hi₀] using data.i₀_le r r' pq)))) := by + subst hi₀' hi₀ + exact HasSpectralSequence.isZero_H_obj_mk₁_i₀_le r r' pq hpq n hn + +lemma isZero_H_obj_mk₁_i₃_le (r r' : ℤ) (hrr' : r + 1 = r') (hr : r₀ ≤ r) + (pq : κ) (hpq : ∀ (pq' : κ), ¬ ((c r).Rel pq' pq)) + (n : ℤ) (hn : n = data.deg pq - 1) : + IsZero ((X.H n).obj (mk₁ (homOfLE (data.i₃_le r r' pq)))) := + HasSpectralSequence.isZero_H_obj_mk₁_i₃_le r r' pq hpq n hn + +lemma isZero_H_obj_mk₁_i₃_le' (r r' : ℤ) (hrr' : r + 1 = r') (hr : r₀ ≤ r) + (pq : κ) (hpq : ∀ (pq' : κ), ¬ ((c r).Rel pq' pq)) + (n : ℤ) (hn : n = data.deg pq - 1) (i₃ i₃' : ι) + (hi₃ : i₃ = data.i₃ r pq) + (hi₃' : i₃' = data.i₃ r' pq) : + IsZero ((X.H n).obj (mk₁ (homOfLE (show i₃ ≤ i₃' by + simpa only [hi₃, hi₃'] using data.i₃_le r r' pq)))) := by + subst hi₃ hi₃' + exact HasSpectralSequence.isZero_H_obj_mk₁_i₃_le r r' pq hpq n hn + +instance (E : SpectralObject C EInt) : E.HasSpectralSequence mkDataE₂Cohomological where + isZero_H_obj_mk₁_i₀_le r r' pq hpq n hn hrr' hr := by + exfalso + exact hpq _ rfl + isZero_H_obj_mk₁_i₃_le r r' pq hpq n hn hrr' hr := by + exfalso + exact hpq (pq - (r, 1-r)) (by simp) + +instance {l : ℕ} (E : SpectralObject C (Fin (l + 1))) : + E.HasSpectralSequence (mkDataE₂CohomologicalFin l) where + isZero_H_obj_mk₁_i₀_le r r' pq hpq n hn hrr' hr := by + have : (mkDataE₂CohomologicalFin l).i₀ r' pq = + (mkDataE₂CohomologicalFin l).i₀ r pq := by + subst hrr' + obtain ⟨k, rfl⟩ := Int.le.dest hr + obtain ⟨p, q, hq⟩ := pq + ext + have h : q ≤ k := by + by_contra! + simp only [ComplexShape.spectralSequenceFin_rel_iff, not_and, Prod.forall] at hpq + obtain ⟨t, rfl⟩ := Nat.le.dest (Nat.add_one_le_of_lt this) + exact hpq _ ⟨t, by lia⟩ rfl (by simp; lia) + simp_all + lia + have := isIso_homOfLE this + apply E.isZero_H_map_mk₁_of_isIso + isZero_H_obj_mk₁_i₃_le r r' pq hpq n hn hrr' hr := by + have : (mkDataE₂CohomologicalFin l).i₃ r pq = + (mkDataE₂CohomologicalFin l).i₃ r' pq := by + subst hrr' + obtain ⟨p, q, hq⟩ := pq + have h : l < q + r := by + by_contra! + obtain ⟨t, ht⟩ := Int.le.dest this + simp only [ComplexShape.spectralSequenceFin_rel_iff, not_and, Prod.forall] at hpq + exact hpq (p - r) ⟨l - 1 - t, by lia⟩ (by lia) (by lia) + dsimp + rw [add_sub_cancel_right, Fin.clamp_eq_last _ _ (by lia), + Fin.clamp_eq_last _ _ (by lia)] + have := isIso_homOfLE this + apply E.isZero_H_map_mk₁_of_isIso + +section + +variable (Y : SpectralObject C EInt) + +/-- The conditions on a spectral object indexed by `EInt` which allow +to obtain a (convergent) first quadrant `E₂` cohomological spectral sequence. -/ +class IsFirstQuadrant : Prop where + isZero₁ (i j : EInt) (hij : i ≤ j) (hj : j ≤ (0 : ℤ)) (n : ℤ) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) + isZero₂ (i j : EInt) (hij : i ≤ j) (n : ℤ) (hi : n < i) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) + +variable [Y.IsFirstQuadrant] + +lemma isZero₁_of_isFirstQuadrant (i j : EInt) (hij : i ≤ j) (hj : j ≤ (0 : ℤ)) (n : ℤ) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) := + IsFirstQuadrant.isZero₁ i j hij hj n + +lemma isZero₂_of_isFirstQuadrant (i j : EInt) (hij : i ≤ j) (n : ℤ) (hi : n < i) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) := + IsFirstQuadrant.isZero₂ i j hij n hi + +instance : Y.HasSpectralSequence mkDataE₂CohomologicalNat where + isZero_H_obj_mk₁_i₀_le := by + rintro r _ ⟨p, q⟩ hpq n rfl rfl hr + apply isZero₁_of_isFirstQuadrant + dsimp + simp only [WithBotTop.coe_le_coe] + by_contra! + obtain ⟨p', hp'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ p + r by lia) + obtain ⟨q', hq'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ q + 1 - r by lia) + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + exact hpq ⟨p', q'⟩ (by constructor <;> lia) + isZero_H_obj_mk₁_i₃_le := by + rintro r _ ⟨p, q⟩ hpq n rfl rfl hr + apply isZero₂_of_isFirstQuadrant + dsimp + simp only [WithBotTop.coe_lt_coe] + by_contra! + obtain ⟨p', hp'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ p - r by lia) + obtain ⟨q', hq'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ q - 1 + r by lia) + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + exact hpq ⟨p', q'⟩ (by constructor <;> lia) + +end + +section + +variable (Y : SpectralObject C EInt) + +/-- The conditions on a spectral object indexed by `EInt` which allow +to obtain a (convergent) third quadrant `E₂` cohomological spectral sequence, +or a (convergent) first quadrant `E₂` *homological* spectral sequence -/ +class IsThirdQuadrant where + isZero₁ (i j : EInt) (hij : i ≤ j) (hi : (0 : ℤ) < i) (n : ℤ) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) + isZero₂ (i j : EInt) (hij : i ≤ j) (n : ℤ) (hj : j ≤ n) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) + +variable [Y.IsThirdQuadrant] + +lemma isZero₁_of_isThirdQuadrant (i j : EInt) (hij : i ≤ j) (hi : (0 : ℤ) < i) (n : ℤ) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) := + IsThirdQuadrant.isZero₁ i j hij hi n + +lemma isZero₂_of_isThirdQuadrant (i j : EInt) (hij : i ≤ j) (n : ℤ) (hj : j ≤ n) : + IsZero ((Y.H n).obj (mk₁ (homOfLE hij))) := + IsThirdQuadrant.isZero₂ i j hij n hj + +instance : Y.HasSpectralSequence mkDataE₂HomologicalNat where + isZero_H_obj_mk₁_i₀_le := by + rintro r _ ⟨p, q⟩ hpq n rfl rfl hr + apply isZero₂_of_isThirdQuadrant + dsimp + simp only [WithBotTop.coe_le_coe] + by_contra! + obtain ⟨p', hp'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ p - r by lia) + obtain ⟨q', hq'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ q + r - 1 by lia) + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + exact hpq ⟨p', q'⟩ (by constructor <;> lia) + isZero_H_obj_mk₁_i₃_le := by + rintro r _ ⟨p, q⟩ hpq n rfl rfl hr + apply isZero₁_of_isThirdQuadrant + dsimp + simp only [WithBotTop.coe_lt_coe] + by_contra! + obtain ⟨p', hp'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ p + r by lia) + obtain ⟨q', hq'⟩ := Int.eq_ofNat_of_zero_le (show 0 ≤ q + 1 - r by lia) + simp only [ComplexShape.spectralSequenceNat_rel_iff] at hpq + exact hpq ⟨p', q'⟩ (by constructor <;> lia) + +end + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/Homology.lean b/Mathlib/Algebra/Homology/SpectralObject/Homology.lean new file mode 100644 index 00000000000000..298123d7ee7a7b --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/Homology.lean @@ -0,0 +1,157 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.EpiMono + +/-! +# The homology of the differentials of a spectral object + +Let `X` be a spectral object indexed by a category `ι` in an abelian +category `C`. Assume we have seven composable arrows +`f₁`, `f₂`, `f₃`, `f₄`, `f₅`, `f₆`, `f₇` in `ι`. In this file, +we compute the homology of the differentials, i.e. the homology of the short complex +`E^{n - 1}(f₅, f₆, f₇) ⟶ E^n(f₃, f₄, f₅) ⟶ E^{n + 1}(f₁, f₂, f₃)`. +The main definition for this is `dHomologyData` which is an homology data +for this short complex where: +* the cycles are `E^n(f₂ ≫ f₃, f₄, f₅)`; +* the opcycles are `E^n(f₃, f₄, f₅ ≫ f₆)`; +* the homology is `E^n(f₂ ≫ f₃, f₄, f₅ ≫ f₆)`. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category Limits ComposableArrows Preadditive + +namespace Abelian + +variable {C ι : Type*} [Category C] [Abelian C] [Category ι] + +namespace SpectralObject + +variable (X : SpectralObject C ι) + +section + +variable (n₀ n₁ n₂ n₃ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ i₃ i₄ i₅ i₆ i₇ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) + (f₂₃ : i₁ ⟶ i₃) (h₂₃ : f₂ ≫ f₃ = f₂₃) + (f₃₄ : i₂ ⟶ i₄) (h₃₄ : f₃ ≫ f₄ = f₃₄) + +/-- The (exact) sequence expressing `E^n(f₁, f₂, f₃ ≫ f₄)` as the cokernel +of the differential `E^{n-1}(f₃, f₄, f₅) ⟶ E^n(f₁, f₂, f₃)` -/ +@[simps!] +noncomputable def dCokernelSequence : ShortComplex C := + ShortComplex.mk _ _ (X.d_EMap_fourδ₄Toδ₃ n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₃₄ h₃₄) + +instance : Epi (X.dCokernelSequence n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₃₄ h₃₄).g := by + dsimp + infer_instance + +lemma dCokernelSequence_exact : + (X.dCokernelSequence n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₃₄ h₃₄).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A x₂ hx₂ + dsimp at x₂ hx₂ ⊢ + have hx₂' := hx₂ =≫ X.ιE _ _ _ _ _ _ _ _ + simp only [assoc, zero_comp] at hx₂' + rw [X.EMap_ιE n₁ n₂ n₃ hn₂ hn₃ f₁ f₂ f₃ f₁ f₂ f₃₄ (fourδ₄Toδ₃ f₁ f₂ f₃ f₄ f₃₄ h₃₄) + (threeδ₃Toδ₂ f₂ f₃ f₄ f₃₄ h₃₄) (by cat_disch)] at hx₂' + obtain ⟨A₁, π₁, _, x₁, hx₁⟩ := + ((X.sequenceΨ_exact n₁ n₂ hn₂ f₂ f₃ f₄ _ rfl + f₃₄ h₃₄).exact 1).exact_up_to_refinements (x₂ ≫ X.ιE _ _ _ _ _ _ _ _) (by + dsimp [sequenceΨ, Precomp.map] + rw [assoc, hx₂']) + dsimp [sequenceΨ, Precomp.map] at x₁ hx₁ + refine ⟨A₁, π₁, inferInstance, x₁ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅, ?_⟩ + rw [← cancel_mono (X.ιE _ _ _ _ _ _ _ _), assoc, assoc, assoc, hx₁, πE_d_ιE] + +/-- The (exact) sequence expressing `E^n(f₂ ≫ f₃, f₄, f₅)` as the kernel +of the differential `E^n(f₃, f₄, f₅) ⟶ E^{n+1}(f₁, f₂, f₃)` -/ +@[simps!] +noncomputable def dKernelSequence : ShortComplex C := + ShortComplex.mk _ _ (X.EMap_fourδ₁Toδ₀_d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₂₃ h₂₃) + +instance : Mono (X.dKernelSequence n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₂₃ h₂₃).f := by + dsimp + infer_instance + +lemma dKernelSequence_exact : + (X.dKernelSequence n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ f₂₃ h₂₃).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A x₂ hx₂ + dsimp at x₂ hx₂ ⊢ + obtain ⟨A₁, π₁, _, y₂, hy₂⟩ := + surjective_up_to_refinements_of_epi (X.πE n₀ n₁ n₂ hn₁ hn₂ f₃ f₄ f₅) x₂ + have hy₂' := hy₂ =≫ (X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ ≫ X.ιE _ _ _ _ _ _ _ _) + simp only [assoc, reassoc_of% hx₂, zero_comp, comp_zero, πE_d_ιE] at hy₂' + obtain ⟨A₂, π₂, _, y₁, hy₁⟩ := + ((X.sequenceΨ_exact n₁ n₂ hn₂ f₂ f₃ f₄ + f₂₃ h₂₃ _ rfl).exact 0).exact_up_to_refinements y₂ hy₂'.symm + dsimp [sequenceΨ] at y₁ hy₁ + refine ⟨A₂, π₂ ≫ π₁, inferInstance, y₁ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅, ?_⟩ + rw [assoc, assoc, hy₂, reassoc_of% hy₁, + X.πE_EMap n₀ n₁ n₂ hn₁ hn₂ f₂₃ f₄ f₅ f₃ f₄ f₅ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃) + (threeδ₁Toδ₀ f₂ f₃ f₄ f₂₃ h₂₃) (by ext <;> simp; rfl)] + +end + +variable (n₀ n₁ n₂ n₃ n₄ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) (hn₄ : n₃ + 1 = n₄) + {i₀ i₁ i₂ i₃ i₄ i₅ i₆ i₇ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) (f₆ : i₅ ⟶ i₆) (f₇ : i₆ ⟶ i₇) + (f₂₃ : i₁ ⟶ i₃) (h₂₃ : f₂ ≫ f₃ = f₂₃) + (f₅₆ : i₄ ⟶ i₆) (h₅₆ : f₅ ≫ f₆ = f₅₆) + +/-- The short complex `E^{n₁}(f₅, f₆, f₇) ⟶ E^{n₀}(f₃, f₄, f₅) ⟶ E^{n₂}(f₁, f₂, f₃)` +given by the differentials of a spectral object. -/ +@[simps!] +noncomputable def dShortComplex : ShortComplex C := + ShortComplex.mk _ _ (X.d_d n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ f₆ f₇) + +@[reassoc] +lemma EMap_fourδ₁Toδ₀_EMap_fourδ₄Toδ₃ : + X.EMap n₁ n₂ n₃ hn₂ hn₃ f₂₃ f₄ f₅ f₃ f₄ f₅ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅ f₂₃ h₂₃) ≫ + X.EMap n₁ n₂ n₃ hn₂ hn₃ f₃ f₄ f₅ f₃ f₄ f₅₆ (fourδ₄Toδ₃ f₃ f₄ f₅ f₆ f₅₆ h₅₆) = + X.EMap n₁ n₂ n₃ hn₂ hn₃ f₂₃ f₄ f₅ f₂₃ f₄ f₅₆ (fourδ₄Toδ₃ f₂₃ f₄ f₅ f₆ f₅₆ h₅₆) ≫ + X.EMap n₁ n₂ n₃ hn₂ hn₃ f₂₃ f₄ f₅₆ f₃ f₄ f₅₆ (fourδ₁Toδ₀ f₂ f₃ f₄ f₅₆ f₂₃ h₂₃) := by + simp only [← EMap_comp] + congr 1 + ext <;> simp + +/-- The homology data of the short complex +`E^{n-1}(f₅, f₆, f₇) ⟶ E^{n}(f₃, f₄, f₅) ⟶ E^{n+1}(f₁, f₂, f₃)` for which +* the cycles are `E^n(f₂ ≫ f₃, f₄, f₅)`; +* the opcycles are `E^n(f₃, f₄, f₅ ≫ f₆)`; +* the homology is `E^n(f₂ ≫ f₃, f₄, f₅ ≫ f₆)`. -/ +@[simps!] +noncomputable def dHomologyData : + (X.dShortComplex n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ f₆ f₇).HomologyData := + ShortComplex.HomologyData.ofEpiMonoFactorisation + (X.dShortComplex n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ f₆ f₇) + (X.dKernelSequence_exact n₁ n₂ n₃ n₄ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ f₂₃ h₂₃).fIsKernel + (X.dCokernelSequence_exact n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₃ f₄ f₅ f₆ f₇ f₅₆ h₅₆).gIsCokernel + (X.EMap_fourδ₁Toδ₀_EMap_fourδ₄Toδ₃ n₁ n₂ n₃ hn₂ hn₃ f₂ f₃ f₄ f₅ f₆ f₂₃ h₂₃ f₅₆ h₅₆) + +/-- The homology of the short complex +`E^{n₁}(f₅, f₆, f₇) ⟶ E^{n₀}(f₃, f₄, f₅) ⟶ E^{n₂}(f₁, f₂, f₃)` identifies to +`E^n(f₂ ≫ f₃, f₄, f₅ ≫ f₆)`. -/ +noncomputable def dHomologyIso : + (X.dShortComplex n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ f₁ f₂ f₃ f₄ f₅ f₆ f₇).homology ≅ + X.E n₁ n₂ n₃ hn₂ hn₃ f₂₃ f₄ f₅₆ := + (X.dHomologyData n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ + f₁ f₂ f₃ f₄ f₅ f₆ f₇ f₂₃ h₂₃ f₅₆ h₅₆).left.homologyIso + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/Page.lean b/Mathlib/Algebra/Homology/SpectralObject/Page.lean new file mode 100644 index 00000000000000..b1822ad0383348 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/Page.lean @@ -0,0 +1,870 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.Cycles +public import Mathlib.Algebra.Homology.ShortComplex.ShortExact +public import Mathlib.CategoryTheory.Abelian.Refinements +public import Mathlib.CategoryTheory.ComposableArrows.Three + +/-! +# Spectral objects in abelian categories + +Let `X` be a spectral object index by the category `ι` +in the abelian category `C`. The purpose of this file +is to introduce the homology `X.E` of the short complex `X.shortComplexE` +`(X.H n₀).obj (mk₁ f₃) ⟶ (X.H n₁).obj (mk₁ f₂) ⟶ (X.H n₂).obj (mk₁ f₁)` +when `f₁`, `f₂` and `f₃` are composable morphisms in `ι` and the +equalities `n₀ + 1 = n₁` and `n₁ + 1 = n₂` hold (both maps in the +short complex are given by `X.δ`). All the relevant objects in the +spectral sequence attached to spectral objects can be defined +in terms of this homology `X.E`: the objects in all pages, including +the page at infinity. + +## References +* [Jean-Louis Verdier, *Des catégories dérivées des catégories abéliennes*, II.4][verdier1996] + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Limits ComposableArrows + +namespace Abelian + +variable {C ι : Type*} [Category C] [Category ι] [Abelian C] + +namespace SpectralObject + +variable (X : SpectralObject C ι) + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i j k l : ι} (f₁ : i ⟶ j) (f₂ : j ⟶ k) (f₃ : k ⟶ l) + +/-- The short complex consisting of the composition of +two morphisms `X.δ`, given three composable morphisms `f₁`, `f₂` +and `f₃` in `ι`, and three consecutive integers. -/ +@[simps] +def shortComplexE : ShortComplex C where + X₁ := (X.H n₀).obj (mk₁ f₃) + X₂ := (X.H n₁).obj (mk₁ f₂) + X₃ := (X.H n₂).obj (mk₁ f₁) + f := X.δ n₀ n₁ hn₁ f₂ f₃ + g := X.δ n₁ n₂ hn₂ f₁ f₂ + +/-- The homology of the short complex `shortComplexE` consisting of +two morphisms `X.δ`. In the documentation, we shorten it as `E^n₁(f₁, f₂, f₃)` -/ +noncomputable def E : C := (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).homology + +lemma isZero_E_of_isZero_H (h : IsZero ((X.H n₁).obj (mk₁ f₂))) : + IsZero (X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃) := + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).exact_iff_isZero_homology.1 + (ShortComplex.exact_of_isZero_X₂ _ h) + +end + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i j k l : ι} + {i j k l : ι} (f₁ : i ⟶ j) (f₂ : j ⟶ k) (f₃ : k ⟶ l) + {i' j' k' l' : ι} (f₁' : i' ⟶ j') (f₂' : j' ⟶ k') (f₃' : k' ⟶ l') + {i'' j'' k'' l'' : ι} (f₁'' : i'' ⟶ j'') (f₂'' : j'' ⟶ k'') (f₃'' : k'' ⟶ l'') + (α : mk₃ f₁ f₂ f₃ ⟶ mk₃ f₁' f₂' f₃') + (β : mk₃ f₁' f₂' f₃' ⟶ mk₃ f₁'' f₂'' f₃'') + (γ : mk₃ f₁ f₂ f₃ ⟶ mk₃ f₁'' f₂'' f₃'') + +/-- The functoriality of `shortComplexE` with respect to morphisms +in `ComposableArrows ι 3`. -/ +@[simps] +def shortComplexEMap : + X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ⟶ + X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' where + τ₁ := (X.H n₀).map (homMk₁ (α.app 2) (α.app 3) (naturality' α 2 3)) + τ₂ := (X.H n₁).map (homMk₁ (α.app 1) (α.app 2) (naturality' α 1 2)) + τ₃ := (X.H n₂).map (homMk₁ (α.app 0) (α.app 1) (naturality' α 0 1)) + comm₁₂ := δ_naturality .. + comm₂₃ := δ_naturality .. + +@[simp] +lemma shortComplexEMap_id : + X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁ f₂ f₃ (𝟙 _) = 𝟙 _ := by + ext + all_goals dsimp; convert (X.H _).map_id _; cat_disch + +@[reassoc, simp] +lemma shortComplexEMap_comp : + X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁'' f₂'' f₃'' (α ≫ β) = + X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α ≫ + X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' f₁'' f₂'' f₃'' β := by + ext + all_goals dsimp; rw [← Functor.map_comp]; congr 1; cat_disch + +/-- The functoriality of `E` with respect to morphisms +in `ComposableArrows ι 3`. -/ +noncomputable def EMap : + X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ⟶ X.E n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' := + ShortComplex.homologyMap (X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α) + +@[simp] +lemma EMap_id : + X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁ f₂ f₃ (𝟙 _) = 𝟙 _ := by + dsimp only [EMap] + rw [shortComplexEMap_id, ShortComplex.homologyMap_id] + rfl + +@[reassoc, simp] +lemma EMap_comp : + X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁'' f₂'' f₃'' (α ≫ β) = + X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α ≫ + X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' f₁'' f₂'' f₃'' β := by + dsimp only [EMap] + rw [shortComplexEMap_comp, ShortComplex.homologyMap_comp] + +lemma isIso_EMap + (h₀ : IsIso ((X.H n₀).map ((functorArrows ι 2 3 3).map α))) + (h₁ : IsIso ((X.H n₁).map ((functorArrows ι 1 2 3).map α))) + (h₂ : IsIso ((X.H n₂).map ((functorArrows ι 0 1 3).map α))) : + IsIso (X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α) := by + have : IsIso (shortComplexEMap X n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α) := by + apply (config := { allowSynthFailures := true}) + ShortComplex.isIso_of_isIso <;> assumption + dsimp [EMap] + infer_instance + +end + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) + {i j k : ι} (f : i ⟶ j) (g : j ⟶ k) + +lemma δ_eq_zero_of_isIso₁ (hf : IsIso f) : + X.δ n₀ n₁ hn₁ f g = 0 := by + simpa only [Preadditive.IsIso.comp_left_eq_zero] using X.zero₃ n₀ n₁ hn₁ f g _ rfl + +lemma δ_eq_zero_of_isIso₂ (hg : IsIso g) : + X.δ n₀ n₁ hn₁ f g = 0 := by + simpa only [Preadditive.IsIso.comp_right_eq_zero] using X.zero₁ n₀ n₁ hn₁ f g _ rfl + +end + +lemma isZero_H_obj_of_isIso (n : ℤ) {i j : ι} (f : i ⟶ j) (hf : IsIso f) : + IsZero ((X.H n).obj (mk₁ f)) := by + let e : mk₁ (𝟙 i) ≅ mk₁ f := isoMk₁ (Iso.refl _) (asIso f) (by simp) + refine IsZero.of_iso ?_ ((X.H n).mapIso e.symm) + have h := X.zero₂ n (𝟙 i) (𝟙 i) (𝟙 i) (by simp) + rw [← Functor.map_comp] at h + rw [IsZero.iff_id_eq_zero, ← Functor.map_id, ← h] + congr 1 + cat_disch + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i j k l : ι} (f₁ : i ⟶ j) (f₂ : j ⟶ k) (f₃ : k ⟶ l) + (f₁₂ : i ⟶ k) (h₁₂ : f₁ ≫ f₂ = f₁₂) (f₂₃ : j ⟶ l) (h₂₃ : f₂ ≫ f₃ = f₂₃) + +/-- `E^n₁(f₁, f₂, f₃)` identifies to the cokernel +of `δToCycles : H^{n₀}(f₃) ⟶ Z^{n₁}(f₁, f₂)`. -/ +@[simps] +noncomputable def leftHomologyDataShortComplexE : + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).LeftHomologyData := by + let hi := (X.kernelSequenceCycles_exact _ _ hn₂ f₁ f₂).fIsKernel + have : hi.lift (KernelFork.ofι _ (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).zero) = + X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃ := + Fork.IsLimit.hom_ext hi (by simpa using hi.fac _ .zero) + exact { + K := X.cycles n₁ f₁ f₂ + H := cokernel (X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃) + i := X.iCycles n₁ f₁ f₂ + π := cokernel.π _ + wi := by simp + hi := hi + wπ := by rw [this]; simp + hπ := by + refine (IsColimit.equivOfNatIsoOfIso ?_ _ _ ?_).2 + (cokernelIsCokernel (X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃)) + · exact parallelPair.ext (Iso.refl _) (Iso.refl _) (by simpa) (by simp) + · exact Cofork.ext (Iso.refl _)} + +@[simp] +lemma leftHomologyDataShortComplexE_f' : + (X.leftHomologyDataShortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).f' = + X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃ := by + let hi := (X.kernelSequenceCycles_exact _ _ hn₂ f₁ f₂).fIsKernel + exact Fork.IsLimit.hom_ext hi (by simpa using hi.fac _ .zero) + +/-- The cycles of the short complex `shortComplexE` at `E^{n₁}(f₁, f₂, f₃)` +identifies to `Z^{n₁}(f₁, f₂)`. -/ +noncomputable def cyclesIso : + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).cycles ≅ X.cycles n₁ f₁ f₂ := + (X.leftHomologyDataShortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).cyclesIso + +@[reassoc (attr := simp)] +lemma cyclesIso_inv_i : + (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).inv ≫ + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).iCycles = X.iCycles n₁ f₁ f₂ := + ShortComplex.LeftHomologyData.cyclesIso_inv_comp_iCycles _ + +@[reassoc (attr := simp)] +lemma cyclesIso_hom_i : + (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).hom ≫ X.iCycles n₁ f₁ f₂ = + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).iCycles := + ShortComplex.LeftHomologyData.cyclesIso_hom_comp_i _ + +/-- The epimorphism `Z^{n₁}(f₁, f₂) ⟶ E^{n₁}(f₁, f₂, f₃)`. -/ +noncomputable def πE : X.cycles n₁ f₁ f₂ ⟶ X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ := + (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).inv ≫ + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).homologyπ + deriving Epi + +@[reassoc (attr := simp)] +lemma δToCycles_cyclesIso_inv : + X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃ ≫ (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).inv = + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).toCycles := by + rw [← cancel_mono (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).iCycles, Category.assoc, + cyclesIso_inv_i, δToCycles_iCycles, ShortComplex.toCycles_i, shortComplexE_f] + +@[reassoc (attr := simp)] +lemma δToCycles_πE : + X.δToCycles n₀ n₁ hn₁ f₁ f₂ f₃ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ = 0 := by + simp only [πE, δToCycles_cyclesIso_inv_assoc, ShortComplex.toCycles_comp_homologyπ] + +/-- The (exact) sequence `H^{n-1}(f₃) ⟶ Z^n(f₁, f₂) ⟶ E^n(f₁, f₂, f₃) ⟶ 0`. -/ +@[simps] +noncomputable def cokernelSequenceCyclesE : ShortComplex C := + ShortComplex.mk _ _ (X.δToCycles_πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃) + +/-- The short complex `H^{n-1}(f₃) ⟶ Z^n(f₁, f₂) ⟶ E^n(f₁, f₂, f₃)` identifies +to the cokernel sequence of the definition of the homology of the short +complex `shortComplexE` as a cokernel of `ShortComplex.toCycles`. -/ +@[simps!] +noncomputable def cokernelSequenceCyclesEIso : + X.cokernelSequenceCyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≅ ShortComplex.mk _ _ + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).toCycles_comp_homologyπ := + ShortComplex.isoMk (Iso.refl _) (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).symm + (Iso.refl _) (by simp) (by simp [πE]) + +lemma cokernelSequenceCyclesE_exact : + (X.cokernelSequenceCyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).Exact := + ShortComplex.exact_of_iso (X.cokernelSequenceCyclesEIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).symm + (ShortComplex.exact_of_g_is_cokernel _ (ShortComplex.homologyIsCokernel _)) + +instance : Epi (X.cokernelSequenceCyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).g := by + dsimp; infer_instance + +/-- `E^n₁(f₁, f₂, f₃)` identifies to the kernel +of `δFromOpcycles : opZ^{n₁}(f₂, f₃) ⟶ H^{n₂}(f₁)`. -/ +@[simps] +noncomputable def rightHomologyDataShortComplexE : + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).RightHomologyData := by + let hp := (X.cokernelSequenceOpcycles_exact _ _ hn₁ f₂ f₃).gIsCokernel + have : hp.desc (CokernelCofork.ofπ _ (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).zero) = + X.δFromOpcycles n₁ n₂ hn₂ f₁ f₂ f₃ := + Cofork.IsColimit.hom_ext hp (by simpa using hp.fac _ .one) + exact { + Q := X.opcycles n₁ f₂ f₃ + H := kernel (X.δFromOpcycles n₁ n₂ hn₂ f₁ f₂ f₃) + p := X.pOpcycles n₁ f₂ f₃ + ι := kernel.ι _ + wp := by simp + hp := hp + wι := by rw [this]; simp + hι := by + refine (IsLimit.equivOfNatIsoOfIso ?_ _ _ ?_).2 + (kernelIsKernel (X.δFromOpcycles n₁ n₂ hn₂ f₁ f₂ f₃)) + · exact parallelPair.ext (Iso.refl _) (Iso.refl _) (by simpa) (by simp) + · exact Fork.ext (Iso.refl _) } + +@[simp] +lemma rightHomologyDataShortComplexE_g' : + (X.rightHomologyDataShortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).g' = + X.δFromOpcycles n₁ n₂ hn₂ f₁ f₂ f₃ := by + let hp := (X.cokernelSequenceOpcycles_exact _ _ hn₁ f₂ f₃).gIsCokernel + exact Cofork.IsColimit.hom_ext hp (by simpa using hp.fac _ .one) + +/-- The opcycles of the short complex `shortComplexE` at `E^{n₁}(f₁, f₂, f₃)` +identifies to `opZ^{n₁}(f₂, f₃)`. -/ +noncomputable def opcyclesIso : + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).opcycles ≅ X.opcycles n₁ f₂ f₃ := + (X.rightHomologyDataShortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).opcyclesIso + +@[reassoc (attr := simp)] +lemma p_opcyclesIso_hom : + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).pOpcycles ≫ + (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).hom = + X.pOpcycles n₁ f₂ f₃ := + ShortComplex.RightHomologyData.pOpcycles_comp_opcyclesIso_hom _ + +@[reassoc (attr := simp)] +lemma p_opcyclesIso_inv : + X.pOpcycles n₁ f₂ f₃ ≫ (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).inv = + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).pOpcycles := + (X.rightHomologyDataShortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).p_comp_opcyclesIso_inv + +/-- The monomorphism `E^{n₁}(f₁, f₂, f₃) ⟶ opZ^{n₁}(f₂, f₃) ⟶ `. -/ +noncomputable def ιE : X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ⟶ X.opcycles n₁ f₂ f₃ := + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).homologyι ≫ + (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).hom + deriving Mono + +@[reassoc (attr := simp)] +lemma opcyclesIso_hom_δFromOpcycles : + (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).hom ≫ X.δFromOpcycles n₁ n₂ hn₂ f₁ f₂ f₃ = + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).fromOpcycles := by + rw [← cancel_epi (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).pOpcycles, + p_opcyclesIso_hom_assoc, ShortComplex.p_fromOpcycles, shortComplexE_g, + pOpcycles_δFromOpcycles] + +@[reassoc (attr := simp)] +lemma ιE_δFromOpcycles : + X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.δFromOpcycles n₁ n₂ hn₂ f₁ f₂ f₃ = 0 := by + simp only [ιE, Category.assoc, opcyclesIso_hom_δFromOpcycles, + ShortComplex.homologyι_comp_fromOpcycles] + +@[reassoc (attr := simp)] +lemma πE_ιE : + X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ = + X.iCycles n₁ f₁ f₂ ≫ X.pOpcycles n₁ f₂ f₃ := by + simp [πE, ιE] + +/-- The (exact) sequence `0 ⟶ E^n(f₁, f₂, f₃) ⟶ opZ^n(f₂, f₃) ⟶ H^{n+1}(f₁)`. -/ +@[simps] +noncomputable def kernelSequenceOpcyclesE : ShortComplex C := + ShortComplex.mk _ _ (X.ιE_δFromOpcycles n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃) + +/-- The short complex `E^n(f₁, f₂, f₃) ⟶ opZ^n(f₂, f₃) ⟶ H^{n+1}(f₁)` identifies +to the kernel sequence of the definition of the homology of the short +complex `shortComplexE` as a kernel of `ShortComplex.fromOpcycles`. -/ +@[simps!] +noncomputable def kernelSequenceOpcyclesEIso : + X.kernelSequenceOpcyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≅ + ShortComplex.mk _ _ + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).homologyι_comp_fromOpcycles := + Iso.symm (ShortComplex.isoMk (Iso.refl _) (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃) + (Iso.refl _) (by simp [ιE]) (by simp)) + +lemma kernelSequenceOpcyclesE_exact : + (X.kernelSequenceOpcyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).Exact := + ShortComplex.exact_of_iso (X.kernelSequenceOpcyclesEIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).symm + (ShortComplex.exact_of_f_is_kernel _ (ShortComplex.homologyIsKernel _)) + +instance : Mono (X.kernelSequenceOpcyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).f := by + dsimp; infer_instance + +/-- The (exact) sequence `H^n(f₁) ⊞ H^{n-1}(f₃) ⟶ H^n(f₁ ≫ f₂) ⟶ E^n(f₁, f₂, f₃) ⟶ 0`. -/ +@[simps] +noncomputable def cokernelSequenceE : ShortComplex C where + X₁ := (X.H n₁).obj (mk₁ f₁) ⊞ (X.H n₀).obj (mk₁ f₃) + X₂ := (X.H n₁).obj (mk₁ f₁₂) + X₃ := X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ + f := biprod.desc ((X.H n₁).map (twoδ₂Toδ₁ f₁ f₂ f₁₂ h₁₂)) (X.δ n₀ n₁ hn₁ f₁₂ f₃) + g := X.toCycles n₁ f₁ f₂ f₁₂ h₁₂ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ + zero := by ext <;> simp + +instance : Epi (X.cokernelSequenceE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).g := by + dsimp; infer_instance + +lemma cokernelSequenceE_exact : + (X.cokernelSequenceE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A x₂ hx₂ + dsimp at x₂ hx₂ + obtain ⟨A₁, π₁, _, y₁, hy₁⟩ := + (X.cokernelSequenceCyclesE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).exact_up_to_refinements + (x₂ ≫ X.toCycles n₁ f₁ f₂ f₁₂ h₁₂) (by simpa using hx₂) + dsimp at y₁ hy₁ + let z := π₁ ≫ x₂ - y₁ ≫ X.δ n₀ n₁ hn₁ f₁₂ f₃ + obtain ⟨A₂, π₂, _, x₁, hx₁⟩ := (X.exact₂ n₁ f₁ f₂ f₁₂ h₁₂).exact_up_to_refinements z (by + have : z ≫ X.toCycles n₁ f₁ f₂ f₁₂ h₁₂ = 0 := by simp [z, hy₁] + simpa only [zero_comp, Category.assoc, toCycles_i] using this =≫ X.iCycles n₁ f₁ f₂) + dsimp at x₁ hx₁ + exact ⟨A₂, π₂ ≫ π₁, epi_comp _ _, biprod.lift x₁ (π₂ ≫ y₁), by simp [z, ← hx₁]⟩ + +section + +variable {A : C} (x : (X.H n₁).obj (mk₁ f₁₂) ⟶ A) + (h : (X.H n₁).map (twoδ₂Toδ₁ f₁ f₂ f₁₂ h₁₂) ≫ x = 0) + (h' : X.δ n₀ n₁ hn₁ f₁₂ f₃ ≫ x = 0) + +/-- Constructor for morphisms for `E^{n₁}(f₁, f₂, f₃)`. -/ +noncomputable def descE : + X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ⟶ A := + (X.cokernelSequenceE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).desc x (by cat_disch) + +@[reassoc (attr := simp)] +lemma toCycles_πE_descE : + X.toCycles n₁ f₁ f₂ f₁₂ h₁₂ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ + X.descE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ x h h' = x := by + dsimp only [descE] + rw [← Category.assoc] + apply (X.cokernelSequenceE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).g_desc + +end + +/-- The (exact) sequence `0 ⟶ E^n(f₁, f₂, f₃) ⟶ H^n(f₂ ≫ f₃) ⟶ H^n(f₃) ⊞ H^{n+1}(f₁)`. -/ +@[simps] +noncomputable def kernelSequenceE : ShortComplex C where + X₁ := X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ + X₂ := (X.H n₁).obj (mk₁ f₂₃) + X₃ := (X.H n₁).obj (mk₁ f₃) ⊞ (X.H n₂).obj (mk₁ f₁) + f := X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.fromOpcycles n₁ f₂ f₃ f₂₃ h₂₃ + g := biprod.lift ((X.H n₁).map (twoδ₁Toδ₀ f₂ f₃ f₂₃ h₂₃)) (X.δ n₁ n₂ hn₂ f₁ f₂₃) + zero := by ext <;> simp + +instance : Mono (X.kernelSequenceE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).f := by + dsimp; infer_instance + +lemma kernelSequenceE_exact : + (X.kernelSequenceE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A x₂ hx₂ + dsimp at x₂ hx₂ + obtain ⟨A₁, π₁, _, x₁, hx₁⟩ := + (X.kernelSequenceOpcyclesE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).exact_up_to_refinements + (X.liftOpcycles n₁ f₂ f₃ f₂₃ h₂₃ x₂ (by simpa using hx₂ =≫ biprod.fst)) (by + dsimp + rw [← X.fromOpcyles_δ n₁ n₂ hn₂ f₁ f₂ f₃ f₂₃ h₂₃, + X.liftOpcycles_fromOpcycles_assoc ] + simpa using hx₂ =≫ biprod.snd) + dsimp at x₁ hx₁ + refine ⟨A₁, π₁, inferInstance, x₁, ?_⟩ + dsimp + rw [← reassoc_of% hx₁, liftOpcycles_fromOpcycles] + +section + +variable {A : C} (x : A ⟶ (X.H n₁).obj (mk₁ f₂₃)) + (h : x ≫ (X.H n₁).map (twoδ₁Toδ₀ f₂ f₃ f₂₃ h₂₃) = 0) + (h' : x ≫ X.δ n₁ n₂ hn₂ f₁ f₂₃ = 0) + +/-- Constructor for morphisms to `E^{n₁}(f₁, f₂, f₃)`. -/ +noncomputable def liftE : + A ⟶ X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ := + (X.kernelSequenceE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).lift x (by cat_disch) + +@[reassoc (attr := simp)] +lemma liftE_ιE_fromOpcycles : + X.liftE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃ x h h' ≫ X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ + X.fromOpcycles n₁ f₂ f₃ f₂₃ h₂₃ = x := by + apply (X.kernelSequenceE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).lift_f + +end + +end + +section + +variable (n₀ n₁ n₂ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i₀ i₁ i₂ i₃ : ι} + (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + {i₀' i₁' i₂' i₃' : ι} + (f₁' : i₀' ⟶ i₁') (f₂' : i₁' ⟶ i₂') (f₃' : i₂' ⟶ i₃') + (α : mk₃ f₁ f₂ f₃ ⟶ mk₃ f₁' f₂' f₃') + +@[reassoc] +lemma cyclesIso_inv_cyclesMap + (β : mk₂ f₁ f₂ ⟶ mk₂ f₁' f₂') + (hβ : β = homMk₂ (α.app 0) (α.app 1) (α.app 2) (naturality' α 0 1 (by lia) (by lia)) + (naturality' α 1 2 (by lia) (by lia))) : + (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).inv ≫ + ShortComplex.cyclesMap (X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α) = + X.cyclesMap n₁ f₁ f₂ f₁' f₂' β ≫ + (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃').inv := by + subst hβ + rw [← cancel_mono (ShortComplex.iCycles _), Category.assoc, Category.assoc, + ShortComplex.cyclesMap_i, cyclesIso_inv_i_assoc, cyclesIso_inv_i, + shortComplexEMap_τ₂, cyclesMap_i] + dsimp + +@[reassoc] +lemma opcyclesMap_opcyclesIso_hom + (γ : mk₂ f₂ f₃ ⟶ mk₂ f₂' f₃') + (hγ : γ = homMk₂ (α.app 1) (α.app 2) (α.app 3) (naturality' α 1 2) (naturality' α 2 3)) : + ShortComplex.opcyclesMap (X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α) ≫ + (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃').hom = + (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃).hom ≫ X.opcyclesMap n₁ f₂ f₃ f₂' f₃' γ := by + subst hγ + rw [← cancel_epi (ShortComplex.pOpcycles _), ShortComplex.p_opcyclesMap_assoc, + p_opcyclesIso_hom, p_opcyclesIso_hom_assoc, shortComplexEMap_τ₂, p_opcyclesMap] + dsimp + +@[reassoc] +lemma πE_EMap (β : mk₂ f₁ f₂ ⟶ mk₂ f₁' f₂') + (hβ : β = homMk₂ (α.app 0) (α.app 1) (α.app 2) (naturality' α 0 1 (by lia) (by lia)) + (naturality' α 1 2 (by lia) (by lia))) : + X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α = + X.cyclesMap n₁ f₁ f₂ f₁' f₂' β ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' := by + dsimp [πE, EMap] + simp only [Category.assoc, ShortComplex.homologyπ_naturality, + X.cyclesIso_inv_cyclesMap_assoc n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α β hβ] + +@[reassoc] +lemma EMap_ιE + (γ : mk₂ f₂ f₃ ⟶ mk₂ f₂' f₃') + (hγ : γ = homMk₂ (α.app 1) (α.app 2) (α.app 3) (naturality' α 1 2) (naturality' α 2 3)) : + X.EMap n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α ≫ X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' = + X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.opcyclesMap n₁ f₂ f₃ f₂' f₃' γ := by + dsimp [ιE, EMap] + simp only [ShortComplex.homologyι_naturality_assoc, Category.assoc, + X.opcyclesMap_opcyclesIso_hom n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁' f₂' f₃' α γ hγ] + +end + +section + +variable (n₀ n₁ n₂ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i₀ i₁ i₂ i₃ : ι} + (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₁₂ : i₀ ⟶ i₂) (f₂₃ : i₁ ⟶ i₃) + (h₁₂ : f₁ ≫ f₂ = f₁₂) (h₂₃ : f₂ ≫ f₃ = f₂₃) + +/-- The map `opZ^n(f₁ ≫ f₂, f₃) ⟶ E^n(f₁, f₂, f₃)`. -/ +noncomputable def opcyclesToE : X.opcycles n₁ f₁₂ f₃ ⟶ X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ := + X.descOpcycles n₀ _ hn₁ _ _ + (X.toCycles n₁ f₁ f₂ f₁₂ h₁₂ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃) (by simp) + +@[reassoc (attr := simp)] +lemma p_opcyclesToE : + X.pOpcycles n₁ f₁₂ f₃ ≫ X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ = + X.toCycles n₁ f₁ f₂ f₁₂ h₁₂ ≫ X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ := by + simp [opcyclesToE] + +@[reassoc (attr := simp)] +lemma opcyclesToE_ιE : + X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ ≫ X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ = + X.opcyclesMap n₁ f₁₂ f₃ f₂ f₃ (threeδ₁Toδ₀ f₁ f₂ f₃ f₁₂ h₁₂) := by + rw [← cancel_epi (X.pOpcycles n₁ f₁₂ f₃), p_opcyclesToE_assoc, + πE_ιE, toCycles_i_assoc] + exact (X.p_opcyclesMap _ _ _ _ _ _ _ (by rfl)).symm + +instance : Epi (X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂) := + epi_of_epi_fac (X.p_opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂) + +/-- The (exact) sequence `H^n(f₁) ⟶ opZ^n(f₁ ≫ f₂, f₃) ⟶ E^n(f₁, f₂, f₃) ⟶ 0`. -/ +@[simps!] +noncomputable def cokernelSequenceOpcyclesE : ShortComplex C where + X₁ := (X.H n₁).obj (mk₁ f₁) + X₂ := X.opcycles n₁ f₁₂ f₃ + X₃ := X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ + f := (X.H n₁).map (twoδ₂Toδ₁ f₁ f₂ f₁₂ h₁₂) ≫ X.pOpcycles n₁ f₁₂ f₃ + g := X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ + +instance : Epi (X.cokernelSequenceOpcyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).g := by + dsimp; infer_instance + +lemma cokernelSequenceOpcyclesE_exact : + (X.cokernelSequenceOpcyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A x₂ hx₂ + dsimp at x₂ hx₂ + obtain ⟨A₁, π₁, _, y₂, hy₂⟩ := + surjective_up_to_refinements_of_epi (X.pOpcycles n₁ f₁₂ f₃) x₂ + obtain ⟨A₂, π₂, _, y₁, hy₁⟩ := + (X.cokernelSequenceE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂).exact_up_to_refinements y₂ + (by simpa only [Category.assoc, p_opcyclesToE, hx₂, comp_zero] + using hy₂.symm =≫ X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂) + dsimp at y₁ hy₁ + obtain ⟨a, b, rfl⟩ : ∃ a b, y₁ = a ≫ biprod.inl + b ≫ biprod.inr := + ⟨y₁ ≫ biprod.fst, y₁ ≫ biprod.snd, by ext <;> simp⟩ + simp only [Preadditive.add_comp, Category.assoc, biprod.inl_desc, biprod.inr_desc] at hy₁ + refine ⟨A₂, π₂ ≫ π₁, inferInstance, a, ?_⟩ + dsimp + simp only [Category.assoc, hy₂, reassoc_of% hy₁, Preadditive.add_comp, δ_pOpcycles, + comp_zero, add_zero] + +-- TODO: dual statement? + +/-- The map `E^n(f₁, f₂, f₃) ⟶ Z^n(f₁, f₂ ≫ f₃)`. -/ +noncomputable def EToCycles : X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ⟶ X.cycles n₁ f₁ f₂₃ := + X.liftCycles n₁ n₂ hn₂ _ _ + (X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.fromOpcycles n₁ f₂ f₃ f₂₃ h₂₃) (by simp) + +@[reassoc (attr := simp)] +lemma EToCycles_i : + X.EToCycles n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃ ≫ X.iCycles n₁ f₁ f₂₃ = + X.ιE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.fromOpcycles n₁ f₂ f₃ f₂₃ h₂₃ := by + simp [EToCycles] + +@[reassoc (attr := simp)] +lemma πE_EToCycles : + X.πE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ ≫ X.EToCycles n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃ = + X.cyclesMap n₁ f₁ f₂ f₁ f₂₃ (threeδ₃Toδ₂ f₁ f₂ f₃ f₂₃ h₂₃) := by + rw [← cancel_mono (X.iCycles n₁ f₁ f₂₃), Category.assoc, EToCycles_i, + πE_ιE_assoc, p_fromOpcycles] + exact (X.cyclesMap_i _ _ _ _ _ _ _ (by rfl)).symm + +instance : Mono (X.EToCycles n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃) := + mono_of_mono_fac (X.EToCycles_i n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃) + +/-- The (exact) sequence `0 ⟶ E^n(f₁, f₂, f₃) ⟶ Z^n(f₁, f₂ ≫ f₃) ⟶ H^n(f₃)`. -/ +@[simps!] +noncomputable def kernelSequenceCyclesE : ShortComplex C where + X₁ := X.E n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ + X₂ := X.cycles n₁ f₁ f₂₃ + X₃ := (X.H n₁).obj (mk₁ f₃) + f := X.EToCycles n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃ + g := X.iCycles n₁ f₁ f₂₃ ≫ (X.H n₁).map (twoδ₁Toδ₀ f₂ f₃ f₂₃ h₂₃) + +instance : Mono (X.kernelSequenceCyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).f := by + dsimp; infer_instance + +lemma kernelSequenceCyclesE_exact : + (X.kernelSequenceCyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).Exact := by + rw [ShortComplex.exact_iff_exact_up_to_refinements] + intro A x₂ hx₂ + dsimp at x₂ hx₂ + obtain ⟨A₁, π₁, _, x₁, hx₁⟩ := + (X.kernelSequenceE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₂₃ h₂₃).exact_up_to_refinements + (x₂ ≫ X.iCycles n₁ f₁ f₂₃) (by cat_disch) + exact ⟨A₁, π₁, inferInstance, x₁, by simpa [← cancel_mono (X.iCycles ..)]⟩ + +end + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i j : ι} (f : i ⟶ j) {i' j' : ι} (f' : i' ⟶ j') + +/-- An homology data for `X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j)`, +expressing `H^n₁(f)` as the homology of this short complex, +see `EIsoH`. -/ +@[simps!] +noncomputable def homologyDataEIdId : + (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j)).HomologyData := + (ShortComplex.HomologyData.ofZeros (X.shortComplexE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j)) + (X.δ_eq_zero_of_isIso₂ n₀ n₁ hn₁ f (𝟙 j) inferInstance) + (X.δ_eq_zero_of_isIso₁ n₁ n₂ hn₂ (𝟙 i) f inferInstance)) + +/-- For any morphism `f : i ⟶ j`, this is the isomorphism from +`E^n₁(𝟙 i, f, 𝟙 j)` to `H^n₁(f)`. -/ +noncomputable def EIsoH : + X.E n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j) ≅ (X.H n₁).obj (mk₁ f) := + (X.homologyDataEIdId ..).left.homologyIso + +lemma EIsoH_hom_naturality + (α : mk₁ f ⟶ mk₁ f') (β : mk₃ (𝟙 _) f (𝟙 _) ⟶ mk₃ (𝟙 _) f' (𝟙 _)) + (hβ : β = homMk₃ (α.app 0) (α.app 0) (α.app 1) (α.app 1) + (by simp) (naturality' α 0 1) (by simp [Precomp.obj, Precomp.map])) : + X.EMap n₀ n₁ n₂ hn₁ hn₂ (𝟙 _) f (𝟙 _) (𝟙 _) f' (𝟙 _) β ≫ + (X.EIsoH n₀ n₁ n₂ hn₁ hn₂ f').hom = + (X.EIsoH n₀ n₁ n₂ hn₁ hn₂ f).hom ≫ (X.H n₁).map α := by + obtain rfl : α = homMk₁ (β.app 1) (β.app 2) (naturality' β 1 2) := by + subst hβ + exact hom_ext₁ rfl rfl + exact (ShortComplex.LeftHomologyMapData.ofZeros + (X.shortComplexEMap n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _ β) _ _ _ _).homologyMap_comm + +end + +section + +variable (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) + {i₀ i₁ : ι} (f : i₀ ⟶ i₁) + +/-- The isomorphism `Z^n(𝟙 _, f) ≅ H^n(f)`. -/ +noncomputable def cyclesIsoH : + X.cycles n₀ (𝟙 i₀) f ≅ (X.H n₀).obj (mk₁ f) := + (X.cyclesIso (n₀ - 1) n₀ n₁ (by lia) hn₁ (𝟙 i₀) f (𝟙 i₁)).symm ≪≫ + (X.homologyDataEIdId ..).left.cyclesIso + +@[simp] +lemma cyclesIsoH_inv : + (X.cyclesIsoH n₀ n₁ hn₁ f).inv = X.toCycles n₀ (𝟙 _) f f (by simp) := by + rw [← cancel_mono (X.iCycles n₀ (𝟙 _) f ), toCycles_i] + dsimp [cyclesIsoH] + rw [Category.assoc, cyclesIso_hom_i, + ShortComplex.LeftHomologyData.cyclesIso_inv_comp_iCycles, + homologyDataEIdId_left_i, ← Functor.map_id] + congr 1 + cat_disch + +@[reassoc (attr := simp)] +lemma cyclesIsoH_hom_inv_id : + (X.cyclesIsoH n₀ n₁ hn₁ f).hom ≫ + X.toCycles n₀ (𝟙 _) f f (by simp) = 𝟙 _ := by + simpa using (X.cyclesIsoH n₀ n₁ hn₁ f).hom_inv_id + +@[reassoc (attr := simp)] +lemma cyclesIsoH_inv_hom_id : + X.toCycles n₀ (𝟙 _) f f (by simp) ≫ + (X.cyclesIsoH n₀ n₁ hn₁ f).hom = 𝟙 _ := by + simpa using (X.cyclesIsoH n₀ n₁ hn₁ f).inv_hom_id + +/-- The isomorphism `opZ^n(f, 𝟙 _) ≅ H^n(f)`. -/ +noncomputable def opcyclesIsoH : + X.opcycles n₁ f (𝟙 i₁) ≅ (X.H n₁).obj (mk₁ f) := + (X.opcyclesIso n₀ n₁ (n₁ + 1) hn₁ (by lia) (𝟙 i₀) f (𝟙 i₁)).symm ≪≫ + (X.homologyDataEIdId ..).right.opcyclesIso + +@[simp] +lemma opcyclesIsoH_hom : + (X.opcyclesIsoH n₀ n₁ hn₁ f).hom = X.fromOpcycles n₁ f (𝟙 _) f (by simp) := by + rw [← cancel_epi (X.pOpcycles n₁ f (𝟙 _)), p_fromOpcycles] + dsimp [opcyclesIsoH] + rw [p_opcyclesIso_inv_assoc, ShortComplex.RightHomologyData.pOpcycles_comp_opcyclesIso_hom, + homologyDataEIdId_right_p, ← Functor.map_id] + congr 1 + cat_disch + +@[reassoc (attr := simp)] +lemma opcyclesIsoH_hom_inv_id : + X.fromOpcycles n₁ f (𝟙 _) f (by simp) ≫ + (X.opcyclesIsoH n₀ n₁ hn₁ f).inv = 𝟙 _ := by + simpa using (X.opcyclesIsoH n₀ n₁ hn₁ f).hom_inv_id + +@[reassoc (attr := simp)] +lemma opcyclesIsoH_inv_hom_id : + (X.opcyclesIsoH n₀ n₁ hn₁ f).inv ≫ + X.fromOpcycles n₁ f (𝟙 _) f (by simp) = 𝟙 _ := by + simpa using (X.opcyclesIsoH n₀ n₁ hn₁ f).inv_hom_id + +end + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) {i j : ι} (f : i ⟶ j) + +@[reassoc (attr := simp)] +lemma cyclesIsoH_hom_EIsoH_inv : + (X.cyclesIsoH n₁ n₂ hn₂ f).hom ≫ (X.EIsoH n₀ n₁ n₂ hn₁ hn₂ f).inv = + X.πE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j) := by + let h := (X.homologyDataEIdId n₀ n₁ n₂ hn₁ hn₂ f).left + have : h.cyclesIso.inv = + X.toCycles n₁ (𝟙 i) f f (by simp) ≫ + (X.cyclesIso n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j)).inv := by + rw [← cancel_mono (X.cyclesIso ..).hom, + Category.assoc, Iso.inv_hom_id, Category.comp_id, + ← cancel_mono (X.iCycles ..), Category.assoc, cyclesIso_hom_i, + h.cyclesIso_inv_comp_iCycles, toCycles_i] + dsimp [h] + rw [← Functor.map_id] + congr 1 + cat_disch + obtain rfl : n₀ = n₁ - 1 := by lia + rw [← cancel_epi (X.cyclesIsoH n₁ n₂ hn₂ f).inv, + cyclesIsoH_inv, cyclesIsoH_inv_hom_id_assoc] + dsimp [EIsoH] + rw [← cancel_epi h.π, h.π_comp_homologyIso_inv] + simp [πE, h, this] + +@[reassoc (attr := simp)] +lemma EIsoH_hom_opcyclesIsoH_inv : + (X.EIsoH n₀ n₁ n₂ hn₁ hn₂ f).hom ≫ (X.opcyclesIsoH n₀ n₁ hn₁ f).inv = + X.ιE n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j) := by + let h := (X.homologyDataEIdId n₀ n₁ n₂ hn₁ hn₂ f) + have : h.right.opcyclesIso.hom = + (X.opcyclesIso n₀ n₁ n₂ hn₁ hn₂ (𝟙 i) f (𝟙 j)).hom ≫ + X.fromOpcycles n₁ f (𝟙 j) f (by simp) := by + rw [← cancel_epi (X.opcyclesIso ..).inv, Iso.inv_hom_id_assoc, + ← cancel_epi (X.pOpcycles ..), p_opcyclesIso_inv_assoc, + h.right.pOpcycles_comp_opcyclesIso_hom, p_fromOpcycles] + dsimp [h] + rw [← Functor.map_id] + congr 1 + cat_disch + obtain rfl : n₂ = n₁ + 1 := by lia + rw [← cancel_mono (X.opcyclesIsoH n₀ n₁ hn₁ f).hom, Category.assoc, + opcyclesIsoH_hom, opcyclesIsoH_inv_hom_id] + dsimp [EIsoH, ιE] + rw [Category.assoc, ← this, + h.left_homologyIso_eq_right_homologyIso_trans_iso_symm, + ← ShortComplex.RightHomologyData.homologyIso_hom_comp_ι] + simp [h] + +end + +section + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i₀ i₁ i₂ i₃ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₁₂ : i₀ ⟶ i₂) (f₂₃ : i₁ ⟶ i₃) + (h₁₂ : f₁ ≫ f₂ = f₁₂) (h₂₃ : f₂ ≫ f₃ = f₂₃) + +@[reassoc (attr := simp)] +lemma opcyclesMap_threeδ₂Toδ₁_opcyclesToE : + X.opcyclesMap n₁ _ _ _ _ (threeδ₂Toδ₁ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃) ≫ + X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ = 0 := by + rw [← cancel_epi (X.pOpcycles ..), comp_zero, + p_opcyclesMap_assoc _ _ _ _ _ _ _ (twoδ₂Toδ₁ f₁ f₂ f₁₂ h₁₂) rfl _, + p_opcyclesToE, H_map_twoδ₂Toδ₁_toCycles_assoc, zero_comp] + +/-- The short exact sequence +`0 ⟶ opZ^(f₁, f₂ ≫ f₃) ⟶ opZ^n(f₁ ≫ f₂, f₃) ⟶ H^n(f₁, f₂, f₃) ⟶ 0`. -/ +@[simps] +noncomputable def shortComplexOpcyclesThreeδ₂Toδ₁ : ShortComplex C := + ShortComplex.mk _ _ + (X.opcyclesMap_threeδ₂Toδ₁_opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃) + +instance : + Mono (X.shortComplexOpcyclesThreeδ₂Toδ₁ n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃).f := by + dsimp + rw [Preadditive.mono_iff_cancel_zero] + intro A x hx + replace hx := hx =≫ X.fromOpcycles n₁ f₁₂ f₃ _ rfl + rw [zero_comp, Category.assoc, + X.opcyclesMap_fromOpcycles n₁ f₁ f₂₃ f₁₂ f₃ (f₁₂ ≫ f₃) (by cat_disch) _ rfl _ (𝟙 _) + (by simp) (by cat_disch), Functor.map_id, Category.comp_id] at hx + rw [← cancel_mono (X.fromOpcycles n₁ f₁ f₂₃ (f₁₂ ≫ f₃) (by cat_disch)), hx, zero_comp] + +instance : + Epi (X.shortComplexOpcyclesThreeδ₂Toδ₁ n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃).g := by + dsimp; infer_instance + +lemma shortComplexOpcyclesThreeδ₂Toδ₁_exact : + (X.shortComplexOpcyclesThreeδ₂Toδ₁ n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃).Exact := by + let φ : X.cokernelSequenceOpcyclesE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ ⟶ + (X.shortComplexOpcyclesThreeδ₂Toδ₁ n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃) := + { τ₁ := X.pOpcycles n₁ f₁ f₂₃ + τ₂ := 𝟙 _ + τ₃ := 𝟙 _ + comm₁₂ := by + dsimp + rw [Category.comp_id, X.p_opcyclesMap _ _ _ _ _ _ (twoδ₂Toδ₁ f₁ f₂ f₁₂) rfl] } + rw [← ShortComplex.exact_iff_of_epi_of_isIso_of_mono φ] + exact X.cokernelSequenceOpcyclesE_exact n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ + +lemma shortComplexOpcyclesThreeδ₂Toδ₁_shortExact : + (X.shortComplexOpcyclesThreeδ₂Toδ₁ n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ f₂₃ h₁₂ h₂₃).ShortExact where + exact := X.shortComplexOpcyclesThreeδ₂Toδ₁_exact .. + +end + +variable (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + {i₀ i₁ i₂ i₃ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₁₂ : i₀ ⟶ i₂) (h₁₂ : f₁ ≫ f₂ = f₁₂) + {i₀' i₁' i₂' i₃' : ι} (f₁' : i₀' ⟶ i₁') (f₂' : i₁' ⟶ i₂') (f₃' : i₂' ⟶ i₃') + (f₁₂' : i₀' ⟶ i₂') (h₁₂' : f₁' ≫ f₂' = f₁₂') + +@[reassoc] +lemma opcyclesToE_EMap (α : mk₃ f₁ f₂ f₃ ⟶ mk₃ f₁' f₂' f₃') (β : mk₂ f₁₂ f₃ ⟶ mk₂ f₁₂' f₃') + (h₀ : β.app 0 = α.app 0) (h₁ : β.app 1 = α.app 2) : + X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁ f₂ f₃ f₁₂ h₁₂ ≫ X.EMap _ _ _ _ _ _ _ _ _ _ _ α = + X.opcyclesMap _ _ _ _ _ β ≫ X.opcyclesToE n₀ n₁ n₂ hn₁ hn₂ f₁' f₂' f₃' f₁₂' h₁₂' := by + rw [← cancel_mono (X.ιE ..), Category.assoc, Category.assoc, opcyclesToE_ιE, + ← cancel_epi (X.pOpcycles ..), p_opcyclesToE_assoc, + X.πE_EMap_assoc _ _ _ _ _ _ _ _ _ _ _ _ + (homMk₂ (α.app 0) (α.app 1) (α.app 2) (naturality' α 0 1) (naturality' α 1 2)) rfl, + πE_ιE, X.cyclesMap_i_assoc _ _ _ _ _ _ _ rfl, toCycles_i_assoc, + X.p_opcyclesMap_assoc _ _ _ _ _ _ _ rfl, X.p_opcyclesMap _ _ _ _ _ _ _ rfl, + ← Functor.map_comp_assoc, ← Functor.map_comp_assoc] + congr 2 + ext + · simpa [h₀] using naturality' α 0 1 + · simp [h₁] + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralObject/SpectralSequence.lean b/Mathlib/Algebra/Homology/SpectralObject/SpectralSequence.lean new file mode 100644 index 00000000000000..5c08b75587f4b6 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralObject/SpectralSequence.lean @@ -0,0 +1,695 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.SpectralObject.Homology +public import Mathlib.Algebra.Homology.SpectralObject.HasSpectralSequence +public import Mathlib.Algebra.Homology.SpectralSequence.Basic +public import Mathlib.Order.WithBotTop + +/-! +# The spectral sequence of a spectral object + +The main definition in this file is `Abelian.SpectralObject.spectralSequence`. +Assume that `X` is a spectral object indexed by `ι` in an abelian category `C`, +and that we have `data : SpectralSequenceMkData ι c r₀` for a family +of complexes shapes `c : ℤ → ComplexShape κ` for a type `κ` and `r₀ : ℤ`. +Then, under the assumption `X.HasSpectralSequence data` (see the file +`Mathlib/Algebra/Homology/SpectralObject/HasSpectralSequence.lean`), +we obtain `X.spectralSequence data` which is a spectral sequence starting +on page `r₀`, such that the `r`th page (for `r₀ ≤ r`) is a homological +complex of shape `c r`. + +## Outline of the construction + +The construction of the spectral sequence is as follows. If `r₀ ≤ r` +and `pq : κ`, we define the object of the spectral sequence in position `pq` +on the `r`th page as `E^d(i₀ r pq ≤ i₁ pq ≤ i₂ pq ≤ i₃ r pq)` +where `d := data.deg pq` and the indices `i₀`, `i₁`, `i₂`, `i₃` are given +by data (they all depend on `pq`, and `i₀` and `i₃` also depend on the page `r`), +see `spectralSequencePageXIso`. + +When `(c r).Rel pq pq'`, the differential from the object in position `pq` +to the object in position `pq'` on the `r`th page can be related to +the differential `X.d` of the spectral object (see the lemma +`spectralSequence_page_d_eq`). Indeed, the assumptions that +are part of `data` give equalities of indices `i₂ r pq' = i₀ r pq` +and `i₃ pq' = i₁ pq`, so that we have a chain of inequalities +`i₀ r pq' ≤ i₁ pq' ≤ i₂ pq' ≤ i₃ r pq' ≤ i₂ pq ≤ i₄ r pq` for which +the API of spectral objects provides a differential +`X.d : E^n(i₀ r pq ≤ i₁ pq ≤ i₂ pq ≤ i₃ r pq) ⟶ E^{n + 1}(i₀ r pq' ≤ i₁ pq' ≤ i₂ pq' ≤ i₃ r pq')`. + +Now, fix `r` and three positions `pq`, `pq'` and `pq''` such that +`pq` is the previous object of `pq'` for `c r` and `pq''` is the next +object of `pq'`. (Note that in case there are no nontrivial differentials +to the object `pq'` for the complex shape `c r`, according to the homological +complex API, we have `pq = pq'` and the differential is zero. Similarly, +when there are no nontrivial differentials from the object in position `pq'`, +we have `pq'' = pq` and the corresponding differential is zero.) +In the favourable case where both `(c r).Rel pq pq'` and `(c r).Rel pq' pq''` +hold, the definitions `SpectralObject.SpectralSequence.shortComplexIso` and +`SpectralObject.spectralSequencePageSc'Iso` in this file can be +used in combination to `SpectralObject.SpectralSequence.dHomologyIso` in order to compute +the homology of the differentials.) + +In the general case, using the assumptions in `X.HasSpectralSequence data`, +we provide a limit kernel fork `kf` and +a limit cokernel cofork `cc` of the differentials on the `r`th page, +together with an epi-mono factorization `fac` which allows +to obtain that the homology of the `r`th page identifies to the homology +of the next page (see the definitions +`SpectralObject.SpectralSequence.homologyData` and +`SpectralObject.spectralSequenceHomologyData`). + +## Spectral objects indexed by `EInt`. + +When `X` is a spectral object indexed by the extended integers `EInt`, +we obtain the `E₂`-cohomological spectral sequence +`X.E₂SpectralSequence` where the objects of each page are indexed by +`ℤ × ℤ` (the condition `HasSpectralSequence` is automatically satisfied). +Under the `X.IsFirstQuadrant` assumption, we obtain +`X.E₂SpectralSequenceNat` which is a first quadrant `E₂`-spectral +sequence (the objects in the pages are indexed by `ℕ × ℕ` instead +of `ℤ × ℤ`). + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Limits ComposableArrows + +namespace Abelian + +namespace SpectralObject + +variable {C ι κ : Type*} [Category C] [Abelian C] [Preorder ι] + (X : SpectralObject C ι) + {c : ℤ → ComplexShape κ} {r₀ : ℤ} + +variable (data : SpectralSequenceMkData ι c r₀) + +namespace SpectralSequence + +/-- The object on position `pq` on the `r`th page of the spectral sequence. -/ +noncomputable def pageX (r : ℤ) (pq : κ) (hr : r₀ ≤ r := by lia) : C := + X.E (data.deg pq - 1) (data.deg pq) (data.deg pq + 1) (by simp) rfl + (homOfLE (data.le₀₁ r pq)) (homOfLE (data.le₁₂ pq)) (homOfLE (data.le₂₃ r pq)) + +/-- The object on position `pq` on the `r`th page of the spectral sequence identifies +to `E^{deg pq}(i₀ ≤ i₁ ≤ i₂ ≤ i₃)`. -/ +noncomputable def pageXIso (r : ℤ) (hr : r₀ ≤ r) (pq : κ) (n₀ n₁ n₂ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (h : n₁ = data.deg pq) + (i₀ i₁ i₂ i₃ : ι) (h₀ : i₀ = data.i₀ r pq) (h₁ : i₁ = data.i₁ pq) + (h₂ : i₂ = data.i₂ pq) (h₃ : i₃ = data.i₃ r pq) : + pageX X data r pq hr ≅ X.E n₀ n₁ n₂ hn₁ hn₂ + (homOfLE (data.le₀₁' r hr pq h₀ h₁)) + (homOfLE (data.le₁₂' pq h₁ h₂)) + (homOfLE (data.le₂₃' r hr pq h₂ h₃)) := + eqToIso (by + obtain rfl : n₀ = n₁ - 1 := by lia + subst h hn₂ h₀ h₁ h₂ h₃ + rfl) + +open Classical in +/-- The differential on the `r`th page of the spectral sequence. -/ +noncomputable def pageD (r : ℤ) (pq pq' : κ) (hr : r₀ ≤ r := by lia) : + pageX X data r pq hr ⟶ pageX X data r pq' hr := + if hpq : (c r).Rel pq pq' + then + X.d (data.deg pq - 1) (data.deg pq) (data.deg pq + 1) (data.deg pq + 2) _ rfl + (by lia) (homOfLE (data.le₀₁ r pq')) + (homOfLE (data.le₁₂' pq' rfl (data.hc₀₂ r pq pq' hpq))) + (homOfLE (data.le₀₁ r pq)) (homOfLE (data.le₁₂ pq)) (homOfLE (data.le₂₃ r pq)) ≫ + (pageXIso _ _ _ _ _ _ _ _ _ _ (data.hc r pq pq' hpq) _ _ _ _ rfl rfl + (data.hc₀₂ r pq pq' hpq) (data.hc₁₃ r pq pq' hpq)).inv + else 0 + +lemma pageD_eq (r : ℤ) (hr : r₀ ≤ r) (pq pq' : κ) (hpq : (c r).Rel pq pq') + (n₀ n₁ n₂ n₃ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ i₃ i₄ i₅ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) (hn₁' : n₁ = data.deg pq) + (h₀ : i₀ = data.i₀ r pq') (h₁ : i₁ = data.i₁ pq') (h₂ : i₂ = data.i₀ r pq) + (h₃ : i₃ = data.i₁ pq) (h₄ : i₄ = data.i₂ pq) (h₅ : i₅ = data.i₃ r pq) : + pageD X data r pq pq' = + (pageXIso _ _ _ _ _ _ _ _ _ _ hn₁' _ _ _ _ h₂ h₃ h₄ h₅).hom ≫ + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ ≫ + (pageXIso _ _ _ _ _ _ _ _ _ _ + (by simpa only [← hn₂, hn₁'] using data.hc r pq pq' hpq) _ _ _ _ h₀ h₁ + (by rw [h₂, data.hc₀₂ r pq pq' hpq]) + (by rw [h₃, data.hc₁₃ r pq pq' hpq])).inv := by + subst hn₁' h₀ h₁ h₂ h₃ h₄ h₅ + obtain rfl : n₀ = data.deg pq - 1 := by lia + obtain rfl : n₂ = data.deg pq + 1 := by lia + obtain rfl : n₃ = data.deg pq + 2 := by lia + dsimp [pageD, pageXIso] + rw [dif_pos hpq, Category.id_comp] + rfl + +@[reassoc (attr := simp)] +lemma pageD_pageD (r : ℤ) (hr : r₀ ≤ r) (pq pq' pq'' : κ) : + pageD X data r pq pq' hr ≫ pageD X data r pq' pq'' hr = 0 := by + by_cases hpq : (c r).Rel pq pq' + · by_cases hpq' : (c r).Rel pq' pq'' + · rw [pageD_eq X data r hr pq pq' hpq (data.deg pq - 1) (data.deg pq) _ _ (by simp) + rfl rfl (homOfLE (data.le₂₃ r pq'')) + (homOfLE (data.le₁₂' pq' (data.hc₁₃ r pq' pq'' hpq').symm + (data.hc₀₂ r pq pq' hpq))) (homOfLE (data.le₀₁ r pq)) (homOfLE (data.le₁₂ pq)) + (homOfLE (data.le₂₃ r pq)) rfl (data.hc₀₂ r pq' pq'' hpq').symm + (data.hc₁₃ r pq' pq'' hpq').symm rfl rfl rfl rfl, + pageD_eq X data r hr pq' pq'' hpq' (data.deg pq) _ _ _ rfl rfl rfl _ _ _ _ _ + (data.hc r pq pq' hpq) rfl rfl (data.hc₀₂ r pq' pq'' hpq').symm + (data.hc₁₃ r pq' pq'' hpq').symm (data.hc₀₂ r pq pq' hpq) + (data.hc₁₃ r pq pq' hpq), Category.assoc, Category.assoc, Iso.inv_hom_id_assoc, + d_d_assoc, zero_comp, comp_zero] + · dsimp only [pageD] + rw [dif_neg hpq', comp_zero] + · dsimp only [pageD] + rw [dif_neg hpq, zero_comp] + +/-- The `r`th page of the spectral sequence. -/ +@[simps] +noncomputable def page (r : ℤ) (hr : r₀ ≤ r) : + HomologicalComplex C (c r) where + X pq := pageX X data r pq + d := pageD X data r + shape pq pq' hpq := dif_neg hpq + +section + +/-- The short complex of the `r`th page of the spectral sequence on position `pq'` +identifies to the short complex given by the differentials of the spectral object. +Then, the homology of this short complex can be computed using +`SpectralSequence.dHomologyIso`. +(This only applies in the favourable case when there are `pq` and `pq''` such +that `(c r).Rel pq pq'` and `(c r).Rel pq' pq''` hold.) -/ +noncomputable def shortComplexIso (r : ℤ) (hr : r₀ ≤ r) (pq pq' pq'' : κ) + (hpq : (c r).Rel pq pq') (hpq' : (c r).Rel pq' pq'') + (n₀ n₁ n₂ n₃ n₄ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) (hn₄ : n₃ + 1 = n₄) + (hn₂' : n₂ = data.deg pq') : + (page X data r hr).sc' pq pq' pq'' ≅ + X.dShortComplex n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ (homOfLE (data.le₀₁ r pq'')) + (homOfLE (data.le₁₂ pq'')) (homOfLE (data.le₂₃ r pq'')) + (homOfLE (by simpa only [← data.hc₁₃ r pq' pq'' hpq', data.hc₀₂ r pq pq' hpq] + using data.le₁₂ pq')) (homOfLE (data.le₀₁ r pq)) + (homOfLE (data.le₁₂ pq)) (homOfLE (data.le₂₃ r pq)) := by + refine ShortComplex.isoMk + (pageXIso X data _ hr _ _ _ _ _ _ (by have := data.hc r pq pq' hpq; lia) _ _ _ _ + rfl rfl rfl rfl) + (pageXIso X data _ hr _ _ _ _ _ _ hn₂' _ _ _ _ + (by rw [data.hc₀₂ r pq' pq'' hpq']) (by rw [data.hc₁₃ r pq' pq'' hpq']) + (by rw [data.hc₀₂ r pq pq' hpq]) (by rw [data.hc₁₃ r pq pq' hpq])) + (pageXIso X data _ hr _ _ _ _ _ _ (by have := data.hc r pq' pq'' hpq'; lia) + _ _ _ _ rfl rfl rfl rfl) ?_ ?_ + · dsimp + rw [pageD_eq X data r hr pq pq' hpq, Category.assoc, Category.assoc, + Iso.inv_hom_id, Category.comp_id] + · exact (data.hc₀₂ r pq' pq'' hpq').symm + · exact (data.hc₁₃ r pq' pq'' hpq').symm + · dsimp + rw [pageD_eq X data r hr pq' pq'' hpq', Category.assoc, Category.assoc, + Iso.inv_hom_id, Category.comp_id] + · rfl + · rfl + +section + +variable (r r' : ℤ) (hrr' : r + 1 = r') (hr : r₀ ≤ r) + (pq pq' pq'' : κ) (hpq : (c r).prev pq' = pq) (hpq' : (c r).next pq' = pq'') + (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + (hn₁' : n₁ = data.deg pq') + (i₀' i₀ i₁ i₂ i₃ i₃' : ι) + (hi₀' : i₀' = data.i₀ r' pq') + (hi₀ : i₀ = data.i₀ r pq') + (hi₁ : i₁ = data.i₁ pq') + (hi₂ : i₂ = data.i₂ pq') + (hi₃ : i₃ = data.i₃ r pq') + (hi₃' : i₃' = data.i₃ r' pq') + +namespace HomologyData + +lemma mk₃fac : + fourδ₁Toδ₀' i₀' i₀ i₁ i₂ i₃ (data.le₀'₀ hrr' hr pq' hi₀' hi₀) + (data.le₀₁' r hr pq' hi₀ hi₁) (data.le₁₂' pq' hi₁ hi₂) (data.le₂₃' r hr pq' hi₂ hi₃) ≫ + fourδ₄Toδ₃' i₀ i₁ i₂ i₃ i₃' _ _ _ (data.le₃₃' hrr' hr pq' hi₃ hi₃') = + fourδ₄Toδ₃' i₀' i₁ i₂ i₃ i₃' _ _ _ (data.le₃₃' hrr' hr pq' hi₃ hi₃') ≫ + fourδ₁Toδ₀' i₀' i₀ i₁ i₂ i₃' (data.le₀'₀ hrr' hr pq' hi₀' hi₀) _ _ _ := by + rfl + +lemma kf_w : + (X.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀' i₀ i₁ i₂ i₃ (data.le₀'₀ hrr' hr pq' hi₀' hi₀) + (data.le₀₁' r hr pq' hi₀ hi₁) (data.le₁₂' pq' hi₁ hi₂) (data.le₂₃' r hr pq' hi₂ hi₃) ≫ + (pageXIso X data _ hr _ _ _ _ _ _ hn₁' _ _ _ _ hi₀ hi₁ hi₂ hi₃).inv) ≫ + (page X data r hr).d pq' pq'' = 0 := by + by_cases h : (c r).Rel pq' pq'' + · dsimp + rw [pageD_eq X data r hr pq' pq'' h n₀ n₁ n₂ _ hn₁ hn₂ rfl + (homOfLE (by simpa only [hi₀', data.i₀_prev r r' _ _ h] using data.le₀₁ r pq'')) + (homOfLE (data.le₀'₀ hrr' hr pq' hi₀' hi₀)) _ _ _ hn₁' + rfl (by rw [hi₀', data.i₀_prev r r' pq' pq'' h]) hi₀ hi₁ hi₂ hi₃, + Category.assoc, Iso.inv_hom_id_assoc, EMap_fourδ₁Toδ₀_d_assoc, zero_comp] + · rw [HomologicalComplex.shape _ _ _ h, comp_zero] + +/-- A (limit) kernel fork of the differential on the `r`th page whose point +identifies to an object `X.E` -/ +noncomputable abbrev kf : + KernelFork ((page X data r hr).d pq' pq'') := + KernelFork.ofι _ (kf_w X data r r' hrr' hr pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃) + +/-- The (exact) short complex attached to the kernel fork `kf`. -/ +@[simps!] +noncomputable def kfSc : ShortComplex C := + ShortComplex.mk _ _ (kf_w X data r r' hrr' hr pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃) + +instance : Mono (kfSc X data r r' hrr' hr pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃).f := by + dsimp + infer_instance + +variable [X.HasSpectralSequence data] in +include hpq' hn₁' in +lemma isIso_EMapFourδ₁Toδ₀' (h : ¬ (c r).Rel pq' pq'') : + IsIso (X.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ + i₀' i₀ i₁ i₂ i₃ (data.le₀'₀ hrr' hr pq' hi₀' hi₀) (data.le₀₁' r hr pq' hi₀ hi₁) + (data.le₁₂' pq' hi₁ hi₂) (data.le₂₃' r hr pq' hi₂ hi₃)) := by + apply X.isIso_EMap_fourδ₁Toδ₀_of_isZero + refine X.isZero_H_obj_mk₁_i₀_le' data r r' hrr' hr pq' + (fun k hk ↦ ?_) _ (by lia) _ _ hi₀' hi₀ + obtain rfl := (c r).next_eq' hk + subst hpq' + exact h hk + +variable [X.HasSpectralSequence data] in +include hpq' in +lemma kfSc_exact : (kfSc X data r r' hrr' hr pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃).Exact := by + by_cases h : (c r).Rel pq' pq'' + · refine ShortComplex.exact_of_iso (Iso.symm ?_) + (X.dKernelSequence_exact n₀ n₁ n₂ _ hn₁ hn₂ rfl + (homOfLE (show data.i₀ r pq'' ≤ i₀' by + simpa only [hi₀', data.i₀_prev r r' _ _ h] using data.le₀₁ r pq'')) + (homOfLE (data.le₀'₀ hrr' hr pq' hi₀' hi₀)) (homOfLE (data.le₀₁' r hr pq' hi₀ hi₁)) + (homOfLE (data.le₁₂' pq' hi₁ hi₂)) (homOfLE (data.le₂₃' r hr pq' hi₂ hi₃)) _ rfl) + refine ShortComplex.isoMk (Iso.refl _) + (pageXIso X data _ hr _ _ _ _ _ _ hn₁' _ _ _ _ hi₀ hi₁ hi₂ hi₃) + (pageXIso X data _ hr _ _ _ _ _ _ (by have := data.hc r _ _ h; lia) _ _ _ _ + rfl (by rw [hi₀', data.i₀_prev r r' _ _ h]) (by rw [hi₀, data.hc₀₂ r _ _ h]) + (by rw [hi₁, data.hc₁₃ r _ _ h])) ?_ ?_ + · dsimp + rw [Category.id_comp, Category.assoc, Iso.inv_hom_id, Category.comp_id] + · dsimp + rw [pageD_eq X data r hr pq' pq'' h n₀ n₁ n₂ _ hn₁ hn₂ rfl + (homOfLE (show data.i₀ r pq'' ≤ i₀' by + simpa only [hi₀', data.i₀_prev r r' _ _ h] using data.le₀₁ r pq'')), + Category.assoc, Category.assoc, Iso.inv_hom_id, Category.comp_id] + · rfl + · rw [hi₀', data.i₀_prev r r' _ _ h] + · rw [ShortComplex.exact_iff_epi]; swap + · exact (page X data r hr).shape _ _ h + have := isIso_EMapFourδ₁Toδ₀' X data r r' hrr' hr pq' pq'' hpq' n₀ n₁ n₂ hn₁ hn₂ + hn₁' i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃ h + dsimp + infer_instance + +variable [X.HasSpectralSequence data] in +/-- The kernel fork `kf` is a limit. -/ +noncomputable def isLimitKf : + IsLimit (kf X data r r' hrr' hr pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃) := + (kfSc_exact X data r r' hrr' hr pq' pq'' hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃).fIsKernel + +lemma cc_w : + (page X data r hr).d pq pq' ≫ + (pageXIso X data _ hr _ _ _ _ _ _ hn₁' _ _ _ _ hi₀ hi₁ hi₂ hi₃).hom ≫ + X.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₃' _ _ _ + (data.le₃₃' hrr' hr pq' hi₃ hi₃') = 0 := by + by_cases h : (c r).Rel pq pq' + · dsimp + rw [pageD_eq X data r hr pq pq' h (n₀ - 1) n₀ n₁ n₂ (by simp) hn₁ hn₂ _ + _ (homOfLE (data.le₂₃' r hr pq' hi₂ hi₃)) (homOfLE (data.le₃₃' hrr' hr pq' hi₃ hi₃')) + (homOfLE (by simpa only [hi₃', data.i₃_next r r' _ _ h] using data.le₂₃ r pq)) + (by have := data.hc r pq pq' h; lia) hi₀ hi₁ (by rw [hi₂, data.hc₀₂ r _ _ h]) + (by rw [hi₃, data.hc₁₃ r _ _ h]) (by rw [hi₃', data.i₃_next r r' _ _ h]) rfl, + Category.assoc, Category.assoc, Iso.inv_hom_id_assoc, d_EMap_fourδ₄Toδ₃, comp_zero] + · rw [HomologicalComplex.shape _ _ _ h, zero_comp] + +/-- A (limit) cokernel cofork of the differential on the `r`th page whose point +identifies to an object `X.E` -/ +noncomputable abbrev cc : + CokernelCofork ((page X data r hr).d pq pq') := + CokernelCofork.ofπ _ + (cc_w X data r r' hrr' hr pq pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃') + +/-- The (exact) short complex attached to the cokernel cofork `cc`. -/ +@[simps!] +noncomputable def ccSc : ShortComplex C := + ShortComplex.mk _ _ (cc_w X data r r' hrr' hr pq pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃') + +instance : Epi (ccSc X data r r' hrr' hr pq pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃').g := by + dsimp + infer_instance + +variable [X.HasSpectralSequence data] in +include hpq hn₁' in +lemma isIso_EMapFourδ₄Toδ₃' (h : ¬ (c r).Rel pq pq') : + IsIso (X.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₃' + (data.le₀₁' r hr pq' hi₀ hi₁) (data.le₁₂' pq' hi₁ hi₂) + (data.le₂₃' r hr pq' hi₂ hi₃) (data.le₃₃' hrr' hr pq' hi₃ hi₃')) := by + apply X.isIso_EMap_fourδ₄Toδ₃_of_isZero + refine X.isZero_H_obj_mk₁_i₃_le' data r r' hrr' hr pq' ?_ _ (by lia) _ _ hi₃ hi₃' + intro k hk + obtain rfl := (c r).prev_eq' hk + subst hpq + exact h hk + +variable [X.HasSpectralSequence data] in +include hpq in +lemma ccSc_exact : + (ccSc X data r r' hrr' hr pq pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃').Exact := by + by_cases h : (c r).Rel pq pq' + · refine ShortComplex.exact_of_iso (Iso.symm ?_) + (X.dCokernelSequence_exact (n₀ - 1) n₀ n₁ n₂ (by simp) hn₁ hn₂ + (homOfLE (data.le₀₁' r hr pq' hi₀ hi₁)) + (homOfLE (data.le₁₂' pq' hi₁ hi₂)) (homOfLE (data.le₂₃' r hr pq' hi₂ hi₃)) + (homOfLE (data.le₃₃' hrr' hr pq' hi₃ hi₃')) + (show i₃' ⟶ data.i₃ r pq from homOfLE (by + simpa only [hi₃', data.i₃_next r r' _ _ h] using data.le₂₃ r pq)) _ rfl) + refine ShortComplex.isoMk + (pageXIso X data _ hr _ _ _ _ _ _ (by have := data.hc r _ _ h; lia) _ _ _ _ + (by rw [hi₂, data.hc₀₂ r _ _ h]) (by rw [hi₃, data.hc₁₃ r _ _ h]) + (by rw [hi₃', data.i₃_next r r' _ _ h]) rfl) + (pageXIso X data _ hr _ _ _ _ _ _ hn₁' _ _ _ _ hi₀ hi₁ hi₂ hi₃) (Iso.refl _) ?_ ?_ + · dsimp + rw [pageD_eq X data r hr pq pq' h (n₀ - 1) n₀ n₁ n₂ (by simp) hn₁ hn₂, + Category.assoc, Category.assoc, Iso.inv_hom_id, Category.comp_id] + · exact hi₀ + · exact hi₁ + · dsimp + rw [Category.comp_id, Iso.cancel_iso_hom_left] + · rw [ShortComplex.exact_iff_mono]; swap + · exact (page X data r hr).shape _ _ h + have := isIso_EMapFourδ₄Toδ₃' X data r r' hrr' hr pq pq' hpq n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃' h + dsimp + infer_instance + +variable [X.HasSpectralSequence data] in +/-- The cokernel cofork `cc` is a colimit. -/ +noncomputable def isColimitCc : + IsColimit (cc X data r r' hrr' hr pq pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃') := + (ccSc_exact X data r r' hrr' hr pq pq' hpq n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃').gIsCokernel + +lemma fac : + (kf X data r r' hrr' hr pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃).ι ≫ + (cc X data r r' hrr' hr pq pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃').π = + X.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀' i₁ i₂ i₃ i₃' _ _ _ (data.le₃₃' hrr' hr pq' hi₃ hi₃') ≫ + X.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀' i₀ i₁ i₂ i₃' + (data.le₀'₀ hrr' hr pq' hi₀' hi₀) _ _ _ := by + dsimp + simpa only [Category.assoc, Iso.inv_hom_id_assoc, EMap_comp] using + congr_arg (X.EMap n₀ n₁ n₂ hn₁ hn₂ _ _ _ _ _ _) + (mk₃fac data r r' hrr' hr pq' i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃') + +end HomologyData + +variable [X.HasSpectralSequence data] + +open HomologyData in +/-- The homology data for the short complex given by differentials on the +`r`th page of the spectral sequence which shows that the homology identifies +to an object on the next page. -/ +@[simps!] +noncomputable def homologyData : ((page X data r hr).sc' pq pq' pq'').HomologyData := + ShortComplex.HomologyData.ofEpiMonoFactorisation + ((page X data r hr).sc' pq pq' pq'') + (isLimitKf X data r r' hrr' hr pq' pq'' hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ hi₀' hi₀ hi₁ hi₂ hi₃) + (isColimitCc X data r r' hrr' hr pq pq' hpq n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ i₃' hi₀ hi₁ hi₂ hi₃ hi₃') + (fac X data r r' hrr' hr pq pq' pq'' n₀ n₁ n₂ hn₁ hn₂ hn₁' i₀' i₀ i₁ i₂ i₃ i₃' + hi₀' hi₀ hi₁ hi₂ hi₃ hi₃') + +/-- The homology of the differentials on a page of the spectral sequence identifies +to the objects on the next page. -/ +noncomputable def homologyIso' : + ((page X data r hr).sc' pq pq' pq'').homology ≅ (page X data r' (by lia)).X pq' := + (homologyData X data r r' hrr' hr pq pq' pq'' hpq hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃').left.homologyIso ≪≫ + (pageXIso X data _ (by lia) _ _ _ _ _ _ hn₁' _ _ _ _ hi₀' hi₁ hi₂ hi₃').symm + +/-- The homology of the differentials on a page of the spectral sequence identifies +to the objects on the next page. -/ +noncomputable def homologyIso : + (page X data r hr).homology pq' ≅ + (page X data r' (hr.trans (by lia))).X pq' := + homologyIso' X data r r' hrr' hr _ pq' _ rfl rfl + (data.deg pq' - 1) (data.deg pq') (data.deg pq' + 1) (by simp) + rfl rfl _ _ _ _ _ _ rfl rfl rfl rfl rfl rfl + +end + +end + +end SpectralSequence + +section + +variable [X.HasSpectralSequence data] in +/-- The spectral sequence attached to a spectral object in an abelian category. -/ +noncomputable def spectralSequence : SpectralSequence C c r₀ where + page := SpectralSequence.page X data + iso r r' pq hrr' hr := SpectralSequence.homologyIso X data r r' hrr' hr pq + +variable [X.HasSpectralSequence data] + +/-- The objects on the pages of a spectral sequence attached to a spectral object `X` +identifies an object `X.E`. -/ +noncomputable def spectralSequencePageXIso (r : ℤ) (hr : r₀ ≤ r) + (pq : κ) (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (h : n₁ = data.deg pq) + (i₀ i₁ i₂ i₃ : ι) (h₀ : i₀ = data.i₀ r pq) + (h₁ : i₁ = data.i₁ pq) (h₂ : i₂ = data.i₂ pq) + (h₃ : i₃ = data.i₃ r pq) : + ((X.spectralSequence data).page r).X pq ≅ + X.E n₀ n₁ n₂ hn₁ hn₂ + (homOfLE (data.le₀₁' r hr pq h₀ h₁)) + (homOfLE (data.le₁₂' pq h₁ h₂)) + (homOfLE (data.le₂₃' r hr pq h₂ h₃)) := + SpectralSequence.pageXIso X data _ hr _ _ _ _ _ _ h _ _ _ _ h₀ h₁ h₂ h₃ + +lemma spectralSequence_page_d_eq (r : ℤ) (hr : r₀ ≤ r) + (pq pq' : κ) (hpq : (c r).Rel pq pq') + (n₀ n₁ n₂ n₃ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) + {i₀ i₁ i₂ i₃ i₄ i₅ : ι} (f₁ : i₀ ⟶ i₁) (f₂ : i₁ ⟶ i₂) (f₃ : i₂ ⟶ i₃) + (f₄ : i₃ ⟶ i₄) (f₅ : i₄ ⟶ i₅) (hn₁' : n₁ = data.deg pq) + (h₀ : i₀ = data.i₀ r pq') (h₁ : i₁ = data.i₁ pq') + (h₂ : i₂ = data.i₀ r pq) + (h₃ : i₃ = data.i₁ pq) (h₄ : i₄ = data.i₂ pq) (h₅ : i₅ = data.i₃ r pq) : + ((X.spectralSequence data).page r).d pq pq' = + (X.spectralSequencePageXIso data r hr _ _ _ _ _ _ hn₁' _ _ _ _ h₂ h₃ h₄ h₅).hom ≫ + X.d n₀ n₁ n₂ n₃ hn₁ hn₂ hn₃ f₁ f₂ f₃ f₄ f₅ ≫ + (X.spectralSequencePageXIso data r hr _ _ _ _ _ _ + (by simpa only [← hn₂, hn₁'] using data.hc r pq pq' hpq) _ _ _ _ h₀ h₁ + (by rw [h₂, ← data.hc₀₂ r pq pq' hpq]) + (by rw [h₃, data.hc₁₃ r pq pq' hpq])).inv := + SpectralSequence.pageD_eq _ _ _ hr _ _ hpq .. + +lemma isZero_spectralSequence_page_X_iff (r : ℤ) (hr : r₀ ≤ r) (pq : κ) + (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (h : n₁ = data.deg pq) + (i₀ i₁ i₂ i₃ : ι) (h₀ : i₀ = data.i₀ r pq) + (h₁ : i₁ = data.i₁ pq) (h₂ : i₂ = data.i₂ pq) + (h₃ : i₃ = data.i₃ r pq) : + IsZero (((X.spectralSequence data).page r).X pq) ↔ + IsZero (X.E n₀ n₁ n₂ hn₁ hn₂ + (homOfLE (data.le₀₁' r hr pq h₀ h₁)) + (homOfLE (data.le₁₂' pq h₁ h₂)) + (homOfLE (data.le₂₃' r hr pq h₂ h₃))) := + Iso.isZero_iff (X.spectralSequencePageXIso data r hr pq n₀ n₁ n₂ hn₁ hn₂ h i₀ i₁ i₂ i₃ + h₀ h₁ h₂ h₃) + +lemma isZero_spectralSequence_page_X_of_isZero_H (r : ℤ) (hr : r₀ ≤ r) + (pq : κ) (n : ℤ) (hn : n = data.deg pq) + (i₁ i₂ : ι) (h₁ : i₁ = data.i₁ pq) (h₂ : i₂ = data.i₂ pq) + (h : IsZero ((X.H n).obj + (mk₁ (homOfLE (by simpa only [h₁, h₂] using data.le₁₂ pq) : i₁ ⟶ i₂)))) : + IsZero (((X.spectralSequence data).page r).X pq) := by + rw [X.isZero_spectralSequence_page_X_iff data r hr pq (n - 1) n (n + 1) (by simp) rfl hn + _ i₁ i₂ _ rfl h₁ h₂ rfl] + apply isZero_E_of_isZero_H + exact h + +/-- isZero_spectralSequence_page_X_of_isZero_H' -/ +lemma isZero_spectralSequence_page_X_of_isZero_H' (r : ℤ) (hr : r₀ ≤ r) + (pq : κ) + (h : IsZero ((X.H (data.deg pq)).obj (mk₁ (homOfLE (data.le₁₂ pq))))) : + IsZero (((X.spectralSequence data).page r).X pq) := + X.isZero_spectralSequence_page_X_of_isZero_H data r hr pq _ rfl _ _ rfl rfl h + +/-- The short complex of the `r`th page of the spectral sequence on position `pq'` +identifies to the short complex given by the differentials of the spectral object. +Then, the homology of this short complex can be computed using +`SpectralSequence.dHomologyIso`. +(This only applies in the favourable case when there are `pq` and `pq''` such +that `(c r).Rel pq pq'` and `(c r).Rel pq' pq''` hold.) -/ +noncomputable def spectralSequencePageSc'Iso (r : ℤ) (hr : r₀ ≤ r) (pq pq' pq'' : κ) + (hpq : (c r).Rel pq pq') (hpq' : (c r).Rel pq' pq'') + (n₀ n₁ n₂ n₃ n₄ : ℤ) + (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) (hn₃ : n₂ + 1 = n₃) (hn₄ : n₃ + 1 = n₄) + (hn₂' : n₂ = data.deg pq') : + ((X.spectralSequence data).page r).sc' pq pq' pq'' ≅ + X.dShortComplex n₀ n₁ n₂ n₃ n₄ hn₁ hn₂ hn₃ hn₄ (homOfLE (data.le₀₁ r pq'')) + (homOfLE (data.le₁₂ pq'')) (homOfLE (data.le₂₃ r pq'')) + (homOfLE (by simpa only [← data.hc₁₃ r pq' pq'' hpq', data.hc₀₂ r pq pq' hpq] + using data.le₁₂ pq')) (homOfLE (data.le₀₁ r pq)) + (homOfLE (data.le₁₂ pq)) (homOfLE (data.le₂₃ r pq)) := + SpectralSequence.shortComplexIso _ _ _ hr _ _ _ hpq hpq' _ _ _ _ _ _ _ _ _ hn₂' + +section + +variable (r r' : ℤ) (hrr' : r + 1 = r') (hr : r₀ ≤ r) + (pq pq' pq'' : κ) (hpq : (c r).prev pq' = pq) (hpq' : (c r).next pq' = pq'') + (n₀ n₁ n₂ : ℤ) (hn₁ : n₀ + 1 = n₁) (hn₂ : n₁ + 1 = n₂) + (hn₁' : n₁ = data.deg pq') + (i₀' i₀ i₁ i₂ i₃ i₃' : ι) + (hi₀' : i₀' = data.i₀ r' pq') + (hi₀ : i₀ = data.i₀ r pq') + (hi₁ : i₁ = data.i₁ pq') + (hi₂ : i₂ = data.i₂ pq') + (hi₃ : i₃ = data.i₃ r pq') + (hi₃' : i₃' = data.i₃ r' pq') + +/-- The homology data for the short complexes given by the differentials +of a spectral sequence attached to a spectral object in an abelian category. -/ +@[simps! left_K left_H left_π right_Q right_H right_ι iso_hom iso_inv] +noncomputable def spectralSequenceHomologyData : + (((X.spectralSequence data).page r hr).sc' pq pq' pq'').HomologyData := + SpectralSequence.homologyData X data r r' hrr' hr + pq pq' pq'' hpq hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃' + +@[simp] +lemma spectralSequenceHomologyData_left_i : + (X.spectralSequenceHomologyData data r r' hrr' hr pq pq' pq'' hpq hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃').left.i = + X.EMapFourδ₁Toδ₀' n₀ n₁ n₂ hn₁ hn₂ i₀' i₀ i₁ i₂ i₃ + (data.le₀'₀ hrr' hr pq' hi₀' hi₀) _ _ _ ≫ + (X.spectralSequencePageXIso data r hr pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ hi₀ hi₁ hi₂ hi₃).inv := rfl + +@[simp] +lemma spectralSequenceHomologyData_right_p : + (X.spectralSequenceHomologyData data r r' hrr' hr pq pq' pq'' hpq hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃').right.p = + (X.spectralSequencePageXIso data r hr pq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀ i₁ i₂ i₃ hi₀ hi₁ hi₂ hi₃).hom ≫ + X.EMapFourδ₄Toδ₃' n₀ n₁ n₂ hn₁ hn₂ i₀ i₁ i₂ i₃ i₃' _ _ _ + (data.le₃₃' hrr' hr pq' hi₃ hi₃') := rfl + +lemma spectralSequenceHomologyData_right_homologyIso_eq_left_homologyIso : + (X.spectralSequenceHomologyData data r r' hrr' hr pq pq' pq'' hpq hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃').right.homologyIso = + (X.spectralSequenceHomologyData data r r' hrr' hr pq pq' pq'' hpq hpq' n₀ n₁ n₂ hn₁ hn₂ hn₁' + i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃').left.homologyIso := by + ext1 + simp [ShortComplex.HomologyData.right_homologyIso_eq_left_homologyIso_trans_iso] + +lemma spectralSequence_iso : + (X.spectralSequence data).iso r r' pq' = + ((X.spectralSequence data).page r).homologyIsoSc' pq pq' pq'' hpq hpq' ≪≫ + (X.spectralSequenceHomologyData data r r' hrr' hr pq pq' pq'' hpq hpq' + n₀ n₁ n₂ hn₁ hn₂ hn₁' i₀' i₀ i₁ i₂ i₃ i₃' hi₀' hi₀ hi₁ hi₂ hi₃ hi₃').left.homologyIso ≪≫ + (X.spectralSequencePageXIso data r' (by lia) _ _ _ _ _ _ hn₁' _ _ _ _ + hi₀' hi₁ hi₂ hi₃').symm := by + obtain rfl : n₀ = n₁ - 1 := by lia + obtain rfl : n₂ = n₁ + 1 := by lia + subst hpq hpq' hn₁' hi₀ hi₁ hi₂ hi₃ hi₀' hi₃' + ext + dsimp [ + spectralSequencePageXIso, spectralSequence, + spectralSequenceHomologyData, + SpectralSequence.pageX, SpectralSequence.pageXIso, + SpectralSequence.homologyIso, SpectralSequence.homologyIso'] + rw [Category.comp_id] + convert (Category.id_comp _).symm + apply ShortComplex.homologyMap_id + +end + +end + +section + +variable (Y : SpectralObject C EInt) + +/-- The `E₂` cohomologial spectral sequence indexed by `ℤ × ℤ` attached to +a first quadrant spectral object indexed by `EInt`. -/ +noncomputable abbrev E₂SpectralSequence : E₂CohomologicalSpectralSequence C := + Y.spectralSequence mkDataE₂Cohomological + +section + +variable [Y.IsFirstQuadrant] + +example (r : ℤ) (hr : 2 ≤ r) (p q : ℤ) (hq : q < 0) : + IsZero ((Y.E₂SpectralSequence.page r).X ⟨p, q⟩) := by + apply isZero_spectralSequence_page_X_of_isZero_H' _ _ _ hr + apply Y.isZero₁_of_isFirstQuadrant + simp + lia + +example (r : ℤ) (hr : 2 ≤ r) (p q : ℤ) (hp : p < 0) : + IsZero ((Y.E₂SpectralSequence.page r).X ⟨p, q⟩) := by + apply isZero_spectralSequence_page_X_of_isZero_H' _ _ _ hr + apply Y.isZero₂_of_isFirstQuadrant + simp + lia + +/-- The `E₂` cohomologial spectral sequence indexed by `ℕ × ℕ` attached to +a first quadrant spectral object indexed by `EInt`. -/ +noncomputable abbrev E₂SpectralSequenceNat := Y.spectralSequence mkDataE₂CohomologicalNat + +end + +section + +variable [Y.IsThirdQuadrant] + +example (r : ℤ) (hr : 2 ≤ r) (p q : ℤ) (hq : 0 < q) : + IsZero ((Y.E₂SpectralSequence.page r).X ⟨p, q⟩) := by + apply isZero_spectralSequence_page_X_of_isZero_H' _ _ _ hr + apply Y.isZero₁_of_isThirdQuadrant + simp + lia + +example (r : ℤ) (hr : 2 ≤ r) (p q : ℤ) (hp : 0 < p) : + IsZero ((Y.E₂SpectralSequence.page r).X ⟨p, q⟩) := by + apply isZero_spectralSequence_page_X_of_isZero_H' _ _ _ hr + apply Y.isZero₂_of_isThirdQuadrant + simp + lia + +/-- The `E₂` homologial spectral sequence indexed by `ℕ × ℕ` attached to +a third quadrant spectral object indexed by `EInt`. -/ +noncomputable abbrev E₂HomologicalSpectralSequenceNat := Y.spectralSequence mkDataE₂HomologicalNat + +end + +end + +end SpectralObject + +end Abelian + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralSequence/Basic.lean b/Mathlib/Algebra/Homology/SpectralSequence/Basic.lean new file mode 100644 index 00000000000000..39fd06b2d1e620 --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralSequence/Basic.lean @@ -0,0 +1,137 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex +public import Mathlib.Algebra.Homology.ShortComplex.Abelian +public import Mathlib.Algebra.Homology.SpectralSequence.ComplexShape + +/-! +# Spectral sequences + +In this file, we define the category `SpectralSequence C c r₀` of spectral sequences +in an abelian category `C` with `Eᵣ`-pages defined from `r₀ : ℤ` having differentials +given by complex shapes `c : ℤ → ComplexShape ι`, where `ι` is the index type +for the objects on each page (e.g. `ι := ℤ × ℤ` or `ι := ℕ × ℕ`). +A spectral sequence is defined as the data of a sequence of homological complexes +(the pages) and a sequence of isomorphism between the homology of a page and the +next page. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category Limits + +variable (C : Type*) [Category C] [Abelian C] + {κ : Type*} (c : ℤ → ComplexShape κ) (r₀ : ℤ) + +/-- Given an abelian category `C`, a sequence of complex shapes `c : ℤ → ComplexShape ι` +and a starting page `r₀ : ℤ`, a spectral sequence involves pages which are homological +complexes and isomorphisms saying that the homology of a page identifies to the next page. -/ +structure SpectralSequence where + /-- the `r`th page of a spectral sequence is an homological complex -/ + page (r : ℤ) (hr : r₀ ≤ r := by lia) : HomologicalComplex C (c r) + /-- the isomorphism between the homology of the `r`-th page at an object `pq : ι` + and the corresponding object on the next page -/ + iso (r r' : ℤ) (pq : κ) (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + (page r).homology pq ≅ (page r').X pq + +namespace SpectralSequence + +variable {C c r₀} + +/-- A morphism of spectral sequence is a sequence of morphisms between the +pages which commutes with the isomorphisms in homology. -/ +@[ext] +structure Hom (E E' : SpectralSequence C c r₀) where + /-- the morphism of homological complexes between the `r`th pages -/ + hom (r : ℤ) (hr : r₀ ≤ r := by lia) : E.page r ⟶ E'.page r + comm (r r' : ℤ) (pq : κ) (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + HomologicalComplex.homologyMap (hom r) pq ≫ (E'.iso r r' pq).hom = + (E.iso r r' pq).hom ≫ (hom r').f pq := by cat_disch + +/-- If `E` is a spectral sequence, and `r = r'`, this is the +isomorphism `(E.page r).X pq ≅ (E.page r').X pq`. -/ +def pageXIsoOfEq (E : SpectralSequence C c r₀) (pq : κ) (r r' : ℤ) (h : r = r' := by lia) + (hr : r₀ ≤ r := by lia) : + (E.page r).X pq ≅ (E.page r').X pq := + eqToIso (by subst h; rfl) + +attribute [reassoc (attr := simp)] Hom.comm + +@[simps! id_hom comp_hom] +instance : Category (SpectralSequence C c r₀) where + Hom := Hom + id _ := { hom _ _ := 𝟙 _} + comp f g := + { hom r hr := f.hom r ≫ g.hom r + comm r r' hrr' pq hr := by + dsimp + simp [HomologicalComplex.homologyMap_comp, assoc, g.comm r r', f.comm_assoc r r'] } + +@[ext] +lemma hom_ext {E E' : SpectralSequence C c r₀} {f f' : E ⟶ E'} + (h : ∀ (r : ℤ) (hr : r₀ ≤ r), f.hom r = f'.hom r) : + f = f' := + Hom.ext (by grind) + +attribute [simp] id_hom +attribute [reassoc, simp] comp_hom + +variable (C c r₀) + +/-- The functor `SpectralSequence C c r₀ ⥤ HomologicalComplex C (c r)` which +sends a spectral sequence to its `r`th page. -/ +@[simps] +def pageFunctor (r : ℤ) (hr : r₀ ≤ r := by lia) : + SpectralSequence C c r₀ ⥤ HomologicalComplex C (c r) where + obj E := E.page r + map f := f.hom r + +/-- The natural isomorphism between the homology of a spectral sequence on the +object `pq : ι` of the `r`th page and the corresponding object on the next page. -/ +@[simps!] +noncomputable def pageHomologyNatIso + (r r' : ℤ) (pq : κ) (hrr' : r + 1 = r' := by lia) (hr : r₀ ≤ r := by lia) : + pageFunctor C c r₀ r ⋙ HomologicalComplex.homologyFunctor _ _ pq ≅ + pageFunctor C c r₀ r' ⋙ HomologicalComplex.eval _ _ pq := + NatIso.ofComponents (fun E ↦ E.iso r r' pq) + +end SpectralSequence + +/-- A cohomological spectral sequence has differentials given by the +vector `(r, 1 - r)` on the `r`th page. -/ +abbrev CohomologicalSpectralSequence := + SpectralSequence C (fun r ↦ ComplexShape.up' (⟨r, 1 - r⟩ : ℤ × ℤ)) + +/-- A `E₂`-cohomological spectral sequence has differentials given by the +vector `(r, 1 - r)` on the `r`th page for `2 ≤ r`. -/ +abbrev E₂CohomologicalSpectralSequence := CohomologicalSpectralSequence C 2 + +/-- A first quadrant cohomological spectral sequence has differentials +given by the vector `(r, 1 - r)` on the `r`th page. -/ +abbrev CohomologicalSpectralSequenceNat := + SpectralSequence C (fun r ↦ ComplexShape.spectralSequenceNat ⟨r, 1 - r⟩) + +/-- A first quadrant `E₂`-cohomological spectral sequence has differentials +given by the vector `(r, 1 - r)` on the `r`th page for `2 ≤ r`. -/ +abbrev E₂CohomologicalSpectralSequenceNat := + CohomologicalSpectralSequenceNat C 2 + +/-- A cohomological spectral sequence lying on finitely many rows +has differentials given by the vector `(r, 1 - r)` on the `r`th page. -/ +abbrev CohomologicalSpectralSequenceFin (l : ℕ) := + SpectralSequence C (fun r ↦ ComplexShape.spectralSequenceFin l ⟨r, 1 - r⟩) + +/-- A `E₂`-cohomological spectral sequence lying on finitely many rows +has differentials given by the vector `(r, 1 - r)` on the `r`th page for `2 ≤ r`. -/ +abbrev E₂CohomologicalSpectralSequenceFin (l : ℕ) := + CohomologicalSpectralSequenceFin C 2 l + +end CategoryTheory diff --git a/Mathlib/Algebra/Homology/SpectralSequence/ComplexShape.lean b/Mathlib/Algebra/Homology/SpectralSequence/ComplexShape.lean new file mode 100644 index 00000000000000..aeb6a6dba6b71e --- /dev/null +++ b/Mathlib/Algebra/Homology/SpectralSequence/ComplexShape.lean @@ -0,0 +1,54 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.Algebra.Homology.ComplexShape + +/-! +# Complex shapes for pages of spectral sequences + +In this file, we define complex shapes which correspond +to pages of spectral sequences: +* `ComplexShape.spectralSequenceNat`: for any `u : ℤ × ℤ`, this +is the complex shape on `ℕ × ℕ` corresponding to differentials +of `ComplexShape.up' u : ComplexShape (ℤ × ℤ)` with source +and target in `ℕ × ℕ`. (With `u := (r, 1 - r)`, this will +apply to the `r`th-page of first quadrant `E₂` cohomological +spectral sequence). +* `ComplexShape.spectralSequenceFin`: for any `u : ℤ × ℤ` and `l : ℕ`, +this is a similar definition as `ComplexShape.spectralSequenceNat` +but for `ℤ × Fin l` (identified as a subset of `ℤ × ℤ`). (This could +be used for spectral sequences associated to a *finite* filtration.) + +-/ + +@[expose] public section + +namespace ComplexShape + +/-- For `u : ℤ × ℤ`, this is the complex shape on `ℕ × ℕ`, which +connects `a` to `b` when the equality `a + u = b` holds in `ℤ × ℤ`. -/ +def spectralSequenceNat (u : ℤ × ℤ) : ComplexShape (ℕ × ℕ) where + Rel a b := a.1 + u.1 = b.1 ∧ a.2 + u.2 = b.2 + next_eq _ _ := by ext <;> lia + prev_eq _ _ := by ext <;> lia + +@[simp] +lemma spectralSequenceNat_rel_iff (u : ℤ × ℤ) (a b : ℕ × ℕ) : + (spectralSequenceNat u).Rel a b ↔ a.1 + u.1 = b.1 ∧ a.2 + u.2 = b.2 := Iff.rfl + +/-- For `l : ℕ` and `u : ℤ × ℤ`, this is the complex shape on `ℤ × Fin l`, which +connects `a` to `b` when the equality `a + u = b` holds in `ℤ × Fin l`. -/ +def spectralSequenceFin (l : ℕ) (u : ℤ × ℤ) : ComplexShape (ℤ × Fin l) where + Rel a b := a.1 + u.1 = b.1 ∧ a.2.1 + u.2 = b.2.1 + next_eq _ _ := by ext <;> lia + prev_eq _ _ := by ext <;> lia + +@[simp] +lemma spectralSequenceFin_rel_iff {l : ℕ} (u : ℤ × ℤ) (a b : ℤ × Fin l) : + (spectralSequenceFin l u).Rel a b ↔ a.1 + u.1 = b.1 ∧ a.2 + u.2 = b.2 := Iff.rfl + +end ComplexShape diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean index 052b91c067e9ee..f68f0ed4ec437c 100644 --- a/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean @@ -29,13 +29,7 @@ use depending on the context. ## TODO - -* define functors `t.truncLE n : C ⥤ C`, `t.truncGE n : C ⥤ C` and the - associated distinguished triangles -* promote these truncations to a (functorial) spectral object * define the heart of `t` and show it is an abelian category -* define triangulated subcategories `t.plus`, `t.minus`, `t.bounded` and show - that there are induced t-structures on these full subcategories ## References * [Beilinson, Bernstein, Deligne, Gabber, *Faisceaux pervers*][bbd-1982] diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/ETrunc.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/ETrunc.lean new file mode 100644 index 00000000000000..b34c95662a8b64 --- /dev/null +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/ETrunc.lean @@ -0,0 +1,541 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.CategoryTheory.Triangulated.TStructure.TruncLEGT +public import Mathlib.Order.WithBotTop + +/-! +# Truncations for a t-structure + +Let `t` be a t-structure on a triangulated category `C`. +In this file, we extend the definition of the truncation functors +`truncLT` and `truncGE` for indices in `ℤ` to `EInt`, +as `t.eTruncLT : EInt ⥤ C ⥤ C` and `t.eTruncGE : EInt ⥤ C ⥤ C`. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Category Limits Pretriangulated ZeroObject Preadditive + +variable {C : Type*} [Category* C] [Preadditive C] [HasZeroObject C] [HasShift C ℤ] + [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] + +namespace Triangulated + +namespace TStructure + +variable (t : TStructure C) + +/-- The functor `EInt ⥤ C ⥤ C` which sends `⊥` to the zero functor, +`n : ℤ` to `t.truncLT n` and `⊤` to `𝟭 C`. -/ +noncomputable def eTruncLT : EInt ⥤ C ⥤ C where + obj n := by + induction n using WithBotTop.rec with + | bot => exact 0 + | coe a => exact t.truncLT a + | top => exact 𝟭 C + map {x y} f := by + induction x using WithBotTop.rec with + | bot => + induction y using WithBotTop.rec with + | bot => exact 𝟙 _ + | coe b => exact 0 + | top => exact 0 + | coe a => + induction y using WithBotTop.rec with + | bot => exact 0 + | coe b => exact t.natTransTruncLTOfLE a b (by simpa using leOfHom f) + | top => exact t.truncLTι a + | top => + induction y using WithBotTop.rec with + | bot => exact 0 + | coe b => exact 0 + | top => exact 𝟙 _ + map_id n := by induction n using WithBotTop.rec <;> simp + map_comp {x y z} f g := by + have f' := leOfHom f + have g' := leOfHom g + induction x using WithBotTop.rec <;> induction y using WithBotTop.rec <;> + induction z using WithBotTop.rec <;> cat_disch + +@[simp] +lemma eTruncLT_obj_top : t.eTruncLT.obj ⊤ = 𝟭 _ := rfl + +@[simp] +lemma eTruncLT_obj_bot : t.eTruncLT.obj ⊥ = 0 := rfl + +@[simp] +lemma eTruncLT_obj_coe (n : ℤ) : t.eTruncLT.obj n = t.truncLT n := rfl + +@[simp] +lemma eTruncLT_map_eq_truncLTι (n : ℤ) : + t.eTruncLT.map (homOfLE (show (n : EInt) ≤ ⊤ by simp)) = t.truncLTι n := rfl + +instance (i : EInt) : (t.eTruncLT.obj i).Additive := by + induction i using WithBotTop.rec <;> constructor <;> cat_disch + +/-- The functor `EInt ⥤ C ⥤ C` which sends `⊥` to `𝟭 C`, +`n : ℤ` to `t.truncGE n` and `⊤` to the zero functor. -/ +noncomputable def eTruncGE : EInt ⥤ C ⥤ C where + obj n := by + induction n using WithBotTop.rec with + | bot => exact 𝟭 C + | coe a => exact t.truncGE a + | top => exact 0 + map {x y} f := by + induction x using WithBotTop.rec with + | bot => + induction y using WithBotTop.rec with + | bot => exact 𝟙 _ + | coe b => exact t.truncGEπ b + | top => exact 0 + | coe a => + induction y using WithBotTop.rec with + | bot => exact 0 + | coe b => exact t.natTransTruncGEOfLE a b (by simpa using leOfHom f) + | top => exact 0 + | top => + induction y using WithBotTop.rec with + | bot => exact 0 + | coe b => exact 0 + | top => exact 𝟙 _ + map_id n := by induction n using WithBotTop.rec <;> simp + map_comp {x y z} f g := by + have f' := leOfHom f + have g' := leOfHom g + induction x using WithBotTop.rec <;> induction y using WithBotTop.rec <;> + induction z using WithBotTop.rec <;> cat_disch + +@[simp] +lemma eTruncGE_obj_bot : + t.eTruncGE.obj ⊥ = 𝟭 _ := rfl + +@[simp] +lemma eTruncGE_obj_top : + t.eTruncGE.obj ⊤ = 0 := rfl + +@[simp] +lemma eTruncGE_obj_coe (n : ℤ) : t.eTruncGE.obj n = t.truncGE n := rfl + +instance (i : EInt) : (t.eTruncGE.obj i).Additive := by + induction i using WithBotTop.rec <;> constructor <;> cat_disch + +/-- The connecting homomorphism from `t.eTruncGE` to the +shift by `1` of `t.eTruncLT`. -/ +noncomputable def eTruncGEδLT : + t.eTruncGE ⟶ t.eTruncLT ⋙ ((Functor.whiskeringRight C C C).obj (shiftFunctor C (1 : ℤ))) where + app a := by + induction a using WithBotTop.rec with + | bot => exact 0 + | coe a => exact t.truncGEδLT a + | top => exact 0 + naturality {a b} hab := by + replace hab := leOfHom hab + induction a using WithBotTop.rec; rotate_right + · apply (isZero_zero _).eq_of_src + all_goals + induction b using WithBotTop.rec <;> simp at hab <;> + dsimp [eTruncGE, eTruncLT] <;> + simp [t.truncGEδLT_comp_whiskerRight_natTransTruncLTOfLE] + +@[simp] +lemma eTruncGEδLT_coe (n : ℤ) : + t.eTruncGEδLT.app n = t.truncGEδLT n := rfl + +/-- The natural transformation `t.eTruncLT.obj i ⟶ 𝟭 C` for all `i : EInt`. -/ +noncomputable abbrev eTruncLTι (i : EInt) : t.eTruncLT.obj i ⟶ 𝟭 _ := + t.eTruncLT.map (homOfLE (le_top)) + +@[simp] lemma eTruncLT_ι_bot : t.eTruncLTι ⊥ = 0 := rfl +@[simp] lemma eTruncLT_ι_coe (n : ℤ) : t.eTruncLTι n = t.truncLTι n := rfl +@[simp] lemma eTruncLT_ι_top : t.eTruncLTι ⊤ = 𝟙 _ := rfl + +@[reassoc] +lemma eTruncLTι_naturality (i : EInt) {X Y : C} (f : X ⟶ Y) : + (t.eTruncLT.obj i).map f ≫ (t.eTruncLTι i).app Y = (t.eTruncLTι i).app X ≫ f := + (t.eTruncLTι i).naturality f + +instance : IsIso (t.eTruncLTι ⊤) := by + dsimp [eTruncLTι] + infer_instance + +@[reassoc (attr := simp)] +lemma eTruncLT_map_app_eTruncLTι_app {i j : EInt} (f : i ⟶ j) (X : C) : + (t.eTruncLT.map f).app X ≫ (t.eTruncLTι j).app X = (t.eTruncLTι i).app X := by + simp only [← NatTrans.comp_app, ← Functor.map_comp] + rfl + +@[reassoc] +lemma eTruncLT_obj_map_eTruncLTι_app (i : EInt) (X : C) : + (t.eTruncLT.obj i).map ((t.eTruncLTι i).app X) = + (t.eTruncLTι i).app ((t.eTruncLT.obj i).obj X) := by + induction i using WithBotTop.rec with + | bot => simp + | coe n => simp [truncLT_map_truncLTι_app] + | top => simp + +/-- The natural transformation `𝟭 C ⟶ t.eTruncGE.obj i` for all `i : EInt`. -/ +noncomputable abbrev eTruncGEπ (i : EInt) : 𝟭 C ⟶ t.eTruncGE.obj i := + t.eTruncGE.map (homOfLE (bot_le)) + +@[simp] lemma eTruncGEπ_bot : t.eTruncGEπ ⊥ = 𝟙 _ := rfl +@[simp] lemma eTruncGEπ_coe (n : ℤ) : t.eTruncGEπ n = t.truncGEπ n := rfl +@[simp] lemma eTruncGEπ_top : t.eTruncGEπ ⊤ = 0 := rfl + +@[reassoc (attr := simp)] +lemma eTruncGEπ_naturality (i : EInt) {X Y : C} (f : X ⟶ Y) : + (t.eTruncGEπ i).app X ≫ (t.eTruncGE.obj i).map f = f ≫ (t.eTruncGEπ i).app Y := + ((t.eTruncGEπ i).naturality f).symm + +instance : IsIso (t.eTruncGEπ ⊥) := by + dsimp [eTruncGEπ] + infer_instance + +@[reassoc (attr := simp)] +lemma eTruncGEπ_app_eTruncGE_map_app {i j : EInt} (f : i ⟶ j) (X : C) : + (t.eTruncGEπ i).app X ≫ (t.eTruncGE.map f).app X = (t.eTruncGEπ j).app X := by + simp only [← NatTrans.comp_app, ← Functor.map_comp] + rfl + +@[reassoc] +lemma eTruncGE_obj_map_eTruncGEπ_app (i : EInt) (X : C) : + (t.eTruncGE.obj i).map ((t.eTruncGEπ i).app X) = + (t.eTruncGEπ i).app ((t.eTruncGE.obj i).obj X) := by + induction i using WithBotTop.rec with + | bot => simp + | coe n => simp [truncGE_map_truncGEπ_app] + | top => simp + +/-- The (distinguished) triangles given by the natural transformations +`t.eTruncLT.obj i ⟶ 𝟭 C ⟶ t.eTruncGE.obj i ⟶ ...` for all `i : EInt`. -/ +@[simps!] +noncomputable def eTriangleLTGE : EInt ⥤ C ⥤ Triangle C where + obj i := Triangle.functorMk (t.eTruncLTι i) (t.eTruncGEπ i) (t.eTruncGEδLT.app i) + map f := Triangle.functorHomMk _ _ (t.eTruncLT.map f) (𝟙 _) (t.eTruncGE.map f) + +lemma eTriangleLTGE_distinguished (i : EInt) (X : C) : + (t.eTriangleLTGE.obj i).obj X ∈ distTriang _ := by + induction i using WithBotTop.rec with + | bot => + rw [Triangle.distinguished_iff_of_isZero₁ _ (Functor.zero_obj X)] + dsimp + infer_instance + | coe n => exact t.triangleLTGE_distinguished n X + | top => + rw [Triangle.distinguished_iff_of_isZero₃ _ (Functor.zero_obj X)] + dsimp + infer_instance + +instance (X : C) (n : ℤ) [t.IsLE X n] (i : EInt) : + t.IsLE ((t.eTruncLT.obj i).obj X) n := by + induction i using WithBotTop.rec with + | bot => exact isLE_of_isZero _ (by simp) _ + | coe _ => dsimp; infer_instance + | top => dsimp; infer_instance + +instance (X : C) (n : ℤ) [t.IsGE X n] (i : EInt) : + t.IsGE ((t.eTruncGE.obj i).obj X) n := by + induction i using WithBotTop.rec with + | bot => dsimp; infer_instance + | coe _ => dsimp; infer_instance + | top => exact isGE_of_isZero _ (by simp) _ + +lemma isGE_eTruncGE_obj_obj (n : ℤ) (i : EInt) (h : n ≤ i) (X : C) : + t.IsGE ((t.eTruncGE.obj i).obj X) n := by + induction i using WithBotTop.rec with + | bot => simp at h + | coe i => + dsimp + exact t.isGE_of_ge _ _ _ (by simpa using h) + | top => exact t.isGE_of_isZero (Functor.zero_obj _) _ + +lemma isLE_eTruncLT_obj_obj (n : ℤ) (i : EInt) (h : i ≤ (n + 1 :)) (X : C) : + t.IsLE (((t.eTruncLT.obj i)).obj X) n := by + induction i using WithBotTop.rec with + | bot => exact t.isLE_of_isZero (by simp) _ + | coe i => + simp only [WithBotTop.coe_le_coe] at h + dsimp + exact t.isLE_of_le _ (i - 1) n (by lia) + | top => simp at h + +lemma isZero_eTruncLT_obj_obj (X : C) (n : ℤ) [t.IsGE X n] (j : EInt) (hj : j ≤ n) : + IsZero ((t.eTruncLT.obj j).obj X) := by + induction j using WithBotTop.rec with + | bot => simp + | coe j => + have := t.isGE_of_ge X j n (by simpa using hj) + exact t.isZero_truncLT_obj_of_isGE _ _ + | top => simp at hj + +lemma isZero_eTruncGE_obj_obj (X : C) (n : ℤ) [t.IsLE X n] (j : EInt) (hj : n < j) : + IsZero ((t.eTruncGE.obj j).obj X) := by + induction j using WithBotTop.rec with + | bot => simp at hj + | coe j => + simp only [WithBotTop.coe_lt_coe] at hj + have := t.isLE_of_le X n (j - 1) (by lia) + exact t.isZero_truncGE_obj_of_isLE (j - 1) j (by lia) _ + | top => simp + +section + +variable [IsTriangulated C] + +lemma isIso_eTruncGE_obj_map_truncGEπ_app (a b : EInt) (h : a ≤ b) (X : C) : + IsIso ((t.eTruncGE.obj b).map ((t.eTruncGEπ a).app X)) := by + induction b using WithBotTop.rec with + | bot => + obtain rfl : a = ⊥ := by simpa using h + infer_instance + | coe b => + induction a using WithBotTop.rec with + | bot => dsimp; infer_instance + | coe a => exact t.isIso_truncGE_map_truncGEπ_app b a (by simpa using h) X + | top => simp at h + | top => exact ⟨0, IsZero.eq_of_src (by simp) _ _, IsZero.eq_of_src (by simp) _ _⟩ + +lemma isIso_eTruncLT_obj_map_truncLTπ_app (a b : EInt) (h : a ≤ b) (X : C) : + IsIso ((t.eTruncLT.obj a).map ((t.eTruncLTι b).app X)) := by + induction a using WithBotTop.rec with + | bot => exact ⟨0, IsZero.eq_of_src (by simp) _ _, IsZero.eq_of_src (by simp) _ _⟩ + | coe a => + induction b using WithBotTop.rec with + | bot => simp at h + | coe b => + exact t.isIso_truncLT_map_truncLTι_app a b (by simpa using h) X + | top => dsimp; infer_instance + | top => + obtain rfl : b = ⊤ := by simpa using h + infer_instance + +instance (a : EInt) (X : C) : IsIso ((t.eTruncLT.obj a).map ((t.eTruncLTι a).app X)) := + isIso_eTruncLT_obj_map_truncLTπ_app t a a (by rfl) X + +instance (a : EInt) (X : C) : IsIso ((t.eTruncLTι a).app ((t.eTruncLT.obj a).obj X)) := by + rw [← eTruncLT_obj_map_eTruncLTι_app] + infer_instance + +instance (X : C) (n : ℤ) [t.IsGE X n] (i : EInt) : + t.IsGE ((t.eTruncLT.obj i).obj X) n := by + induction i using WithBotTop.rec with + | bot => exact isGE_of_isZero _ (by simp) _ + | coe _ => dsimp; infer_instance + | top => dsimp; infer_instance + +instance (X : C) (n : ℤ) [t.IsLE X n] (i : EInt) : + t.IsLE ((t.eTruncGE.obj i).obj X) n := by + induction i using WithBotTop.rec with + | bot => dsimp; infer_instance + | coe _ => dsimp; infer_instance + | top => exact isLE_of_isZero _ (by simp) _ + +/-- The natural transformation `t.eTruncGE.obj b ⟶ t.eTruncGE.obj a ⋙ t.eTruncGE.obj b` +for all `a` and `b` in `EInt`. -/ +@[simps!] +noncomputable def eTruncGEToGEGE (a b : EInt) : + t.eTruncGE.obj b ⟶ t.eTruncGE.obj a ⋙ t.eTruncGE.obj b := + (Functor.leftUnitor _).inv ≫ Functor.whiskerRight (t.eTruncGEπ a) _ + +lemma isIso_eTruncGEIsoGEGE (a b : EInt) (hab : a ≤ b) : + IsIso (t.eTruncGEToGEGE a b) := by + rw [NatTrans.isIso_iff_isIso_app] + intro X + simp only [Functor.comp_obj, eTruncGEToGEGE_app] + exact t.isIso_eTruncGE_obj_map_truncGEπ_app _ _ hab _ + +section + +variable (a b : EInt) (hab : a ≤ b) + +/-- The natural isomorphism `t.eTruncGE.obj b ≅ t.eTruncGE.obj a ⋙ t.eTruncGE.obj b` +when `a` and `b` in `EInt` satisfy `a ≤ b`. -/ +@[simps! hom] +noncomputable def eTruncGEIsoGEGE : + t.eTruncGE.obj b ≅ t.eTruncGE.obj a ⋙ t.eTruncGE.obj b := + haveI := t.isIso_eTruncGEIsoGEGE a b hab + asIso (t.eTruncGEToGEGE a b) + +@[reassoc (attr := simp)] +lemma eTruncGEIsoGEGE_hom_inv_id_app (X : C) : + (t.eTruncGE.obj b).map ((t.eTruncGEπ a).app X) ≫ (t.eTruncGEIsoGEGE a b hab).inv.app X = + 𝟙 _ := by + simpa using (t.eTruncGEIsoGEGE a b hab).hom_inv_id_app X + +@[reassoc (attr := simp)] +lemma eTruncGEIsoGEGE_inv_hom_id_app (X : C) : + (t.eTruncGEIsoGEGE a b hab).inv.app X ≫ (t.eTruncGE.obj b).map ((t.eTruncGEπ a).app X) = + 𝟙 _ := by + simpa using (t.eTruncGEIsoGEGE a b hab).inv_hom_id_app X + +end + +/-- The natural transformation `t.eTruncLT.obj a ⋙ t.eTruncLT.obj b ⟶ t.eTruncLT.obj b` +for all `a` and `b` in `EInt`. -/ +@[simps!] +noncomputable def eTruncLTLTToLT (a b : EInt) : + t.eTruncLT.obj a ⋙ t.eTruncLT.obj b ⟶ t.eTruncLT.obj b := + Functor.whiskerRight (t.eTruncLTι a) _ ≫ (Functor.leftUnitor _).hom + +lemma isIso_eTruncLTLTIsoLT (a b : EInt) (hab : b ≤ a) : + IsIso (t.eTruncLTLTToLT a b) := by + rw [NatTrans.isIso_iff_isIso_app] + intro X + simp only [Functor.comp_obj, eTruncLTLTToLT_app] + exact t.isIso_eTruncLT_obj_map_truncLTπ_app _ _ hab _ + +section + +variable (a b : EInt) (hab : b ≤ a) + +/-- The natural isomorphism `t.eTruncLT.obj a ⋙ t.eTruncLT.obj b ⟶ t.eTruncLT.obj b` +when `a` and `b` in `EInt` satisfy `b ≤ a`. -/ +@[simps! hom] +noncomputable def eTruncLTLTIsoLT : + t.eTruncLT.obj a ⋙ t.eTruncLT.obj b ≅ t.eTruncLT.obj b := + haveI := t.isIso_eTruncLTLTIsoLT a b hab + asIso (t.eTruncLTLTToLT a b) + +@[reassoc] +lemma eTruncLTLTIsoLT_hom_inv_id_app (X : C) : + (t.eTruncLT.obj b).map ((t.eTruncLTι a).app X) ≫ + (t.eTruncLTLTIsoLT a b hab).inv.app X = 𝟙 _ := by + simpa using (t.eTruncLTLTIsoLT a b hab).hom_inv_id_app X + +@[reassoc (attr := simp)] +lemma eTruncLTLTIsoLT_inv_hom_id_app (X : C) : + (t.eTruncLTLTIsoLT a b hab).inv.app X ≫ + (t.eTruncLT.obj b).map ((t.eTruncLTι a).app X) = 𝟙 _ := by + simpa using (t.eTruncLTLTIsoLT a b hab).inv_hom_id_app X + +@[reassoc (attr := simp)] +lemma eTruncLTLTIsoLT_inv_hom_id_app_eTruncLT_obj (X : C) : + (t.eTruncLTLTIsoLT a b hab).inv.app ((t.eTruncLT.obj a).obj X) ≫ + (t.eTruncLT.obj b).map ((t.eTruncLT.obj a).map ((t.eTruncLTι a).app X)) = 𝟙 _ := by + simp [eTruncLT_obj_map_eTruncLTι_app] + +end + + +section + +variable (a b : EInt) + +/-- The natural transformation from +`t.eTruncLT.obj b ⋙ t.eTruncGE.obj a ⋙ t.eTruncLT.obj b` to +`t.eTruncGE.obj a ⋙ t.eTruncLT.obj b`. (This is an isomorphism.) -/ +@[simps!] +noncomputable def eTruncLTGELTSelfToLTGE : + t.eTruncLT.obj b ⋙ t.eTruncGE.obj a ⋙ t.eTruncLT.obj b ⟶ + t.eTruncGE.obj a ⋙ t.eTruncLT.obj b := + Functor.whiskerRight (t.eTruncLTι b) _ ≫ (Functor.leftUnitor _).hom + +/-- The natural transformation from +`t.eTruncLT.obj b ⋙ t.eTruncGE.obj a ⋙ t.eTruncLT.obj b` to +`t.eTruncLT.obj b ⋙ t.eTruncGE.obj a`. (This is an isomorphism.) -/ +@[simps!] +noncomputable def eTruncLTGELTSelfToGELT : + t.eTruncLT.obj b ⋙ t.eTruncGE.obj a ⋙ t.eTruncLT.obj b ⟶ + t.eTruncLT.obj b ⋙ t.eTruncGE.obj a := + (Functor.associator _ _ _).inv ≫ Functor.whiskerLeft _ (t.eTruncLTι b) ≫ + (Functor.rightUnitor _).hom + +instance : IsIso (t.eTruncLTGELTSelfToLTGE a b) := by + rw [NatTrans.isIso_iff_isIso_app] + intro X + induction b using WithBotTop.rec with + | bot => simp [isIsoZero_iff_source_target_isZero] + | coe b => + induction a using WithBotTop.rec with + | bot => simpa using inferInstanceAs (IsIso ((t.truncLT b).map ((t.truncLTι b).app X))) + | coe a => + simp only [eTruncLT_obj_coe, eTruncGE_obj_coe, Functor.comp_obj, eTruncLTGELTSelfToLTGE_app, + eTruncLT_map_eq_truncLTι] + infer_instance + | top => + simp only [eTruncLT_obj_coe, eTruncGE_obj_top, Functor.comp_obj, eTruncLTGELTSelfToLTGE_app, + eTruncLT_map_eq_truncLTι, zero_map, Functor.map_zero, isIsoZero_iff_source_target_isZero] + constructor + all_goals exact Functor.map_isZero _ (Functor.zero_obj _) + | top => simpa using inferInstanceAs (IsIso (𝟙 _)) + +variable (b : EInt) (X : C) + +instance : IsIso (t.eTruncLTGELTSelfToGELT a b) := by + rw [NatTrans.isIso_iff_isIso_app] + intro X + induction a using WithBotTop.rec with + | bot => simpa using inferInstanceAs (IsIso ((t.eTruncLTι b).app ((t.eTruncLT.obj b).obj X))) + | coe a => + induction b using WithBotTop.rec with + | bot => simpa [isIsoZero_iff_source_target_isZero] using + (t.eTruncGE.obj a).map_isZero (Functor.zero_obj _) + | coe b => + simp only [eTruncLT_obj_coe, eTruncGE_obj_coe, Functor.comp_obj, eTruncLTGELTSelfToGELT_app, + eTruncLT_map_eq_truncLTι] + infer_instance + | top => simpa using inferInstanceAs (IsIso (𝟙 _)) + | top => + exact ⟨0, ((t.eTruncLT.obj b).map_isZero (by simp)).eq_of_src _ _, + IsZero.eq_of_src (by simp) _ _⟩ + +end + +/-- The commutation natural isomorphism +`t.eTruncGE.obj a ⋙ t.eTruncLT.obj b ≅ t.eTruncLT.obj b ⋙ t.eTruncGE.obj a` +for all `a` and `b` in `EInt`. -/ +noncomputable def eTruncLTGEIsoLEGT (a b : EInt) : + t.eTruncGE.obj a ⋙ t.eTruncLT.obj b ≅ t.eTruncLT.obj b ⋙ t.eTruncGE.obj a := + (asIso (t.eTruncLTGELTSelfToLTGE a b)).symm ≪≫ asIso (t.eTruncLTGELTSelfToGELT a b) + +@[reassoc (attr := simp)] +lemma eTruncLTGEIsoLEGT_hom_naturality (a b : EInt) {X Y : C} (f : X ⟶ Y) : + (t.eTruncLT.obj b).map ((t.eTruncGE.obj a).map f) ≫ (t.eTruncLTGEIsoLEGT a b).hom.app Y = + (t.eTruncLTGEIsoLEGT a b).hom.app X ≫ (t.eTruncGE.obj a).map ((t.eTruncLT.obj b).map f) := + (t.eTruncLTGEIsoLEGT a b).hom.naturality f + +@[reassoc] +lemma eTruncLTGEIsoLEGT_hom_app_fac (a b : EInt) (X : C) : + (t.eTruncLT.obj b).map ((t.eTruncGE.obj a).map ((t.eTruncLTι b).app X)) ≫ + (t.eTruncLTGEIsoLEGT a b).hom.app X = + (t.eTruncLTι b).app ((t.eTruncGE.obj a).obj ((t.eTruncLT.obj b).obj X)):= by + simp [eTruncLTGEIsoLEGT] + +@[reassoc (attr := simp)] +lemma eTruncLTGEIsoLEGT_hom_app_fac' (a b : EInt) (X : C) : + (t.eTruncLTGEIsoLEGT a b).hom.app X ≫ (t.eTruncGE.obj a).map ((t.eTruncLTι b).app X) = + (t.eTruncLTι b).app ((t.eTruncGE.obj a).obj X) := by + simp [eTruncLTGEIsoLEGT] + +open ComposableArrows in +@[reassoc] +lemma eTruncLTGEIsoLEGT_naturality_app (a b : EInt) (hab : a ≤ b) + (a' b' : EInt) (hab' : a' ≤ b') (φ : mk₁ (homOfLE hab) ⟶ mk₁ (homOfLE hab')) (X : C) : + (t.eTruncLT.map (φ.app 1)).app ((t.eTruncGE.obj a).obj X) ≫ + (t.eTruncLT.obj b').map ((t.eTruncGE.map (φ.app 0)).app X) ≫ + (t.eTruncLTGEIsoLEGT a' b').hom.app X = + (t.eTruncLTGEIsoLEGT a b).hom.app X ≫ (t.eTruncGE.map (φ.app 0)).app _ ≫ + (t.eTruncGE.obj a').map ((t.eTruncLT.map (φ.app 1)).app X) := by + rw [← cancel_epi ((t.eTruncLTGELTSelfToLTGE a b).app X)] + dsimp + rw [eTruncLTGELTSelfToLTGE_app, eTruncLTGEIsoLEGT_hom_app_fac_assoc, + NatTrans.naturality_assoc, ← Functor.map_comp_assoc, NatTrans.naturality, + Functor.map_comp_assoc, ← t.eTruncLT_map_app_eTruncLTι_app (φ.app 1) X, + Functor.map_comp, Functor.map_comp, Category.assoc, + t.eTruncLTGEIsoLEGT_hom_app_fac] + simp + +end + +end TStructure + +end Triangulated + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/Induced.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/Induced.lean new file mode 100644 index 00000000000000..927b92bc66fcdf --- /dev/null +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/Induced.lean @@ -0,0 +1,148 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.CategoryTheory.ObjectProperty.Shift +public import Mathlib.CategoryTheory.Triangulated.Subcategory +public import Mathlib.CategoryTheory.Triangulated.TStructure.TruncLEGT + +/-! +# Induced t-structures + +Let `t` be a t-structure on a pretriangulated category `C`. +If `P` is a triangulated subcategory of `C`, we introduce a typeclass +`P.HasInducedTStructure t` which essentially says that up to isomorphisms +`P` is stable by the application of the truncation functors. + +In particular, we show that the triangulated subcategory `t.plus` +of `t`-bounded above objects can be endowed with a t-structure `t.onPlus`, +and the same applis to `t.minus` and `t.bounded`. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Limits Pretriangulated Triangulated + +variable {C : Type*} [Category* C] [Preadditive C] [HasZeroObject C] [HasShift C ℤ] + [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] + (P : ObjectProperty C) (t : TStructure C) + +namespace ObjectProperty + +/-- The property that a full subcategory of a pretriangulated category +equipped with a t-structure can be endowed with an induced t-structure. -/ +class HasInducedTStructure [P.IsTriangulated] : Prop where + exists_triangle_zero_one (A : C) (hA : P A) : + ∃ (X Y : C) (_ : t.IsLE X 0) (_ : t.IsGE Y 1) + (f : X ⟶ A) (g : A ⟶ Y) (h : Y ⟶ X⟦(1 : ℤ)⟧) (_ : Triangle.mk f g h ∈ distTriang C), + P.isoClosure X ∧ P.isoClosure Y + +variable [P.IsTriangulated] [h : P.HasInducedTStructure t] + +/-- The t-structure induced on a full subcategory. -/ +noncomputable def tStructure : TStructure P.FullSubcategory where + le n X := t.le n X.obj + ge n X := t.ge n X.obj + le_isClosedUnderIsomorphisms n := ⟨fun {X Y} e hX ↦ (t.le n).prop_of_iso (P.ι.mapIso e) hX⟩ + ge_isClosedUnderIsomorphisms n := ⟨fun {X Y} e hX ↦ (t.ge n).prop_of_iso (P.ι.mapIso e) hX⟩ + le_shift n a n' h X hX := (t.le n').prop_of_iso ((P.ι.commShiftIso a).symm.app X) + (t.le_shift n a n' h X.obj hX) + ge_shift n a n' h X hX := (t.ge n').prop_of_iso ((P.ι.commShiftIso a).symm.app X) + (t.ge_shift n a n' h X.obj hX) + zero' {X Y} f hX hY := P.ι.map_injective (by + rw [Functor.map_zero] + exact t.zero' (P.ι.map f) hX hY) + le_zero_le X hX := t.le_zero_le _ hX + ge_one_le X hX := t.ge_one_le _ hX + exists_triangle_zero_one A := by + obtain ⟨X, Y, hX, hY, f, g, h, hT, ⟨X', hX', ⟨e⟩⟩, ⟨Y', hY', ⟨e'⟩⟩⟩ := + h.exists_triangle_zero_one A.1 A.2 + exact ⟨⟨X', hX'⟩, ⟨Y', hY'⟩, (t.le 0).prop_of_iso e hX.le, + (t.ge 1).prop_of_iso e' hY.ge, + P.fullyFaithfulι.preimage (e.inv ≫ f), + P.fullyFaithfulι.preimage (g ≫ e'.hom), + P.fullyFaithfulι.preimage (e'.inv ≫ h ≫ e.hom⟦(1 : ℤ)⟧' ≫ + (P.ι.commShiftIso (1 : ℤ)).inv.app ⟨X', hX'⟩), + isomorphic_distinguished _ hT _ (Triangle.isoMk _ _ e.symm (Iso.refl _) e'.symm)⟩ + +lemma tStructure_isLE_iff (X : P.FullSubcategory) (n : ℤ) : + (P.tStructure t).IsLE X n ↔ t.IsLE X.obj n := + ⟨fun h => ⟨h.1⟩, fun h => ⟨h.1⟩⟩ + +lemma tStructure_isGE_iff (X : P.FullSubcategory) (n : ℤ) : + (P.tStructure t).IsGE X n ↔ t.IsGE X.obj n := + ⟨fun h => ⟨h.1⟩, fun h => ⟨h.1⟩⟩ + +/-- Constructor for `HasInducedTStructure`. -/ +lemma HasInducedTStructure.mk' {P : ObjectProperty C} [P.IsTriangulated] {t : TStructure C} + (h : ∀ (X : C) (_ : P X) (n : ℤ), P ((t.truncLE n).obj X) ∧ P ((t.truncGE n).obj X)) : + P.HasInducedTStructure t where + exists_triangle_zero_one X hX := + ⟨_, _, inferInstance, inferInstance, _, _, _, + t.triangleLEGE_distinguished 0 1 (by lia) X, + P.le_isoClosure _ ((h X hX _).1), P.le_isoClosure _ ((h X hX _).2)⟩ + +lemma mem_of_hasInductedTStructure (P : ObjectProperty C) [P.IsTriangulated] (t : TStructure C) + [P.IsClosedUnderIsomorphisms] [P.HasInducedTStructure t] + (T : Triangle C) (hT : T ∈ distTriang C) + (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (h₁ : t.IsLE T.obj₁ n₀) (h₂ : P T.obj₂) + (h₃ : t.IsGE T.obj₃ n₁) : + P T.obj₁ ∧ P T.obj₃ := by + obtain ⟨e, _⟩ := t.triangle_iso_exists hT + (P.ι.map_distinguished _ ((P.tStructure t).triangleLEGE_distinguished n₀ n₁ h ⟨_, h₂⟩)) + (Iso.refl _) n₀ n₁ inferInstance inferInstance + (by dsimp; rw [← P.tStructure_isLE_iff]; infer_instance) + (by dsimp; rw [← P.tStructure_isGE_iff]; infer_instance) + exact ⟨(P.prop_iff_of_iso (Triangle.π₁.mapIso e)).2 (P.prop_ι_obj _), + (P.prop_iff_of_iso (Triangle.π₃.mapIso e)).2 (P.prop_ι_obj _)⟩ + +instance (P P' : ObjectProperty C) [P.IsTriangulated] [P'.IsTriangulated] (t : TStructure C) + [P.HasInducedTStructure t] [P'.HasInducedTStructure t] + [P.IsClosedUnderIsomorphisms] [P'.IsClosedUnderIsomorphisms] : + (P ⊓ P').HasInducedTStructure t := + .mk' (by + rintro X ⟨hX, hX'⟩ n + exact + ⟨⟨(P.mem_of_hasInductedTStructure t _ (t.triangleLEGE_distinguished n _ rfl X) n _ rfl + (by dsimp; infer_instance) hX (by dsimp; infer_instance)).1, + (P'.mem_of_hasInductedTStructure t _ (t.triangleLEGE_distinguished n _ rfl X) n _ rfl + (by dsimp; infer_instance) hX' (by dsimp; infer_instance)).1⟩, + ⟨(P.mem_of_hasInductedTStructure t _ (t.triangleLEGE_distinguished (n - 1) n (by lia) X) + (n - 1) n (by lia) (by dsimp; infer_instance) hX (by dsimp; infer_instance)).2, + (P'.mem_of_hasInductedTStructure t _ (t.triangleLEGE_distinguished (n - 1) n (by lia) X) + (n - 1) n (by lia) (by dsimp; infer_instance) hX' (by dsimp; infer_instance)).2⟩⟩) + +end ObjectProperty + +namespace Triangulated.TStructure + +variable [IsTriangulated C] + +instance : t.plus.HasInducedTStructure t := + .mk' (by rintro X ⟨a, _⟩ n; exact ⟨⟨a, inferInstance⟩, ⟨a, inferInstance⟩⟩) + +instance : t.minus.HasInducedTStructure t := + .mk' (by rintro X ⟨a, _⟩ n; exact ⟨⟨a, inferInstance⟩, ⟨a, inferInstance⟩⟩) + +instance : t.bounded.HasInducedTStructure t := by + dsimp [bounded] + infer_instance + +/-- The t-structure induced on the full subcategory of `t`-bounded above objects. -/ +noncomputable abbrev onPlus : TStructure t.plus.FullSubcategory := t.plus.tStructure t + +/-- The t-structure induced on the full subcategory of `t`-bounded below objects. -/ +noncomputable abbrev onMinus : TStructure t.minus.FullSubcategory := t.minus.tStructure t + +/-- The t-structure induced on the full subcategory of `t`-bounded objects. -/ +noncomputable abbrev onBounded : TStructure t.bounded.FullSubcategory := t.bounded.tStructure t + +end Triangulated.TStructure + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/SpectralObject.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/SpectralObject.lean new file mode 100644 index 00000000000000..a984d060e8f313 --- /dev/null +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/SpectralObject.lean @@ -0,0 +1,177 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.CategoryTheory.Triangulated.SpectralObject +public import Mathlib.CategoryTheory.Triangulated.TStructure.ETrunc + +/-! +# Spectral objects attached t-structures + +Let `C` be a triangulated category equipped with a t-structure `t`. +We define a functor `t.ω₁ : ComposableArrows EInt 1 ⥤ C ⥤ C` which sends +a map `a ⟶ b` in `EInt` (i.e. `a ≤ b`) to the functor +`t.eTruncLT.obj b ⋙ t.eTruncGE.obj a`. (Roughly speaking, we "keep" the +`t`-homology only in degree `n` such that `a ≤ n < b`.) +When we have two composable morphisms `f : a ⟶ b` and `g : b ⟶ c` in `EInt`, +we define a connecting homomorphism +`ω₁δ : t.ω₁.obj (mk₁ g) ⟶ t.ω₁.obj (mk₁ f) ⋙ shiftFunctor C (1 : ℤ)`, and +this gives distinguished triangles that are functorial both in `X : C` +and `a ⟶ b ⟶ c` in `ComposableArrows EInt 2`. + +In other words, for each `X : C`, we define a spectral +object `t.spectralObject X : SpectralObject C EInt` in the +triangulated category `C`, and this extends to a functor +`t.spectralObjectFunctor : C ⥤ SpectralObject C EInt`. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Limits Pretriangulated ZeroObject Preadditive ComposableArrows + +variable {C : Type*} [Category* C] [Preadditive C] [HasZeroObject C] [HasShift C ℤ] + [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] + +namespace Triangulated + +namespace TStructure + +variable (t : TStructure C) [IsTriangulated C] + +/-- Given a t-structure `t` on a triangulated category `C`, this is the functor +`ComposableArrows EInt 1 ⥤ C ⥤ C` which sends an arrows `a ⟶ b` in `EInt` +to the functor `t.eTruncLT.obj b ⋙ t.eTruncGE.obj a`. -/ +@[simps] +noncomputable def ω₁ : ComposableArrows EInt 1 ⥤ C ⥤ C where + obj D := t.eTruncLT.obj (D.obj 1) ⋙ t.eTruncGE.obj (D.obj 0) + map φ := t.eTruncLT.map (φ.app 1) ◫ t.eTruncGE.map (φ.app 0) + +section + +variable (a b c : EInt) (hab : a ≤ b) (hbc : b ≤ c) + +open Functor in +/-- The connecting homomorphism (as a natural transformation) for the spectral +objects attached to the objects of a triangulated equipped with a t-structure. -/ +@[simps!] +noncomputable def ω₁δ : + t.ω₁.obj (mk₁ (homOfLE hbc)) ⟶ t.ω₁.obj (mk₁ (homOfLE hab)) ⋙ shiftFunctor C (1 : ℤ) := + whiskerLeft _ (t.eTruncGEToGEGE a b) ≫ (associator _ _ _).inv ≫ + (t.ω₁.obj (mk₁ (homOfLE (hab.trans hbc)))).whiskerLeft (t.eTruncGEδLT.app b) ≫ + (associator _ _ _).inv ≫ + whiskerRight + ((associator _ _ _).hom ≫ whiskerLeft _ (t.eTruncLTGEIsoLEGT a b).hom ≫ + (associator _ _ _).inv ≫ whiskerRight (t.eTruncLTLTToLT c b) _) _ + +@[reassoc] +lemma ω₁δ_naturality (a' b' c' : EInt) (hab' : a' ≤ b') (hbc' : b' ≤ c') + (φ : mk₂ (homOfLE hab) (homOfLE hbc) ⟶ mk₂ (homOfLE hab') (homOfLE hbc')) : + t.ω₁.map (homMk₁ (φ.app 1) (φ.app 2)) ≫ t.ω₁δ a' b' c' hab' hbc' = + t.ω₁δ a b c hab hbc ≫ Functor.whiskerRight (t.ω₁.map (homMk₁ (φ.app 0) (φ.app 1))) _ := by + ext X + simp only [ω₁_obj, mk₁_obj, Mk₁.obj, Functor.comp_obj, ω₁_map, homMk₁_app, + NatTrans.comp_app, NatTrans.hcomp_app, ω₁δ_app, + ← Functor.map_comp, Category.assoc, NatTrans.naturality_assoc, Functor.comp_map, + ← Functor.map_comp_assoc, NatTrans.naturality_app_assoc, Functor.whiskeringRight_obj_obj, + Functor.whiskeringRight_obj_map, Functor.whiskerRight_app, NatTrans.naturality] + congr 2 + have h₁ := t.eTruncLTGEIsoLEGT_naturality_app a b hab a' b' hab' (homMk₁ (φ.app 0) (φ.app 1)) + dsimp at h₁ + simp only [Functor.map_comp, Category.assoc] + rw [← reassoc_of% h₁, ← eTruncLTGEIsoLEGT_hom_naturality, ← eTruncLTGEIsoLEGT_hom_naturality, + ← t.eTruncLT_map_app_eTruncLTι_app (φ.app 2) X, NatTrans.naturality_assoc, + ← Functor.map_comp_assoc, ← Functor.map_comp_assoc, + ← Functor.map_comp_assoc, ← Functor.map_comp_assoc] + simp only [homOfLE_leOfHom, Fin.isValue, Category.assoc, eTruncGEπ_naturality, + eTruncLT_map_app_eTruncLTι_app_assoc, Functor.map_comp, eTruncGEπ_app_eTruncGE_map_app, + eTruncLT_map_app_eTruncLTι_app] + +/-- The functorial (distinguished) triangles that are part of the spectral +object attached to objects in a triangulated category equipped with a t-structure. -/ +@[simps!] +noncomputable def triangleω₁δ : C ⥤ Triangle C := + Triangle.functorMk (t.ω₁.map (twoδ₂Toδ₁' a b c hab hbc)) + (t.ω₁.map (twoδ₁Toδ₀' a b c hab hbc)) (t.ω₁δ a b c hab hbc) + +/-- The triangle `(t.triangleω₁δ a b c hab hbc).obj X` is isomorphic to +the (distinguished) triangle obtained by applying the functor `t.eTriangleLTGE.obj b` +to the object `(t.eTruncGE.obj a).obj ((t.eTruncLT.obj c).obj X)`. -/ +noncomputable def triangleω₁δObjIso (X : C) : + (t.triangleω₁δ a b c hab hbc).obj X ≅ + (t.eTriangleLTGE.obj b).obj ((t.ω₁.obj (mk₁ (homOfLE (hab.trans hbc)))).obj X) := by + refine Triangle.isoMk _ _ + ((t.eTruncGE.obj a).mapIso ((t.eTruncLTLTIsoLT c b hbc).symm.app X) ≪≫ + (t.eTruncLTGEIsoLEGT a b).symm.app _) + (Iso.refl _) ((t.eTruncGEIsoGEGE a b hab).app _) ?_ ?_ ?_ + · dsimp + simp only [triangleω₁δ_obj_mor₁, homOfLE_leOfHom, Category.comp_id, Category.assoc] + rw [← cancel_epi ((t.eTruncGE.obj a).map ((t.eTruncLTLTIsoLT c b hbc).hom.app X)), + ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.map_id, Category.id_comp, + ← cancel_epi ((t.eTruncLTGEIsoLEGT a b).hom.app ((t.eTruncLT.obj c).obj X)), + Iso.hom_inv_id_app_assoc, eTruncLTLTIsoLT_hom, eTruncLTLTToLT_app, + ← Functor.map_comp] + -- this should be cleanup and made a separate lemma + have : ((t.eTruncLT.obj b).map ((t.eTruncLTι c).app X) ≫ + (t.eTruncLT.map (homOfLE hbc)).app X) = (t.eTruncLTι _).app _ := by + dsimp [eTruncLTι] + rw [← homOfLE_comp hbc le_top, Functor.map_comp, NatTrans.comp_app, + NatTrans.naturality] + congr 1 + induction c using WithBotTop.rec with + | bot => simp + | coe c => simp [truncLT_map_truncLTι_app] + | top => simp + simp [this] + · dsimp + simp only [triangleω₁δ_obj_mor₂, eTruncGEToGEGE_app, Category.id_comp, + ← t.eTruncGEπ_app_eTruncGE_map_app (homOfLE hab), ← NatTrans.naturality, + eTruncGE_obj_map_eTruncGEπ_app] + · simp [← Functor.map_comp_assoc, ← Functor.map_comp] + +lemma triangleω₁δ_distinguished (X : C) : + (t.triangleω₁δ a b c hab hbc).obj X ∈ distTriang _ := + isomorphic_distinguished _ (t.eTriangleLTGE_distinguished b _) _ + (t.triangleω₁δObjIso a b c hab hbc X) + +end + +/-- The spectral object attached to an object `X : C` in a category +equipped with a t-structure. It consists of all truncations of `X`. -/ +@[simps ω₁] +noncomputable def spectralObject (X : C) : SpectralObject C EInt where + ω₁ := t.ω₁ ⋙ (evaluation _ _).obj X + δ'.app D := (t.ω₁δ (D.obj 0) (D.obj 1) (D.obj 2) + (leOfHom (D.map' 0 1)) (leOfHom (D.map' 1 2))).app X + δ'.naturality {D D'} φ := by + obtain ⟨a, b, c, f, g, rfl⟩ := mk₂_surjective D + obtain ⟨a', b', c', f', g', rfl⟩ := mk₂_surjective D' + exact NatTrans.congr_app (t.ω₁δ_naturality a b c (leOfHom f) (leOfHom g) + a' b' c' (leOfHom f') (leOfHom g') φ) X + distinguished' D := by + obtain ⟨a, b, c, f, g, rfl⟩ := mk₂_surjective D + exact t.triangleω₁δ_distinguished a b c (leOfHom f) (leOfHom g) X + +@[simp] +lemma spectralObject_δ (X : C) {a b c : EInt} (f : a ⟶ b) (g : b ⟶ c) : + (t.spectralObject X).δ f g = (t.ω₁δ a b c (leOfHom f) (leOfHom g)).app X := rfl + +/-- The spectral object attached to an object `X : C` in a category +equipped with a t-structure, as a functor `C ⥤ SpectralObject C EInt`. -/ +@[simps] +noncomputable def spectralObjectFunctor : C ⥤ SpectralObject C EInt where + obj := t.spectralObject + map φ := + { hom := Functor.whiskerLeft _ ((evaluation _ _).map φ) + comm f g := ((t.ω₁δ _ _ _ (leOfHom f) (leOfHom g)).naturality φ).symm } + +end TStructure + +end Triangulated + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLEGT.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLEGT.lean new file mode 100644 index 00000000000000..bf4482420ce068 --- /dev/null +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLEGT.lean @@ -0,0 +1,396 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Mathlib.CategoryTheory.Triangulated.TStructure.TruncLTGE + +/-! +# Truncations for a t-structure + +Let `t` be a t-structure on a (pre)triangulated category `C`. +In this file, for any `n : ℤ`, we introduce the truncation functors +`t.truncLE n : C ⥤ C` and `t.truncGT n : C ⥤ C`, as variants of the functors +`t.truncLT n : C ⥤ C` and `t.truncGE n : C ⥤ C` introduced in the file +`Mathlib/CategoryTheory/Triangulated/TStucture/TruncLTGE.lean`. + +-/ + +@[expose] public section + +namespace CategoryTheory + +open Limits Pretriangulated + +variable {C : Type*} [Category* C] [Preadditive C] [HasZeroObject C] [HasShift C ℤ] + [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] + +namespace Triangulated + +namespace TStructure + +variable (t : TStructure C) + +/-- Given a t-structure `t` on a pretriangulated category `C` and `n : ℤ`, this +is the `≤ n`-truncation functor. See also the natural transformation `truncLEι`. -/ +noncomputable def truncLE (n : ℤ) : C ⥤ C := t.truncLT (n + 1) + +instance (n : ℤ) : (t.truncLE n).Additive := by + dsimp only [truncLE] + infer_instance + +lemma isLE_truncLE_obj (X : C) (a b : ℤ) (hn : a ≤ b := by lia) : + t.IsLE ((t.truncLE a).obj X) b := + t.isLE_truncLT_obj .. + +instance (n : ℤ) (X : C) : t.IsLE ((t.truncLE n).obj X) n := + t.isLE_truncLE_obj .. + +/-- Given a t-structure `t` on a pretriangulated category `C` and `n : ℤ`, this +is the `> n`-truncation functor. See also the natural transformation `truncGTπ`. -/ +noncomputable def truncGT (n : ℤ) : C ⥤ C := t.truncGE (n + 1) + +instance (n : ℤ) : (t.truncGT n).Additive := by + dsimp only [truncGT] + infer_instance + +lemma isGE_truncGT_obj (X : C) (a b : ℤ) (hn : b ≤ a + 1 := by lia) : + t.IsGE ((t.truncGT a).obj X) b := + t.isGE_truncGE_obj .. + +instance (n : ℤ) (X : C) : t.IsGE ((t.truncGT n).obj X) (n + 1) := + t.isGE_truncGT_obj .. + +instance (n : ℤ) (X : C) : t.IsGE ((t.truncGT (n - 1)).obj X) n := + t.isGE_truncGT_obj .. + +/-- The isomorphism `t.truncLE a ≅ t.truncLT b` when `a + 1 = b`. -/ +noncomputable def truncLEIsoTruncLT (a b : ℤ) (h : a + 1 = b) : + t.truncLE a ≅ t.truncLT b := + eqToIso (by rw [← h]; rfl) + +/-- The isomorphism `t.truncGT a ≅ t.truncGE b` when `a + 1 = b`. -/ +noncomputable def truncGTIsoTruncGE (a b : ℤ) (h : a + 1 = b) : + t.truncGT a ≅ t.truncGE b := + eqToIso (by rw [← h]; rfl) + +/-- The natural transformation `t.truncLE n ⟶ 𝟭 C` when `t` is a t-structure +on a category `C` and `n : ℤ`. -/ +noncomputable def truncLEι (n : ℤ) : t.truncLE n ⟶ 𝟭 C := t.truncLTι (n + 1) + +@[reassoc (attr := simp)] +lemma truncLEIsoTruncLT_hom_ι (a b : ℤ) (h : a + 1 = b) : + (t.truncLEIsoTruncLT a b h).hom ≫ t.truncLTι b = t.truncLEι a := by + subst h + dsimp [truncLEIsoTruncLT, truncLEι] + rw [Category.id_comp] + +@[reassoc (attr := simp)] +lemma truncLEIsoTruncLT_hom_ι_app (a b : ℤ) (h : a + 1 = b) (X : C) : + (t.truncLEIsoTruncLT a b h).hom.app X ≫ (t.truncLTι b).app X = (t.truncLEι a).app X := + congr_app (t.truncLEIsoTruncLT_hom_ι a b h) X + +@[reassoc (attr := simp)] +lemma truncLEIsoTruncLT_inv_ι (a b : ℤ) (h : a + 1 = b) : + (t.truncLEIsoTruncLT a b h).inv ≫ t.truncLEι a = t.truncLTι b := by + subst h + dsimp [truncLEIsoTruncLT, truncLEι, truncLE] + rw [Category.id_comp] + +@[reassoc (attr := simp)] +lemma truncLEIsoTruncLT_inv_ι_app (a b : ℤ) (h : a + 1 = b) (X : C) : + (t.truncLEIsoTruncLT a b h).inv.app X ≫ (t.truncLEι a).app X = (t.truncLTι b).app X := + congr_app (t.truncLEIsoTruncLT_inv_ι a b h) X + +/-- The natural transformation `t.truncLE a ⟶ t.truncLE b` when `a ≤ b`. -/ +noncomputable def natTransTruncLEOfLE (a b : ℤ) (h : a ≤ b) : + t.truncLE a ⟶ t.truncLE b := + t.natTransTruncLTOfLE (a+1) (b+1) (by lia) + +@[reassoc (attr := simp)] +lemma natTransTruncLEOfLE_ι_app (n₀ n₁ : ℤ) (h : n₀ ≤ n₁) (X : C) : + (t.natTransTruncLEOfLE n₀ n₁ h).app X ≫ (t.truncLEι n₁).app X = + (t.truncLEι n₀).app X := + t.natTransTruncLTOfLE_ι_app _ _ _ _ + +@[reassoc (attr := simp)] +lemma natTransTruncLEOfLE_ι (a b : ℤ) (h : a ≤ b) : + t.natTransTruncLEOfLE a b h ≫ t.truncLEι b = t.truncLEι a := by cat_disch + +@[simp] +lemma natTransTruncLEOfLE_refl (a : ℤ) : + t.natTransTruncLEOfLE a a (by rfl) = 𝟙 _ := + t.natTransTruncLTOfLE_refl _ + +@[simp] +lemma natTransTruncLEOfLE_trans (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) : + t.natTransTruncLEOfLE a b hab ≫ t.natTransTruncLEOfLE b c hbc = + t.natTransTruncLEOfLE a c (hab.trans hbc) := + t.natTransTruncLTOfLE_trans _ _ _ _ _ + +lemma natTransTruncLEOfLE_refl_app (a : ℤ) (X : C) : + (t.natTransTruncLEOfLE a a (by rfl)).app X = 𝟙 _ := + congr_app (t.natTransTruncLEOfLE_refl a) X + +@[reassoc (attr := simp)] +lemma natTransTruncLEOfLE_trans_app (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) (X : C) : + (t.natTransTruncLEOfLE a b hab).app X ≫ (t.natTransTruncLEOfLE b c hbc).app X = + (t.natTransTruncLEOfLE a c (hab.trans hbc)).app X := + congr_app (t.natTransTruncLEOfLE_trans a b c hab hbc) X + +/-- The natural transformation `𝟭 C ⟶ t.truncGT n` when `t` is a t-structure +on a category `C` and `n : ℤ`. -/ +noncomputable def truncGTπ (n : ℤ) : 𝟭 C ⟶ t.truncGT n := t.truncGEπ (n + 1) + +@[reassoc (attr := simp)] +lemma π_truncGTIsoTruncGE_hom (a b : ℤ) (h : a + 1 = b) : + t.truncGTπ a ≫ (t.truncGTIsoTruncGE a b h).hom = t.truncGEπ b := by + subst h + dsimp [truncGTIsoTruncGE, truncGTπ] + rw [Category.comp_id] + +@[reassoc (attr := simp)] +lemma π_truncGTIsoTruncGE_hom_ι_app (a b : ℤ) (h : a + 1 = b) (X : C) : + (t.truncGTπ a).app X ≫ (t.truncGTIsoTruncGE a b h).hom.app X = (t.truncGEπ b).app X := + congr_app (t.π_truncGTIsoTruncGE_hom a b h) X + +@[reassoc (attr := simp)] +lemma π_truncGTIsoTruncGE_inv (a b : ℤ) (h : a + 1 = b) : + t.truncGEπ b ≫ (t.truncGTIsoTruncGE a b h).inv = t.truncGTπ a := by + subst h + dsimp [truncGTIsoTruncGE, truncGTπ, truncGT] + rw [Category.comp_id] + +@[reassoc (attr := simp)] +lemma π_truncGTIsoTruncGE_inv_ι_app (a b : ℤ) (h : a + 1 = b) (X : C) : + (t.truncGEπ b).app X ≫ (t.truncGTIsoTruncGE a b h).inv.app X = (t.truncGTπ a).app X := + congr_app (t.π_truncGTIsoTruncGE_inv a b h) X + +/-- The connecting homomorphism `(t.truncGE b).obj X ⟶ ((t.truncLE a).obj X)⟦1⟧` +when `a + 1 = b`, as a natural transformation. -/ +noncomputable def truncGEδLE (a b : ℤ) (h : a + 1 = b) : + t.truncGE b ⟶ t.truncLE a ⋙ shiftFunctor C (1 : ℤ) := + t.truncGEδLT b ≫ Functor.whiskerRight (t.truncLEIsoTruncLT a b h).inv (shiftFunctor C (1 : ℤ)) + +/-- The distinguished triangle `(t.truncLE a).obj A ⟶ A ⟶ (t.truncGE b).obj A ⟶ ...` +as a functor `C ⥤ Triangle C` when `t` is a `t`-structure on a pretriangulated +category `C` and `a + 1 = b`. -/ +@[simps!] +noncomputable def triangleLEGE (a b : ℤ) (h : a + 1 = b) : C ⥤ Triangle C := + Triangle.functorMk (t.truncLEι a) (t.truncGEπ b) (t.truncGEδLE a b h) + +/-- The natural isomorphism of triangles `t.triangleLEGE a b h ≅ t.triangleLTGE b` +when `a + 1 = b`. -/ +noncomputable def triangleLEGEIsoTriangleLTGE (a b : ℤ) (h : a + 1 = b) : + t.triangleLEGE a b h ≅ t.triangleLTGE b := by + refine Triangle.functorIsoMk _ _ (t.truncLEIsoTruncLT a b h) (Iso.refl _) (Iso.refl _) ?_ ?_ ?_ + · cat_disch + · cat_disch + · ext + dsimp [truncGEδLE] + simp only [Category.assoc, Category.id_comp, ← Functor.map_comp, + Iso.inv_hom_id_app, Functor.map_id, Category.comp_id] + +lemma triangleLEGE_distinguished (a b : ℤ) (h : a + 1 = b) (X : C) : + (t.triangleLEGE a b h).obj X ∈ distTriang C := + isomorphic_distinguished _ (t.triangleLTGE_distinguished b X) _ + ((t.triangleLEGEIsoTriangleLTGE a b h).app X) + +/-- The connecting homomorphism `(t.truncGT n).obj X ⟶ ((t.truncLE n).obj X)⟦1⟧` +for `n : ℤ`, as a natural transformation. -/ +noncomputable def truncGTδLE (n : ℤ) : + t.truncGT n ⟶ t.truncLE n ⋙ shiftFunctor C (1 : ℤ) := + (t.truncGTIsoTruncGE n (n+1) rfl).hom ≫ t.truncGEδLE n (n + 1) (by lia) + +/-- The distinguished triangle `(t.truncLE n).obj A ⟶ A ⟶ (t.truncGT n).obj A ⟶ ...` +as a functor `C ⥤ Triangle C` when `t` is a t-structure on a pretriangulated +category `C` and `n : ℤ`. -/ +@[simps!] +noncomputable def triangleLEGT (n : ℤ) : C ⥤ Triangle C := + Triangle.functorMk (t.truncLEι n) (t.truncGTπ n) (t.truncGTδLE n) + +/-- The natural isomorphism `t.triangleLEGT a ≅ t.triangleLEGE a b h` +when `a + 1 = b`. -/ +noncomputable def triangleLEGTIsoTriangleLEGE (a b : ℤ) (h : a + 1 = b) : + t.triangleLEGT a ≅ t.triangleLEGE a b h := + Triangle.functorIsoMk _ _ (Iso.refl _) (Iso.refl _) (t.truncGTIsoTruncGE a b h) + (by cat_disch) (by cat_disch) (by + ext + dsimp [truncGTδLE] + subst h + simp only [Functor.map_id, Category.comp_id]) + +lemma triangleLEGT_distinguished (n : ℤ) (X : C) : + (t.triangleLEGT n).obj X ∈ distTriang C := + isomorphic_distinguished _ (t.triangleLEGE_distinguished n (n+1) rfl X) _ + ((t.triangleLEGTIsoTriangleLEGE n (n+1) rfl).app X) + +lemma isLE_iff_isIso_truncLEι_app (n : ℤ) (X : C) : + t.IsLE X n ↔ IsIso ((t.truncLEι n).app X) := + t.isLE_iff_isIso_truncLTι_app n (n + 1) rfl X + +lemma isGE_iff_isIso_truncGTπ_app (n₀ n₁ : ℤ) (hn₁ : n₀ + 1 = n₁) (X : C) : + t.IsGE X n₁ ↔ IsIso ((t.truncGTπ n₀).app X) := by + rw [t.isGE_iff_isIso_truncGEπ_app n₁ X] + exact (MorphismProperty.isomorphisms _).arrow_mk_iso_iff + (Arrow.isoMk (Iso.refl _) ((t.truncGTIsoTruncGE _ _ hn₁).symm.app X)) + +instance (X : C) (n : ℤ) [t.IsLE X n] : IsIso ((t.truncLEι n).app X) := by + rw [← isLE_iff_isIso_truncLEι_app ] + infer_instance + +lemma isLE_iff_isZero_truncGT_obj (n : ℤ) (X : C) : + t.IsLE X n ↔ IsZero ((t.truncGT n).obj X) := by + rw [t.isLE_iff_isIso_truncLEι_app n X] + exact (Triangle.isZero₃_iff_isIso₁ _ (t.triangleLEGT_distinguished n X)).symm + +lemma isGE_iff_isZero_truncLE_obj (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) : + t.IsGE X n₁ ↔ IsZero ((t.truncLE n₀).obj X) := by + rw [t.isGE_iff_isIso_truncGEπ_app n₁ X] + exact (Triangle.isZero₁_iff_isIso₂ _ (t.triangleLEGE_distinguished n₀ n₁ h X)).symm + +lemma isZero_truncLE_obj_of_isGE (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) [t.IsGE X n₁] : + IsZero ((t.truncLE n₀).obj X) := by + rw [← t.isGE_iff_isZero_truncLE_obj _ _ h X] + infer_instance + +lemma to_truncLE_obj_ext {n : ℤ} {Y : C} {X : C} + {f₁ f₂ : Y ⟶ (t.truncLE n).obj X} (h : f₁ ≫ (t.truncLEι n).app X = f₂ ≫ (t.truncLEι n).app X) + [t.IsLE Y n] : + f₁ = f₂ := by + have : t.IsLE Y (n + 1 - 1) := by simpa + rw [← cancel_mono ((t.truncLEIsoTruncLT n (n + 1) rfl).hom.app _)] + exact t.to_truncLT_obj_ext (by simpa) + +section + +variable {X Y : C} (f : X ⟶ Y) (n : ℤ) [t.IsLE X n] + +lemma liftTruncLE_aux : + ∃ (f' : X ⟶ (t.truncLE n).obj Y), f = f' ≫ (t.truncLEι n).app Y := + Triangle.coyoneda_exact₂ _ (t.triangleLEGT_distinguished n Y) f + (t.zero_of_isLE_of_isGE _ n (n + 1) (by lia) inferInstance (by dsimp; infer_instance)) + +/-- Constructor for morphisms to `(t.truncLE n).obj Y`. -/ +noncomputable def liftTruncLE : + X ⟶ (t.truncLE n).obj Y := (t.liftTruncLE_aux f n).choose + +@[reassoc (attr := simp)] +lemma liftTruncLE_ι : + t.liftTruncLE f n ≫ (t.truncLEι n).app Y = f := + (t.liftTruncLE_aux f n).choose_spec.symm + +end + +section + +variable {X Y : C} (f : X ⟶ Y) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) [t.IsGE Y n₁] + +include h in +lemma descTruncGT_aux : + ∃ (f' : (t.truncGT n₀).obj X ⟶ Y), f = (t.truncGTπ n₀).app X ≫ f' := + Triangle.yoneda_exact₂ _ (t.triangleLEGT_distinguished n₀ X) f + (t.zero_of_isLE_of_isGE _ n₀ n₁ (by lia) (by dsimp; infer_instance) inferInstance) + +/-- Constructor for morphisms from `(t.truncGT n₀).obj Y`. -/ +noncomputable def descTruncGT : + (t.truncGT n₀).obj X ⟶ Y := + (t.descTruncGT_aux f n₀ n₁ h).choose + +@[reassoc (attr := simp)] +lemma π_descTruncGT : + (t.truncGTπ n₀).app X ≫ t.descTruncGT f n₀ n₁ h = f := + (t.descTruncGT_aux f n₀ n₁ h).choose_spec.symm + +end + +lemma isIso_truncLE_map_iff {X Y : C} (f : X ⟶ Y) (a b : ℤ) (h : a + 1 = b) : + IsIso ((t.truncLE a).map f) ↔ + ∃ (Z : C) (g : Y ⟶ Z) (h : Z ⟶ ((t.truncLE a).obj X)⟦1⟧) + (_ : Triangle.mk ((t.truncLEι a).app X ≫ f) g h ∈ distTriang _), t.IsGE Z b := by + subst h + apply isIso_truncLT_map_iff + +lemma isIso_truncGT_map_iff {Y Z : C} (g : Y ⟶ Z) (n : ℤ) : + IsIso ((t.truncGT n).map g) ↔ + ∃ (X : C) (f : X ⟶ Y) (h : ((t.truncGT n).obj Z) ⟶ X⟦(1 : ℤ)⟧) + (_ : Triangle.mk f (g ≫ (t.truncGTπ n).app Z) h ∈ distTriang _), t.IsLE X n := + t.isIso_truncGE_map_iff g n (n + 1) rfl + +instance (X : C) (a b : ℤ) [t.IsLE X b] : t.IsLE ((t.truncLE a).obj X) b := by + dsimp [truncLE] + infer_instance + +instance (X : C) (a b : ℤ) [t.IsGE X a] : t.IsGE ((t.truncGT b).obj X) a := by + dsimp [truncGT] + infer_instance + +/-- The composition `t.truncGE a ⋙ t.truncGE b`. -/ +noncomputable abbrev truncLEGE (a b : ℤ) : C ⥤ C := t.truncGE a ⋙ t.truncLE b + +/-- The composition `t.truncLE b ⋙ t.truncGE a`. -/ +noncomputable abbrev truncGELE (a b : ℤ) : C ⥤ C := t.truncLE b ⋙ t.truncGE a + +instance (X : C) (a b : ℤ) : t.IsGE ((t.truncGELE a b).obj X) a := by + dsimp; infer_instance + +/-- The natural isomorphism `t.truncGELE a b ≅ t.truncGELT a b'` when `b + 1 = b'`. -/ +noncomputable def truncGELEIsoTruncGELT (a b b' : ℤ) (hb' : b + 1 = b') : + t.truncGELE a b ≅ t.truncGELT a b' := + Functor.isoWhiskerRight (t.truncLEIsoTruncLT b b' hb') _ + +section + +variable [IsTriangulated C] + +lemma isIso₁_truncLE_map_of_isGE (T : Triangle C) (hT : T ∈ distTriang C) + (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (h₃ : t.IsGE T.obj₃ n₁) : + IsIso ((t.truncLE n₀).map T.mor₁) := by + subst h + exact t.isIso₁_truncLT_map_of_isGE _ hT _ h₃ + +lemma isIso₂_truncGT_map_of_isLE (T : Triangle C) (hT : T ∈ distTriang C) + (n₀ : ℤ) (h₁ : t.IsLE T.obj₁ n₀) : + IsIso ((t.truncGT n₀).map T.mor₂) := + t.isIso₂_truncGE_map_of_isLE _ hT _ _ rfl h₁ + +instance (X : C) (a b : ℤ) [t.IsGE X a] : + t.IsGE ((t.truncLE b).obj X) a := by + dsimp [truncLE]; infer_instance + +instance (X : C) (a b : ℤ) [t.IsLE X b] : + t.IsLE ((t.truncGT a).obj X) b := by + dsimp [truncGT]; infer_instance + +instance (X : C) (a b : ℤ) [t.IsGE X a] : + t.IsGE ((t.truncLE b).obj X) a := by + dsimp [truncLE]; infer_instance + +instance (X : C) (a b : ℤ) : + t.IsLE ((t.truncGELE a b).obj X) b := by + dsimp; infer_instance + +lemma isIso_truncLE_map_truncLEι_app (a b : ℤ) (h : a ≤ b) (X : C) : + IsIso ((t.truncLE a).map ((t.truncLEι b).app X)) := + t.isIso_truncLT_map_truncLTι_app _ _ (by lia) _ + +lemma isIso_truncGT_map_truncGTπ_app (a b : ℤ) (h : b ≤ a) (X : C) : + IsIso ((t.truncGT a).map ((t.truncGTπ b).app X)) := + isIso_truncGE_map_truncGEπ_app _ _ _ (by lia) _ + +instance (X : C) (n : ℤ) : IsIso ((t.truncLE n).map ((t.truncLEι n).app X)) := + t.isIso_truncLE_map_truncLEι_app _ _ (by lia) _ + +/-- The natural isomorphism `t.truncGELE a b ≅ t.truncLEGE a b`. -/ +noncomputable def truncGELEIsoLEGE (a b : ℤ) : t.truncGELE a b ≅ t.truncLEGE a b := + t.truncGELTIsoLTGE a (b + 1) + +end + +end TStructure + +end Triangulated + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLTGE.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLTGE.lean index 44036a78497de9..3ae1a209d394e9 100644 --- a/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLTGE.lean +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/TruncLTGE.lean @@ -6,6 +6,7 @@ Authors: Joël Riou module public import Mathlib.CategoryTheory.Triangulated.TStructure.Basic +public import Mathlib.CategoryTheory.Triangulated.Subcategory /-! # Truncations for a t-structure @@ -19,13 +20,21 @@ part of a distinguished triangle `(t.truncLT n).obj X ⟶ X ⟶ (t.truncGE n).obj X ⟶ ((t.truncLT n).obj X)⟦1⟧` for any `X : C`, with `(t.truncLT n).obj X < n` and `(t.truncGE n).obj X ≥ n`. +We obtain various properties of these truncation functors. +Variants `truncGT` and `truncLE` are introduced in the file +`Mathlib/CategoryTheory/Triangulated/TStucture/TruncLEGT.lean`. +Extensions to indices in `EInt` instead of `ℤ` are introduced in the file +`Mathlib/CategoryTheory/Triangulated/TStucture/ETrunc.lean`. +The spectral object attached to an object `X : C` is constructed in the file +`Mathlib/CategoryTheory/Triangulated/TStucture/SpectralObject.lean`. + -/ universe v u namespace CategoryTheory -open Limits Pretriangulated +open Limits Pretriangulated ZeroObject variable {C : Type u} [Category.{v} C] [Preadditive C] [HasZeroObject C] [HasShift C ℤ] [∀ (n : ℤ), (shiftFunctor C n).Additive] [Pretriangulated C] @@ -163,6 +172,43 @@ instance isGE_triangleFunctor_obj_obj₃ : dsimp [triangleFunctor] infer_instance +noncomputable def triangleMapOfLE (a b : ℤ) (h : a ≤ b) : triangle t a A ⟶ triangle t b A := + have H := triangle_map_exists t (triangle_distinguished t a A) + (triangle_distinguished t b A) (𝟙 _) (a-1) b inferInstance inferInstance + { hom₁ := H.choose.hom₁ + hom₂ := 𝟙 _ + hom₃ := H.choose.hom₃ + comm₁ := by rw [← H.choose.comm₁, H.choose_spec] + comm₂ := by rw [H.choose.comm₂, H.choose_spec] + comm₃ := H.choose.comm₃ } + +noncomputable def triangleFunctorNatTransOfLE (a b : ℤ) (h : a ≤ b) : + triangleFunctor t a ⟶ triangleFunctor t b where + app X := triangleMapOfLE t X a b h + naturality {X₁ X₂} φ := + triangle_map_ext t (triangleFunctor_obj_distinguished _ _ _) + (triangleFunctor_obj_distinguished _ _ _) (a - 1) b inferInstance inferInstance + (by simp [triangleMapOfLE]) + +@[simp] +lemma triangleFunctorNatTransOfLE_app_hom₂ (a b : ℤ) (h : a ≤ b) (X : C) : + ((triangleFunctorNatTransOfLE t a b h).app X).hom₂ = 𝟙 X := rfl + +lemma triangleFunctorNatTransOfLE_trans (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) : + triangleFunctorNatTransOfLE t a b hab ≫ triangleFunctorNatTransOfLE t b c hbc = + triangleFunctorNatTransOfLE t a c (hab.trans hbc) := by + apply NatTrans.ext + ext1 X + exact triangle_map_ext t (triangleFunctor_obj_distinguished _ _ _) + (triangleFunctor_obj_distinguished _ _ _) (a - 1) c inferInstance inferInstance (by simp) + +lemma triangleFunctorNatTransOfLE_refl (a : ℤ) : + triangleFunctorNatTransOfLE t a a (by rfl) = 𝟙 _ := by + apply NatTrans.ext + ext1 X + exact triangle_map_ext t (triangleFunctor_obj_distinguished _ _ _) + (triangleFunctor_obj_distinguished _ _ _) (a - 1) a inferInstance inferInstance (by simp) + instance : (triangleFunctor t n).Additive where end TruncAux @@ -201,13 +247,29 @@ on a category `C` and `n : ℤ`. -/ noncomputable def truncGEπ (n : ℤ) : 𝟭 _ ⟶ t.truncGE n := Functor.whiskerLeft (TruncAux.triangleFunctor t n) Triangle.π₂Toπ₃ -instance (X : C) (n : ℤ) : t.IsLE ((t.truncLT n).obj X) (n - 1) := by - dsimp [truncLT] - infer_instance +@[reassoc (attr := simp)] +lemma truncGEπ_naturality (n : ℤ) {X Y : C} (f : X ⟶ Y) : + (t.truncGEπ n).app X ≫ (t.truncGE n).map f = f ≫ (t.truncGEπ n).app Y := + ((t.truncGEπ n).naturality f).symm -instance (X : C) (n : ℤ) : t.IsGE ((t.truncGE n).obj X) n := by - dsimp [truncGE] - infer_instance +lemma isLE_truncLT_obj (X : C) (a b : ℤ) (hn : a ≤ b + 1 := by lia) : + t.IsLE ((t.truncLT a).obj X) b := by + have : t.IsLE ((t.truncLT a).obj X) (a - 1) := by dsimp [truncLT]; infer_instance + exact t.isLE_of_le _ (a - 1) _ (by lia) + +instance (X : C) (n : ℤ) : t.IsLE ((t.truncLT n).obj X) (n - 1) := + t.isLE_truncLT_obj .. + +instance (X : C) (n : ℤ) : t.IsLE ((t.truncLT (n + 1)).obj X) n := + t.isLE_truncLT_obj .. + +lemma isGE_truncGE_obj (X : C) (a b : ℤ) (hn : b ≤ a := by lia) : + t.IsGE ((t.truncGE a).obj X) b := by + have : t.IsGE ((t.truncGE a).obj X) a := by dsimp [truncGE]; infer_instance + exact t.isGE_of_ge _ _ a (by lia) + +instance (X : C) (n : ℤ) : t.IsGE ((t.truncGE n).obj X) n := + t.isGE_truncGE_obj .. /-- The connecting morphism `t.truncGE n ⟶ t.truncLT n ⋙ shiftFunctor C (1 : ℤ)` when `t` is a t-structure on a pretriangulated category and `n : ℤ`. -/ @@ -234,6 +296,562 @@ instance (X : C) (n : ℤ) : t.IsGE ((t.triangleLTGE n).obj X).obj₃ n := by dsimp infer_instance +@[reassoc (attr := simp)] +lemma truncLTι_comp_truncGEπ_app (n : ℤ) (X : C) : + (t.truncLTι n).app X ≫ (t.truncGEπ n).app X = 0 := + comp_distTriang_mor_zero₁₂ _ (t.triangleLTGE_distinguished n X) + +@[reassoc (attr := simp)] +lemma truncGEπ_comp_truncGEδLT_app (n : ℤ) (X : C) : + (t.truncGEπ n).app X ≫ (t.truncGEδLT n).app X = 0 := + comp_distTriang_mor_zero₂₃ _ (t.triangleLTGE_distinguished n X) + +@[reassoc (attr := simp)] +lemma truncGEδLT_comp_truncLTι_app (n : ℤ) (X : C) : + (t.truncGEδLT n).app X ≫ ((t.truncLTι n).app X)⟦(1 : ℤ)⟧' = 0 := + comp_distTriang_mor_zero₃₁ _ (t.triangleLTGE_distinguished n X) + +@[reassoc (attr := simp)] +lemma truncLTι_comp_truncGEπ (n : ℤ) : + t.truncLTι n ≫ t.truncGEπ n = 0 := by cat_disch + +@[reassoc (attr := simp)] +lemma truncGEπ_comp_truncGEδLT (n : ℤ) : + t.truncGEπ n ≫ t.truncGEδLT n = 0 := by cat_disch + +@[reassoc (attr := simp)] +lemma truncGEδLT_comp_truncLTι (n : ℤ) : + t.truncGEδLT n ≫ Functor.whiskerRight (t.truncLTι n) (shiftFunctor C (1 : ℤ)) = 0 := by + cat_disch + +/-- The natural transformation `t.truncLT a ⟶ t.truncLT b` when `a ≤ b`. -/ +noncomputable def natTransTruncLTOfLE (a b : ℤ) (h : a ≤ b) : + t.truncLT a ⟶ t.truncLT b := + Functor.whiskerRight (TruncAux.triangleFunctorNatTransOfLE t a b h) Triangle.π₁ + +/-- The natural transformation `t.truncGE a ⟶ t.truncGE b` when `a ≤ b`. -/ +noncomputable def natTransTruncGEOfLE (a b : ℤ) (h : a ≤ b) : + t.truncGE a ⟶ t.truncGE b := + Functor.whiskerRight (TruncAux.triangleFunctorNatTransOfLE t a b h) Triangle.π₃ + +@[reassoc (attr := simp)] +lemma natTransTruncLTOfLE_ι_app (a b : ℤ) (h : a ≤ b) (X : C) : + (t.natTransTruncLTOfLE a b h).app X ≫ (t.truncLTι b).app X = (t.truncLTι a).app X := by + simpa using ((TruncAux.triangleFunctorNatTransOfLE t a b h).app X).comm₁.symm + +@[reassoc (attr := simp)] +lemma natTransTruncLTOfLE_ι (a b : ℤ) (h : a ≤ b) : + t.natTransTruncLTOfLE a b h ≫ t.truncLTι b = t.truncLTι a := by cat_disch + +@[reassoc (attr := simp)] +lemma π_natTransTruncGEOfLE_app (a b : ℤ) (h : a ≤ b) (X : C) : + (t.truncGEπ a).app X ≫ (t.natTransTruncGEOfLE a b h).app X = (t.truncGEπ b).app X := by + simpa only [TruncAux.triangleFunctor_obj, TruncAux.triangle_obj₂, + TruncAux.triangleFunctorNatTransOfLE_app_hom₂, Category.id_comp] using + ((TruncAux.triangleFunctorNatTransOfLE t a b h).app X).comm₂ + +@[reassoc] +lemma truncGEδLT_comp_natTransTruncLTOfLE_app (a b : ℤ) (h : a ≤ b) (X : C) : + (t.truncGEδLT a).app X ≫ ((natTransTruncLTOfLE t a b h).app X)⟦(1 :ℤ)⟧' = + (t.natTransTruncGEOfLE a b h).app X ≫ (t.truncGEδLT b).app X := + ((TruncAux.triangleFunctorNatTransOfLE t a b h).app X).comm₃ + +@[reassoc] +lemma truncGEδLT_comp_whiskerRight_natTransTruncLTOfLE (a b : ℤ) (h : a ≤ b) : + t.truncGEδLT a ≫ Functor.whiskerRight (natTransTruncLTOfLE t a b h) (shiftFunctor C (1 : ℤ)) = + t.natTransTruncGEOfLE a b h ≫ t.truncGEδLT b := by + ext X + exact t.truncGEδLT_comp_natTransTruncLTOfLE_app a b h X + +@[reassoc (attr := simp)] +lemma π_natTransTruncGEOfLE (a b : ℤ) (h : a ≤ b) : + t.truncGEπ a ≫ t.natTransTruncGEOfLE a b h = t.truncGEπ b := by cat_disch + +/-- The natural transformation `t.triangleLTGE a ⟶ t.triangleLTGE b` +when `a ≤ b`. -/ +noncomputable def natTransTriangleLTGEOfLE (a b : ℤ) (h : a ≤ b) : + t.triangleLTGE a ⟶ t.triangleLTGE b := by + refine Triangle.functorHomMk' (t.natTransTruncLTOfLE a b h) (𝟙 _) + ((t.natTransTruncGEOfLE a b h)) ?_ ?_ ?_ + · simp + · simp + · exact t.truncGEδLT_comp_whiskerRight_natTransTruncLTOfLE a b h + +@[simp] +lemma natTransTriangleLTGEOfLE_refl (a : ℤ) : + t.natTransTriangleLTGEOfLE a a (by rfl) = 𝟙 _ := + TruncAux.triangleFunctorNatTransOfLE_refl t a + +lemma natTransTriangleLTGEOfLE_trans (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) : + t.natTransTriangleLTGEOfLE a b hab ≫ t.natTransTriangleLTGEOfLE b c hbc = + t.natTransTriangleLTGEOfLE a c (hab.trans hbc) := + TruncAux.triangleFunctorNatTransOfLE_trans t a b c hab hbc + +@[simp] +lemma natTransTruncLTOfLE_refl (a : ℤ) : + t.natTransTruncLTOfLE a a (by rfl) = 𝟙 _ := + congr_arg (fun x ↦ Functor.whiskerRight x (Triangle.π₁)) (t.natTransTriangleLTGEOfLE_refl a) + +@[simp] +lemma natTransTruncLTOfLE_trans (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) : + t.natTransTruncLTOfLE a b hab ≫ t.natTransTruncLTOfLE b c hbc = + t.natTransTruncLTOfLE a c (hab.trans hbc) := + congr_arg (fun x ↦ Functor.whiskerRight x Triangle.π₁) + (t.natTransTriangleLTGEOfLE_trans a b c hab hbc) + +@[simp] +lemma natTransTruncGEOfLE_refl (a : ℤ) : + t.natTransTruncGEOfLE a a (by rfl) = 𝟙 _ := + congr_arg (fun x ↦ Functor.whiskerRight x (Triangle.π₃)) (t.natTransTriangleLTGEOfLE_refl a) + +@[simp] +lemma natTransTruncGEOfLE_trans (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) : + t.natTransTruncGEOfLE a b hab ≫ t.natTransTruncGEOfLE b c hbc = + t.natTransTruncGEOfLE a c (hab.trans hbc) := + congr_arg (fun x ↦ Functor.whiskerRight x Triangle.π₃) + (t.natTransTriangleLTGEOfLE_trans a b c hab hbc) + +lemma natTransTruncLTOfLE_refl_app (a : ℤ) (X : C) : + (t.natTransTruncLTOfLE a a (by rfl)).app X = 𝟙 _ := + congr_app (t.natTransTruncLTOfLE_refl a) X + +lemma natTransTruncLTOfLE_trans_app (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) (X : C) : + (t.natTransTruncLTOfLE a b hab).app X ≫ (t.natTransTruncLTOfLE b c hbc).app X = + (t.natTransTruncLTOfLE a c (hab.trans hbc)).app X := + congr_app (t.natTransTruncLTOfLE_trans a b c hab hbc) X + +lemma natTransTruncGEOfLE_refl_app (a : ℤ) (X : C) : + (t.natTransTruncGEOfLE a a (by rfl)).app X = 𝟙 _ := + congr_app (t.natTransTruncGEOfLE_refl a) X + +lemma natTransTruncGEOfLE_trans_app (a b c : ℤ) (hab : a ≤ b) (hbc : b ≤ c) (X : C) : + (t.natTransTruncGEOfLE a b hab).app X ≫ (t.natTransTruncGEOfLE b c hbc).app X = + (t.natTransTruncGEOfLE a c (hab.trans hbc)).app X := + congr_app (t.natTransTruncGEOfLE_trans a b c hab hbc) X + +lemma isLE_of_isZero {X : C} (hX : IsZero X) (n : ℤ) : t.IsLE X n := + t.isLE_of_iso (((t.truncLT (n + 1)).map_isZero hX).isoZero ≪≫ hX.isoZero.symm) n + +lemma isGE_of_isZero {X : C} (hX : IsZero X) (n : ℤ) : t.IsGE X n := + t.isGE_of_iso (((t.truncGE n).map_isZero hX).isoZero ≪≫ hX.isoZero.symm) n + +instance (n : ℤ) : t.IsLE (0 : C) n := t.isLE_of_isZero (isZero_zero C) n + +instance (n : ℤ) : t.IsGE (0 : C) n := t.isGE_of_isZero (isZero_zero C) n + +lemma isLE_iff_isIso_truncLTι_app (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) : + t.IsLE X n₀ ↔ IsIso (((t.truncLTι n₁)).app X) := by + subst h + refine ⟨fun _ ↦ ?_, + fun _ ↦ t.isLE_of_iso (asIso (((t.truncLTι (n₀ + 1))).app X)) n₀⟩ + obtain ⟨e, he⟩ := t.triangle_iso_exists + (contractible_distinguished X) (t.triangleLTGE_distinguished (n₀ + 1) X) + (Iso.refl X) n₀ (n₀ + 1) + (by dsimp; infer_instance) (by dsimp; infer_instance) + (by dsimp; infer_instance) (by dsimp; infer_instance) + have he' : e.inv.hom₂ = 𝟙 X := by + rw [← cancel_mono e.hom.hom₂, ← comp_hom₂, e.inv_hom_id, he] + simp + have : (t.truncLTι (n₀ + 1)).app X = e.inv.hom₁ := by + simpa [he'] using e.inv.comm₁ + rw [this] + infer_instance + +lemma isGE_iff_isIso_truncGEπ_app (n : ℤ) (X : C) : + t.IsGE X n ↔ IsIso ((t.truncGEπ n).app X) := by + constructor + · intro h + obtain ⟨e, he⟩ := t.triangle_iso_exists + (inv_rot_of_distTriang _ (contractible_distinguished X)) + (t.triangleLTGE_distinguished n X) (Iso.refl X) (n - 1) n + (t.isLE_of_iso (shiftFunctor C (-1 : ℤ)).mapZeroObject.symm _) + (by dsimp; infer_instance) (by dsimp; infer_instance) (by dsimp; infer_instance) + dsimp at he + have : (truncGEπ t n).app X = e.hom.hom₃ := by + have := e.hom.comm₂ + dsimp at this + rw [← cancel_epi e.hom.hom₂, ← this, he] + rw [this] + infer_instance + · intro + exact t.isGE_of_iso (asIso ((truncGEπ t n).app X)).symm n + +instance (X : C) (n : ℤ) [t.IsGE X n] : IsIso ((t.truncGEπ n).app X) := by + rw [← isGE_iff_isIso_truncGEπ_app] + infer_instance + +lemma isGE_iff_isZero_truncLT_obj (n : ℤ) (X : C) : + t.IsGE X n ↔ IsZero ((t.truncLT n).obj X) := by + rw [t.isGE_iff_isIso_truncGEπ_app n X] + exact (Triangle.isZero₁_iff_isIso₂ _ (t.triangleLTGE_distinguished n X)).symm + +lemma isLE_iff_isZero_truncGE_obj (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) : + t.IsLE X n₀ ↔ IsZero ((t.truncGE n₁).obj X) := by + rw [t.isLE_iff_isIso_truncLTι_app n₀ n₁ h X] + exact (Triangle.isZero₃_iff_isIso₁ _ (t.triangleLTGE_distinguished n₁ X)).symm + +lemma isZero_truncLT_obj_of_isGE (n : ℤ) (X : C) [t.IsGE X n] : + IsZero ((t.truncLT n).obj X) := by + rw [← isGE_iff_isZero_truncLT_obj] + infer_instance + +lemma isZero_truncGE_obj_of_isLE (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) [t.IsLE X n₀] : + IsZero ((t.truncGE n₁).obj X) := by + rw [← t.isLE_iff_isZero_truncGE_obj _ _ h X] + infer_instance + +lemma from_truncGE_obj_ext {n : ℤ} {X : C} {Y : C} + {f₁ f₂ : (t.truncGE n).obj X ⟶ Y} (h : (t.truncGEπ n).app X ≫ f₁ = (t.truncGEπ n).app X ≫ f₂) + [t.IsGE Y n] : + f₁ = f₂ := by + suffices ∀ (f : (t.truncGE n).obj X ⟶ Y), (t.truncGEπ n).app X ≫ f = 0 → f = 0 by + rw [← sub_eq_zero, this (f₁ - f₂) (by cat_disch)] + intro f hf + obtain ⟨g, hg⟩ := Triangle.yoneda_exact₃ _ + (t.triangleLTGE_distinguished n X) f hf + have hg' := t.zero_of_isLE_of_isGE g (n-2) n (by lia) + (by exact t.isLE_shift _ (n-1) 1 (n-2) (by lia)) inferInstance + rw [hg, hg', comp_zero] + +lemma to_truncLT_obj_ext {n : ℤ} {Y : C} {X : C} + {f₁ f₂ : Y ⟶ (t.truncLT n).obj X} + (h : f₁ ≫ (t.truncLTι n).app X = f₂ ≫ (t.truncLTι n).app X) + [t.IsLE Y (n - 1)] : + f₁ = f₂ := by + suffices ∀ (f : Y ⟶ (t.truncLT n).obj X) (_ : f ≫ (t.truncLTι n).app X = 0), f = 0 by + rw [← sub_eq_zero, this (f₁ - f₂) (by cat_disch)] + intro f hf + obtain ⟨g, hg⟩ := Triangle.coyoneda_exact₂ _ (inv_rot_of_distTriang _ + (t.triangleLTGE_distinguished n X)) f hf + have hg' := t.zero_of_isLE_of_isGE g (n - 1) (n + 1) (by lia) inferInstance + (by dsimp; apply (t.isGE_shift _ n (-1) (n + 1) (by lia))) + rw [hg, hg', zero_comp] + +@[reassoc] +lemma truncLT_map_truncLTι_app (n : ℤ) (X : C) : + (t.truncLT n).map ((t.truncLTι n).app X) = (t.truncLTι n).app ((t.truncLT n).obj X) := + t.to_truncLT_obj_ext (by simp) + +@[reassoc] +lemma truncGE_map_truncGEπ_app (n : ℤ) (X : C) : + (t.truncGE n).map ((t.truncGEπ n).app X) = (t.truncGEπ n).app ((t.truncGE n).obj X) := + t.from_truncGE_obj_ext (by simp) + +section + +variable {X Y : C} (f : X ⟶ Y) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) [t.IsLE X n₀] + +include h in +lemma liftTruncLT_aux : + ∃ (f' : X ⟶ (t.truncLT n₁).obj Y), f = f' ≫ (t.truncLTι n₁).app Y := + Triangle.coyoneda_exact₂ _ (t.triangleLTGE_distinguished n₁ Y) f + (t.zero_of_isLE_of_isGE _ n₀ n₁ (by lia) inferInstance (by dsimp; infer_instance)) + +/-- Constructor for morphisms to `(t.truncLT n₁).obj Y`. -/ +noncomputable def liftTruncLT {X Y : C} (f : X ⟶ Y) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) [t.IsLE X n₀] : + X ⟶ (t.truncLT n₁).obj Y := + (t.liftTruncLT_aux f n₀ n₁ h).choose + +@[reassoc (attr := simp)] +lemma liftTruncLT_ι {X Y : C} (f : X ⟶ Y) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) [t.IsLE X n₀] : + t.liftTruncLT f n₀ n₁ h ≫ (t.truncLTι n₁).app Y = f := + (t.liftTruncLT_aux f n₀ n₁ h).choose_spec.symm + +end + +section + +variable {X Y : C} (f : X ⟶ Y) (n : ℤ) [t.IsGE Y n] + +lemma descTruncGE_aux : + ∃ (f' : (t.truncGE n).obj X ⟶ Y), f = (t.truncGEπ n).app X ≫ f' := + Triangle.yoneda_exact₂ _ (t.triangleLTGE_distinguished n X) f + (t.zero_of_isLE_of_isGE _ (n-1) n (by lia) (by dsimp; infer_instance) inferInstance) + +/-- Constructor for morphisms from `(t.truncGE n).obj X`. -/ +noncomputable def descTruncGE : + (t.truncGE n).obj X ⟶ Y := + (t.descTruncGE_aux f n).choose + +@[reassoc (attr := simp)] +lemma π_descTruncGE {X Y : C} (f : X ⟶ Y) (n : ℤ) [t.IsGE Y n] : + (t.truncGEπ n).app X ≫ t.descTruncGE f n = f := + (t.descTruncGE_aux f n).choose_spec.symm + +end + +lemma isLE_iff_orthogonal (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) : + t.IsLE X n₀ ↔ ∀ (Y : C) (f : X ⟶ Y) (_ : t.IsGE Y n₁), f = 0 := by + refine ⟨fun _ Y f _ ↦ t.zero f n₀ n₁ (by lia), fun hX ↦ ?_⟩ + rw [t.isLE_iff_isZero_truncGE_obj n₀ n₁ h, IsZero.iff_id_eq_zero] + exact t.from_truncGE_obj_ext (by simpa using hX _ _ inferInstance) + +lemma isGE_iff_orthogonal (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (X : C) : + t.IsGE X n₁ ↔ ∀ (Y : C) (f : Y ⟶ X) (_ : t.IsLE Y n₀), f = 0 := by + refine ⟨fun _ Y f _ ↦ t.zero f n₀ n₁ (by lia), fun hX ↦ ?_⟩ + rw [t.isGE_iff_isZero_truncLT_obj n₁ X, IsZero.iff_id_eq_zero] + exact t.to_truncLT_obj_ext (by simpa using hX _ _ (by rw [← h]; infer_instance)) + +lemma isLE₂ (T : Triangle C) (hT : T ∈ distTriang C) (n : ℤ) (h₁ : t.IsLE T.obj₁ n) + (h₃ : t.IsLE T.obj₃ n) : t.IsLE T.obj₂ n := by + rw [t.isLE_iff_orthogonal n (n+1) rfl] + intro Y f hY + obtain ⟨f', hf'⟩ := Triangle.yoneda_exact₂ _ hT f + (t.zero _ n (n + 1) (by lia) ) + rw [hf', t.zero f' n (n + 1) (by lia), comp_zero] + +lemma isGE₂ (T : Triangle C) (hT : T ∈ distTriang C) (n : ℤ) (h₁ : t.IsGE T.obj₁ n) + (h₃ : t.IsGE T.obj₃ n) : t.IsGE T.obj₂ n := by + rw [t.isGE_iff_orthogonal (n-1) n (by lia)] + intro Y f hY + obtain ⟨f', hf'⟩ := Triangle.coyoneda_exact₂ _ hT f (t.zero _ (n-1) n (by lia)) + rw [hf', t.zero f' (n-1) n (by lia), zero_comp] + +instance : t.minus.IsTriangulated where + exists_zero := ⟨0, isZero_zero C, 0, inferInstance⟩ + toIsTriangulatedClosed₂ := .mk' (fun T hT ↦ by + rintro ⟨i₁, hi₁⟩ ⟨i₃, hi₃⟩ + exact ⟨max i₁ i₃, t.isLE₂ T hT _ (t.isLE_of_le _ _ _ (le_max_left i₁ i₃)) + (t.isLE_of_le _ _ _ (le_max_right i₁ i₃))⟩) + +instance : t.plus.IsTriangulated where + exists_zero := ⟨0, isZero_zero C, 0, inferInstance⟩ + toIsTriangulatedClosed₂ := .mk' (fun T hT ↦ by + rintro ⟨i₁, hi₁⟩ ⟨i₃, hi₃⟩ + exact ⟨min i₁ i₃, t.isGE₂ T hT _ (t.isGE_of_ge _ _ _ (min_le_left i₁ i₃)) + (t.isGE_of_ge _ _ _ (min_le_right i₁ i₃))⟩) + +instance : t.bounded.IsTriangulated := by + dsimp [bounded] + infer_instance + +lemma isIso_truncLT_map_iff {X Y : C} (f : X ⟶ Y) (n : ℤ) : + IsIso ((t.truncLT n).map f) ↔ + ∃ (Z : C) (g : Y ⟶ Z) (h : Z ⟶ ((t.truncLT n).obj X)⟦1⟧) + (_ : Triangle.mk ((t.truncLTι n).app X ≫ f) g h ∈ distTriang _), t.IsGE Z n := by + refine ⟨fun hf ↦ ?_, fun ⟨Z, g, h, mem, _⟩ ↦ ?_⟩ + · refine ⟨(t.truncGE n).obj Y, (t.truncGEπ n).app Y, + (t.truncGEδLT n).app Y ≫ (inv ((t.truncLT n).map f))⟦1⟧', + isomorphic_distinguished _ (t.triangleLTGE_distinguished n Y) _ ?_, inferInstance⟩ + exact Triangle.isoMk _ _ (asIso ((t.truncLT n).map f)) (Iso.refl _) (Iso.refl _) + · obtain ⟨e, he⟩ := t.triangle_iso_exists + mem (t.triangleLTGE_distinguished n Y) (Iso.refl _) (n - 1) n + (by dsimp; infer_instance) (by dsimp; infer_instance) + (by dsimp; infer_instance) (by dsimp; infer_instance) + suffices ((t.truncLT n).map f) = e.hom.hom₁ by rw [this]; infer_instance + exact t.to_truncLT_obj_ext (Eq.trans (by cat_disch) e.hom.comm₁) + +lemma isIso_truncGE_map_iff {Y Z : C} (g : Y ⟶ Z) (n₀ n₁ : ℤ) (hn : n₀ + 1 = n₁) : + IsIso ((t.truncGE n₁).map g) ↔ + ∃ (X : C) (f : X ⟶ Y) (h : ((t.truncGE n₁).obj Z) ⟶ X⟦(1 : ℤ)⟧) + (_ : Triangle.mk f (g ≫ (t.truncGEπ n₁).app Z) h ∈ distTriang _), t.IsLE X n₀ := by + refine ⟨fun hf ↦ ?_, fun ⟨X, f, h, mem, _⟩ ↦ ?_⟩ + · refine ⟨_, (t.truncLTι n₁).app Y, inv ((t.truncGE n₁).map g) ≫ (t.truncGEδLT n₁).app Y, + isomorphic_distinguished _ (t.triangleLTGE_distinguished n₁ Y) _ ?_, + by subst hn; infer_instance⟩ + exact Iso.symm (Triangle.isoMk _ _ (Iso.refl _) (Iso.refl _) + (asIso ((t.truncGE n₁).map g)) (by simp) (by simp) (by simp)) + · obtain ⟨e, he⟩ := + t.triangle_iso_exists (t.triangleLTGE_distinguished n₁ Y) mem (Iso.refl _) n₀ n₁ + (by dsimp; rw [← hn]; infer_instance) (by dsimp; infer_instance) + (by dsimp; infer_instance) (by dsimp; infer_instance) + suffices ((t.truncGE n₁).map g) = e.hom.hom₃ by rw [this]; infer_instance + exact t.from_truncGE_obj_ext (Eq.trans (by cat_disch) e.hom.comm₂.symm) + +instance (X : C) (a b : ℤ) [t.IsLE X b] : t.IsLE ((t.truncLT a).obj X) b := by + by_cases h : a ≤ b + 1 + · exact t.isLE_truncLT_obj .. + · have := (t.isLE_iff_isIso_truncLTι_app (a - 1) a (by lia) X).1 (t.isLE_of_le _ b _ (by lia)) + exact t.isLE_of_iso (show X ≅ _ from (asIso ((t.truncLTι a).app X)).symm) _ + +instance (X : C) (a b : ℤ) [t.IsGE X a] : t.IsGE ((t.truncGE b).obj X) a := by + by_cases h : a ≤ b + · exact t.isGE_truncGE_obj .. + · have : t.IsGE X b := t.isGE_of_ge X b a (by lia) + exact t.isGE_of_iso (show X ≅ _ from asIso ((t.truncGEπ b).app X)) _ + +/-- The composition `t.truncLT b ⋙ t.truncGE a`. -/ +noncomputable abbrev truncGELT (a b : ℤ) : C ⥤ C := t.truncLT b ⋙ t.truncGE a + +/-- The composition `t.truncGE b ⋙ t.truncLT a`. -/ +noncomputable abbrev truncLTGE (a b : ℤ) : C ⥤ C := t.truncGE a ⋙ t.truncLT b + +instance (X : C) (a b : ℤ) : t.IsGE ((t.truncGELT a b).obj X) a := by + dsimp; infer_instance + +instance (X : C) (a b : ℤ) : t.IsLE ((t.truncLTGE a b).obj X) (b - 1) := by + dsimp; infer_instance + +section + +variable [IsTriangulated C] + +lemma isIso₁_truncLT_map_of_isGE (T : Triangle C) (hT : T ∈ distTriang C) + (n : ℤ) (h₃ : t.IsGE T.obj₃ n) : + IsIso ((t.truncLT n).map T.mor₁) := by + rw [isIso_truncLT_map_iff] + obtain ⟨Z, g, k, mem⟩ := distinguished_cocone_triangle ((t.truncLTι n).app T.obj₁ ≫ T.mor₁) + refine ⟨_, _, _, mem, ?_⟩ + let H := someOctahedron rfl (t.triangleLTGE_distinguished n T.obj₁) hT mem + exact t.isGE₂ _ H.mem n (by dsimp; infer_instance) (by dsimp; infer_instance) + +lemma isIso₂_truncGE_map_of_isLE (T : Triangle C) (hT : T ∈ distTriang C) + (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) (h₁ : t.IsLE T.obj₁ n₀) : + IsIso ((t.truncGE n₁).map T.mor₂) := by + rw [isIso_truncGE_map_iff _ _ _ _ h] + obtain ⟨X, f, k, mem⟩ := distinguished_cocone_triangle₁ (T.mor₂ ≫ (t.truncGEπ n₁).app T.obj₃) + refine ⟨_, _, _, mem, ?_⟩ + subst h + have H := someOctahedron rfl (rot_of_distTriang _ hT) + (rot_of_distTriang _ (t.triangleLTGE_distinguished (n₀ + 1) T.obj₃)) + (rot_of_distTriang _ mem) + have : t.IsLE (X⟦(1 : ℤ)⟧) (n₀ - 1) := + t.isLE₂ _ H.mem (n₀ - 1) (t.isLE_shift T.obj₁ n₀ 1 (n₀ - 1) (by lia)) + (t.isLE_shift ((t.truncLT (n₀ + 1)).obj T.obj₃) n₀ 1 (n₀-1) (by lia)) + exact t.isLE_of_shift X n₀ 1 (n₀ - 1) (by lia) + +instance (X : C) (a b : ℤ) [t.IsGE X a] : + t.IsGE ((t.truncLT b).obj X) a := by + rw [t.isGE_iff_isZero_truncLT_obj] + have := t.isIso₁_truncLT_map_of_isGE _ ((t.triangleLTGE_distinguished b X)) a + (by dsimp; infer_instance) + dsimp at this + refine IsZero.of_iso ?_ (asIso ((t.truncLT a).map ((t.truncLTι b).app X))) + rwa [← isGE_iff_isZero_truncLT_obj] + +instance (X : C) (a b : ℤ) [t.IsLE X b] : t.IsLE ((t.truncGE a).obj X) b := by + rw [t.isLE_iff_isZero_truncGE_obj b (b + 1) rfl] + have := t.isIso₂_truncGE_map_of_isLE _ (t.triangleLTGE_distinguished a X) b _ rfl + (by dsimp; infer_instance) + dsimp at this + refine IsZero.of_iso ?_ (asIso ((t.truncGE (b + 1)).map ((t.truncGEπ a).app X))).symm + rwa [← isLE_iff_isZero_truncGE_obj _ _ _ rfl] + +instance (X : C) (a b : ℤ) : + t.IsLE ((t.truncGELT a b).obj X) (b - 1) := by + dsimp; infer_instance + +instance (X : C) (a b : ℤ) : + t.IsGE ((t.truncLTGE a b).obj X) a := by + dsimp; infer_instance + +lemma isIso_truncGE_map_truncGEπ_app (a b : ℤ) (h : b ≤ a) (X : C) : + IsIso ((t.truncGE a).map ((t.truncGEπ b).app X)) := + t.isIso₂_truncGE_map_of_isLE _ (t.triangleLTGE_distinguished b X) + (a - 1) a (by lia) (t.isLE_truncLT_obj _ _ _ (by simpa)) + +lemma isIso_truncLT_map_truncLTι_app (a b : ℤ) (h : a ≤ b) (X : C) : + IsIso ((t.truncLT a).map ((t.truncLTι b).app X)) := + t.isIso₁_truncLT_map_of_isGE _ (t.triangleLTGE_distinguished b X) a + (t.isGE_of_ge ((t.truncGE b).obj X) a b (by lia)) + +instance (X : C) (n : ℤ) : IsIso ((t.truncLT n).map ((t.truncLTι n).app X)) := + isIso_truncLT_map_truncLTι_app t _ _ (by rfl) X + +instance (X : C) (n : ℤ) : IsIso ((t.truncGE n).map ((t.truncGEπ n).app X)) := + t.isIso_truncGE_map_truncGEπ_app _ _ (by rfl) _ + +instance (a b : ℤ) (X : C) : + IsIso ((t.truncLTι b).app ((t.truncGE a).obj ((t.truncLT b).obj X))) := by + rw [← t.isLE_iff_isIso_truncLTι_app (b - 1) b (by lia)] + infer_instance + +/-- The natural transformation `t.truncGELT a b ⟶ t.truncLTGE a b` +(which is an isomorphism, see `truncGELTIsoLTGE`.) -/ +noncomputable def truncGELTToLTGE (a b : ℤ) : + t.truncGELT a b ⟶ t.truncLTGE a b where + app X := t.liftTruncLT (t.descTruncGE + ((t.truncLTι b).app X ≫ (t.truncGEπ a).app X) a) (b - 1) b (by lia) + naturality _ _ _ := + t.to_truncLT_obj_ext (by dsimp; exact t.from_truncGE_obj_ext (by simp)) + +@[reassoc (attr := simp)] +lemma truncGELTToLTGE_app_pentagon (a b : ℤ) (X : C) : + (t.truncGEπ a).app _ ≫ (t.truncGELTToLTGE a b).app X ≫ (t.truncLTι b).app _ = + (t.truncLTι b).app X ≫ (t.truncGEπ a).app X := by + simp [truncGELTToLTGE] + +lemma truncGELTToLTGE_app_pentagon_uniqueness {a b : ℤ} {X : C} + (φ : (t.truncGELT a b).obj X ⟶ (t.truncLTGE a b).obj X) + (hφ : (t.truncGEπ a).app _ ≫ φ ≫ (t.truncLTι b).app _ = + (t.truncLTι b).app X ≫ (t.truncGEπ a).app X) : + (t.truncGELTToLTGE a b).app X = φ := + t.to_truncLT_obj_ext (by dsimp; exact t.from_truncGE_obj_ext (by cat_disch)) + +@[reassoc] +lemma truncLT_map_truncGE_map_truncLTι_app_fac (a b : ℤ) (X : C) : + (t.truncLTι b).app ((t.truncGE a).obj ((t.truncLT b).obj X)) ≫ + (t.truncGELTToLTGE a b).app X = + (t.truncLT b).map ((t.truncGE a).map ((t.truncLTι b).app X)) := by + rw [← cancel_epi (inv ((t.truncLTι b).app ((t.truncGE a).obj ((t.truncLT b).obj X)))), + IsIso.inv_hom_id_assoc] + exact t.truncGELTToLTGE_app_pentagon_uniqueness _ (by simp) + +/-- The connecting homomorphism +`(t.truncGELT a b).obj X ⟶ ((t.truncLT a).obj X)⟦1⟧`, +as a natural transformation. -/ +@[expose, simps!] +noncomputable def truncGELTδLT (a b : ℤ) : + t.truncGELT a b ⟶ t.truncLT a ⋙ shiftFunctor C (1 : ℤ) := + Functor.whiskerLeft (t.truncLT b) (t.truncGEδLT a) ≫ + Functor.whiskerRight (t.truncLTι b) (t.truncLT a ⋙ shiftFunctor C (1 : ℤ)) + +/-- The functorial (distinguished) triangle +`(t.truncLT a).obj X ⟶ (t.truncLT b).obj X ⟶ (t.truncGELT a b).obj X ⟶ ...` +when `a ≤ b`. -/ +@[expose, simps!] +noncomputable def triangleLTLTGELT (a b : ℤ) (h : a ≤ b) : C ⥤ Triangle C := + Triangle.functorMk (t.natTransTruncLTOfLE a b h) + (Functor.whiskerLeft (t.truncLT b) (t.truncGEπ a)) (t.truncGELTδLT a b) + +lemma triangleLTLTGELT_distinguished (a b : ℤ) (h : a ≤ b) (X : C) : + (t.triangleLTLTGELT a b h).obj X ∈ distTriang C := by + have := t.isIso_truncLT_map_truncLTι_app a b h X + refine isomorphic_distinguished _ (t.triangleLTGE_distinguished a ((t.truncLT b).obj X)) _ ?_ + refine Triangle.isoMk _ _ ((asIso ((t.truncLT a).map ((t.truncLTι b).app X))).symm) + (Iso.refl _) (Iso.refl _) ?_ ?_ ?_ + · dsimp + simp only [Category.comp_id, IsIso.eq_inv_comp] + exact t.to_truncLT_obj_ext (by simp) + · simp + · simp + +instance (a b : ℤ) : IsIso (t.truncGELTToLTGE a b) := by + rw [NatTrans.isIso_iff_isIso_app] + intro X + by_cases h : a ≤ b + · let u₁₂ := (t.natTransTruncLTOfLE a b h).app X + let u₂₃ : (t.truncLT b).obj X ⟶ X := (t.truncLTι b).app X + let u₁₃ : _ ⟶ X := (t.truncLTι a).app X + have eq : u₁₂ ≫ u₂₃ = u₁₃ := by simp [u₁₂, u₂₃, u₁₃] + have H := someOctahedron eq (t.triangleLTLTGELT_distinguished a b h X) + (t.triangleLTGE_distinguished b X) (t.triangleLTGE_distinguished a X) + let m₁ : (t.truncGELT a b).obj X ⟶ _ := H.m₁ + have : IsIso ((t.truncLT b).map H.m₁) := + t.isIso₁_truncLT_map_of_isGE _ H.mem b (by dsimp; infer_instance) + have eq' : t.liftTruncLT m₁ (b - 1) b (by lia) = (t.truncGELTToLTGE a b).app X := + t.to_truncLT_obj_ext + (by dsimp; exact t.from_truncGE_obj_ext (by simpa using H.comm₁)) + rw [← eq'] + have fac : (t.truncLTι b).app ((t.truncGE a).obj ((t.truncLT b).obj X)) ≫ + t.liftTruncLT m₁ (b - 1) b (by lia) = (t.truncLT b).map m₁ := + t.to_truncLT_obj_ext (by simp [truncGELT]) + exact IsIso.of_isIso_fac_left fac + · simp at h + refine ⟨0, ?_, ?_⟩ + all_goals exact IsZero.eq_of_src (t.isZero _ (b-1) a (by lia)) _ _ + +instance (a b : ℤ) (X : C) : + IsIso ((t.truncLT b).map ((t.truncGE a).map ((t.truncLTι b).app X))) := by + rw [← t.truncLT_map_truncGE_map_truncLTι_app_fac a b X] + infer_instance + +/-- The natural transformation `t.truncGELT a b ≅ t.truncLTGE a b`. -/ +noncomputable def truncGELTIsoLTGE (a b : ℤ) : t.truncGELT a b ≅ t.truncLTGE a b := + asIso (t.truncGELTToLTGE a b) + +end + end end TStructure diff --git a/Mathlib/Order/Fin/Clamp.lean b/Mathlib/Order/Fin/Clamp.lean new file mode 100644 index 00000000000000..cbe5cfd1ab8208 --- /dev/null +++ b/Mathlib/Order/Fin/Clamp.lean @@ -0,0 +1,29 @@ +/- +Copyright (c) 2026 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +module + +public import Batteries.Data.Fin.Lemmas +public import Mathlib.Order.Fin.Basic +public import Mathlib.Order.MinMax + +/-! +# Lemmas about `Fin.clamp` + +-/ + +namespace Fin + +public lemma clamp_mono {m : ℕ} : Monotone (fun n ↦ clamp n m) := by + intro a b h + rw [le_iff_val_le_val] + exact min_le_min_right m h + +public lemma clamp_eq_last (n m : ℕ) (hnm : m ≤ n) : + clamp n m = last _ := by + ext + simpa + +end Fin