From f78f389b9932e49457ecfc4f80261db6433ad253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 24 Feb 2025 15:32:42 +0100 Subject: [PATCH 01/46] wip --- Mathlib.lean | 1 + .../Abelian/SerreClass/Localization.lean | 108 ++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean diff --git a/Mathlib.lean b/Mathlib.lean index 38465c0dd33734..856509da4371f8 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1728,6 +1728,7 @@ import Mathlib.CategoryTheory.Abelian.Projective.Resolution import Mathlib.CategoryTheory.Abelian.Pseudoelements import Mathlib.CategoryTheory.Abelian.Refinements import Mathlib.CategoryTheory.Abelian.RightDerived +import Mathlib.CategoryTheory.Abelian.SerreClass.Basic import Mathlib.CategoryTheory.Abelian.Subobject import Mathlib.CategoryTheory.Abelian.Transfer import Mathlib.CategoryTheory.Abelian.Yoneda diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean new file mode 100644 index 00000000000000..b732c60270bd9f --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -0,0 +1,108 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.Subobject.Lattice + +/-! +# Localization with respect to a Serre class + +-/ + +universe v u + +namespace CategoryTheory + +open Category Limits + +variable {C : Type u} [Category.{v} C] + +namespace Limits + +variable [HasZeroMorphisms C] + +lemma isZero_kernel_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] [HasKernel f] : + IsZero (kernel f) := by + rw [IsZero.iff_id_eq_zero, ← cancel_mono (kernel.ι f), ← cancel_mono f, + assoc, assoc, kernel.condition, comp_zero, zero_comp] + +lemma isZero_cokernel_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] [HasCokernel f] : + IsZero (cokernel f) := by + rw [IsZero.iff_id_eq_zero, ← cancel_epi (cokernel.π f), ← cancel_epi f, + cokernel.condition_assoc, zero_comp, comp_zero, comp_zero] + +end Limits + +variable [Abelian C] + +namespace SerreClass + +variable (c : SerreClass C) + +def W : MorphismProperty C := fun _ _ f ↦ c.prop (kernel f) ∧ c.prop (cokernel f) + +lemma W_iff_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] : c.W f ↔ c.prop (cokernel f) := by + dsimp [W] + have : c.prop (kernel f) := c.prop_of_isZero (isZero_kernel_of_mono f) + tauto + +lemma W_iff_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] : c.W f ↔ c.prop (kernel f) := by + dsimp [W] + have : c.prop (cokernel f) := c.prop_of_isZero (isZero_cokernel_of_epi f) + tauto + +lemma W_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hf : c.prop (cokernel f)) : c.W f := by + rwa [W_iff_of_mono] + +lemma W_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hf : c.prop (kernel f)) : c.W f := by + rwa [W_iff_of_epi] + +lemma W_of_isIso {X Y : C} (f : X ⟶ Y) [IsIso f] : c.W f := + c.W_of_epi _ (c.prop_of_isZero (isZero_kernel_of_mono f)) + +@[nolint unusedArguments] +structure Localization (c : SerreClass C) : Type u where + obj : C + +namespace Localization + +variable {c} + +structure Hom' (X Y : c.Localization) where + X' : C + Y' : C + i : X' ⟶ X.obj + [mono_i : Mono i] + hi : c.W i + p : Y.obj ⟶ Y' + [mono_p : Epi p] + hp : c.W p + f : X' ⟶ Y' + +namespace Hom' + +attribute [instance] mono_i mono_p + +noncomputable def ofHom {X Y : C} (f : X ⟶ Y ) : Hom' (.mk (c := c) X) (.mk Y) where + X' := X + Y' := Y + i := 𝟙 X + p := 𝟙 Y + f := f + hi := W_of_isIso c _ + hp := W_of_isIso c _ + +noncomputable def id (X : c.Localization) : Hom' X X := ofHom (𝟙 _) + +--def comp {X Y Z : c.Localization} (f : Hom' X Y) (g : Hom' Y Z) : Hom' X Z := sorry + + +end Hom' + +end Localization + +end SerreClass + +end CategoryTheory From 1809cad5ebb8ed2df99560d6a7b1e02912a4a62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 24 Feb 2025 15:53:26 +0100 Subject: [PATCH 02/46] wip --- Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index b732c60270bd9f..20ae6c014c5061 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.MorphismProperty.Composition import Mathlib.CategoryTheory.Subobject.Lattice /-! @@ -62,6 +63,9 @@ lemma W_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hf : c.prop (kernel f)) : c.W f lemma W_of_isIso {X Y : C} (f : X ⟶ Y) [IsIso f] : c.W f := c.W_of_epi _ (c.prop_of_isZero (isZero_kernel_of_mono f)) +instance : c.W.ContainsIdentities where + id_mem _ := c.W_of_isIso _ + @[nolint unusedArguments] structure Localization (c : SerreClass C) : Type u where obj : C From e4e391c5cd8d17118c246c74bef08357e9a9ad72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 24 Feb 2025 18:48:41 +0100 Subject: [PATCH 03/46] wip --- Mathlib.lean | 2 + .../DiagramLemmas/KernelCokernelComp.lean | 165 ++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean diff --git a/Mathlib.lean b/Mathlib.lean index 856509da4371f8..da22783ba10463 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1696,6 +1696,7 @@ import Mathlib.Analysis.VonNeumannAlgebra.Basic import Mathlib.CategoryTheory.Abelian.Basic import Mathlib.CategoryTheory.Abelian.CommSq import Mathlib.CategoryTheory.Abelian.DiagramLemmas.Four +import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp import Mathlib.CategoryTheory.Abelian.EpiWithInjectiveKernel import Mathlib.CategoryTheory.Abelian.Exact import Mathlib.CategoryTheory.Abelian.Ext @@ -1729,6 +1730,7 @@ import Mathlib.CategoryTheory.Abelian.Pseudoelements import Mathlib.CategoryTheory.Abelian.Refinements import Mathlib.CategoryTheory.Abelian.RightDerived import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.Abelian.SerreClass.Localization import Mathlib.CategoryTheory.Abelian.Subobject import Mathlib.CategoryTheory.Abelian.Transfer import Mathlib.CategoryTheory.Abelian.Yoneda diff --git a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean new file mode 100644 index 00000000000000..456e20fdc1befc --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean @@ -0,0 +1,165 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.Algebra.Homology.ShortComplex.SnakeLemma + +/-! +# Long exact sequence for the kernel and cokernel of a composition + +If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms in an +abelian category, we construct a long exact sequence : +`0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`. + +-/ + +universe v u + +namespace CategoryTheory + +open Limits Category + +variable {C : Type u} [Category.{v} C] [Abelian C] + {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) + +namespace kernelCokernelCompSequence + +@[simps (config := .lemmasOnly) L₁ L₂ v₁₂] +noncomputable def snakeInput : ShortComplex.SnakeInput C where + L₁_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct X Y).exact + L₂_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct Y Z).exact + v₁₂ := + { τ₁ := f + τ₂ := biprod.desc (f ≫ biprod.inl) (biprod.lift (-𝟙 Y) g) + τ₃ := g } + h₀ := kernelIsKernel _ + h₃ := cokernelIsCokernel _ + epi_L₁_g := by dsimp; infer_instance + mono_L₂_f := by dsimp; infer_instance + +@[simp] +lemma snakeInput_v₀₁ : (snakeInput f g).v₀₁ = kernel.ι ((snakeInput f g).v₁₂) := rfl + +@[simp] +lemma snakeInput_v₂₃ : (snakeInput f g).v₂₃ = cokernel.π ((snakeInput f g).v₁₂) := rfl + +attribute [simp] snakeInput_L₁ snakeInput_L₂ + +attribute [local simp] snakeInput_v₁₂ in +@[simps!] +noncomputable def kernelFork : KernelFork (snakeInput f g).v₁₂.τ₂ := + KernelFork.ofι (biprod.lift (kernel.ι (f ≫ g)) (kernel.ι _ ≫ f)) + (by aesop_cat) + +def isLimitKernelFork : IsLimit (kernelFork f g) := sorry + +@[simps!] +noncomputable def cokernelCofork : CokernelCofork (snakeInput f g).v₁₂.τ₂ := + CokernelCofork.ofπ (biprod.desc (g ≫ cokernel.π (f ≫ g)) (cokernel.π (f ≫ g))) + (by + dsimp [snakeInput_v₁₂] + ext + · simp only [biprod.inl_desc_assoc, assoc, biprod.inl_desc, comp_zero] + rw [← assoc, cokernel.condition] + · simp) + +def isColimitCokernelCofork : IsColimit (cokernelCofork f g) := sorry + +noncomputable def iso₀ : kernel f ≅ (snakeInput f g).L₀.X₁ := + (asIso (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₁)).symm + +noncomputable def iso₁' : kernel (f ≫ g) ≅ kernel (snakeInput f g).v₁₂.τ₂ := by + let e := IsLimit.conePointUniqueUpToIso (isLimitKernelFork f g) + (kernelIsKernel ((snakeInput f g).v₁₂.τ₂)) + exact e + +noncomputable def iso₁ : kernel (f ≫ g) ≅ (snakeInput f g).L₀.X₂ := + iso₁' f g ≪≫ (asIso (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₂)).symm + +noncomputable def iso₂ : kernel g ≅ (snakeInput f g).L₀.X₃ := + (asIso (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₃)).symm + +noncomputable def iso₃ : cokernel f ≅ (snakeInput f g).L₃.X₁ := + asIso (cokernelComparison (snakeInput f g).v₁₂ ShortComplex.π₁) + +def iso₄ : cokernel (f ≫ g) ≅ (snakeInput f g).L₃.X₂ := sorry + +noncomputable def iso₅ : cokernel g ≅ (snakeInput f g).L₃.X₃ := + asIso (cokernelComparison (snakeInput f g).v₁₂ ShortComplex.π₃) + +noncomputable def δ : kernel g ⟶ cokernel f := + (iso₂ f g).hom ≫ (snakeInput f g).δ ≫ (iso₃ f g).inv + +@[reassoc (attr := simp)] +lemma comm₀₁' : + kernel.map f (f ≫ g) (𝟙 X) g (by simp) ≫ (iso₁' f g).hom = + kernel.map _ _ biprod.inl biprod.inl (by simp [snakeInput_v₁₂]) := by + have := IsLimit.conePointUniqueUpToIso_hom_comp (isLimitKernelFork f g) + (kernelIsKernel ((snakeInput f g).v₁₂.τ₂)) .zero + dsimp [kernelFork] at this ⊢ + rw [← cancel_mono (kernel.ι _), assoc, kernel.lift_ι, iso₁', this] + aesop + +@[reassoc (attr := simp)] +lemma comm₀₁ : + kernel.map f (f ≫ g) (𝟙 X) g (by simp) ≫ (iso₁ f g).hom = + (iso₀ f g).hom ≫ (snakeInput f g).L₀.f := by + have h₁ := kernelComparison_comp_ι (snakeInput f g).v₁₂ ShortComplex.π₂ + have h₂ := (snakeInput f g).v₀₁.comm₁₂ + dsimp at h₁ h₂ + dsimp only [iso₁, Iso.trans, Iso.symm, asIso_inv] + rw [← cancel_mono (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₂)] + dsimp + rw [comm₀₁'_assoc, assoc, assoc, IsIso.inv_hom_id, comp_id, + ← cancel_mono (kernel.ι _), kernel.lift_ι, assoc, assoc, h₁, ← h₂] + rw [← assoc] + congr 1 + dsimp [iso₀] + rw [IsIso.eq_inv_comp] + apply kernelComparison_comp_ι + +@[reassoc (attr := simp)] +lemma comm₁₂ : + kernel.map (f ≫ g) g f (𝟙 _) (by simp) ≫ (iso₂ f g).hom = + (iso₁ f g).hom ≫ (snakeInput f g).L₀.g := sorry + +@[reassoc (attr := simp)] +lemma comm₂₃ : + δ f g ≫ (iso₃ f g).hom = + (iso₂ f g).hom ≫ (snakeInput f g).δ := by + simp [δ] + +@[reassoc (attr := simp)] +lemma comm₃₄ : + cokernel.map f (f ≫ g) (𝟙 X) g (by simp) ≫ (iso₄ f g).hom = + (iso₃ f g).hom ≫ (snakeInput f g).L₃.f := sorry + +@[reassoc (attr := simp)] +lemma comm₄₅ : + cokernel.map (f ≫ g) g f (𝟙 _) (by simp) ≫ (iso₅ f g).hom = + (iso₄ f g).hom ≫ (snakeInput f g).L₃.g := sorry + +end kernelCokernelCompSequence + +open kernelCokernelCompSequence + +noncomputable abbrev kernelCokernelCompSequence : ComposableArrows C 5 := + .mk₅ (kernel.map f (f ≫ g) (𝟙 _) g (by simp)) + (kernel.map (f ≫ g) g f (𝟙 _) (by simp)) + (δ f g) + (cokernel.map f (f ≫ g) (𝟙 _) g (by simp)) + (cokernel.map (f ≫ g) g f (𝟙 _) (by simp)) + +attribute [local simp] ComposableArrows.Precomp.map + +noncomputable def kernelCokernelCompSequence.iso : + kernelCokernelCompSequence f g ≅ (snakeInput f g).composableArrows := + ComposableArrows.isoMk₅ (iso₀ _ _) (iso₁ _ _) (iso₂ _ _) (iso₃ _ _) (iso₄ _ _) (iso₅ _ _) + (by simp) (by simp) (by simp) (by simp) (by simp) + +lemma kernelCokernelCompSequence_exact : + (kernelCokernelCompSequence f g).Exact := + ComposableArrows.exact_of_iso (iso f g).symm (snakeInput f g).snake_lemma + +end CategoryTheory From 75adabd21e99182df4b70458a4e527d93c2abbb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 24 Feb 2025 21:15:58 +0100 Subject: [PATCH 04/46] wip --- .../DiagramLemmas/KernelCokernelComp.lean | 268 +++++++++++------- 1 file changed, 166 insertions(+), 102 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean index 456e20fdc1befc..9ee342627c6982 100644 --- a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean +++ b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean @@ -12,138 +12,202 @@ If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms in an abelian category, we construct a long exact sequence : `0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`. +This is obtained by applying the snake lemma to the following morphism of +exact sequences, where the rows are the obvious split exact sequences +``` +0 ⟶ X ⟶ X ⊞ Y ⟶ Y ⟶ 0 + |f |φ |g + v v v +0 ⟶ Y ⟶ Y ⊞ Z ⟶ Z ⟶ 0 +``` +and `φ` is given by the following matrix: +``` +(f -𝟙 Y) +(0 g) +``` + +Indeed the snake lemma gives an exact sequence involving the kernels and cokernels +of the vertical maps: in order to get the expected long exact sequence, it suffices +to obtain isomorphisms `ker φ ≅ ker (f ≫ g)` and `coker φ ≅ coker (f ⋙ g)`. + -/ universe v u namespace CategoryTheory -open Limits Category +open Limits Category Preadditive variable {C : Type u} [Category.{v} C] [Abelian C] {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) -namespace kernelCokernelCompSequence +lemma Limits.biprod.decompose_hom_to (f : X ⟶ Y ⊞ Z) : + ∃ f₁ f₂, f = f₁ ≫ biprod.inl + f₂ ≫ biprod.inr := + ⟨f ≫ biprod.fst, f ≫ biprod.snd, by aesop⟩ -@[simps (config := .lemmasOnly) L₁ L₂ v₁₂] -noncomputable def snakeInput : ShortComplex.SnakeInput C where - L₁_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct X Y).exact - L₂_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct Y Z).exact - v₁₂ := - { τ₁ := f - τ₂ := biprod.desc (f ≫ biprod.inl) (biprod.lift (-𝟙 Y) g) - τ₃ := g } - h₀ := kernelIsKernel _ - h₃ := cokernelIsCokernel _ - epi_L₁_g := by dsimp; infer_instance - mono_L₂_f := by dsimp; infer_instance - -@[simp] -lemma snakeInput_v₀₁ : (snakeInput f g).v₀₁ = kernel.ι ((snakeInput f g).v₁₂) := rfl - -@[simp] -lemma snakeInput_v₂₃ : (snakeInput f g).v₂₃ = cokernel.π ((snakeInput f g).v₁₂) := rfl - -attribute [simp] snakeInput_L₁ snakeInput_L₂ - -attribute [local simp] snakeInput_v₁₂ in -@[simps!] -noncomputable def kernelFork : KernelFork (snakeInput f g).v₁₂.τ₂ := - KernelFork.ofι (biprod.lift (kernel.ι (f ≫ g)) (kernel.ι _ ≫ f)) - (by aesop_cat) - -def isLimitKernelFork : IsLimit (kernelFork f g) := sorry - -@[simps!] -noncomputable def cokernelCofork : CokernelCofork (snakeInput f g).v₁₂.τ₂ := - CokernelCofork.ofπ (biprod.desc (g ≫ cokernel.π (f ≫ g)) (cokernel.π (f ≫ g))) - (by - dsimp [snakeInput_v₁₂] - ext - · simp only [biprod.inl_desc_assoc, assoc, biprod.inl_desc, comp_zero] - rw [← assoc, cokernel.condition] - · simp) - -def isColimitCokernelCofork : IsColimit (cokernelCofork f g) := sorry +lemma Limits.biprod.ext_to_iff {f g : X ⟶ Y ⊞ Z} : + f = g ↔ f ≫ biprod.fst = g ≫ biprod.fst ∧ f ≫ biprod.snd = g ≫ biprod.snd := by + aesop -noncomputable def iso₀ : kernel f ≅ (snakeInput f g).L₀.X₁ := - (asIso (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₁)).symm +lemma Limits.biprod.decompose_hom_from (f : X ⊞ Y ⟶ Z) : + ∃ f₁ f₂, f = biprod.fst ≫ f₁ + biprod.snd ≫ f₂ := + ⟨biprod.inl ≫ f, biprod.inr ≫ f, by aesop⟩ -noncomputable def iso₁' : kernel (f ≫ g) ≅ kernel (snakeInput f g).v₁₂.τ₂ := by - let e := IsLimit.conePointUniqueUpToIso (isLimitKernelFork f g) - (kernelIsKernel ((snakeInput f g).v₁₂.τ₂)) - exact e +lemma Limits.biprod.ext_from_iff {f g : X ⊞ Y ⟶ Z} : + f = g ↔ biprod.inl ≫ f = biprod.inl ≫ g ∧ biprod.inr ≫ f = biprod.inr ≫ g := by + aesop -noncomputable def iso₁ : kernel (f ≫ g) ≅ (snakeInput f g).L₀.X₂ := - iso₁' f g ≪≫ (asIso (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₂)).symm +namespace kernelCokernelCompSequence -noncomputable def iso₂ : kernel g ≅ (snakeInput f g).L₀.X₃ := - (asIso (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₃)).symm +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +this is the morphism `kernel (f ≫ g) ⟶ X ⊞ Y` which +"sends `x` to `(x, f(x))`". -/ +noncomputable def ι : kernel (f ≫ g) ⟶ X ⊞ Y := + biprod.lift (kernel.ι (f ≫ g)) (kernel.ι (f ≫ g) ≫ f) -noncomputable def iso₃ : cokernel f ≅ (snakeInput f g).L₃.X₁ := - asIso (cokernelComparison (snakeInput f g).v₁₂ ShortComplex.π₁) +@[reassoc (attr := simp)] +lemma ι_fst : ι f g ≫ biprod.fst = kernel.ι (f ≫ g) := by simp [ι] -def iso₄ : cokernel (f ≫ g) ≅ (snakeInput f g).L₃.X₂ := sorry +@[reassoc (attr := simp)] +lemma ι_snd : ι f g ≫ biprod.snd = kernel.ι (f ≫ g) ≫ f := by simp [ι] + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +this is the morphism `X ⊞ Y ⟶ Y ⊞ Z` given by the matrix +``` +(f -𝟙 Y) +(0 g) +``` +-/ +noncomputable def φ : X ⊞ Y ⟶ Y ⊞ Z := + biprod.desc (f ≫ biprod.inl) (biprod.lift (-𝟙 Y) g) -noncomputable def iso₅ : cokernel g ≅ (snakeInput f g).L₃.X₃ := - asIso (cokernelComparison (snakeInput f g).v₁₂ ShortComplex.π₃) +@[reassoc (attr := simp)] +lemma inl_φ : biprod.inl ≫ φ f g = f ≫ biprod.inl := by simp [φ] -noncomputable def δ : kernel g ⟶ cokernel f := - (iso₂ f g).hom ≫ (snakeInput f g).δ ≫ (iso₃ f g).inv +@[reassoc (attr := simp)] +lemma inr_φ_fst : biprod.inr ≫ φ f g ≫ biprod.fst = - 𝟙 Y := by simp [φ] @[reassoc (attr := simp)] -lemma comm₀₁' : - kernel.map f (f ≫ g) (𝟙 X) g (by simp) ≫ (iso₁' f g).hom = - kernel.map _ _ biprod.inl biprod.inl (by simp [snakeInput_v₁₂]) := by - have := IsLimit.conePointUniqueUpToIso_hom_comp (isLimitKernelFork f g) - (kernelIsKernel ((snakeInput f g).v₁₂.τ₂)) .zero - dsimp [kernelFork] at this ⊢ - rw [← cancel_mono (kernel.ι _), assoc, kernel.lift_ι, iso₁', this] +lemma φ_snd : φ f g ≫ biprod.snd = biprod.snd ≫ g := by + dsimp [φ] aesop -@[reassoc (attr := simp)] -lemma comm₀₁ : - kernel.map f (f ≫ g) (𝟙 X) g (by simp) ≫ (iso₁ f g).hom = - (iso₀ f g).hom ≫ (snakeInput f g).L₀.f := by - have h₁ := kernelComparison_comp_ι (snakeInput f g).v₁₂ ShortComplex.π₂ - have h₂ := (snakeInput f g).v₀₁.comm₁₂ - dsimp at h₁ h₂ - dsimp only [iso₁, Iso.trans, Iso.symm, asIso_inv] - rw [← cancel_mono (kernelComparison (snakeInput f g).v₁₂ ShortComplex.π₂)] - dsimp - rw [comm₀₁'_assoc, assoc, assoc, IsIso.inv_hom_id, comp_id, - ← cancel_mono (kernel.ι _), kernel.lift_ι, assoc, assoc, h₁, ← h₂] - rw [← assoc] - congr 1 - dsimp [iso₀] - rw [IsIso.eq_inv_comp] - apply kernelComparison_comp_ι +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +this is the morphism `Y ⊞ Z ⟶ cokernel (f ≫ g)` which +"sends `(y, z)` to `[g(y)] + [z]`". -/ +noncomputable def π : Y ⊞ Z ⟶ cokernel (f ≫ g) := + biprod.desc (g ≫ cokernel.π (f ≫ g)) (cokernel.π (f ≫ g)) @[reassoc (attr := simp)] -lemma comm₁₂ : - kernel.map (f ≫ g) g f (𝟙 _) (by simp) ≫ (iso₂ f g).hom = - (iso₁ f g).hom ≫ (snakeInput f g).L₀.g := sorry +lemma inl_π : biprod.inl ≫ π f g = g ≫ cokernel.π (f ≫ g) := by simp [π] @[reassoc (attr := simp)] -lemma comm₂₃ : - δ f g ≫ (iso₃ f g).hom = - (iso₂ f g).hom ≫ (snakeInput f g).δ := by - simp [δ] +lemma inr_π : biprod.inr ≫ π f g = cokernel.π (f ≫ g) := by simp [π] @[reassoc (attr := simp)] -lemma comm₃₄ : - cokernel.map f (f ≫ g) (𝟙 X) g (by simp) ≫ (iso₄ f g).hom = - (iso₃ f g).hom ≫ (snakeInput f g).L₃.f := sorry +lemma ι_φ : ι f g ≫ φ f g = 0 := by + dsimp [ι, φ] + aesop @[reassoc (attr := simp)] -lemma comm₄₅ : - cokernel.map (f ≫ g) g f (𝟙 _) (by simp) ≫ (iso₅ f g).hom = - (iso₄ f g).hom ≫ (snakeInput f g).L₃.g := sorry +lemma φ_π : φ f g ≫ π f g = 0 := by + dsimp [φ, π] + ext + · rw [biprod.inl_desc_assoc, assoc, biprod.inl_desc, comp_zero, + ← assoc, cokernel.condition] + · simp + +instance : Mono (ι f g) := mono_of_mono_fac (ι_fst f g) + +instance : Epi (π f g) := epi_of_epi_fac (inr_π f g) + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +then the kernel of `φ f g : X ⊞ Y ⟶ Y ⊞ Z` identifies +to `kernel (f ≫ g)`. -/ +noncomputable def isLimit : IsLimit (KernelFork.ofι _ (ι_φ f g)) := + KernelFork.IsLimit.ofι' _ _ (fun {A} k hk ↦ by + refine ⟨kernel.lift _ (k ≫ biprod.fst) ?_, ?_⟩ + all_goals + obtain ⟨k₁, k₂, rfl⟩ := biprod.decompose_hom_to k + simp only [biprod.ext_to_iff, add_comp, assoc, inl_φ, BinaryBicone.inl_fst, + comp_id, inr_φ_fst, comp_neg, zero_comp, BinaryBicone.inl_snd, comp_zero, φ_snd, + BinaryBicone.inr_snd_assoc, zero_add, add_neg_eq_zero] at hk + obtain ⟨rfl, hk⟩ := hk + aesop) + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +then the cokernel of `φ f g : X ⊞ Y ⟶ Y ⊞ Z` identifies +to `cokernel (f ≫ g)`. -/ +noncomputable def isColimit : IsColimit (CokernelCofork.ofπ _ (φ_π f g)) := + CokernelCofork.IsColimit.ofπ' _ _ (fun {A} k hk ↦ by + refine ⟨cokernel.desc _ (biprod.inr ≫ k) ?_, ?_⟩ + all_goals + obtain ⟨k₁, k₂, rfl⟩ := biprod.decompose_hom_from k + simp only [comp_add, φ_snd_assoc, biprod.ext_from_iff, inl_φ_assoc, + BinaryBicone.inl_fst_assoc, BinaryBicone.inl_snd_assoc, zero_comp, add_zero, comp_zero, + inr_φ_fst_assoc, neg_comp, id_comp, BinaryBicone.inr_snd_assoc, neg_add_eq_zero] at hk + obtain ⟨hk, rfl⟩ := hk + aesop) + +/-- The "snake input" which gives the exact sequence +`0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`, +see `kernelCokernelCompSequence_exact`. -/ +@[simps] +noncomputable def snakeInput : ShortComplex.SnakeInput C where + L₀ := + { f := kernel.map f (f ≫ g) (𝟙 _) g (by simp) + g := kernel.map (f ≫ g) g f (𝟙 _) (by simp) + zero := by aesop } + L₁ := ShortComplex.mk (biprod.inl : X ⟶ _) (biprod.snd : _ ⟶ Y) (by simp) + L₂ := ShortComplex.mk (biprod.inl : Y ⟶ _) (biprod.snd : _ ⟶ Z) (by simp) + L₃ := + { f := cokernel.map f (f ≫ g) (𝟙 _) g (by simp) + g := cokernel.map (f ≫ g) g f (𝟙 _) (by simp) + zero := by aesop } + v₀₁ := + { τ₁ := kernel.ι f + τ₂ := ι f g + τ₃ := kernel.ι g } + v₁₂ := + { τ₁ := f + τ₂ := φ f g + τ₃ := g } + v₂₃ := + { τ₁ := cokernel.π f + τ₂ := π f g + τ₃ := cokernel.π g } + h₀ := by + apply ShortComplex.isLimitOfIsLimitπ <;> + apply (KernelFork.isLimitMapConeEquiv _ _).2 + · exact kernelIsKernel _ + · exact isLimit f g + · exact kernelIsKernel _ + h₃ := by + apply ShortComplex.isColimitOfIsColimitπ <;> + apply (CokernelCofork.isColimitMapCoconeEquiv _ _).2 + · exact cokernelIsCokernel _ + · exact isColimit f g + · exact cokernelIsCokernel _ + epi_L₁_g := by dsimp; infer_instance + mono_L₂_f := by dsimp; infer_instance + L₁_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct X Y).exact + L₂_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct Y Z).exact + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, this +is the connecting homomorphism `kernel g ⟶ cokernel f`. -/ +noncomputable def δ : kernel g ⟶ cokernel f := (snakeInput f g).δ + +lemma δ_fac : δ f g = - kernel.ι g ≫ cokernel.π f := by + simpa using (snakeInput f g).δ_eq (𝟙 _) (kernel.ι g ≫ biprod.inr) (-kernel.ι g) + (by simp) (by aesop) end kernelCokernelCompSequence open kernelCokernelCompSequence +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms in an +abelian category, this is the long exact sequence +`0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`. -/ noncomputable abbrev kernelCokernelCompSequence : ComposableArrows C 5 := .mk₅ (kernel.map f (f ≫ g) (𝟙 _) g (by simp)) (kernel.map (f ≫ g) g f (𝟙 _) (by simp)) @@ -151,15 +215,15 @@ noncomputable abbrev kernelCokernelCompSequence : ComposableArrows C 5 := (cokernel.map f (f ≫ g) (𝟙 _) g (by simp)) (cokernel.map (f ≫ g) g f (𝟙 _) (by simp)) -attribute [local simp] ComposableArrows.Precomp.map +instance : Mono ((kernelCokernelCompSequence f g).map' 0 1) := by + dsimp; infer_instance -noncomputable def kernelCokernelCompSequence.iso : - kernelCokernelCompSequence f g ≅ (snakeInput f g).composableArrows := - ComposableArrows.isoMk₅ (iso₀ _ _) (iso₁ _ _) (iso₂ _ _) (iso₃ _ _) (iso₄ _ _) (iso₅ _ _) - (by simp) (by simp) (by simp) (by simp) (by simp) +instance : Epi ((kernelCokernelCompSequence f g).map' 4 5) := by + dsimp [ComposableArrows.Precomp.map] + infer_instance lemma kernelCokernelCompSequence_exact : (kernelCokernelCompSequence f g).Exact := - ComposableArrows.exact_of_iso (iso f g).symm (snakeInput f g).snake_lemma + (snakeInput f g).snake_lemma end CategoryTheory From b137963674c2fb0cfdb657d8067e071b0e91ba69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 24 Feb 2025 21:30:44 +0100 Subject: [PATCH 05/46] feat(CategoryTheory): kernel and cokernel of a composition --- Mathlib.lean | 1 + .../DiagramLemmas/KernelCokernelComp.lean | 213 ++++++++++++++++++ .../Preadditive/Biproducts.lean | 22 ++ 3 files changed, 236 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean diff --git a/Mathlib.lean b/Mathlib.lean index 88b99becd46c33..ce3bd41b30affc 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1698,6 +1698,7 @@ import Mathlib.Analysis.VonNeumannAlgebra.Basic import Mathlib.CategoryTheory.Abelian.Basic import Mathlib.CategoryTheory.Abelian.CommSq import Mathlib.CategoryTheory.Abelian.DiagramLemmas.Four +import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp import Mathlib.CategoryTheory.Abelian.EpiWithInjectiveKernel import Mathlib.CategoryTheory.Abelian.Exact import Mathlib.CategoryTheory.Abelian.Ext diff --git a/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean new file mode 100644 index 00000000000000..c582498328e85a --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/DiagramLemmas/KernelCokernelComp.lean @@ -0,0 +1,213 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.Algebra.Homology.ShortComplex.SnakeLemma + +/-! +# Long exact sequence for the kernel and cokernel of a composition + +If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms in an +abelian category, we construct a long exact sequence : +`0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`. + +This is obtained by applying the snake lemma to the following morphism of +exact sequences, where the rows are the obvious split exact sequences +``` +0 ⟶ X ⟶ X ⊞ Y ⟶ Y ⟶ 0 + |f |φ |g + v v v +0 ⟶ Y ⟶ Y ⊞ Z ⟶ Z ⟶ 0 +``` +and `φ` is given by the following matrix: +``` +(f -𝟙 Y) +(0 g) +``` + +Indeed the snake lemma gives an exact sequence involving the kernels and cokernels +of the vertical maps: in order to get the expected long exact sequence, it suffices +to obtain isomorphisms `ker φ ≅ ker (f ≫ g)` and `coker φ ≅ coker (f ⋙ g)`. + +-/ + +universe v u + +namespace CategoryTheory + +open Limits Category Preadditive + +variable {C : Type u} [Category.{v} C] [Abelian C] + {X Y Z : C} (f : X ⟶ Y) (g : Y ⟶ Z) + +namespace kernelCokernelCompSequence + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +this is the morphism `kernel (f ≫ g) ⟶ X ⊞ Y` which +"sends `x` to `(x, f(x))`". -/ +noncomputable def ι : kernel (f ≫ g) ⟶ X ⊞ Y := + biprod.lift (kernel.ι (f ≫ g)) (kernel.ι (f ≫ g) ≫ f) + +@[reassoc (attr := simp)] +lemma ι_fst : ι f g ≫ biprod.fst = kernel.ι (f ≫ g) := by simp [ι] + +@[reassoc (attr := simp)] +lemma ι_snd : ι f g ≫ biprod.snd = kernel.ι (f ≫ g) ≫ f := by simp [ι] + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +this is the morphism `X ⊞ Y ⟶ Y ⊞ Z` given by the matrix +``` +(f -𝟙 Y) +(0 g) +``` +-/ +noncomputable def φ : X ⊞ Y ⟶ Y ⊞ Z := + biprod.desc (f ≫ biprod.inl) (biprod.lift (-𝟙 Y) g) + +@[reassoc (attr := simp)] +lemma inl_φ : biprod.inl ≫ φ f g = f ≫ biprod.inl := by simp [φ] + +@[reassoc (attr := simp)] +lemma inr_φ_fst : biprod.inr ≫ φ f g ≫ biprod.fst = - 𝟙 Y := by simp [φ] + +@[reassoc (attr := simp)] +lemma φ_snd : φ f g ≫ biprod.snd = biprod.snd ≫ g := by + dsimp [φ] + aesop + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +this is the morphism `Y ⊞ Z ⟶ cokernel (f ≫ g)` which +"sends `(y, z)` to `[g(y)] + [z]`". -/ +noncomputable def π : Y ⊞ Z ⟶ cokernel (f ≫ g) := + biprod.desc (g ≫ cokernel.π (f ≫ g)) (cokernel.π (f ≫ g)) + +@[reassoc (attr := simp)] +lemma inl_π : biprod.inl ≫ π f g = g ≫ cokernel.π (f ≫ g) := by simp [π] + +@[reassoc (attr := simp)] +lemma inr_π : biprod.inr ≫ π f g = cokernel.π (f ≫ g) := by simp [π] + +@[reassoc (attr := simp)] +lemma ι_φ : ι f g ≫ φ f g = 0 := by + dsimp [ι, φ] + aesop + +@[reassoc (attr := simp)] +lemma φ_π : φ f g ≫ π f g = 0 := by + dsimp [φ, π] + ext + · rw [biprod.inl_desc_assoc, assoc, biprod.inl_desc, comp_zero, + ← assoc, cokernel.condition] + · simp + +instance : Mono (ι f g) := mono_of_mono_fac (ι_fst f g) + +instance : Epi (π f g) := epi_of_epi_fac (inr_π f g) + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +then the kernel of `φ f g : X ⊞ Y ⟶ Y ⊞ Z` identifies +to `kernel (f ≫ g)`. -/ +noncomputable def isLimit : IsLimit (KernelFork.ofι _ (ι_φ f g)) := + KernelFork.IsLimit.ofι' _ _ (fun {A} k hk ↦ by + refine ⟨kernel.lift _ (k ≫ biprod.fst) ?_, ?_⟩ + all_goals + obtain ⟨k₁, k₂, rfl⟩ := biprod.decomp_hom_to k + simp only [biprod.ext_to_iff, add_comp, assoc, inl_φ, BinaryBicone.inl_fst, + comp_id, inr_φ_fst, comp_neg, zero_comp, BinaryBicone.inl_snd, comp_zero, φ_snd, + BinaryBicone.inr_snd_assoc, zero_add, add_neg_eq_zero] at hk + obtain ⟨rfl, hk⟩ := hk + aesop) + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, +then the cokernel of `φ f g : X ⊞ Y ⟶ Y ⊞ Z` identifies +to `cokernel (f ≫ g)`. -/ +noncomputable def isColimit : IsColimit (CokernelCofork.ofπ _ (φ_π f g)) := + CokernelCofork.IsColimit.ofπ' _ _ (fun {A} k hk ↦ by + refine ⟨cokernel.desc _ (biprod.inr ≫ k) ?_, ?_⟩ + all_goals + obtain ⟨k₁, k₂, rfl⟩ := biprod.decomp_hom_from k + simp only [comp_add, φ_snd_assoc, biprod.ext_from_iff, inl_φ_assoc, + BinaryBicone.inl_fst_assoc, BinaryBicone.inl_snd_assoc, zero_comp, add_zero, comp_zero, + inr_φ_fst_assoc, neg_comp, id_comp, BinaryBicone.inr_snd_assoc, neg_add_eq_zero] at hk + obtain ⟨hk, rfl⟩ := hk + aesop) + +/-- The "snake input" which gives the exact sequence +`0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`, +see `kernelCokernelCompSequence_exact`. -/ +@[simps] +noncomputable def snakeInput : ShortComplex.SnakeInput C where + L₀ := + { f := kernel.map f (f ≫ g) (𝟙 _) g (by simp) + g := kernel.map (f ≫ g) g f (𝟙 _) (by simp) + zero := by aesop } + L₁ := ShortComplex.mk (biprod.inl : X ⟶ _) (biprod.snd : _ ⟶ Y) (by simp) + L₂ := ShortComplex.mk (biprod.inl : Y ⟶ _) (biprod.snd : _ ⟶ Z) (by simp) + L₃ := + { f := cokernel.map f (f ≫ g) (𝟙 _) g (by simp) + g := cokernel.map (f ≫ g) g f (𝟙 _) (by simp) + zero := by aesop } + v₀₁ := + { τ₁ := kernel.ι f + τ₂ := ι f g + τ₃ := kernel.ι g } + v₁₂ := + { τ₁ := f + τ₂ := φ f g + τ₃ := g } + v₂₃ := + { τ₁ := cokernel.π f + τ₂ := π f g + τ₃ := cokernel.π g } + h₀ := by + apply ShortComplex.isLimitOfIsLimitπ <;> + apply (KernelFork.isLimitMapConeEquiv _ _).2 + · exact kernelIsKernel _ + · exact isLimit f g + · exact kernelIsKernel _ + h₃ := by + apply ShortComplex.isColimitOfIsColimitπ <;> + apply (CokernelCofork.isColimitMapCoconeEquiv _ _).2 + · exact cokernelIsCokernel _ + · exact isColimit f g + · exact cokernelIsCokernel _ + epi_L₁_g := by dsimp; infer_instance + mono_L₂_f := by dsimp; infer_instance + L₁_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct X Y).exact + L₂_exact := (ShortComplex.Splitting.ofHasBinaryBiproduct Y Z).exact + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms, this +is the connecting homomorphism `kernel g ⟶ cokernel f`. -/ +noncomputable def δ : kernel g ⟶ cokernel f := (snakeInput f g).δ + +lemma δ_fac : δ f g = - kernel.ι g ≫ cokernel.π f := by + simpa using (snakeInput f g).δ_eq (𝟙 _) (kernel.ι g ≫ biprod.inr) (-kernel.ι g) + (by simp) (by aesop) + +end kernelCokernelCompSequence + +open kernelCokernelCompSequence + +/-- If `f : X ⟶ Y` and `g : Y ⟶ Z` are composable morphisms in an +abelian category, this is the long exact sequence +`0 ⟶ ker f ⟶ ker (f ≫ g) ⟶ ker g ⟶ coker f ⟶ coker (f ≫ g) ⟶ coker g ⟶ 0`. -/ +noncomputable abbrev kernelCokernelCompSequence : ComposableArrows C 5 := + .mk₅ (kernel.map f (f ≫ g) (𝟙 _) g (by simp)) + (kernel.map (f ≫ g) g f (𝟙 _) (by simp)) + (δ f g) + (cokernel.map f (f ≫ g) (𝟙 _) g (by simp)) + (cokernel.map (f ≫ g) g f (𝟙 _) (by simp)) + +instance : Mono ((kernelCokernelCompSequence f g).map' 0 1) := by + dsimp; infer_instance + +instance : Epi ((kernelCokernelCompSequence f g).map' 4 5) := by + dsimp [ComposableArrows.Precomp.map] + infer_instance + +lemma kernelCokernelCompSequence_exact : + (kernelCokernelCompSequence f g).Exact := + (snakeInput f g).snake_lemma + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean index b851909f82c197..4975a4249b34da 100644 --- a/Mathlib/CategoryTheory/Preadditive/Biproducts.lean +++ b/Mathlib/CategoryTheory/Preadditive/Biproducts.lean @@ -445,6 +445,28 @@ theorem biprod.map_eq [HasBinaryBiproducts C] {W X Y Z : C} {f : W ⟶ Y} {g : X biprod.map f g = biprod.fst ≫ f ≫ biprod.inl + biprod.snd ≫ g ≫ biprod.inr := by ext <;> simp +section + +variable {Z : C} + +lemma biprod.decomp_hom_to (f : Z ⟶ X ⊞ Y) : + ∃ f₁ f₂, f = f₁ ≫ biprod.inl + f₂ ≫ biprod.inr := + ⟨f ≫ biprod.fst, f ≫ biprod.snd, by aesop⟩ + +lemma biprod.ext_to_iff {f g : Z ⟶ X ⊞ Y} : + f = g ↔ f ≫ biprod.fst = g ≫ biprod.fst ∧ f ≫ biprod.snd = g ≫ biprod.snd := by + aesop + +lemma biprod.decomp_hom_from (f : X ⊞ Y ⟶ Z) : + ∃ f₁ f₂, f = biprod.fst ≫ f₁ + biprod.snd ≫ f₂ := + ⟨biprod.inl ≫ f, biprod.inr ≫ f, by aesop⟩ + +lemma biprod.ext_from_iff {f g : X ⊞ Y ⟶ Z} : + f = g ↔ biprod.inl ≫ f = biprod.inl ≫ g ∧ biprod.inr ≫ f = biprod.inr ≫ g := by + aesop + +end + /-- Every split mono `f` with a cokernel induces a binary bicone with `f` as its `inl` and the cokernel map as its `snd`. We will show in `is_bilimit_binary_bicone_of_split_mono_of_cokernel` that this binary bicone is in From 07add15ddf66817dc877f9961ef7b5cd8a527857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 12:46:11 +0100 Subject: [PATCH 06/46] wip --- .../Abelian/SerreClass/Localization.lean | 113 ++++++++++++++---- 1 file changed, 91 insertions(+), 22 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 20ae6c014c5061..946ed69121c815 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp import Mathlib.CategoryTheory.MorphismProperty.Composition +import Mathlib.CategoryTheory.MorphismProperty.Retract import Mathlib.CategoryTheory.Subobject.Lattice /-! @@ -63,8 +65,24 @@ lemma W_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hf : c.prop (kernel f)) : c.W f lemma W_of_isIso {X Y : C} (f : X ⟶ Y) [IsIso f] : c.W f := c.W_of_epi _ (c.prop_of_isZero (isZero_kernel_of_mono f)) -instance : c.W.ContainsIdentities where +instance : c.W.IsMultiplicative where id_mem _ := c.W_of_isIso _ + comp_mem f g hf hg := + ⟨c.prop_of_exact ((kernelCokernelCompSequence_exact f g).exact 0) hf.1 hg.1, + c.prop_of_exact ((kernelCokernelCompSequence_exact f g).exact 3) hf.2 hg.2⟩ + +instance : c.W.HasTwoOutOfThreeProperty where + of_postcomp f g hg hfg := + ⟨c.prop_of_mono (kernel.map f (f ≫ g) (𝟙 _) g (by simp)) hfg.1, + c.prop_of_exact ((kernelCokernelCompSequence_exact f g).exact 2) hg.1 hfg.2⟩ + of_precomp f g hf hfg := + ⟨c.prop_of_exact ((kernelCokernelCompSequence_exact f g).exact 1) hfg.1 hf.2, + c.prop_of_epi (cokernel.map (f ≫ g) g f (𝟙 _) (by simp)) hfg.2⟩ + +instance : c.W.IsStableUnderRetracts where + of_retract {X' Y' X Y} f' f h hf := + ⟨c.prop_of_mono (kernel.map f' f h.left.i h.right.i (by simp)) hf.1, + c.prop_of_epi (cokernel.map f f' h.left.r h.right.r (by simp)) hf.2⟩ @[nolint unusedArguments] structure Localization (c : SerreClass C) : Type u where @@ -72,38 +90,89 @@ structure Localization (c : SerreClass C) : Type u where namespace Localization -variable {c} +variable {c} (X Y : c.Localization) -structure Hom' (X Y : c.Localization) where - X' : C - Y' : C - i : X' ⟶ X.obj +namespace Hom + +structure DefDomain where + src : C + i : src ⟶ X.obj [mono_i : Mono i] hi : c.W i - p : Y.obj ⟶ Y' - [mono_p : Epi p] + tgt : C + p : Y.obj ⟶ tgt + [epi_p : Epi p] hp : c.W p - f : X' ⟶ Y' -namespace Hom' +namespace DefDomain + +attribute [instance] mono_i epi_p + +variable {X Y} (d₁ d₂ d₃ : DefDomain X Y) + +structure Hom where + ι : d₁.src ⟶ d₂.src + ι_i : ι ≫ d₂.i = d₁.i := by aesop_cat + π : d₂.tgt ⟶ d₁.tgt + p_π : d₂.p ≫ π = d₁.p := by aesop_cat + +namespace Hom + +attribute [reassoc (attr := simp)] ι_i p_π + +@[simps] +def id (d : DefDomain X Y) : Hom d d where + ι := 𝟙 _ + π := 𝟙 _ + +variable {d₁ d₂ d₃} in +@[simps] +def comp (φ : Hom d₁ d₂) (ψ : Hom d₂ d₃) : Hom d₁ d₃ where + ι := φ.ι ≫ ψ.ι + π := ψ.π ≫ φ.π + +variable (φ : Hom d₁ d₂) + +instance : Mono φ.ι := mono_of_mono_fac φ.ι_i + +instance : Epi φ.π := epi_of_epi_fac φ.p_π + +instance : Subsingleton (Hom d₁ d₂) where + allEq φ ψ := by + suffices φ.ι = ψ.ι ∧ φ.π = ψ.π by cases φ; cases ψ; aesop + constructor + · simp [← cancel_mono d₂.i] + · simp [← cancel_epi d₂.p] -attribute [instance] mono_i mono_p +instance : Category (DefDomain X Y) where + id := Hom.id + comp := Hom.comp -noncomputable def ofHom {X Y : C} (f : X ⟶ Y ) : Hom' (.mk (c := c) X) (.mk Y) where - X' := X - Y' := Y - i := 𝟙 X - p := 𝟙 Y - f := f - hi := W_of_isIso c _ - hp := W_of_isIso c _ +end Hom -noncomputable def id (X : c.Localization) : Hom' X X := ofHom (𝟙 _) +lemma exists_min (d₁ d₂ : DefDomain X Y) : + ∃ (d : DefDomain X Y), Nonempty (d ⟶ d₁) ∧ Nonempty (d ⟶ d₂) := by + let d : DefDomain X Y := + { src := pullback d₁.i d₂.i + i := pullback.fst _ _ ≫ d₁.i + hi := by + refine MorphismProperty.comp_mem _ _ _ ?_ d₁.hi + sorry + tgt := pushout d₁.p d₂.p + p := d₁.p ≫ pushout.inl _ _ + hp := by + refine MorphismProperty.comp_mem _ _ _ d₁.hp ?_ + sorry } + refine ⟨d, ⟨{ ι := pullback.fst _ _, π := pushout.inl _ _ }⟩, ⟨ + { ι := pullback.snd _ _, + ι_i := pullback.condition.symm + π := pushout.inr _ _ + p_π := pushout.condition.symm }⟩⟩ ---def comp {X Y Z : c.Localization} (f : Hom' X Y) (g : Hom' Y Z) : Hom' X Z := sorry +end DefDomain -end Hom' +end Hom end Localization From 1e91204fccbf2b34dc6751a0261410614c266a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 12:57:21 +0100 Subject: [PATCH 07/46] feat(CategoryTheory/Abelian): Serre classes --- Mathlib.lean | 1 + .../Homology/ShortComplex/ShortExact.lean | 20 ++++ .../Abelian/SerreClass/Basic.lean | 102 ++++++++++++++++++ docs/references.bib | 16 +++ 4 files changed, 139 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean diff --git a/Mathlib.lean b/Mathlib.lean index 54fb5fb9f718cf..292dc27eb46c09 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1731,6 +1731,7 @@ import Mathlib.CategoryTheory.Abelian.Projective.Resolution import Mathlib.CategoryTheory.Abelian.Pseudoelements import Mathlib.CategoryTheory.Abelian.Refinements import Mathlib.CategoryTheory.Abelian.RightDerived +import Mathlib.CategoryTheory.Abelian.SerreClass.Basic import Mathlib.CategoryTheory.Abelian.Subobject import Mathlib.CategoryTheory.Abelian.Transfer import Mathlib.CategoryTheory.Abelian.Yoneda diff --git a/Mathlib/Algebra/Homology/ShortComplex/ShortExact.lean b/Mathlib/Algebra/Homology/ShortComplex/ShortExact.lean index d1c5e0307a8a69..c8a355754ec0e6 100644 --- a/Mathlib/Algebra/Homology/ShortComplex/ShortExact.lean +++ b/Mathlib/Algebra/Homology/ShortComplex/ShortExact.lean @@ -167,6 +167,26 @@ noncomputable def ShortExact.gIsCokernel [Balanced C] {S : ShortComplex C} (hS : have := hS.epi_g exact hS.exact.gIsCokernel +/-- Is `S` is an exact short complex and `h : S.HomologyData`, there is +a short exact sequence `0 ⟶ h.left.K ⟶ S.X₂ ⟶ h.right.Q ⟶ 0`. -/ +lemma Exact.shortExact {S : ShortComplex C} (hS : S.Exact) (h : S.HomologyData) : + (ShortComplex.mk _ _ (h.exact_iff_i_p_zero.1 hS)).ShortExact where + exact := by + have := hS.epi_f' h.left + have := hS.mono_g' h.right + let S' := ShortComplex.mk h.left.i S.g (by simp) + let S'' := ShortComplex.mk _ _ (h.exact_iff_i_p_zero.1 hS) + let a : S ⟶ S' := + { τ₁ := h.left.f' + τ₂ := 𝟙 _ + τ₃ := 𝟙 _ } + let b : S'' ⟶ S' := + { τ₁ := 𝟙 _ + τ₂ := 𝟙 _ + τ₃ := h.right.g' } + rwa [ShortComplex.exact_iff_of_epi_of_isIso_of_mono b, + ← ShortComplex.exact_iff_of_epi_of_isIso_of_mono a] + /-- A split short complex is short exact. -/ lemma Splitting.shortExact {S : ShortComplex C} [HasZeroObject C] (s : S.Splitting) : S.ShortExact where diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean new file mode 100644 index 00000000000000..dde60e8ffa213e --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean @@ -0,0 +1,102 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Abelian.Basic +import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.Algebra.Homology.ShortComplex.ShortExact + +/-! +# Serre classes + +For any abelian category `C`, we introduce the type `SerreClass C` of Serre classes in C +(also known as "Serre subcategories"). A Serre class consists of a predicate +on objects of `C` which holds for the zero object and is such that if +`0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` is a short exact sequence, then `X₂` belongs to the class +iff `X₁` and `X₃` do. This implies that the class is stable under subobjects, +quotients, extensions. As a result, if `X₁ ⟶ X₂ ⟶ X₃` is an exact sequence such +that `X₁` and `X₃` belong to the class, then so does `X₂` (see `SerreClass.prop_of_exact`). + +## Future works + +* Construct the localization of `C` with respect to a Serre class. + +-/ + +universe v u + +namespace CategoryTheory + +open Limits ZeroObject + +variable (C : Type u) [Category.{v} C] [Abelian C] + +/-- A Serre class in an abelian category consists of predicate which +is stable by subobject, quotient, extension and for the zero object. -/ +structure SerreClass where + /-- a predicate on objects -/ + prop : C → Prop + prop_zero : prop 0 + iff_of_shortExact {S : ShortComplex C} (hS : S.ShortExact) : + prop S.X₂ ↔ prop S.X₁ ∧ prop S.X₃ + +namespace SerreClass + +variable {C} (c : SerreClass C) + +section + +variable {S : ShortComplex C} (hS : S.ShortExact) + +include hS + +lemma prop_X₂_of_shortExact (h₁ : c.prop S.X₁) (h₃ : c.prop S.X₃) : c.prop S.X₂ := by + rw [c.iff_of_shortExact hS] + constructor <;> assumption + +lemma prop_X₁_of_shortExact (h₂ : c.prop S.X₂) : c.prop S.X₁ := by + rw [c.iff_of_shortExact hS] at h₂ + exact h₂.1 + +lemma prop_X₃_of_shortExact (h₂ : c.prop S.X₂) : c.prop S.X₃ := by + rw [c.iff_of_shortExact hS] at h₂ + exact h₂.2 + +end + +lemma prop_biprod {X₁ X₂ : C} (h₁ : c.prop X₁) (h₂ : c.prop X₂) : + c.prop (X₁ ⊞ X₂) := + c.prop_X₂_of_shortExact + (ShortComplex.Splitting.ofHasBinaryBiproduct X₁ X₂).shortExact h₁ h₂ + +lemma prop_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hY : c.prop Y) : c.prop X := by + have hS : (ShortComplex.mk _ _ (cokernel.condition f)).ShortExact := + { exact := ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel f) } + exact c.prop_X₁_of_shortExact hS hY + +lemma prop_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hX : c.prop X) : c.prop Y := by + have hS : (ShortComplex.mk _ _ (kernel.condition f)).ShortExact := + { exact := ShortComplex.exact_of_f_is_kernel _ (kernelIsKernel f) } + exact c.prop_X₃_of_shortExact hS hX + +lemma prop_iff_of_iso {X Y : C} (e : X ≅ Y) : c.prop X ↔ c.prop Y := + ⟨c.prop_of_epi e.hom, c.prop_of_mono e.hom⟩ + +instance : ClosedUnderIsomorphisms c.prop where + of_iso e hX := by rwa [← c.prop_iff_of_iso e] + +lemma prop_of_isZero {X : C} (hX : IsZero X) : c.prop X := by + simpa only [c.prop_iff_of_iso (hX.iso (isZero_zero _))] using c.prop_zero + +lemma prop_of_exact {S : ShortComplex C} (hS : S.Exact) + (h₁ : c.prop S.X₁) (h₃ : c.prop S.X₃) : c.prop S.X₂ := by + let d := S.homologyData + have := hS.epi_f' d.left + have := hS.mono_g' d.right + exact (c.prop_X₂_of_shortExact (hS.shortExact d) + (c.prop_of_epi d.left.f' h₁) (c.prop_of_mono d.right.g' h₃) :) + +end SerreClass + +end CategoryTheory diff --git a/docs/references.bib b/docs/references.bib index b7b2a878c7f38a..2c5ee075a80cc3 100644 --- a/docs/references.bib +++ b/docs/references.bib @@ -3501,6 +3501,22 @@ @Article{ serre1951 mrreviewer = {W. S. Massey} } +@Article{ serre1958, + author = {Serre, Jean-Pierre}, + title = {Groupes d'homotopie et classes de groupes ab\'eliens}, + journal = {Ann. of Math. (2)}, + fjournal = {Annals of Mathematics. Second Series}, + volume = {58}, + year = {1953}, + pages = {258--294}, + issn = {0003-486X}, + mrclass = {56.0X}, + mrnumber = {59548}, + mrreviewer = {W.\ S.\ Massey}, + doi = {10.2307/1969789}, + url = {https://doi.org/10.2307/1969789} +} + @Book{ serre1965, author = {Serre, Jean-Pierre}, title = {Complex semisimple {L}ie algebras}, From d7bf1dad44ca5cbdcb0887e95ca29aef82829f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 12:59:26 +0100 Subject: [PATCH 08/46] reference --- Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean index dde60e8ffa213e..c1fbb7069b9129 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean @@ -20,7 +20,11 @@ that `X₁` and `X₃` belong to the class, then so does `X₂` (see `SerreClass ## Future works -* Construct the localization of `C` with respect to a Serre class. +* Show that the localization of `C` with respect to a Serre class is an abelian category. + +## References + +* [Jean-Pierre Serre, *Groupes d'homotopie et classes de groupes abéliens*][serre1958] -/ From 4b40703617fb19cafd98df8931546abee38c6023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 14:21:58 +0100 Subject: [PATCH 09/46] refactor(CategoryTheory): introduce ObjectProperty --- Mathlib.lean | 3 +- .../Homology/DerivedCategory/Basic.lean | 2 +- .../ClosedUnderIsomorphisms.lean | 70 --------------- .../Limits/FullSubcategory.lean | 16 ++-- .../Limits/Indization/IndObject.lean | 4 +- .../Localization/Bousfield.lean | 8 +- .../CategoryTheory/ObjectProperty/Basic.lean | 23 +++++ .../ClosedUnderIsomorphisms.lean | 85 +++++++++++++++++++ Mathlib/CategoryTheory/Shift/Predicate.lean | 20 ++--- .../Triangulated/HomologicalFunctor.lean | 2 +- .../Triangulated/Subcategory.lean | 40 ++++----- .../Triangulated/TStructure/Basic.lean | 12 +-- 12 files changed, 162 insertions(+), 123 deletions(-) delete mode 100644 Mathlib/CategoryTheory/ClosedUnderIsomorphisms.lean create mode 100644 Mathlib/CategoryTheory/ObjectProperty/Basic.lean create mode 100644 Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean diff --git a/Mathlib.lean b/Mathlib.lean index 54fb5fb9f718cf..64e9edd7a312c4 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1819,7 +1819,6 @@ import Mathlib.CategoryTheory.Closed.Ideal import Mathlib.CategoryTheory.Closed.Monoidal import Mathlib.CategoryTheory.Closed.Types import Mathlib.CategoryTheory.Closed.Zero -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.CodiscreteCategory import Mathlib.CategoryTheory.CofilteredSystem import Mathlib.CategoryTheory.CommSq @@ -2217,6 +2216,8 @@ import Mathlib.CategoryTheory.MorphismProperty.TransfiniteComposition import Mathlib.CategoryTheory.NatIso import Mathlib.CategoryTheory.NatTrans import Mathlib.CategoryTheory.Noetherian +import Mathlib.CategoryTheory.ObjectProperty.Basic +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.Opposites import Mathlib.CategoryTheory.PEmpty import Mathlib.CategoryTheory.PUnit diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean index 7d2a7a5dbdb085..96a4f624a92e98 100644 --- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean +++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean @@ -75,7 +75,7 @@ of acyclic complexes. -/ def subcategoryAcyclic : Triangulated.Subcategory (HomotopyCategory C (ComplexShape.up ℤ)) := (homologyFunctor C (ComplexShape.up ℤ) 0).homologicalKernel -instance : ClosedUnderIsomorphisms (subcategoryAcyclic C).P := by +instance : (subcategoryAcyclic C).P.IsClosedUnderIsomorphisms := by dsimp [subcategoryAcyclic] infer_instance diff --git a/Mathlib/CategoryTheory/ClosedUnderIsomorphisms.lean b/Mathlib/CategoryTheory/ClosedUnderIsomorphisms.lean deleted file mode 100644 index 0435d3f5675728..00000000000000 --- a/Mathlib/CategoryTheory/ClosedUnderIsomorphisms.lean +++ /dev/null @@ -1,70 +0,0 @@ -/- -Copyright (c) 2024 Joël Riou. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Joël Riou --/ -import Mathlib.CategoryTheory.Iso -import Mathlib.Order.Basic - -/-! # Predicates on objects which are closed under isomorphisms - -This file introduces the type class `ClosedUnderIsomorphisms P` for predicates -`P : C → Prop` on the objects of a category `C`. - --/ - -namespace CategoryTheory - -variable {C : Type*} [Category C] (P Q : C → Prop) - -/-- A predicate `C → Prop` on the objects of a category is closed under isomorphisms -if whenever `P X`, then all the objects `Y` that are isomorphic to `X` also satisfy `P Y`. -/ -class ClosedUnderIsomorphisms : Prop where - of_iso {X Y : C} (_ : X ≅ Y) (_ : P X) : P Y - -lemma mem_of_iso [ClosedUnderIsomorphisms P] {X Y : C} (e : X ≅ Y) (hX : P X) : P Y := - ClosedUnderIsomorphisms.of_iso e hX - -lemma mem_iff_of_iso [ClosedUnderIsomorphisms P] {X Y : C} (e : X ≅ Y) : P X ↔ P Y := - ⟨mem_of_iso P e, mem_of_iso P e.symm⟩ - -lemma mem_of_isIso [ClosedUnderIsomorphisms P] {X Y : C} (f : X ⟶ Y) [IsIso f] (hX : P X) : P Y := - mem_of_iso P (asIso f) hX - -lemma mem_iff_of_isIso [ClosedUnderIsomorphisms P] {X Y : C} (f : X ⟶ Y) [IsIso f] : P X ↔ P Y := - mem_iff_of_iso P (asIso f) - -/-- The closure by isomorphisms of a predicate on objects in a category. -/ -def isoClosure : C → Prop := fun X => ∃ (Y : C) (_ : P Y), Nonempty (X ≅ Y) - -lemma mem_isoClosure_iff (X : C) : - isoClosure P X ↔ ∃ (Y : C) (_ : P Y), Nonempty (X ≅ Y) := by rfl - -variable {P} in -lemma mem_isoClosure {X Y : C} (h : P X) (e : X ⟶ Y) [IsIso e] : isoClosure P Y := - ⟨X, h, ⟨(asIso e).symm⟩⟩ - -lemma le_isoClosure : P ≤ isoClosure P := - fun X hX => ⟨X, hX, ⟨Iso.refl X⟩⟩ - -variable {P Q} in -lemma monotone_isoClosure (h : P ≤ Q) : isoClosure P ≤ isoClosure Q := by - rintro X ⟨X', hX', ⟨e⟩⟩ - exact ⟨X', h _ hX', ⟨e⟩⟩ - -lemma isoClosure_eq_self [ClosedUnderIsomorphisms P] : isoClosure P = P := by - apply le_antisymm - · intro X ⟨Y, hY, ⟨e⟩⟩ - exact mem_of_iso P e.symm hY - · exact le_isoClosure P - -lemma isoClosure_le_iff [ClosedUnderIsomorphisms Q] : isoClosure P ≤ Q ↔ P ≤ Q := - ⟨(le_isoClosure P).trans, - fun h => (monotone_isoClosure h).trans (by rw [isoClosure_eq_self])⟩ - -instance : ClosedUnderIsomorphisms (isoClosure P) where - of_iso := by - rintro X Y e ⟨Z, hZ, ⟨f⟩⟩ - exact ⟨Z, hZ, ⟨e.symm.trans f⟩⟩ - -end CategoryTheory diff --git a/Mathlib/CategoryTheory/Limits/FullSubcategory.lean b/Mathlib/CategoryTheory/Limits/FullSubcategory.lean index 11c03c8e182d83..3366113fda6f0c 100644 --- a/Mathlib/CategoryTheory/Limits/FullSubcategory.lean +++ b/Mathlib/CategoryTheory/Limits/FullSubcategory.lean @@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Markus Himmel -/ import Mathlib.CategoryTheory.Limits.Creates -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms /-! # Limits in full subcategories @@ -27,32 +27,32 @@ namespace CategoryTheory.Limits /-- We say that a property is closed under limits of shape `J` if whenever all objects in a `J`-shaped diagram have the property, any limit of this diagram also has the property. -/ def ClosedUnderLimitsOfShape {C : Type u} [Category.{v} C] (J : Type w) [Category.{w'} J] - (P : C → Prop) : Prop := + (P : ObjectProperty C) : Prop := ∀ ⦃F : J ⥤ C⦄ ⦃c : Cone F⦄ (_hc : IsLimit c), (∀ j, P (F.obj j)) → P c.pt /-- We say that a property is closed under colimits of shape `J` if whenever all objects in a `J`-shaped diagram have the property, any colimit of this diagram also has the property. -/ def ClosedUnderColimitsOfShape {C : Type u} [Category.{v} C] (J : Type w) [Category.{w'} J] - (P : C → Prop) : Prop := + (P : ObjectProperty C) : Prop := ∀ ⦃F : J ⥤ C⦄ ⦃c : Cocone F⦄ (_hc : IsColimit c), (∀ j, P (F.obj j)) → P c.pt section -variable {C : Type u} [Category.{v} C] {J : Type w} [Category.{w'} J] {P : C → Prop} +variable {C : Type u} [Category.{v} C] {J : Type w} [Category.{w'} J] {P : ObjectProperty C} -theorem closedUnderLimitsOfShape_of_limit [ClosedUnderIsomorphisms P] +theorem closedUnderLimitsOfShape_of_limit [P.IsClosedUnderIsomorphisms] (h : ∀ {F : J ⥤ C} [HasLimit F], (∀ j, P (F.obj j)) → P (limit F)) : ClosedUnderLimitsOfShape J P := by intros F c hc hF have : HasLimit F := ⟨_, hc⟩ - exact mem_of_iso P ((limit.isLimit _).conePointUniqueUpToIso hc) (h hF) + exact P.prop_of_iso ((limit.isLimit _).conePointUniqueUpToIso hc) (h hF) -theorem closedUnderColimitsOfShape_of_colimit [ClosedUnderIsomorphisms P] +theorem closedUnderColimitsOfShape_of_colimit [P.IsClosedUnderIsomorphisms] (h : ∀ {F : J ⥤ C} [HasColimit F], (∀ j, P (F.obj j)) → P (colimit F)) : ClosedUnderColimitsOfShape J P := by intros F c hc hF have : HasColimit F := ⟨_, hc⟩ - exact mem_of_iso P ((colimit.isColimit _).coconePointUniqueUpToIso hc) (h hF) + exact P.prop_of_iso ((colimit.isColimit _).coconePointUniqueUpToIso hc) (h hF) theorem ClosedUnderLimitsOfShape.limit (h : ClosedUnderLimitsOfShape J P) {F : J ⥤ C} [HasLimit F] : (∀ j, P (F.obj j)) → P (limit F) := diff --git a/Mathlib/CategoryTheory/Limits/Indization/IndObject.lean b/Mathlib/CategoryTheory/Limits/Indization/IndObject.lean index 8a152c96d37b84..c80072057c9e0e 100644 --- a/Mathlib/CategoryTheory/Limits/Indization/IndObject.lean +++ b/Mathlib/CategoryTheory/Limits/Indization/IndObject.lean @@ -6,7 +6,7 @@ Authors: Markus Himmel import Mathlib.CategoryTheory.Limits.FinallySmall import Mathlib.CategoryTheory.Limits.Presheaf import Mathlib.CategoryTheory.Filtered.Small -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.Limits.Preserves.Finite import Mathlib.CategoryTheory.Limits.Preserves.Presheaf @@ -141,7 +141,7 @@ theorem map {A B : Cᵒᵖ ⥤ Type v} (η : A ⟶ B) [IsIso η] : IsIndObject A theorem iff_of_iso {A B : Cᵒᵖ ⥤ Type v} (η : A ⟶ B) [IsIso η] : IsIndObject A ↔ IsIndObject B := ⟨.map η, .map (inv η)⟩ -instance : ClosedUnderIsomorphisms (IsIndObject (C := C)) where +instance : ObjectProperty.IsClosedUnderIsomorphisms (IsIndObject (C := C)) where of_iso i h := h.map i.hom /-- Pick a presentation for an ind-object using choice. -/ diff --git a/Mathlib/CategoryTheory/Localization/Bousfield.lean b/Mathlib/CategoryTheory/Localization/Bousfield.lean index 23380e283b29a1..466777a011dff5 100644 --- a/Mathlib/CategoryTheory/Localization/Bousfield.lean +++ b/Mathlib/CategoryTheory/Localization/Bousfield.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.MorphismProperty.Composition import Mathlib.CategoryTheory.Localization.Adjunction @@ -42,7 +42,7 @@ namespace LeftBousfield section -variable (P : C → Prop) +variable (P : ObjectProperty C) /-- Given a predicate `P : C → Prop`, this is the class of morphisms `f : X ⟶ Y` such that for all `Z : C` such that `P Z`, the precomposition with `f` induces @@ -58,11 +58,11 @@ noncomputable def W.homEquiv {X Y : C} {f : X ⟶ Y} (hf : W P f) (Z : C) (hZ : (Y ⟶ Z) ≃ (X ⟶ Z) := Equiv.ofBijective _ (hf Z hZ) -lemma W_isoClosure : W (isoClosure P) = W P := by +lemma W_isoClosure : W P.isoClosure = W P := by ext X Y f constructor · intro hf Z hZ - exact hf _ (le_isoClosure _ _ hZ) + exact hf _ (P.le_isoClosure _ hZ) · rintro hf Z ⟨Z', hZ', ⟨e⟩⟩ constructor · intro g₁ g₂ eq diff --git a/Mathlib/CategoryTheory/ObjectProperty/Basic.lean b/Mathlib/CategoryTheory/ObjectProperty/Basic.lean new file mode 100644 index 00000000000000..60c335781fe170 --- /dev/null +++ b/Mathlib/CategoryTheory/ObjectProperty/Basic.lean @@ -0,0 +1,23 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Category.Basic + +/-! +# Properties of objects in a category + +Given a category `C`, we introduce an abbreviation `ObjectProperty C` +for predicated `C → Prop`. + +-/ + +universe v u + +namespace CategoryTheory + +/-- A property of objects in a category `C` is a predicate `C → Prop`. -/ +abbrev ObjectProperty (C : Type u) [Category.{v} C] : Type u := C → Prop + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean new file mode 100644 index 00000000000000..cd106680e851e0 --- /dev/null +++ b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean @@ -0,0 +1,85 @@ +/- +Copyright (c) 2024 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Iso +import Mathlib.CategoryTheory.ObjectProperty.Basic +import Mathlib.Order.Basic + +/-! # Properties of objects which are closed under isomorphisms + +Given a category `C` and `P : ObjectProperty C` (i.e. `P : C → Prop`), +this file introduces the type class `P.IsClosedUnderIsomorphisms P`. + +-/ + +namespace CategoryTheory + +variable {C : Type*} [Category C] (P Q : ObjectProperty C) + +namespace ObjectProperty + +/-- A predicate `C → Prop` on the objects of a category is closed under isomorphisms +if whenever `P X`, then all the objects `Y` that are isomorphic to `X` also satisfy `P Y`. -/ +class IsClosedUnderIsomorphisms : Prop where + of_iso {X Y : C} (_ : X ≅ Y) (_ : P X) : P Y + +@[deprecated (since := "2025-02-25")] alias ClosedUnderIsomorphisms := IsClosedUnderIsomorphisms + +lemma prop_of_iso [IsClosedUnderIsomorphisms P] {X Y : C} (e : X ≅ Y) (hX : P X) : P Y := + IsClosedUnderIsomorphisms.of_iso e hX + +lemma prop_iff_of_iso [IsClosedUnderIsomorphisms P] {X Y : C} (e : X ≅ Y) : P X ↔ P Y := + ⟨prop_of_iso P e, prop_of_iso P e.symm⟩ + +lemma prop_of_isIso [IsClosedUnderIsomorphisms P] {X Y : C} (f : X ⟶ Y) [IsIso f] (hX : P X) : + P Y := + prop_of_iso P (asIso f) hX + +lemma prop_iff_of_isIso [IsClosedUnderIsomorphisms P] {X Y : C} (f : X ⟶ Y) [IsIso f] : P X ↔ P Y := + prop_iff_of_iso P (asIso f) + +/-- The closure by isomorphisms of a predicate on objects in a category. -/ +def isoClosure : ObjectProperty C := fun X => ∃ (Y : C) (_ : P Y), Nonempty (X ≅ Y) + +lemma prop_isoClosure_iff (X : C) : + isoClosure P X ↔ ∃ (Y : C) (_ : P Y), Nonempty (X ≅ Y) := by rfl + +variable {P} in +lemma prop_isoClosure {X Y : C} (h : P X) (e : X ⟶ Y) [IsIso e] : isoClosure P Y := + ⟨X, h, ⟨(asIso e).symm⟩⟩ + +@[deprecated (since := "2025-02-25")] alias mem_of_iso := prop_of_iso +@[deprecated (since := "2025-02-25")] alias mem_iff_of_iso := prop_iff_of_iso +@[deprecated (since := "2025-02-25")] alias mem_of_isIso := prop_of_isIso +@[deprecated (since := "2025-02-25")] alias mem_iff_of_isIso := prop_iff_of_isIso +@[deprecated (since := "2025-02-25")] alias mem_isoClosure_iff := prop_isoClosure_iff +@[deprecated (since := "2025-02-25")] alias mem_isoClosure := prop_isoClosure + +lemma le_isoClosure : P ≤ isoClosure P := + fun X hX => ⟨X, hX, ⟨Iso.refl X⟩⟩ + +variable {P Q} in +lemma monotone_isoClosure (h : P ≤ Q) : isoClosure P ≤ isoClosure Q := by + rintro X ⟨X', hX', ⟨e⟩⟩ + exact ⟨X', h _ hX', ⟨e⟩⟩ + +lemma isoClosure_eq_self [IsClosedUnderIsomorphisms P] : isoClosure P = P := by + apply le_antisymm + · intro X ⟨Y, hY, ⟨e⟩⟩ + exact prop_of_iso P e.symm hY + · exact le_isoClosure P + +lemma isoClosure_le_iff [IsClosedUnderIsomorphisms Q] : isoClosure P ≤ Q ↔ P ≤ Q := + ⟨(le_isoClosure P).trans, + fun h => (monotone_isoClosure h).trans (by rw [isoClosure_eq_self])⟩ + +instance : IsClosedUnderIsomorphisms (isoClosure P) where + of_iso := by + rintro X Y e ⟨Z, hZ, ⟨f⟩⟩ + exact ⟨Z, hZ, ⟨e.symm.trans f⟩⟩ + +end ObjectProperty + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/Shift/Predicate.lean b/Mathlib/CategoryTheory/Shift/Predicate.lean index 8392e0bd926d3e..5a45fac7158e30 100644 --- a/Mathlib/CategoryTheory/Shift/Predicate.lean +++ b/Mathlib/CategoryTheory/Shift/Predicate.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.Shift.Basic /-! @@ -18,31 +18,31 @@ open CategoryTheory Category namespace CategoryTheory -variable {C : Type*} [Category C] (P : C → Prop) +variable {C : Type*} [Category C] (P : ObjectProperty C) {A : Type*} [AddMonoid A] [HasShift C A] /-- Given a predicate `P : C → Prop` on objects of a category equipped with a shift by `A`, this is the predicate which is satisfied by `X` if `P (X⟦a⟧)`. -/ -def PredicateShift (a : A) : C → Prop := fun X => P (X⟦a⟧) +def PredicateShift (a : A) : ObjectProperty C := fun X => P (X⟦a⟧) lemma predicateShift_iff (a : A) (X : C) : PredicateShift P a X ↔ P (X⟦a⟧) := Iff.rfl -instance predicateShift_closedUnderIsomorphisms (a : A) [ClosedUnderIsomorphisms P] : - ClosedUnderIsomorphisms (PredicateShift P a) where - of_iso e hX := mem_of_iso P ((shiftFunctor C a).mapIso e) hX +instance predicateShift_closedUnderIsomorphisms (a : A) [P.IsClosedUnderIsomorphisms] : + (PredicateShift P a).IsClosedUnderIsomorphisms where + of_iso e hX := P.prop_of_iso ((shiftFunctor C a).mapIso e) hX variable (A) @[simp] -lemma predicateShift_zero [ClosedUnderIsomorphisms P] : PredicateShift P (0 : A) = P := by +lemma predicateShift_zero [P.IsClosedUnderIsomorphisms] : PredicateShift P (0 : A) = P := by ext X - exact mem_iff_of_iso P ((shiftFunctorZero C A).app X) + exact P.prop_iff_of_iso ((shiftFunctorZero C A).app X) variable {A} -lemma predicateShift_predicateShift (a b c : A) (h : a + b = c) [ClosedUnderIsomorphisms P] : +lemma predicateShift_predicateShift (a b c : A) (h : a + b = c) [P.IsClosedUnderIsomorphisms] : PredicateShift (PredicateShift P b) a = PredicateShift P c := by ext X - exact mem_iff_of_iso _ ((shiftFunctorAdd' C a b c h).symm.app X) + exact P.prop_iff_of_iso ((shiftFunctorAdd' C a b c h).symm.app X) end CategoryTheory diff --git a/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean b/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean index afa7602914d26a..0c8f26f271f919 100644 --- a/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean +++ b/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean @@ -110,7 +110,7 @@ def homologicalKernel [F.IsHomological] : (Triangle.shift_distinguished T hT n)).isZero_of_both_zeros (IsZero.eq_of_src (h₁ n) _ _) (IsZero.eq_of_tgt (h₃ n) _ _)) -instance [F.IsHomological] : ClosedUnderIsomorphisms F.homologicalKernel.P := by +instance [F.IsHomological] : F.homologicalKernel.P.IsClosedUnderIsomorphisms := by dsimp only [homologicalKernel] infer_instance diff --git a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean index cba2f222d1f292..617b4776b3c4d1 100644 --- a/Mathlib/CategoryTheory/Triangulated/Subcategory.lean +++ b/Mathlib/CategoryTheory/Triangulated/Subcategory.lean @@ -3,7 +3,7 @@ Copyright (c) 2024 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.Localization.CalculusOfFractions import Mathlib.CategoryTheory.Localization.Triangulated import Mathlib.CategoryTheory.Shift.Localization @@ -55,23 +55,23 @@ if `X₁ ⟶ X₂ ⟶ X₃ ⟶ X₁⟦1⟧` is a distinguished triangle such tha `P` then `X₂` is isomorphic to an object satisfying `P`. -/ structure Subcategory where /-- the underlying predicate on objects of a triangulated subcategory -/ - P : C → Prop + P : ObjectProperty C zero' : ∃ (Z : C) (_ : IsZero Z), P Z shift (X : C) (n : ℤ) : P X → P (X⟦n⟧) - ext₂' (T : Triangle C) (_ : T ∈ distTriang C) : P T.obj₁ → P T.obj₃ → isoClosure P T.obj₂ + ext₂' (T : Triangle C) (_ : T ∈ distTriang C) : P T.obj₁ → P T.obj₃ → P.isoClosure T.obj₂ namespace Subcategory variable {C} variable (S : Subcategory C) -lemma zero [ClosedUnderIsomorphisms S.P] : S.P 0 := by +lemma zero [S.P.IsClosedUnderIsomorphisms] : S.P 0 := by obtain ⟨X, hX, mem⟩ := S.zero' - exact mem_of_iso _ hX.isoZero mem + exact S.P.prop_of_iso hX.isoZero mem /-- The closure under isomorphisms of a triangulated subcategory. -/ def isoClosure : Subcategory C where - P := CategoryTheory.isoClosure S.P + P := S.P.isoClosure zero' := by obtain ⟨Z, hZ, hZ'⟩ := S.zero' exact ⟨Z, hZ, Z, hZ', ⟨Iso.refl _⟩⟩ @@ -80,7 +80,7 @@ def isoClosure : Subcategory C where exact ⟨Y⟦n⟧, S.shift Y n hY, ⟨(shiftFunctor C n).mapIso e⟩⟩ ext₂' := by rintro T hT ⟨X₁, h₁, ⟨e₁⟩⟩ ⟨X₃, h₃, ⟨e₃⟩⟩ - exact le_isoClosure _ _ + exact ObjectProperty.le_isoClosure _ _ (S.ext₂' (Triangle.mk (e₁.inv ≫ T.mor₁) (T.mor₂ ≫ e₃.hom) (e₃.inv ≫ T.mor₃ ≫ e₁.hom⟦1⟧')) (isomorphic_distinguished _ hT _ (Triangle.isoMk _ _ e₁.symm (Iso.refl _) e₃.symm (by simp) (by simp) (by @@ -88,13 +88,13 @@ def isoClosure : Subcategory C where simp only [assoc, Iso.cancel_iso_inv_left, ← Functor.map_comp, e₁.hom_inv_id, Functor.map_id, comp_id]))) h₁ h₃) -instance : ClosedUnderIsomorphisms S.isoClosure.P := by +instance : S.isoClosure.P.IsClosedUnderIsomorphisms := by dsimp only [isoClosure] infer_instance section -variable (P : C → Prop) (zero : P 0) +variable (P : ObjectProperty C) (zero : P 0) (shift : ∀ (X : C) (n : ℤ), P X → P (X⟦n⟧)) (ext₂ : ∀ (T : Triangle C) (_ : T ∈ distTriang C), P T.obj₁ → P T.obj₃ → P T.obj₂) @@ -103,9 +103,9 @@ def mk' : Subcategory C where P := P zero' := ⟨0, isZero_zero _, zero⟩ shift := shift - ext₂' T hT h₁ h₃ := le_isoClosure P _ (ext₂ T hT h₁ h₃) + ext₂' T hT h₁ h₃ := P.le_isoClosure _ (ext₂ T hT h₁ h₃) -instance : ClosedUnderIsomorphisms (mk' P zero shift ext₂).P where +instance : (mk' P zero shift ext₂).P.IsClosedUnderIsomorphisms where of_iso {X Y} e hX := by refine ext₂ (Triangle.mk e.hom (0 : Y ⟶ 0) 0) ?_ hX zero refine isomorphic_distinguished _ (contractible_distinguished X) _ ?_ @@ -113,10 +113,10 @@ instance : ClosedUnderIsomorphisms (mk' P zero shift ext₂).P where end -lemma ext₂ [ClosedUnderIsomorphisms S.P] +lemma ext₂ [S.P.IsClosedUnderIsomorphisms] (T : Triangle C) (hT : T ∈ distTriang C) (h₁ : S.P T.obj₁) (h₃ : S.P T.obj₃) : S.P T.obj₂ := by - simpa only [isoClosure_eq_self] using S.ext₂' T hT h₁ h₃ + simpa only [ObjectProperty.isoClosure_eq_self] using S.ext₂' T hT h₁ h₃ /-- Given `S : Triangulated.Subcategory C`, this is the class of morphisms on `C` which consists of morphisms whose cone satisfies `S.P`. -/ @@ -151,7 +151,7 @@ lemma isoClosure_W : S.isoClosure.W = S.W := by refine ⟨Z', g ≫ e.hom, e.inv ≫ h, isomorphic_distinguished _ mem _ ?_, hZ'⟩ exact Triangle.isoMk _ _ (Iso.refl _) (Iso.refl _) e.symm · rintro ⟨Z, g, h, mem, hZ⟩ - exact ⟨Z, g, h, mem, le_isoClosure _ _ hZ⟩ + exact ⟨Z, g, h, mem, ObjectProperty.le_isoClosure _ _ hZ⟩ instance respectsIso_W : S.W.RespectsIso where precomp {X' X Y} e (he : IsIso e) := by @@ -203,12 +203,12 @@ instance [IsTriangulated C] : S.W.IsMultiplicative where variable (S) lemma mem_W_iff_of_distinguished - [ClosedUnderIsomorphisms S.P] (T : Triangle C) (hT : T ∈ distTriang C) : + [S.P.IsClosedUnderIsomorphisms] (T : Triangle C) (hT : T ∈ distTriang C) : S.W T.mor₁ ↔ S.P T.obj₃ := by constructor · rintro ⟨Z, g, h, hT', mem⟩ obtain ⟨e, _⟩ := exists_iso_of_arrow_iso _ _ hT' hT (Iso.refl _) - exact mem_of_iso S.P (Triangle.π₃.mapIso e) mem + exact S.P.prop_of_iso (Triangle.π₃.mapIso e) mem · intro h exact ⟨_, _, _, hT, h⟩ @@ -264,20 +264,20 @@ variable (T : Triangle C) (hT : T ∈ distTriang C) include hT -lemma ext₁ [ClosedUnderIsomorphisms S.P] (h₂ : S.P T.obj₂) (h₃ : S.P T.obj₃) : +lemma ext₁ [S.P.IsClosedUnderIsomorphisms] (h₂ : S.P T.obj₂) (h₃ : S.P T.obj₃) : S.P T.obj₁ := S.ext₂ _ (inv_rot_of_distTriang _ hT) (S.shift _ _ h₃) h₂ -lemma ext₃ [ClosedUnderIsomorphisms S.P] (h₁ : S.P T.obj₁) (h₂ : S.P T.obj₂) : +lemma ext₃ [S.P.IsClosedUnderIsomorphisms] (h₁ : S.P T.obj₁) (h₂ : S.P T.obj₂) : S.P T.obj₃ := S.ext₂ _ (rot_of_distTriang _ hT) h₂ (S.shift _ _ h₁) lemma ext₁' (h₂ : S.P T.obj₂) (h₃ : S.P T.obj₃) : - CategoryTheory.isoClosure S.P T.obj₁ := + S.P.isoClosure T.obj₁ := S.ext₂' _ (inv_rot_of_distTriang _ hT) (S.shift _ _ h₃) h₂ lemma ext₃' (h₁ : S.P T.obj₁) (h₂ : S.P T.obj₂) : - CategoryTheory.isoClosure S.P T.obj₃ := + S.P.isoClosure T.obj₃ := S.ext₂' _ (rot_of_distTriang _ hT) h₂ (S.shift _ _ h₁) end diff --git a/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean b/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean index 6ffcb2daa96852..97965682e00200 100644 --- a/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean +++ b/Mathlib/CategoryTheory/Triangulated/TStructure/Basic.lean @@ -54,11 +54,11 @@ open Pretriangulated /-- `TStructure C` is the type of t-structures on the (pre)triangulated category `C`. -/ structure TStructure where /-- the predicate of objects that are `≤ n` for `n : ℤ`. -/ - LE (n : ℤ) : C → Prop + LE (n : ℤ) : ObjectProperty C /-- the predicate of objects that are `≥ n` for `n : ℤ`. -/ - GE (n : ℤ) : C → Prop - LE_closedUnderIsomorphisms (n : ℤ) : ClosedUnderIsomorphisms (LE n) := by infer_instance - GE_closedUnderIsomorphisms (n : ℤ) : ClosedUnderIsomorphisms (GE n) := by infer_instance + GE (n : ℤ) : ObjectProperty C + LE_closedUnderIsomorphisms (n : ℤ) : (LE n).IsClosedUnderIsomorphisms := by infer_instance + GE_closedUnderIsomorphisms (n : ℤ) : (GE n).IsClosedUnderIsomorphisms := by infer_instance LE_shift (n a n' : ℤ) (h : a + n' = n) (X : C) (hX : LE n X) : LE n' (X⟦a⟧) GE_shift (n a n' : ℤ) (h : a + n' = n) (X : C) (hX : GE n X) : GE n' (X⟦a⟧) zero' ⦃X Y : C⦄ (f : X ⟶ Y) (hX : LE 0 X) (hY : GE 1 Y) : f = 0 @@ -92,7 +92,7 @@ lemma predicateShift_LE (a n n' : ℤ) (hn' : a + n = n') : ext X constructor · intro hX - exact (mem_iff_of_iso (LE t n') ((shiftEquiv C a).unitIso.symm.app X)).1 + exact ((LE t n').prop_iff_of_iso ((shiftEquiv C a).unitIso.symm.app X)).1 (t.LE_shift n (-a) n' (by omega) _ hX) · intro hX exact t.LE_shift _ _ _ hn' X hX @@ -102,7 +102,7 @@ lemma predicateShift_GE (a n n' : ℤ) (hn' : a + n = n') : ext X constructor · intro hX - exact (mem_iff_of_iso (GE t n') ((shiftEquiv C a).unitIso.symm.app X)).1 + exact ((GE t n').prop_iff_of_iso ((shiftEquiv C a).unitIso.symm.app X)).1 (t.GE_shift n (-a) n' (by omega) _ hX) · intro hX exact t.GE_shift _ _ _ hn' X hX From 20a379a907aba95b53b1d19b9fac3b9a815bd9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 14:24:49 +0100 Subject: [PATCH 10/46] added todo --- Mathlib/CategoryTheory/ObjectProperty/Basic.lean | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Mathlib/CategoryTheory/ObjectProperty/Basic.lean b/Mathlib/CategoryTheory/ObjectProperty/Basic.lean index 60c335781fe170..69b9f327cc20bc 100644 --- a/Mathlib/CategoryTheory/ObjectProperty/Basic.lean +++ b/Mathlib/CategoryTheory/ObjectProperty/Basic.lean @@ -11,6 +11,13 @@ import Mathlib.CategoryTheory.Category.Basic Given a category `C`, we introduce an abbreviation `ObjectProperty C` for predicated `C → Prop`. +## TODO + +* refactor the file `Limits.FullSubcategory` in order to rename `ClosedUnderLimitsOfShape` +as `ObjectProperty.IsClosedUnderLimitsOfShape` (and make it a type class) +* refactor the file `Triangulated.Subcategory` in order to make it a type class +regarding terms in `ObjectProperty C` when `C` is pretriangulated + -/ universe v u From 9bd0572665febffce08f7ea8c863fa6bfd9c0677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 14:26:34 +0100 Subject: [PATCH 11/46] fix deprecated aliases --- .../ObjectProperty/ClosedUnderIsomorphisms.lean | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean index cd106680e851e0..4e69de3dc0cceb 100644 --- a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean +++ b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean @@ -50,13 +50,6 @@ variable {P} in lemma prop_isoClosure {X Y : C} (h : P X) (e : X ⟶ Y) [IsIso e] : isoClosure P Y := ⟨X, h, ⟨(asIso e).symm⟩⟩ -@[deprecated (since := "2025-02-25")] alias mem_of_iso := prop_of_iso -@[deprecated (since := "2025-02-25")] alias mem_iff_of_iso := prop_iff_of_iso -@[deprecated (since := "2025-02-25")] alias mem_of_isIso := prop_of_isIso -@[deprecated (since := "2025-02-25")] alias mem_iff_of_isIso := prop_iff_of_isIso -@[deprecated (since := "2025-02-25")] alias mem_isoClosure_iff := prop_isoClosure_iff -@[deprecated (since := "2025-02-25")] alias mem_isoClosure := prop_isoClosure - lemma le_isoClosure : P ≤ isoClosure P := fun X hX => ⟨X, hX, ⟨Iso.refl X⟩⟩ @@ -82,4 +75,14 @@ instance : IsClosedUnderIsomorphisms (isoClosure P) where end ObjectProperty +open ObjectProperty + +@[deprecated (since := "2025-02-25")] alias mem_of_iso := prop_of_iso +@[deprecated (since := "2025-02-25")] alias mem_iff_of_iso := prop_iff_of_iso +@[deprecated (since := "2025-02-25")] alias mem_of_isIso := prop_of_isIso +@[deprecated (since := "2025-02-25")] alias mem_iff_of_isIso := prop_iff_of_isIso +@[deprecated (since := "2025-02-25")] alias mem_isoClosure_iff := prop_isoClosure_iff +@[deprecated (since := "2025-02-25")] alias mem_isoClosure := prop_isoClosure + + end CategoryTheory From d50d3c807a75c48c6c2754a585bdaa52e49ef033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 14:26:52 +0100 Subject: [PATCH 12/46] removed blank line --- .../CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean index 4e69de3dc0cceb..b39beff835e71c 100644 --- a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean +++ b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean @@ -84,5 +84,4 @@ open ObjectProperty @[deprecated (since := "2025-02-25")] alias mem_isoClosure_iff := prop_isoClosure_iff @[deprecated (since := "2025-02-25")] alias mem_isoClosure := prop_isoClosure - end CategoryTheory From c0418fa452a25f2723bc8f84514bf66aec305979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 15:21:20 +0100 Subject: [PATCH 13/46] refactor --- Mathlib.lean | 1 + .../Abelian/SerreClass/Basic.lean | 96 +++++++------------ .../ObjectProperty/ContainsZero.lean | 59 ++++++++++++ .../ObjectProperty/EpiMono.lean | 88 +++++++++++++++++ .../ObjectProperty/Extensions.lean | 63 ++++++++++++ 5 files changed, 244 insertions(+), 63 deletions(-) create mode 100644 Mathlib/CategoryTheory/ObjectProperty/ContainsZero.lean create mode 100644 Mathlib/CategoryTheory/ObjectProperty/EpiMono.lean create mode 100644 Mathlib/CategoryTheory/ObjectProperty/Extensions.lean diff --git a/Mathlib.lean b/Mathlib.lean index b0c49cecada9bf..7c70efaf2d988b 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2219,6 +2219,7 @@ import Mathlib.CategoryTheory.NatTrans import Mathlib.CategoryTheory.Noetherian import Mathlib.CategoryTheory.ObjectProperty.Basic import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ContainsZero import Mathlib.CategoryTheory.Opposites import Mathlib.CategoryTheory.PEmpty import Mathlib.CategoryTheory.PUnit diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean index c1fbb7069b9129..cea57a7be54bf5 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean @@ -4,19 +4,25 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.Abelian.Basic -import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.ObjectProperty.ContainsZero +import Mathlib.CategoryTheory.ObjectProperty.EpiMono +import Mathlib.CategoryTheory.ObjectProperty.Extensions import Mathlib.Algebra.Homology.ShortComplex.ShortExact /-! # Serre classes -For any abelian category `C`, we introduce the type `SerreClass C` of Serre classes in C -(also known as "Serre subcategories"). A Serre class consists of a predicate -on objects of `C` which holds for the zero object and is such that if -`0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` is a short exact sequence, then `X₂` belongs to the class -iff `X₁` and `X₃` do. This implies that the class is stable under subobjects, -quotients, extensions. As a result, if `X₁ ⟶ X₂ ⟶ X₃` is an exact sequence such -that `X₁` and `X₃` belong to the class, then so does `X₂` (see `SerreClass.prop_of_exact`). +For any abelian category `C`, we introduce a type class `IsSerreClass C` for +Serre classes in `S` (also known as "Serre subcategories"). A Serre class is +a property `P : ObjectProperty C` of objects in `P` which holds for a zero object, +and is stable under subobjects, quotients and extensions. + +--contains the zero objectconsists of a predicate +--on objects of `C` which holds for the zero object and is such that if +--`0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` is a short exact sequence, then `X₂` belongs to the class +--iff `X₁` and `X₃` do. This implies that the class is stable under subobjects, +--quotients, extensions. As a result, if `X₁ ⟶ X₂ ⟶ X₃` is an exact sequence such +--that `X₁` and `X₃` belong to the class, then so does `X₂` (see `SerreClass.prop_of_exact`). ## Future works @@ -34,73 +40,37 @@ namespace CategoryTheory open Limits ZeroObject -variable (C : Type u) [Category.{v} C] [Abelian C] - -/-- A Serre class in an abelian category consists of predicate which -is stable by subobject, quotient, extension and for the zero object. -/ -structure SerreClass where - /-- a predicate on objects -/ - prop : C → Prop - prop_zero : prop 0 - iff_of_shortExact {S : ShortComplex C} (hS : S.ShortExact) : - prop S.X₂ ↔ prop S.X₁ ∧ prop S.X₃ - -namespace SerreClass - -variable {C} (c : SerreClass C) - -section +variable {C : Type u} [Category.{v} C] [Abelian C] (P : ObjectProperty C) -variable {S : ShortComplex C} (hS : S.ShortExact) +namespace ObjectProperty -include hS - -lemma prop_X₂_of_shortExact (h₁ : c.prop S.X₁) (h₃ : c.prop S.X₃) : c.prop S.X₂ := by - rw [c.iff_of_shortExact hS] - constructor <;> assumption - -lemma prop_X₁_of_shortExact (h₂ : c.prop S.X₂) : c.prop S.X₁ := by - rw [c.iff_of_shortExact hS] at h₂ - exact h₂.1 - -lemma prop_X₃_of_shortExact (h₂ : c.prop S.X₂) : c.prop S.X₃ := by - rw [c.iff_of_shortExact hS] at h₂ - exact h₂.2 - -end - -lemma prop_biprod {X₁ X₂ : C} (h₁ : c.prop X₁) (h₂ : c.prop X₂) : - c.prop (X₁ ⊞ X₂) := - c.prop_X₂_of_shortExact - (ShortComplex.Splitting.ofHasBinaryBiproduct X₁ X₂).shortExact h₁ h₂ +/-- A Serre class in an abelian category consists of predicate which +hold for the zero object and $is stable under subobjects, quotients, extensions. -/ +class IsSerreClass extends P.ContainsZero, + P.IsStableUnderSubobjects, P.IsStableUnderQuotients, + P.IsStableUnderExtensions : Prop where -lemma prop_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hY : c.prop Y) : c.prop X := by - have hS : (ShortComplex.mk _ _ (cokernel.condition f)).ShortExact := - { exact := ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel f) } - exact c.prop_X₁_of_shortExact hS hY +variable [P.IsSerreClass] -lemma prop_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hX : c.prop X) : c.prop Y := by - have hS : (ShortComplex.mk _ _ (kernel.condition f)).ShortExact := - { exact := ShortComplex.exact_of_f_is_kernel _ (kernelIsKernel f) } - exact c.prop_X₃_of_shortExact hS hX +example : P.IsClosedUnderIsomorphisms := inferInstance -lemma prop_iff_of_iso {X Y : C} (e : X ≅ Y) : c.prop X ↔ c.prop Y := - ⟨c.prop_of_epi e.hom, c.prop_of_mono e.hom⟩ +instance : (⊤ : ObjectProperty C).IsSerreClass where -instance : ClosedUnderIsomorphisms c.prop where - of_iso e hX := by rwa [← c.prop_iff_of_iso e] +instance : IsSerreClass (IsZero (C := C)) where -lemma prop_of_isZero {X : C} (hX : IsZero X) : c.prop X := by - simpa only [c.prop_iff_of_iso (hX.iso (isZero_zero _))] using c.prop_zero +lemma prop_iff_of_shortExact {S : ShortComplex C} (hS : S.ShortExact) : + P S.X₂ ↔ P S.X₁ ∧ P S.X₃ := + ⟨fun h ↦ ⟨P.prop_X₁_of_shortExact hS h, P.prop_X₃_of_shortExact hS h⟩, + fun h ↦ P.prop_X₂_of_shortExact hS h.1 h.2⟩ lemma prop_of_exact {S : ShortComplex C} (hS : S.Exact) - (h₁ : c.prop S.X₁) (h₃ : c.prop S.X₃) : c.prop S.X₂ := by + (h₁ : P S.X₁) (h₃ : P S.X₃) : P S.X₂ := by let d := S.homologyData have := hS.epi_f' d.left have := hS.mono_g' d.right - exact (c.prop_X₂_of_shortExact (hS.shortExact d) - (c.prop_of_epi d.left.f' h₁) (c.prop_of_mono d.right.g' h₃) :) + exact (P.prop_X₂_of_shortExact (hS.shortExact d) + (P.prop_of_epi d.left.f' h₁) (P.prop_of_mono d.right.g' h₃) :) -end SerreClass +end ObjectProperty end CategoryTheory diff --git a/Mathlib/CategoryTheory/ObjectProperty/ContainsZero.lean b/Mathlib/CategoryTheory/ObjectProperty/ContainsZero.lean new file mode 100644 index 00000000000000..927aa0af696e83 --- /dev/null +++ b/Mathlib/CategoryTheory/ObjectProperty/ContainsZero.lean @@ -0,0 +1,59 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms +import Mathlib.CategoryTheory.Limits.Shapes.ZeroObjects + +/-! +# Properties of objects which hold for a zero object + +Given a category `C` and `P : ObjectProperty C`, we define a type class `P.ContainsZero` +expressing that there exists a zero object for which `P` holds. (We do not require +that `P` holds for all zero objects, as in some applications (e.g. triangulated categories), +`P` may not necessarily be closed under isomorphisms.) + +-/ + +universe v u + +namespace CategoryTheory + +open Limits ZeroObject + +variable {C : Type u} [Category.{v} C] + +namespace ObjectProperty + +variable (P : ObjectProperty C) + +/-- Given `P : ObjectProperty C`, we say that `P.ContainsZero` if there exists +a zero object for which `P` holds. When `P` is closed under isomorphisms, +this holds for any zero object. -/ +class ContainsZero : Prop where + exists_zero : ∃ (Z : C), IsZero Z ∧ P Z + +lemma exists_prop_of_containsZero [P.ContainsZero] : + ∃ (Z : C), IsZero Z ∧ P Z := + ContainsZero.exists_zero + +lemma prop_of_isZero [P.ContainsZero] [P.IsClosedUnderIsomorphisms] + {Z : C} (hZ : IsZero Z) : + P Z := by + obtain ⟨Z₀, hZ₀, h₀⟩ := P.exists_prop_of_containsZero + exact P.prop_of_iso (hZ₀.iso hZ) h₀ + +lemma prop_zero [P.ContainsZero] [P.IsClosedUnderIsomorphisms] [HasZeroObject C] : + P 0 := + P.prop_of_isZero (isZero_zero C) + +instance [HasZeroObject C] : (⊤ : ObjectProperty C).ContainsZero where + exists_zero := ⟨0, isZero_zero C, by simp⟩ + +instance [HasZeroObject C] : ContainsZero (IsZero (C := C)) where + exists_zero := ⟨0, isZero_zero C, isZero_zero C⟩ + +end ObjectProperty + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/ObjectProperty/EpiMono.lean b/Mathlib/CategoryTheory/ObjectProperty/EpiMono.lean new file mode 100644 index 00000000000000..8d2520628e7782 --- /dev/null +++ b/Mathlib/CategoryTheory/ObjectProperty/EpiMono.lean @@ -0,0 +1,88 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms +import Mathlib.Algebra.Homology.ShortComplex.ShortExact + +/-! +# Properties of objects that are stable under subobjects and quotients + +Given a category `C` and `P : ObjectProperty C`, we define type classes +`P.IsStableUnderSubobjects` and `P.IsStableUnderQuotients` expressing +that `P` is stable under subobjects (resp. quotients). + +-/ + +universe v u + +namespace CategoryTheory + +open Limits + +variable {C : Type u} [Category.{v} C] + +namespace ObjectProperty + +variable (P : ObjectProperty C) + +/-- Given `P : ObjectProperty C`, we say that `P` is stable under subobjects, +if for any monomorphism `X ⟶ Y`, `P Y` implies `P X`. -/ +class IsStableUnderSubobjects : Prop where + prop_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hY : P Y) : P X + +section + +variable [P.IsStableUnderSubobjects] + +lemma prop_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hY : P Y) : P X := + IsStableUnderSubobjects.prop_of_mono f hY + +instance : P.IsClosedUnderIsomorphisms where + of_iso e := P.prop_of_mono e.inv + +lemma prop_X₁_of_shortExact [HasZeroMorphisms C] {S : ShortComplex C} (hS : S.ShortExact) + (h₂ : P S.X₂) : P S.X₁ := by + have := hS.mono_f + exact P.prop_of_mono S.f h₂ + +end + +section + +/-- Given `P : ObjectProperty C`, we say that `P` is stable under quotients, +if for any epimorphism `X ⟶ Y`, `P X` implies `P Y`. -/ +class IsStableUnderQuotients : Prop where + prop_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hX : P X) : P Y + +variable [P.IsStableUnderQuotients] + +lemma prop_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hX : P X) : P Y := + IsStableUnderQuotients.prop_of_epi f hX + +instance : P.IsClosedUnderIsomorphisms where + of_iso e := P.prop_of_epi e.hom + +lemma prop_X₃_of_shortExact [HasZeroMorphisms C] {S : ShortComplex C} (hS : S.ShortExact) + (h₂ : P S.X₂) : P S.X₃ := by + have := hS.epi_g + exact P.prop_of_epi S.g h₂ + +end + +instance : (⊤ : ObjectProperty C).IsStableUnderSubobjects where + prop_of_mono := by simp + +instance : (⊤ : ObjectProperty C).IsStableUnderQuotients where + prop_of_epi := by simp + +instance [HasZeroMorphisms C] : IsStableUnderSubobjects (IsZero (C := C)) where + prop_of_mono f _ hX := IsZero.of_mono f hX + +instance [HasZeroMorphisms C] : IsStableUnderQuotients (IsZero (C := C)) where + prop_of_epi f _ hX := IsZero.of_epi f hX + +end ObjectProperty + +end CategoryTheory diff --git a/Mathlib/CategoryTheory/ObjectProperty/Extensions.lean b/Mathlib/CategoryTheory/ObjectProperty/Extensions.lean new file mode 100644 index 00000000000000..f6eff956d05184 --- /dev/null +++ b/Mathlib/CategoryTheory/ObjectProperty/Extensions.lean @@ -0,0 +1,63 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.Algebra.Homology.ShortComplex.ShortExact +import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms + +/-! +# Properties of objects that are stable under extensions + +Given a category `C` and `P : ObjectProperty C`, we define a type +class `P.IsStableUnderExtensions` expressing that the property +is stable under extensions. + +-/ + +universe v u + +namespace CategoryTheory + +open Limits + +variable {C : Type u} [Category.{v} C] + +namespace ObjectProperty + +variable (P : ObjectProperty C) + +section + +variable [HasZeroMorphisms C] + +/-- Given `P : ObjectProperty C`, we say that `P` is stable under extensions +if whenever `0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` is a short exact short complex, +then `P X₁` and `P X₃` implies `P X₂`. -/ +class IsStableUnderExtensions : Prop where + prop_X₂_of_shortExact {S : ShortComplex C} (hS : S.ShortExact) + (h₁ : P S.X₁) (h₃ : P S.X₃) : P S.X₂ + +lemma prop_X₂_of_shortExact [P.IsStableUnderExtensions] + {S : ShortComplex C} (hS : S.ShortExact) + (h₁ : P S.X₁) (h₃ : P S.X₃) : P S.X₂ := + IsStableUnderExtensions.prop_X₂_of_shortExact hS h₁ h₃ + +instance : (⊤ : ObjectProperty C).IsStableUnderExtensions where + prop_X₂_of_shortExact := by simp + +instance : IsStableUnderExtensions (IsZero (C := C)) where + prop_X₂_of_shortExact hS h₁ h₃ := + hS.exact.isZero_of_both_zeros (h₁.eq_of_src _ _) (h₃.eq_of_tgt _ _) + +end + +lemma prop_biprod {X₁ X₂ : C} (h₁ : P X₁) (h₂ : P X₂) [Preadditive C] [HasZeroObject C] + [P.IsStableUnderExtensions] [HasBinaryBiproduct X₁ X₂] : + P (X₁ ⊞ X₂) := + P.prop_X₂_of_shortExact + (ShortComplex.Splitting.ofHasBinaryBiproduct X₁ X₂).shortExact h₁ h₂ + +end ObjectProperty + +end CategoryTheory From a202128b06c42c6890fa3d2ff3974306df54d2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 15:21:28 +0100 Subject: [PATCH 14/46] fixing Mathlib.lean --- Mathlib.lean | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Mathlib.lean b/Mathlib.lean index 7c70efaf2d988b..50c2bc465dfe44 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2220,6 +2220,8 @@ import Mathlib.CategoryTheory.Noetherian import Mathlib.CategoryTheory.ObjectProperty.Basic import Mathlib.CategoryTheory.ObjectProperty.ClosedUnderIsomorphisms import Mathlib.CategoryTheory.ObjectProperty.ContainsZero +import Mathlib.CategoryTheory.ObjectProperty.EpiMono +import Mathlib.CategoryTheory.ObjectProperty.Extensions import Mathlib.CategoryTheory.Opposites import Mathlib.CategoryTheory.PEmpty import Mathlib.CategoryTheory.PUnit From 58fae9684e76bf60f671196134fe58fec2788a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 15:22:26 +0100 Subject: [PATCH 15/46] fixing name --- Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean index cea57a7be54bf5..c70341be04461c 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean @@ -63,7 +63,7 @@ lemma prop_iff_of_shortExact {S : ShortComplex C} (hS : S.ShortExact) : ⟨fun h ↦ ⟨P.prop_X₁_of_shortExact hS h, P.prop_X₃_of_shortExact hS h⟩, fun h ↦ P.prop_X₂_of_shortExact hS h.1 h.2⟩ -lemma prop_of_exact {S : ShortComplex C} (hS : S.Exact) +lemma prop_X₂_of_exact {S : ShortComplex C} (hS : S.Exact) (h₁ : P S.X₁) (h₃ : P S.X₃) : P S.X₂ := by let d := S.homologyData have := hS.epi_f' d.left From 2554ce4ed17fc131d1ca87382ce2372190257298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 15:23:48 +0100 Subject: [PATCH 16/46] fixing lint --- Mathlib/CategoryTheory/ObjectProperty/Basic.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib/CategoryTheory/ObjectProperty/Basic.lean b/Mathlib/CategoryTheory/ObjectProperty/Basic.lean index 69b9f327cc20bc..872b77087d0480 100644 --- a/Mathlib/CategoryTheory/ObjectProperty/Basic.lean +++ b/Mathlib/CategoryTheory/ObjectProperty/Basic.lean @@ -25,6 +25,7 @@ universe v u namespace CategoryTheory /-- A property of objects in a category `C` is a predicate `C → Prop`. -/ +@[nolint unusedArguments] abbrev ObjectProperty (C : Type u) [Category.{v} C] : Type u := C → Prop end CategoryTheory From 7bf0d499f26753d7fb9986d996274e066a2aa6c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 16:32:56 +0100 Subject: [PATCH 17/46] wip --- .../Abelian/SerreClass/Basic.lean | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean new file mode 100644 index 00000000000000..c97eece3b9782a --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Basic.lean @@ -0,0 +1,122 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Abelian.Basic +import Mathlib.CategoryTheory.ClosedUnderIsomorphisms +import Mathlib.Algebra.Homology.ShortComplex.ShortExact + +/-! +# Serre classes + +For any abelian category `C`, we introduce the type `SerreClass C` of Serre classes +(also known as "Serre subcategories"). A Serre class consists of a predicate +on objects of `C` which hold for the zero object and is such that if +`0 ⟶ X₁ ⟶ X₂ ⟶ X₃ ⟶ 0` is a short exact sequence, then `X₂` belongs to the class +iff `X₁` and `X₃` do. This implies that the class is stable under subobjects, +quotients, extensions. As a result, if `X₁ ⟶ X₂ ⟶ X₃` is an exact sequence such +that `X₁` and `X₃` belong to the class, then so does `X₂` (see `SerreClass.prop_of_exact`). + +## Future works + +* Construct the localization of `C` with respect to a Serre class. + +-/ + +universe v u + +namespace CategoryTheory + +open Limits ZeroObject + +-- to be moved to `Algebra.Homology.ShortComplex.ShortExact` +lemma ShortComplex.Exact.shortExact {C : Type u} [Category.{v} C] [Preadditive C] + {S : ShortComplex C} (hS : S.Exact) (h : S.HomologyData) : + (ShortComplex.mk _ _ (h.exact_iff_i_p_zero.1 hS)).ShortExact where + exact := by + have := hS.epi_f' h.left + have := hS.mono_g' h.right + let S' := ShortComplex.mk h.left.i S.g (by simp) + let S'' := ShortComplex.mk _ _ (h.exact_iff_i_p_zero.1 hS) + let a : S ⟶ S' := + { τ₁ := h.left.f' + τ₂ := 𝟙 _ + τ₃ := 𝟙 _ } + let b : S'' ⟶ S' := + { τ₁ := 𝟙 _ + τ₂ := 𝟙 _ + τ₃ := h.right.g' } + rwa [ShortComplex.exact_iff_of_epi_of_isIso_of_mono b, + ← ShortComplex.exact_iff_of_epi_of_isIso_of_mono a] + +variable (C : Type u) [Category.{v} C] [Abelian C] + +/-- A Serre class in an abelian category consists of predicate which +is stable by subobject, quotient, extension and for the zero object. -/ +structure SerreClass where + /-- a predicate on objects -/ + prop : C → Prop + prop_zero : prop 0 + iff_of_shortExact {S : ShortComplex C} (hS : S.ShortExact) : + prop S.X₂ ↔ prop S.X₁ ∧ prop S.X₃ + +namespace SerreClass + +variable {C} (c : SerreClass C) + +section + +variable {S : ShortComplex C} (hS : S.ShortExact) + +include hS + +lemma prop_X₂_of_shortExact (h₁ : c.prop S.X₁) (h₃ : c.prop S.X₃) : c.prop S.X₂ := by + rw [c.iff_of_shortExact hS] + constructor <;> assumption + +lemma prop_X₁_of_shortExact (h₂ : c.prop S.X₂) : c.prop S.X₁ := by + rw [c.iff_of_shortExact hS] at h₂ + exact h₂.1 + +lemma prop_X₃_of_shortExact (h₂ : c.prop S.X₂) : c.prop S.X₃ := by + rw [c.iff_of_shortExact hS] at h₂ + exact h₂.2 + +end + +lemma prop_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hY : c.prop Y) : c.prop X := by + have hS : (ShortComplex.mk _ _ (cokernel.condition f)).ShortExact := + { exact := ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel f) } + exact c.prop_X₁_of_shortExact hS hY + +lemma prop_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hX : c.prop X) : c.prop Y := by + have hS : (ShortComplex.mk _ _ (kernel.condition f)).ShortExact := + { exact := ShortComplex.exact_of_f_is_kernel _ (kernelIsKernel f) } + exact c.prop_X₃_of_shortExact hS hX + +lemma prop_iff_of_iso {X Y : C} (e : X ≅ Y) : c.prop X ↔ c.prop Y := + ⟨c.prop_of_epi e.hom, c.prop_of_mono e.hom⟩ + +instance : ClosedUnderIsomorphisms c.prop where + of_iso e hX := by rwa [← c.prop_iff_of_iso e] + +lemma prop_of_isZero {X : C} (hX : IsZero X) : c.prop X := by + simpa only [c.prop_iff_of_iso (hX.iso (isZero_zero _))] using c.prop_zero + +lemma prop_biprod {X₁ X₂ : C} (h₁ : c.prop X₁) (h₂ : c.prop X₂) : + c.prop (X₁ ⊞ X₂) := + c.prop_X₂_of_shortExact + (ShortComplex.Splitting.ofHasBinaryBiproduct X₁ X₂).shortExact h₁ h₂ + +lemma prop_of_exact {S : ShortComplex C} (hS : S.Exact) + (h₁ : c.prop S.X₁) (h₃ : c.prop S.X₃) : c.prop S.X₂ := by + let d := S.homologyData + have := hS.epi_f' d.left + have := hS.mono_g' d.right + exact (c.prop_X₂_of_shortExact (hS.shortExact d) + (c.prop_of_epi d.left.f' h₁) (c.prop_of_mono d.right.g' h₃) :) + +end SerreClass + +end CategoryTheory From 7b6f9bdb5108c28b5f58831cbaf5314d9a779b0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 17:35:08 +0100 Subject: [PATCH 18/46] wip --- .../Abelian/SerreClass/Localization.lean | 92 ++++++++++++++++++- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 5ca2e283b8b209..f94af17d18760e 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -94,7 +94,7 @@ variable {P} (X Y : P.SerreWLocalization) namespace Hom -structure DefDomain where +structure DefDomain where src : C i : src ⟶ X.obj [mono_i : Mono i] @@ -148,9 +148,24 @@ instance : Category (DefDomain X Y) where id := Hom.id comp := Hom.comp +instance : Subsingleton (d₁ ⟶ d₂) := + inferInstanceAs (Subsingleton (Hom d₁ d₂)) + end Hom -lemma exists_min (d₁ d₂ : DefDomain X Y) : +@[simp] lemma id_ι (d : DefDomain X Y) : Hom.ι (𝟙 d) = 𝟙 _ := rfl +@[simp] lemma id_π (d : DefDomain X Y) : Hom.π (𝟙 d) = 𝟙 _ := rfl + +section + +variable {d₁ d₂ d₃} + +@[simp] lemma comp_ι (f : d₁ ⟶ d₂) (g : d₂ ⟶ d₃) : (f ≫ g).ι = f.ι ≫ g.ι := rfl +@[simp] lemma comp_π (f : d₁ ⟶ d₂) (g : d₂ ⟶ d₃) : (f ≫ g).π = g.π ≫ f.π := rfl + +end + +lemma exists_min : ∃ (d : DefDomain X Y), Nonempty (d ⟶ d₁) ∧ Nonempty (d ⟶ d₂) := by let d : DefDomain X Y := { src := pullback d₁.i d₂.i @@ -171,6 +186,79 @@ lemma exists_min (d₁ d₂ : DefDomain X Y) : end DefDomain +variable {X Y} in +abbrev restrict {d₁ d₂ : DefDomain X Y} (φ : d₁ ⟶ d₂) (f : d₂.src ⟶ d₂.tgt) : + d₁.src ⟶ d₁.tgt := + φ.ι ≫ f ≫ φ.π + +end Hom + +abbrev Hom' := Σ (d : Hom.DefDomain X Y), d.src ⟶ d.tgt + +section + +variable {X Y} + +abbrev Hom'.mk {d : Hom.DefDomain X Y} (φ : d.src ⟶ d.tgt) : Hom' X Y := ⟨d, φ⟩ + +lemma Hom'.mk_surjective (a : Hom' X Y) : + ∃ (d : Hom.DefDomain X Y) (φ : d.src ⟶ d.tgt), a = .mk φ := + ⟨a.1, a.2, rfl⟩ + +end + +inductive Hom'Rel : Hom' X Y → Hom' X Y → Prop + | restrict (d₁ d₂ : Hom.DefDomain X Y) (φ : d₁ ⟶ d₂) (f : d₂.src ⟶ d₂.tgt) : + Hom'Rel ⟨d₂, f⟩ ⟨d₁, Hom.restrict φ f⟩ + +def Hom := Quot (Hom'Rel X Y) + +namespace Hom + +variable {X Y} + +def mk {d : Hom.DefDomain X Y} (φ : d.src ⟶ d.tgt) : Hom X Y := + Quot.mk _ (.mk φ) + +lemma quotMk_eq_quotMk_iff {x y : Hom' X Y} : + Quot.mk (Hom'Rel X Y) x = Quot.mk (Hom'Rel X Y) y ↔ + ∃ (d : DefDomain X Y) (φ₁ : d ⟶ x.1) (φ₂ : d ⟶ y.1), + restrict φ₁ x.2 = restrict φ₂ y.2 := by + constructor + · intro h + rw [Quot.eq] at h + induction h with + | rel _ _ h => + obtain ⟨d₁, d₂, φ, f⟩ := h + exact ⟨d₁, φ, 𝟙 _, by simp [restrict]⟩ + | refl x => + exact ⟨_, 𝟙 _, 𝟙 _, by simp [restrict]⟩ + | symm _ _ _ h => + obtain ⟨_, _, _, eq⟩ := h + exact ⟨_, _, _, eq.symm⟩ + | trans _ _ _ _ _ h₁₂ h₂₃ => + obtain ⟨d₁₂, φ₁, φ₂, eq₁₂⟩ := h₁₂ + obtain ⟨d₂₃, ψ₂, ψ₃, eq₂₃⟩ := h₂₃ + obtain ⟨d, ⟨i₁₂⟩, ⟨i₂₃⟩⟩ := DefDomain.exists_min d₁₂ d₂₃ + refine ⟨d, i₁₂ ≫ φ₁, i₂₃ ≫ ψ₃, ?_⟩ + simp only [restrict] at eq₁₂ eq₂₃ + simp only [restrict, DefDomain.comp_ι, DefDomain.comp_π, assoc] + have hι := congr_arg DefDomain.Hom.ι (Subsingleton.elim (i₁₂ ≫ φ₂) (i₂₃ ≫ ψ₂)) + have hπ := congr_arg DefDomain.Hom.π (Subsingleton.elim (i₁₂ ≫ φ₂) (i₂₃ ≫ ψ₂)) + dsimp at hι hπ + rw [reassoc_of% eq₁₂, ← reassoc_of% eq₂₃, reassoc_of% hι, hπ] + · obtain ⟨d₁, f₁, rfl⟩ := x.mk_surjective + obtain ⟨d₂, f₂, rfl⟩ := y.mk_surjective + rintro ⟨d, φ₁, φ₂, h⟩ + trans mk (Hom.restrict φ₁ f₁) + · exact (Quot.sound (by constructor)) + · rw [h] + exact (Quot.sound (by constructor)).symm + +lemma ext_iff {d₁ d₂ : DefDomain X Y} (f₁ : d₁.src ⟶ d₁.tgt) (f₂ : d₂.src ⟶ d₂.tgt) : + mk f₁ = mk f₂ ↔ ∃ (d : DefDomain X Y) (φ₁ : d ⟶ d₁) (φ₂ : d ⟶ d₂), + restrict φ₁ f₁ = restrict φ₂ f₂ := by + apply quotMk_eq_quotMk_iff end Hom From c87f261fba597068bcb8134e43a5e3a11696227a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 17:53:30 +0100 Subject: [PATCH 19/46] wip --- Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index f94af17d18760e..5d57c0f3e16196 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -90,7 +90,7 @@ structure SerreWLocalization (P : ObjectProperty C) [P.IsSerreClass] : Type u wh namespace SerreWLocalization -variable {P} (X Y : P.SerreWLocalization) +variable {P} (X Y Z : P.SerreWLocalization) namespace Hom From 8f5925f9f23626f86a8dd4b3aa0838c40045b0e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 25 Feb 2025 21:23:58 +0100 Subject: [PATCH 20/46] wip --- .../Abelian/SerreClass/Localization.lean | 115 ++++++++++++++++-- 1 file changed, 108 insertions(+), 7 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 5d57c0f3e16196..4661c8c730eade 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -85,12 +85,12 @@ instance : P.serreW.IsStableUnderRetracts where P.prop_of_epi (cokernel.map f f' h.left.r h.right.r (by simp)) hf.2⟩ @[nolint unusedArguments] -structure SerreWLocalization (P : ObjectProperty C) [P.IsSerreClass] : Type u where +structure SerreWLoc (P : ObjectProperty C) [P.IsSerreClass] : Type u where obj : C -namespace SerreWLocalization +namespace SerreWLoc -variable {P} (X Y Z : P.SerreWLocalization) +variable {P} (X Y Z T : P.SerreWLoc) namespace Hom @@ -108,7 +108,16 @@ namespace DefDomain attribute [instance] mono_i epi_p -variable {X Y} (d₁ d₂ d₃ : DefDomain X Y) +@[simps] +def top : DefDomain X Y where + src := X.obj + i := 𝟙 X.obj + hi := MorphismProperty.id_mem _ _ + tgt := Y.obj + p := 𝟙 Y.obj + hp := MorphismProperty.id_mem _ _ + +variable {X Y Z T} (d₁ d₂ d₃ : DefDomain X Y) structure Hom where ι : d₁.src ⟶ d₂.src @@ -184,6 +193,18 @@ lemma exists_min : π := pushout.inr _ _ p_π := pushout.condition.symm }⟩⟩ +structure CompStruct (d₁₂ : DefDomain X Y) (d₂₃ : DefDomain Y Z) (d₁₃ : DefDomain X Z) where + ι : d₁₃.src ⟶ d₁₂.src + ι_i : ι ≫ d₁₂.i = d₁₃.i := by aesop_cat + π : d₂₃.tgt ⟶ d₁₃.tgt + p_π : d₂₃.p ≫ π = d₁₃.p := by aesop_cat + obj : C + toObj : d₂₃.src ⟶ obj + fromObj : obj ⟶ d₁₂.tgt + fac : toObj ≫ fromObj = d₂₃.i ≫ d₁₂.p := by aesop_cat + epi_toObj : Epi toObj + mono_toObj : Mono toObj + end DefDomain variable {X Y} in @@ -197,7 +218,7 @@ abbrev Hom' := Σ (d : Hom.DefDomain X Y), d.src ⟶ d.tgt section -variable {X Y} +variable {X Y Z T} abbrev Hom'.mk {d : Hom.DefDomain X Y} (φ : d.src ⟶ d.tgt) : Hom' X Y := ⟨d, φ⟩ @@ -215,7 +236,7 @@ def Hom := Quot (Hom'Rel X Y) namespace Hom -variable {X Y} +variable {X Y Z T} def mk {d : Hom.DefDomain X Y} (φ : d.src ⟶ d.tgt) : Hom X Y := Quot.mk _ (.mk φ) @@ -260,9 +281,89 @@ lemma ext_iff {d₁ d₂ : DefDomain X Y} (f₁ : d₁.src ⟶ d₁.tgt) (f₂ : restrict φ₁ f₁ = restrict φ₂ f₂ := by apply quotMk_eq_quotMk_iff +variable (P) in +def ofHom {X Y : C} (f : X ⟶ Y) : Hom (P := P) ⟨X⟩ ⟨Y⟩ := + mk (d := DefDomain.top _ _) f + +variable (X) in +abbrev id : Hom X X := ofHom P (𝟙 X.obj) + +variable {d₁₂ : DefDomain X Y} {d₂₃ : DefDomain Y Z} + (a : d₁₂.src ⟶ d₁₂.tgt) (b : d₂₃.src ⟶ d₂₃.tgt) + +structure CompStruct {d₁₃ : DefDomain X Z} + (h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃) where + α : d₁₃.src ⟶ h.obj + β : h.obj ⟶ d₁₃.tgt + hα : α ≫ h.fromObj = h.ι ≫ a + hβ : h.toObj ≫ β = b ≫ h.π + +namespace CompStruct + +lemma nonempty : ∃ (d₁₃ : DefDomain X Z) + (h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃), Nonempty (CompStruct a b h) := sorry + +variable {a b} +def comp {d₁₃ : DefDomain X Z} + {h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃} (γ : CompStruct a b h) : + Hom X Z := + Hom.mk (d := d₁₃) (γ.α ≫ γ.β) + +end CompStruct + + end Hom -end SerreWLocalization +variable {X Y Z} + +namespace Hom' + +variable (f : Hom' X Y) (g : Hom' Y Z) + +noncomputable def comp.defDomain : Hom.DefDomain X Z := + (Hom.CompStruct.nonempty f.2 g.2).choose + +noncomputable def comp.defDomainCompStruct : + Hom.DefDomain.CompStruct f.1 g.1 (defDomain f g) := + (Hom.CompStruct.nonempty f.2 g.2).choose_spec.choose + +noncomputable def comp.compStruct : + Hom.CompStruct f.2 g.2 (defDomainCompStruct f g) := + (Hom.CompStruct.nonempty f.2 g.2).choose_spec.choose_spec.some + +noncomputable def comp : Hom X Z := (comp.compStruct f g).comp + +end Hom' + +namespace Hom + +noncomputable def comp : Hom X Y → Hom Y Z → Hom X Z := + Quot.lift₂ Hom'.comp sorry sorry + +@[simp] +lemma id_comp (f : Hom X Y) : (Hom.id X).comp f = f := sorry + +@[simp] +lemma comp_id (f : Hom X Y) : f.comp (.id Y) = f := sorry + +@[simp] +lemma assoc (f : Hom X Y) (g : Hom Y Z) (h : Hom Z T) : + (f.comp g).comp h = f.comp (g.comp h) := sorry + +end Hom + +noncomputable instance : Category P.SerreWLoc where + Hom := Hom + id := Hom.id + comp := Hom.comp + +end SerreWLoc + +def toSerreWLoc : C ⥤ P.SerreWLoc where + obj X := ⟨X⟩ + map f := .ofHom P f + map_id _ := rfl + map_comp := sorry end ObjectProperty From e716dc2c7cc9e259a1cdab06b97311be66ef6e5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 26 Feb 2025 12:49:10 +0100 Subject: [PATCH 21/46] wip --- .../Abelian/SerreClass/Localization.lean | 58 +---------- .../Abelian/SerreClass/MorphismProperty.lean | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+), 57 deletions(-) create mode 100644 Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 4661c8c730eade..b7a77a8205da05 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -3,7 +3,7 @@ Copyright (c) 2025 Joël Riou. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ -import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp import Mathlib.CategoryTheory.MorphismProperty.Composition import Mathlib.CategoryTheory.MorphismProperty.Retract @@ -22,68 +22,12 @@ open Category Limits variable {C : Type u} [Category.{v} C] -namespace Limits - -variable [HasZeroMorphisms C] - -lemma isZero_kernel_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] [HasKernel f] : - IsZero (kernel f) := by - rw [IsZero.iff_id_eq_zero, ← cancel_mono (kernel.ι f), ← cancel_mono f, - assoc, assoc, kernel.condition, comp_zero, zero_comp] - -lemma isZero_cokernel_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] [HasCokernel f] : - IsZero (cokernel f) := by - rw [IsZero.iff_id_eq_zero, ← cancel_epi (cokernel.π f), ← cancel_epi f, - cokernel.condition_assoc, zero_comp, comp_zero, comp_zero] - -end Limits - variable [Abelian C] namespace ObjectProperty variable (P : ObjectProperty C) [P.IsSerreClass] -def serreW : MorphismProperty C := fun _ _ f ↦ P (kernel f) ∧ P (cokernel f) - -lemma serreW_iff_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] : P.serreW f ↔ P (cokernel f) := by - dsimp [serreW] - have := P.prop_of_isZero (isZero_kernel_of_mono f) - tauto - -lemma serreW_iff_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] : P.serreW f ↔ P (kernel f) := by - dsimp [serreW] - have := P.prop_of_isZero (isZero_cokernel_of_epi f) - tauto - -lemma serreW_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hf : P (cokernel f)) : P.serreW f := by - rwa [serreW_iff_of_mono] - -lemma serreW_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hf : P (kernel f)) : P.serreW f := by - rwa [serreW_iff_of_epi] - -lemma serreW_of_isIso {X Y : C} (f : X ⟶ Y) [IsIso f] : P.serreW f := - P.serreW_of_epi _ (P.prop_of_isZero (isZero_kernel_of_mono f)) - -instance : P.serreW.IsMultiplicative where - id_mem _ := P.serreW_of_isIso _ - comp_mem f g hf hg := - ⟨P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 0) hf.1 hg.1, - P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 3) hf.2 hg.2⟩ - -instance : P.serreW.HasTwoOutOfThreeProperty where - of_postcomp f g hg hfg := - ⟨P.prop_of_mono (kernel.map f (f ≫ g) (𝟙 _) g (by simp)) hfg.1, - P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 2) hg.1 hfg.2⟩ - of_precomp f g hf hfg := - ⟨P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 1) hfg.1 hf.2, - P.prop_of_epi (cokernel.map (f ≫ g) g f (𝟙 _) (by simp)) hfg.2⟩ - -instance : P.serreW.IsStableUnderRetracts where - of_retract {X' Y' X Y} f' f h hf := - ⟨P.prop_of_mono (kernel.map f' f h.left.i h.right.i (by simp)) hf.1, - P.prop_of_epi (cokernel.map f f' h.left.r h.right.r (by simp)) hf.2⟩ - @[nolint unusedArguments] structure SerreWLoc (P : ObjectProperty C) [P.IsSerreClass] : Type u where obj : C diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean new file mode 100644 index 00000000000000..d9c2808e17fac0 --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -0,0 +1,95 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp +import Mathlib.CategoryTheory.MorphismProperty.Composition +import Mathlib.CategoryTheory.MorphismProperty.Retract +import Mathlib.CategoryTheory.Subobject.Lattice + +/-! +# The classes of isomorphisms modulo a Serre class + +-/ + +universe v u + +namespace CategoryTheory + +open Category Limits + +variable {C : Type u} [Category.{v} C] + +namespace Limits + +variable [HasZeroMorphisms C] + +lemma isZero_kernel_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] [HasKernel f] : + IsZero (kernel f) := by + rw [IsZero.iff_id_eq_zero, ← cancel_mono (kernel.ι f), ← cancel_mono f, + assoc, assoc, kernel.condition, comp_zero, zero_comp] + +lemma isZero_cokernel_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] [HasCokernel f] : + IsZero (cokernel f) := by + rw [IsZero.iff_id_eq_zero, ← cancel_epi (cokernel.π f), ← cancel_epi f, + cokernel.condition_assoc, zero_comp, comp_zero, comp_zero] + +end Limits + +variable [Abelian C] + +namespace ObjectProperty + +variable (P : ObjectProperty C) + +/-- The class of isomorphisms modulo a Serre class: given `P : ObjectProperty C`, +this is the class of morphisms `f` such that `kernel f` and `cokernel f` satisfy `P`. -/ +def serreW : MorphismProperty C := fun _ _ f ↦ P (kernel f) ∧ P (cokernel f) + +variable [P.IsSerreClass] + +lemma serreW_iff_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] : P.serreW f ↔ P (cokernel f) := by + dsimp [serreW] + have := P.prop_of_isZero (isZero_kernel_of_mono f) + tauto + +lemma serreW_iff_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] : P.serreW f ↔ P (kernel f) := by + dsimp [serreW] + have := P.prop_of_isZero (isZero_cokernel_of_epi f) + tauto + +lemma serreW_of_mono {X Y : C} (f : X ⟶ Y) [Mono f] (hf : P (cokernel f)) : P.serreW f := by + rwa [serreW_iff_of_mono] + +lemma serreW_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hf : P (kernel f)) : P.serreW f := by + rwa [serreW_iff_of_epi] + +lemma serreW_of_isIso {X Y : C} (f : X ⟶ Y) [IsIso f] : P.serreW f := + P.serreW_of_epi _ (P.prop_of_isZero (isZero_kernel_of_mono f)) + +instance : P.serreW.IsMultiplicative where + id_mem _ := P.serreW_of_isIso _ + comp_mem f g hf hg := + ⟨P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 0) hf.1 hg.1, + P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 3) hf.2 hg.2⟩ + +instance : P.serreW.HasTwoOutOfThreeProperty where + of_postcomp f g hg hfg := + ⟨P.prop_of_mono (kernel.map f (f ≫ g) (𝟙 _) g (by simp)) hfg.1, + P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 2) hg.1 hfg.2⟩ + of_precomp f g hf hfg := + ⟨P.prop_X₂_of_exact ((kernelCokernelCompSequence_exact f g).exact 1) hfg.1 hf.2, + P.prop_of_epi (cokernel.map (f ≫ g) g f (𝟙 _) (by simp)) hfg.2⟩ + +instance : P.serreW.IsStableUnderRetracts where + of_retract {X' Y' X Y} f' f h hf := + ⟨P.prop_of_mono (kernel.map f' f h.left.i h.right.i (by simp)) hf.1, + P.prop_of_epi (cokernel.map f f' h.left.r h.right.r (by simp)) hf.2⟩ + +instance : P.serreW.RespectsIso := inferInstance + +end ObjectProperty + +end CategoryTheory From e9ae5e9100a0174274605838fc36e7f123344a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Wed, 26 Feb 2025 13:04:24 +0100 Subject: [PATCH 22/46] wip --- Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index b7a77a8205da05..5451bc5028a2ee 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -4,10 +4,6 @@ Released under Apache 2.0 license as described in the file LICENSE. Authors: Joël Riou -/ import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty -import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp -import Mathlib.CategoryTheory.MorphismProperty.Composition -import Mathlib.CategoryTheory.MorphismProperty.Retract -import Mathlib.CategoryTheory.Subobject.Lattice /-! # Localization with respect to a Serre class From 18249e06181d011531380262c0c2393e0ff24978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 9 Mar 2025 16:08:51 +0100 Subject: [PATCH 23/46] wip --- Mathlib.lean | 1 + .../Abelian/SerreClass/Bousfield.lean | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 Mathlib/CategoryTheory/Abelian/SerreClass/Bousfield.lean diff --git a/Mathlib.lean b/Mathlib.lean index 752bc8e38594c6..672178e7894683 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -1764,6 +1764,7 @@ import Mathlib.CategoryTheory.Abelian.Pseudoelements import Mathlib.CategoryTheory.Abelian.Refinements import Mathlib.CategoryTheory.Abelian.RightDerived import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +import Mathlib.CategoryTheory.Abelian.SerreClass.Bousfield import Mathlib.CategoryTheory.Abelian.SerreClass.Localization import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty import Mathlib.CategoryTheory.Abelian.Subobject diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Bousfield.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Bousfield.lean new file mode 100644 index 00000000000000..ca11a980b56fb7 --- /dev/null +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Bousfield.lean @@ -0,0 +1,71 @@ +/- +Copyright (c) 2025 Joël Riou. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Joël Riou +-/ +import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty +import Mathlib.CategoryTheory.Localization.Bousfield + +/-! +# Bousfield localizations with respect to Serre classes + +-/ + +namespace CategoryTheory + +open Localization Limits MorphismProperty + +variable {C D : Type*} [Category C] [Category D] + +abbrev Functor.kernel (G : D ⥤ C) : ObjectProperty D := + ObjectProperty.inverseImage IsZero G + +variable [Abelian C] [Abelian D] (G : D ⥤ C) + [PreservesFiniteLimits G] [PreservesFiniteColimits G] + +namespace Abelian + +example : G.kernel.IsSerreClass := inferInstance + +lemma serreW_kernel_eq_inverseImage_isomorphisms : + G.kernel.serreW = (isomorphisms C).inverseImage G := by + ext X Y f + simp only [inverseImage_iff, isomorphisms.iff, ObjectProperty.serreW, + ObjectProperty.prop_inverseImage_iff] + have h₁ : Mono (G.map f) ↔ IsZero (G.obj (kernel f)) := by + have hS : ((ShortComplex.mk _ _ (kernel.condition f)).map G).Exact := + (ShortComplex.exact_of_f_is_kernel _ (kernelIsKernel f)).map G + have := hS.mono_g_iff + dsimp at this + rw [this] + refine ⟨fun h ↦ ?_, fun h ↦ h.eq_of_src _ _⟩ + rw [IsZero.iff_id_eq_zero, ← cancel_mono (G.map (kernel.ι f)), h, comp_zero, zero_comp] + have h₂ : Epi (G.map f) ↔ IsZero (G.obj (cokernel f)) := by + have hS : ((ShortComplex.mk _ _ (cokernel.condition f)).map G).Exact := + (ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel f)).map G + have := hS.epi_f_iff + dsimp at this + rw [this] + refine ⟨fun h ↦ ?_, fun h ↦ h.eq_of_tgt _ _⟩ + rw [IsZero.iff_id_eq_zero, ← cancel_epi (G.map (cokernel.π f)), h, comp_zero, zero_comp] + rw [← h₁, ← h₂] + constructor + · rintro ⟨_, _⟩ + exact isIso_of_mono_of_epi (G.map f) + · intro; constructor <;> infer_instance + +lemma serreW_kernel_eq_leftBousfield_W_of_rightAdjoint + {F : C ⥤ D} (adj : G ⊣ F) [F.Full] [F.Faithful] : + G.kernel.serreW = (LeftBousfield.W (· ∈ Set.range F.obj)) := by + rw [LeftBousfield.W_eq_inverseImage_isomorphisms adj, + serreW_kernel_eq_inverseImage_isomorphisms] + +lemma isLocalization_serreW_kernel_of_leftAdjoint + {F : C ⥤ D} (adj : G ⊣ F) [F.Full] [F.Faithful] : + G.IsLocalization G.kernel.serreW := by + rw [serreW_kernel_eq_inverseImage_isomorphisms G] + exact adj.isLocalization + +end Abelian + +end CategoryTheory From 8d15ddd2bab720708d3200411847819aa8c35bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 9 Mar 2025 16:38:22 +0100 Subject: [PATCH 24/46] wip --- .../ObjectProperty/ClosedUnderIsomorphisms.lean | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean index ceb927ce3c1454..3fb529a5b38985 100644 --- a/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean +++ b/Mathlib/CategoryTheory/ObjectProperty/ClosedUnderIsomorphisms.lean @@ -10,11 +10,7 @@ import Mathlib.Order.Basic /-! # Properties of objects which are closed under isomorphisms Given a category `C` and `P : ObjectProperty C` (i.e. `P : C → Prop`), -<<<<<<< HEAD -this file introduces the type class `P.IsClosedUnderIsomorphisms P`. -======= this file introduces the type class `P.IsClosedUnderIsomorphisms`. ->>>>>>> origin -/ From 86bf02e769c15968853124b521ef190559d57faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 24 Jan 2026 16:04:52 +0100 Subject: [PATCH 25/46] wip --- Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 3c40675002b964..af57c24914c9fd 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -102,8 +102,8 @@ instance : Category (DefDomain X Y) where id := Hom.id comp := Hom.comp -instance : Subsingleton (d₁ ⟶ d₂) := - inferInstanceAs (Subsingleton (Hom d₁ d₂)) +instance : Quiver.IsThin (DefDomain X Y) := + fun d₁ d₂ ↦ inferInstanceAs (Subsingleton (Hom d₁ d₂)) end Hom From e5b1ca53287f411a3a81f94d2751f05487120b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 24 Jan 2026 17:02:40 +0100 Subject: [PATCH 26/46] wip --- .../Abelian/SerreClass/Localization.lean | 26 +++++++++++++------ .../Abelian/SerreClass/MorphismProperty.lean | 10 +++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index af57c24914c9fd..166b95a1f48097 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -124,15 +124,13 @@ lemma exists_min : let d : DefDomain X Y := { src := pullback d₁.i d₂.i i := pullback.fst _ _ ≫ d₁.i - hi := by - refine MorphismProperty.comp_mem _ _ _ ?_ d₁.hi - sorry + hi := MorphismProperty.comp_mem _ _ _ + (MorphismProperty.pullback_fst _ _ d₂.hi) d₁.hi tgt := pushout d₁.p d₂.p p := d₁.p ≫ pushout.inl _ _ - hp := by - refine MorphismProperty.comp_mem _ _ _ d₁.hp ?_ - sorry } - refine ⟨d, ⟨{ ι := pullback.fst _ _, π := pushout.inl _ _ }⟩, ⟨ + hp := MorphismProperty.comp_mem _ _ _ d₁.hp + (MorphismProperty.pushout_inl _ _ d₂.hp) } + exact ⟨d, ⟨{ ι := pullback.fst _ _, π := pushout.inl _ _ }⟩, ⟨ { ι := pullback.snd _ _, ι_i := pullback.condition.symm π := pushout.inr _ _ @@ -150,6 +148,17 @@ structure CompStruct (d₁₂ : DefDomain X Y) (d₂₃ : DefDomain Y Z) (d₁ epi_toObj : Epi toObj mono_toObj : Mono toObj +namespace CompStruct + +variable {d₁₂ : DefDomain X Y} {d₂₃ : DefDomain Y Z} {d₁₃ : DefDomain X Z} + (h : CompStruct d₁₂ d₂₃ d₁₃) + +instance : Mono h.ι := mono_of_mono_fac h.ι_i + +instance : Epi h.π := epi_of_epi_fac h.p_π + +end CompStruct + end DefDomain variable {X Y} in @@ -246,7 +255,8 @@ structure CompStruct {d₁₃ : DefDomain X Z} namespace CompStruct lemma nonempty : ∃ (d₁₃ : DefDomain X Z) - (h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃), Nonempty (CompStruct a b h) := sorry + (h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃), Nonempty (CompStruct a b h) := by + sorry variable {a b} def comp {d₁₃ : DefDomain X Z} diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean index 0a2034687217ad..58f5247f369b68 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -9,6 +9,7 @@ public import Mathlib.CategoryTheory.Abelian.SerreClass.Basic public import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp public import Mathlib.CategoryTheory.MorphismProperty.Composition public import Mathlib.CategoryTheory.MorphismProperty.Retract +public import Mathlib.CategoryTheory.MorphismProperty.Limits public import Mathlib.CategoryTheory.MorphismProperty.IsInvertedBy /-! @@ -169,6 +170,15 @@ lemma isoModSerre_isInvertedBy_iff (F : C ⥤ D) (cokernelIsCokernel f)).map F).epi_f (((hF _ h₂).eq_of_tgt _ _)) exact isIso_of_mono_of_epi (F.map f) +instance : P.isoModSerre.IsStableUnderBaseChange := by + have : P.IsSerreClass := inferInstance + sorry + +instance : P.isoModSerre.IsStableUnderCobaseChange := by + have : P.IsSerreClass := inferInstance + sorry + + end ObjectProperty end CategoryTheory From 237054f2cf02d34508954dd8c4c6c68349dd4c8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 24 Jan 2026 17:03:50 +0100 Subject: [PATCH 27/46] wip --- .../CategoryTheory/Abelian/SerreClass/Localization.lean | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 166b95a1f48097..65f0d2d6951e07 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -41,11 +41,11 @@ namespace Hom structure DefDomain where src : C i : src ⟶ X.obj - [mono_i : Mono i] + mono_i : Mono i := by infer_instance hi : P.isoModSerre i tgt : C p : Y.obj ⟶ tgt - [epi_p : Epi p] + epi_p : Epi p := by infer_instance hp : P.isoModSerre p namespace DefDomain @@ -145,8 +145,8 @@ structure CompStruct (d₁₂ : DefDomain X Y) (d₂₃ : DefDomain Y Z) (d₁ toObj : d₂₃.src ⟶ obj fromObj : obj ⟶ d₁₂.tgt fac : toObj ≫ fromObj = d₂₃.i ≫ d₁₂.p := by cat_disch - epi_toObj : Epi toObj - mono_toObj : Mono toObj + epi_toObj : Epi toObj := by infer_instance + mono_toObj : Mono toObj := by infer_instance namespace CompStruct From 6a18cdd566b4479298a8e9196b1418ceebe7922f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 24 Jan 2026 20:13:44 +0100 Subject: [PATCH 28/46] wip --- .../Abelian/SerreClass/Localization.lean | 14 ++++-- .../Abelian/SerreClass/MorphismProperty.lean | 48 ++++++++++++++++++- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 65f0d2d6951e07..cf013cbea51b5e 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -39,11 +39,11 @@ variable {P} (X Y Z T : P.SerreClassLocalization) namespace Hom structure DefDomain where - src : C + {src : C} i : src ⟶ X.obj mono_i : Mono i := by infer_instance hi : P.isoModSerre i - tgt : C + {tgt : C} p : Y.obj ⟶ tgt epi_p : Epi p := by infer_instance hp : P.isoModSerre p @@ -54,10 +54,8 @@ attribute [instance] mono_i epi_p @[simps] def top : DefDomain X Y where - src := X.obj i := 𝟙 X.obj hi := MorphismProperty.id_mem _ _ - tgt := Y.obj p := 𝟙 Y.obj hp := MorphismProperty.id_mem _ _ @@ -157,6 +155,14 @@ instance : Mono h.ι := mono_of_mono_fac h.ι_i instance : Epi h.π := epi_of_epi_fac h.p_π +-- is this useful without additional conditions? +lemma nonempty (d₁₂ : DefDomain X Y) (d₂₃ : DefDomain Y Z) : + ∃ (d₁₃ : DefDomain X Z), Nonempty (CompStruct d₁₂ d₂₃ d₁₃) := + ⟨{i := d₁₂.i + hi := d₁₂.hi + p := d₂₃.p + hp := d₂₃.hp }, sorry⟩ + end CompStruct end DefDomain diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean index 58f5247f369b68..03047e92a33d20 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -39,6 +39,18 @@ open Category Limits ZeroObject MorphismProperty variable {C : Type u} [Category.{v} C] [Abelian C] {D : Type u'} [Category.{v'} D] [Abelian D] +instance {X Y X' Y' : C} (f : X ⟶ Y) (f' : X' ⟶ Y') + (g : X ⟶ X') (g' : Y ⟶ Y') (h : f ≫ g' = g ≫ f') + [IsIso g] [Mono g'] : + IsIso (kernel.map f f' g g' h) := by + sorry + +instance {X Y X' Y' : C} (f : X ⟶ Y) (f' : X' ⟶ Y') + (g : X ⟶ X') (g' : Y ⟶ Y') (h : f ≫ g' = g ≫ f') + [Epi g] [IsIso g'] : + IsIso (cokernel.map f f' g g' h) := by + sorry + namespace ObjectProperty variable (P : ObjectProperty C) @@ -170,9 +182,41 @@ lemma isoModSerre_isInvertedBy_iff (F : C ⥤ D) (cokernelIsCokernel f)).map F).epi_f (((hF _ h₂).eq_of_tgt _ _)) exact isIso_of_mono_of_epi (F.map f) +variable {P} in +nonrec lemma isoModSerre.factorThruImage {X Y : C} {f : X ⟶ Y} + (hf : P.isoModSerre f) : + P.isoModSerre (factorThruImage f) := by + rw [isoModSerre_iff_of_epi, monoModSerre_iff] + exact P.prop_of_iso (asIso (kernel.map (factorThruImage f) f (𝟙 X) + (image.ι f) (by simp))).symm hf.1 + +variable {P} in +lemma isoModSerre.image_ι {X Y : C} {f : X ⟶ Y} + (hf : P.isoModSerre f) : + P.isoModSerre (image.ι f) := by + rw [isoModSerre_iff_of_mono, epiModSerre_iff] + exact P.prop_of_iso + (asIso (cokernel.map f (image.ι f) (Limits.factorThruImage f) (𝟙 Y) (by simp))) hf.2 + instance : P.isoModSerre.IsStableUnderBaseChange := by - have : P.IsSerreClass := inferInstance - sorry + suffices ∀ ⦃X Y : C⦄ (f : X ⟶ Y) (h : Mono f ∨ Epi f) (hf : P.isoModSerre f) + ⦃X' Y' : C⦄ ⦃f' : X' ⟶ Y'⦄ ⦃g' : X' ⟶ X⦄ ⦃g : Y' ⟶ Y⦄ + (sq : IsPullback g' f' f g), P.isoModSerre f' from + ⟨fun {_ _ _ _ g f g' f'} sq hf ↦ by + let f'' : _ ⟶ pullback (image.ι f) g := + pullback.lift (g' ≫ factorThruImage f) f' (by simp [sq.w]) + have sq' : IsPullback g' f'' (factorThruImage f) + (pullback.fst _ _) := + IsPullback.of_bot (by simpa [f'']) (by cat_disch) + (IsPullback.of_hasPullback (image.ι f) g) + rw [show f' = f'' ≫ pullback.snd (image.ι f) g by cat_disch] + refine P.isoModSerre.comp_mem _ _ + (this _ (Or.inr inferInstance) hf.factorThruImage sq') + (this _ (Or.inl inferInstance) hf.image_ι + (IsPullback.of_hasPullback (image.ι f) g))⟩ + rintro X Y f (_ | _) hf X' Y' f' g' g sq + · sorry + · sorry instance : P.isoModSerre.IsStableUnderCobaseChange := by have : P.IsSerreClass := inferInstance From 6b9112c8a5d02fbee84ddac763c09563d4a454b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sat, 24 Jan 2026 22:13:37 +0100 Subject: [PATCH 29/46] wip --- .../Abelian/SerreClass/MorphismProperty.lean | 127 +++++++++++------- 1 file changed, 80 insertions(+), 47 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean index 03047e92a33d20..f92fba29821c25 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -5,6 +5,7 @@ Authors: Joël Riou -/ module +public import Mathlib.Algebra.Homology.Square public import Mathlib.CategoryTheory.Abelian.SerreClass.Basic public import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp public import Mathlib.CategoryTheory.MorphismProperty.Composition @@ -36,20 +37,65 @@ namespace CategoryTheory open Category Limits ZeroObject MorphismProperty +section -- to be moved + +variable {C : Type*} [Category* C] [HasZeroMorphisms C] + {X₁ X₂ X₃ X₄ : C} {t : X₁ ⟶ X₂} {l : X₁ ⟶ X₃} {r : X₂ ⟶ X₄} {b : X₃ ⟶ X₄} + +lemma Abelian.isIso_kernel_map_of_isPullback [HasKernel t] [HasKernel b] + (sq : IsPullback t l r b) : + IsIso (kernel.map _ _ _ _ sq.w) := + ⟨kernel.lift _ (sq.lift 0 (kernel.ι b) (by simp)) (by simp), + by ext; exact sq.hom_ext (by cat_disch) (by cat_disch), by cat_disch⟩ + +lemma Abelian.isIso_cokernel_map_of_isPushout [HasCokernel t] [HasCokernel b] + (sq : IsPushout t l r b) : + IsIso (cokernel.map _ _ _ _ sq.w) := + ⟨cokernel.desc _ (sq.desc (cokernel.π t) 0 (by simp)) (by simp), + by cat_disch, by ext; exact sq.hom_ext (by cat_disch) (by cat_disch)⟩ + +end + variable {C : Type u} [Category.{v} C] [Abelian C] {D : Type u'} [Category.{v'} D] [Abelian D] -instance {X Y X' Y' : C} (f : X ⟶ Y) (f' : X' ⟶ Y') - (g : X ⟶ X') (g' : Y ⟶ Y') (h : f ≫ g' = g ≫ f') - [IsIso g] [Mono g'] : - IsIso (kernel.map f f' g g' h) := by - sorry - -instance {X Y X' Y' : C} (f : X ⟶ Y) (f' : X' ⟶ Y') - (g : X ⟶ X') (g' : Y ⟶ Y') (h : f ≫ g' = g ≫ f') - [Epi g] [IsIso g'] : - IsIso (cokernel.map f f' g g' h) := by - sorry +namespace Abelian -- to be moved + +variable {X₁ X₂ X₃ X₄ : C} {t : X₁ ⟶ X₂} {l : X₁ ⟶ X₃} {r : X₂ ⟶ X₄} {b : X₃ ⟶ X₄} + +lemma mono_cokernel_map_of_isPullback (sq : IsPullback t l r b) : + Mono (cokernel.map _ _ _ _ sq.w) := by + rw [Preadditive.mono_iff_cancel_zero] + intro A₀ z hz + obtain ⟨A₁, π₁, _, x₂, hx₂⟩ := + surjective_up_to_refinements_of_epi (cokernel.π t) z + have : (ShortComplex.mk _ _ (cokernel.condition b)).Exact := + ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel b) + obtain ⟨A₂, π₂, _, x₃, hx₃⟩ := this.exact_up_to_refinements (x₂ ≫ r) (by + simpa [hz] using hx₂.symm =≫ cokernel.map _ _ _ _ sq.w) + obtain ⟨x₁, hx₁, rfl⟩ := sq.exists_lift (π₂ ≫ x₂) x₃ (by simpa) + simp [← cancel_epi π₁, ← cancel_epi π₂, hx₂, ← reassoc_of% hx₁] + +lemma epi_kernel_map_of_isPushout (sq : IsPushout t l r b) : + Epi (kernel.map _ _ _ _ sq.w) := by + rw [epi_iff_surjective_up_to_refinements] + intro A₀ z + obtain ⟨A₁, π₁, _, x₁, hx₁⟩ := ((ShortComplex.mk _ _ + sq.cokernelCofork.condition).exact_of_g_is_cokernel + sq.isColimitCokernelCofork).exact_up_to_refinements + (z ≫ kernel.ι _ ≫ biprod.inr) (by simp) + refine ⟨A₁, π₁, inferInstance, -kernel.lift _ x₁ ?_, ?_⟩ + · simpa using hx₁.symm =≫ biprod.fst + · ext + simpa using hx₁ =≫ biprod.snd + +end Abelian + +instance : (monomorphisms C).IsStableUnderCobaseChange := + .mk' (fun _ _ _ _ _ _ (_ : Mono _) ↦ inferInstanceAs (Mono _)) + +instance : (epimorphisms C).IsStableUnderBaseChange := + .mk' (fun _ _ _ _ _ _ (_ : Epi _) ↦ inferInstanceAs (Epi _)) namespace ObjectProperty @@ -182,46 +228,33 @@ lemma isoModSerre_isInvertedBy_iff (F : C ⥤ D) (cokernelIsCokernel f)).map F).epi_f (((hF _ h₂).eq_of_tgt _ _)) exact isIso_of_mono_of_epi (F.map f) -variable {P} in -nonrec lemma isoModSerre.factorThruImage {X Y : C} {f : X ⟶ Y} - (hf : P.isoModSerre f) : - P.isoModSerre (factorThruImage f) := by - rw [isoModSerre_iff_of_epi, monoModSerre_iff] - exact P.prop_of_iso (asIso (kernel.map (factorThruImage f) f (𝟙 X) - (image.ι f) (by simp))).symm hf.1 - -variable {P} in -lemma isoModSerre.image_ι {X Y : C} {f : X ⟶ Y} - (hf : P.isoModSerre f) : - P.isoModSerre (image.ι f) := by - rw [isoModSerre_iff_of_mono, epiModSerre_iff] - exact P.prop_of_iso - (asIso (cokernel.map f (image.ι f) (Limits.factorThruImage f) (𝟙 Y) (by simp))) hf.2 +instance : P.monoModSerre.IsStableUnderBaseChange where + of_isPullback sq h := + have := Abelian.isIso_kernel_map_of_isPullback sq.flip + P.prop_of_iso (asIso (kernel.map _ _ _ _ sq.w.symm)).symm h + +instance : P.epiModSerre.IsStableUnderBaseChange where + of_isPullback sq h := + have := Abelian.mono_cokernel_map_of_isPullback sq.flip + P.prop_of_mono (cokernel.map _ _ _ _ sq.w.symm) h instance : P.isoModSerre.IsStableUnderBaseChange := by - suffices ∀ ⦃X Y : C⦄ (f : X ⟶ Y) (h : Mono f ∨ Epi f) (hf : P.isoModSerre f) - ⦃X' Y' : C⦄ ⦃f' : X' ⟶ Y'⦄ ⦃g' : X' ⟶ X⦄ ⦃g : Y' ⟶ Y⦄ - (sq : IsPullback g' f' f g), P.isoModSerre f' from - ⟨fun {_ _ _ _ g f g' f'} sq hf ↦ by - let f'' : _ ⟶ pullback (image.ι f) g := - pullback.lift (g' ≫ factorThruImage f) f' (by simp [sq.w]) - have sq' : IsPullback g' f'' (factorThruImage f) - (pullback.fst _ _) := - IsPullback.of_bot (by simpa [f'']) (by cat_disch) - (IsPullback.of_hasPullback (image.ι f) g) - rw [show f' = f'' ≫ pullback.snd (image.ι f) g by cat_disch] - refine P.isoModSerre.comp_mem _ _ - (this _ (Or.inr inferInstance) hf.factorThruImage sq') - (this _ (Or.inl inferInstance) hf.image_ι - (IsPullback.of_hasPullback (image.ι f) g))⟩ - rintro X Y f (_ | _) hf X' Y' f' g' g sq - · sorry - · sorry + dsimp [isoModSerre] + infer_instance -instance : P.isoModSerre.IsStableUnderCobaseChange := by - have : P.IsSerreClass := inferInstance - sorry +instance : P.monoModSerre.IsStableUnderCobaseChange where + of_isPushout sq h := + have := Abelian.epi_kernel_map_of_isPushout sq.flip + P.prop_of_epi (kernel.map _ _ _ _ sq.w.symm) h +instance : P.epiModSerre.IsStableUnderCobaseChange where + of_isPushout sq h := + have := Abelian.isIso_cokernel_map_of_isPushout sq.flip + P.prop_of_iso (asIso (cokernel.map _ _ _ _ sq.w.symm)) h + +instance : P.isoModSerre.IsStableUnderCobaseChange := by + dsimp [isoModSerre] + infer_instance end ObjectProperty From f2bfa6c5ca583b7363d06816ffee1b7bce2bdf81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 00:45:48 +0100 Subject: [PATCH 30/46] wip --- .../Abelian/SerreClass/Localization.lean | 110 ++++++++++++++++++ .../Localization/Construction.lean | 3 + 2 files changed, 113 insertions(+) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index cf013cbea51b5e..e32219ee31e221 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -6,6 +6,7 @@ Authors: Joël Riou module public import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty +public import Mathlib.CategoryTheory.Localization.CalculusOfFractions /-! # Localization with respect to a Serre class @@ -325,6 +326,115 @@ def toSerreClassLocalization : C ⥤ P.SerreClassLocalization where map_id _ := rfl map_comp := sorry +/-! Alternative approach, in two steps: +1) Localization w.r.t. `epimorphisms C ⊓ P.isoModSerre` using a left calculus of fractions +2) Localize the resulting category using a right calculus of fractions +-/ + +namespace IsSerreClass + +namespace Localization + +instance : (P.isoModSerre ⊓ .epimorphisms _).HasLeftCalculusOfFractions where + exists_leftFraction X Y φ := + ⟨{s := pushout.inl φ.f φ.s + f := pushout.inr φ.f φ.s, + hs := MorphismProperty.pushout_inl _ _ φ.hs}, pushout.condition⟩ + ext _ _ _ f₁ f₂ s hs eq := by + have : Epi s := hs.2 + exact ⟨_, 𝟙 _, MorphismProperty.id_mem _ _, by simpa [cancel_epi] using eq⟩ + +variable {D : Type*} [Category* D] + (L : C ⥤ D) + +def LocEpi := (P.isoModSerre ⊓ .epimorphisms _).Localization + deriving Category + +def QEpi : C ⥤ LocEpi P := (P.isoModSerre ⊓ .epimorphisms _).Q + +variable {P} in +lemma QEpi_obj_surjective : Function.Surjective (QEpi P).obj := + (Localization.Construction.objEquiv _).surjective + +instance : (QEpi P).IsLocalization (P.isoModSerre ⊓ .epimorphisms _) := + inferInstanceAs ((MorphismProperty.Q _).IsLocalization _) + +instance : (QEpi P).EssSurj := + Localization.essSurj _ (P.isoModSerre ⊓ .epimorphisms _) + +def mapIsoModSerreInterEpi : + MorphismProperty (LocEpi P) := + fun ⟨⟨X⟩⟩ ⟨⟨Y⟩⟩ f ↦ ∃ (Z : C) (g : X ⟶ Z) (s : Y ⟶ Z) (_ : P.isoModSerre g) + (_ : (P.isoModSerre ⊓ .epimorphisms _) s), + f ≫ (QEpi P).map s = (QEpi P).map g + +lemma mapIsoModSerreInterEpi_iff {X Y : C} (f : (QEpi P).obj X ⟶ (QEpi P).obj Y) : + mapIsoModSerreInterEpi P f ↔ ∃ (Z : C) (g : X ⟶ Z) (s : Y ⟶ Z) (_ : P.isoModSerre g) + (_ : (P.isoModSerre ⊓ .epimorphisms _) s), f ≫ (QEpi P).map s = (QEpi P).map g := + Iff.rfl + +lemma mapIsoModSerreInterEpi.map {X Y : C} (f : X ⟶ Y) (hf : P.isoModSerre f) : + mapIsoModSerreInterEpi P ((QEpi P).map f) := by + rw [mapIsoModSerreInterEpi_iff] + exact ⟨_, f, 𝟙 _, hf, MorphismProperty.id_mem _ _, by simp⟩ + +instance : (mapIsoModSerreInterEpi P).RespectsIso := by + sorry + +instance : (mapIsoModSerreInterEpi P).IsMultiplicative where + id_mem X := by + obtain ⟨X, rfl⟩ := QEpi_obj_surjective X + rw [← Functor.map_id] + exact mapIsoModSerreInterEpi.map _ _ (MorphismProperty.id_mem _ _) + comp_mem := sorry + +instance : (mapIsoModSerreInterEpi P).HasRightCalculusOfFractions where + exists_rightFraction := by + let L := QEpi P + suffices ∀ {X Y Z : C} (f : L.obj X ⟶ L.obj Z) (s : L.obj Y ⟶ L.obj Z) + (hs : mapIsoModSerreInterEpi P s), + ∃ (ψ : (mapIsoModSerreInterEpi P).RightFraction (L.obj X) (L.obj Y)), + ψ.s ≫ f = ψ.f ≫ s by + intro X Y φ + let eX := L.objObjPreimageIso X + let eY := L.objObjPreimageIso Y + let eY' := L.objObjPreimageIso φ.Y' + obtain ⟨ψ, fac⟩ := this (eX.hom ≫ φ.f ≫ eY'.inv) (eY.hom ≫ φ.s ≫ eY'.inv) + ((MorphismProperty.arrow_mk_iso_iff _ (Arrow.isoMk eY eY')).2 φ.hs) + exact + ⟨{s := ψ.s ≫ eX.hom + f := ψ.f ≫ eY.hom + hs := (MorphismProperty.arrow_mk_iso_iff _ + (by exact Arrow.isoMk (Iso.refl _) eX)).1 ψ.hs }, by simpa [← cancel_mono eY'.inv]⟩ + intro X Y Z f s hs + obtain ⟨φf, rfl⟩ := Localization.exists_leftFraction L (P.isoModSerre ⊓ .epimorphisms _) f + obtain ⟨φs, rfl⟩ := Localization.exists_leftFraction L (P.isoModSerre ⊓ .epimorphisms _) s + let W := pushout φf.s φs.s + let f' : X ⟶ W := φf.f ≫ pushout.inl _ _ + let s' : Y ⟶ W := φs.f ≫ pushout.inr _ _ + refine ⟨{ + X' := L.obj (pullback f' s') + s := L.map (pullback.fst _ _) + hs := by + refine mapIsoModSerreInterEpi.map P _ + (MorphismProperty.pullback_fst _ _ + (MorphismProperty.comp_mem _ _ _ ?_ (MorphismProperty.pushout_inr _ _ φf.hs.1))) + sorry + f := L.map (pullback.snd _ _) }, ?_⟩ + have := Localization.inverts L (P.isoModSerre ⊓ .epimorphisms _) φf.s φf.hs + have := Localization.inverts L (P.isoModSerre ⊓ .epimorphisms _) + (pushout.inl φf.s φs.s) (MorphismProperty.pushout_inl _ _ φs.hs) + rw [← cancel_mono (L.map φf.s), assoc, MorphismProperty.LeftFraction.map_comp_map_s, + ← cancel_mono (L.map (pushout.inl φf.s φs.s)), assoc, assoc, assoc, + ← L.map_comp, ← L.map_comp, pullback.condition, + ← L.map_comp, pushout.condition, L.map_comp, L.map_comp, L.map_comp, + MorphismProperty.LeftFraction.map_comp_map_s_assoc] + ext := sorry + +end Localization + +end IsSerreClass + end ObjectProperty end CategoryTheory diff --git a/Mathlib/CategoryTheory/Localization/Construction.lean b/Mathlib/CategoryTheory/Localization/Construction.lean index 2a7f659f1a6edb..d787c51be70c5d 100644 --- a/Mathlib/CategoryTheory/Localization/Construction.lean +++ b/Mathlib/CategoryTheory/Localization/Construction.lean @@ -191,6 +191,9 @@ def objEquiv : C ≃ W.Localization where rintro ⟨⟨X⟩⟩ rfl +instance : W.Q.EssSurj where + mem_essImage Y := ⟨(objEquiv W).symm Y, ⟨Iso.refl _⟩⟩ + /-- A `MorphismProperty` in `W.Localization` is satisfied by all morphisms in the localized category if it contains the image of the morphisms in the original category, the inverses of the morphisms From ea0297b1d700aa46e4db9239979f831bec74bf4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 14:31:11 +0100 Subject: [PATCH 31/46] wip --- .../Abelian/SerreClass/Localization.lean | 449 ++---------------- .../Abelian/SerreClass/MorphismProperty.lean | 10 + .../CalculusOfFractions/Preadditive.lean | 36 +- 3 files changed, 92 insertions(+), 403 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index e32219ee31e221..5c74d8b3c75d34 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -6,7 +6,8 @@ Authors: Joël Riou module public import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty -public import Mathlib.CategoryTheory.Localization.CalculusOfFractions +public import Mathlib.CategoryTheory.Localization.CalculusOfFractions.Preadditive +public import Mathlib.CategoryTheory.Localization.Composition /-! # Localization with respect to a Serre class @@ -29,411 +30,55 @@ namespace ObjectProperty variable (P : ObjectProperty C) [P.IsSerreClass] -@[nolint unusedArguments] -structure SerreClassLocalization (P : ObjectProperty C) [P.IsSerreClass] : Type u where - obj : C - -namespace SerreClassLocalization - -variable {P} (X Y Z T : P.SerreClassLocalization) - -namespace Hom - -structure DefDomain where - {src : C} - i : src ⟶ X.obj - mono_i : Mono i := by infer_instance - hi : P.isoModSerre i - {tgt : C} - p : Y.obj ⟶ tgt - epi_p : Epi p := by infer_instance - hp : P.isoModSerre p - -namespace DefDomain - -attribute [instance] mono_i epi_p - -@[simps] -def top : DefDomain X Y where - i := 𝟙 X.obj - hi := MorphismProperty.id_mem _ _ - p := 𝟙 Y.obj - hp := MorphismProperty.id_mem _ _ - -variable {X Y Z T} (d₁ d₂ d₃ : DefDomain X Y) - -structure Hom where - ι : d₁.src ⟶ d₂.src - ι_i : ι ≫ d₂.i = d₁.i := by cat_disch - π : d₂.tgt ⟶ d₁.tgt - p_π : d₂.p ≫ π = d₁.p := by cat_disch - -namespace Hom - -attribute [reassoc (attr := simp)] ι_i p_π - -@[simps] -def id (d : DefDomain X Y) : Hom d d where - ι := 𝟙 _ - π := 𝟙 _ - -variable {d₁ d₂ d₃} in -@[simps] -def comp (φ : Hom d₁ d₂) (ψ : Hom d₂ d₃) : Hom d₁ d₃ where - ι := φ.ι ≫ ψ.ι - π := ψ.π ≫ φ.π - -variable (φ : Hom d₁ d₂) - -instance : Mono φ.ι := mono_of_mono_fac φ.ι_i - -instance : Epi φ.π := epi_of_epi_fac φ.p_π - -instance : Subsingleton (Hom d₁ d₂) where - allEq φ ψ := by - suffices φ.ι = ψ.ι ∧ φ.π = ψ.π by cases φ; cases ψ; aesop - constructor - · simp [← cancel_mono d₂.i] - · simp [← cancel_epi d₂.p] - -instance : Category (DefDomain X Y) where - Hom := Hom - id := Hom.id - comp := Hom.comp - -instance : Quiver.IsThin (DefDomain X Y) := - fun d₁ d₂ ↦ inferInstanceAs (Subsingleton (Hom d₁ d₂)) - -end Hom - -@[simp] lemma id_ι (d : DefDomain X Y) : Hom.ι (𝟙 d) = 𝟙 _ := rfl -@[simp] lemma id_π (d : DefDomain X Y) : Hom.π (𝟙 d) = 𝟙 _ := rfl - -section - -variable {d₁ d₂ d₃} - -@[simp] lemma comp_ι (f : d₁ ⟶ d₂) (g : d₂ ⟶ d₃) : (f ≫ g).ι = f.ι ≫ g.ι := rfl -@[simp] lemma comp_π (f : d₁ ⟶ d₂) (g : d₂ ⟶ d₃) : (f ≫ g).π = g.π ≫ f.π := rfl - -end - -lemma exists_min : - ∃ (d : DefDomain X Y), Nonempty (d ⟶ d₁) ∧ Nonempty (d ⟶ d₂) := by - let d : DefDomain X Y := - { src := pullback d₁.i d₂.i - i := pullback.fst _ _ ≫ d₁.i - hi := MorphismProperty.comp_mem _ _ _ - (MorphismProperty.pullback_fst _ _ d₂.hi) d₁.hi - tgt := pushout d₁.p d₂.p - p := d₁.p ≫ pushout.inl _ _ - hp := MorphismProperty.comp_mem _ _ _ d₁.hp - (MorphismProperty.pushout_inl _ _ d₂.hp) } - exact ⟨d, ⟨{ ι := pullback.fst _ _, π := pushout.inl _ _ }⟩, ⟨ - { ι := pullback.snd _ _, - ι_i := pullback.condition.symm - π := pushout.inr _ _ - p_π := pushout.condition.symm }⟩⟩ - -structure CompStruct (d₁₂ : DefDomain X Y) (d₂₃ : DefDomain Y Z) (d₁₃ : DefDomain X Z) where - ι : d₁₃.src ⟶ d₁₂.src - ι_i : ι ≫ d₁₂.i = d₁₃.i := by cat_disch - π : d₂₃.tgt ⟶ d₁₃.tgt - p_π : d₂₃.p ≫ π = d₁₃.p := by cat_disch - obj : C - toObj : d₂₃.src ⟶ obj - fromObj : obj ⟶ d₁₂.tgt - fac : toObj ≫ fromObj = d₂₃.i ≫ d₁₂.p := by cat_disch - epi_toObj : Epi toObj := by infer_instance - mono_toObj : Mono toObj := by infer_instance - -namespace CompStruct - -variable {d₁₂ : DefDomain X Y} {d₂₃ : DefDomain Y Z} {d₁₃ : DefDomain X Z} - (h : CompStruct d₁₂ d₂₃ d₁₃) - -instance : Mono h.ι := mono_of_mono_fac h.ι_i - -instance : Epi h.π := epi_of_epi_fac h.p_π - --- is this useful without additional conditions? -lemma nonempty (d₁₂ : DefDomain X Y) (d₂₃ : DefDomain Y Z) : - ∃ (d₁₃ : DefDomain X Z), Nonempty (CompStruct d₁₂ d₂₃ d₁₃) := - ⟨{i := d₁₂.i - hi := d₁₂.hi - p := d₂₃.p - hp := d₂₃.hp }, sorry⟩ - -end CompStruct - -end DefDomain - -variable {X Y} in -abbrev restrict {d₁ d₂ : DefDomain X Y} (φ : d₁ ⟶ d₂) (f : d₂.src ⟶ d₂.tgt) : - d₁.src ⟶ d₁.tgt := - φ.ι ≫ f ≫ φ.π - -end Hom - -abbrev Hom' := Σ (d : Hom.DefDomain X Y), d.src ⟶ d.tgt - -section - -variable {X Y Z T} - -abbrev Hom'.mk {d : Hom.DefDomain X Y} (φ : d.src ⟶ d.tgt) : Hom' X Y := ⟨d, φ⟩ - -lemma Hom'.mk_surjective (a : Hom' X Y) : - ∃ (d : Hom.DefDomain X Y) (φ : d.src ⟶ d.tgt), a = .mk φ := - ⟨a.1, a.2, rfl⟩ - -end - -inductive Hom'Rel : Hom' X Y → Hom' X Y → Prop - | restrict (d₁ d₂ : Hom.DefDomain X Y) (φ : d₁ ⟶ d₂) (f : d₂.src ⟶ d₂.tgt) : - Hom'Rel ⟨d₂, f⟩ ⟨d₁, Hom.restrict φ f⟩ - -def Hom := Quot (Hom'Rel X Y) - -namespace Hom - -variable {X Y Z T} - -def mk {d : Hom.DefDomain X Y} (φ : d.src ⟶ d.tgt) : Hom X Y := - Quot.mk _ (.mk φ) - -lemma quotMk_eq_quotMk_iff {x y : Hom' X Y} : - Quot.mk (Hom'Rel X Y) x = Quot.mk (Hom'Rel X Y) y ↔ - ∃ (d : DefDomain X Y) (φ₁ : d ⟶ x.1) (φ₂ : d ⟶ y.1), - restrict φ₁ x.2 = restrict φ₂ y.2 := by - constructor - · intro h - rw [Quot.eq] at h - induction h with - | rel _ _ h => - obtain ⟨d₁, d₂, φ, f⟩ := h - exact ⟨d₁, φ, 𝟙 _, by simp [restrict]⟩ - | refl x => - exact ⟨_, 𝟙 _, 𝟙 _, by simp [restrict]⟩ - | symm _ _ _ h => - obtain ⟨_, _, _, eq⟩ := h - exact ⟨_, _, _, eq.symm⟩ - | trans _ _ _ _ _ h₁₂ h₂₃ => - obtain ⟨d₁₂, φ₁, φ₂, eq₁₂⟩ := h₁₂ - obtain ⟨d₂₃, ψ₂, ψ₃, eq₂₃⟩ := h₂₃ - obtain ⟨d, ⟨i₁₂⟩, ⟨i₂₃⟩⟩ := DefDomain.exists_min d₁₂ d₂₃ - refine ⟨d, i₁₂ ≫ φ₁, i₂₃ ≫ ψ₃, ?_⟩ - simp only [restrict] at eq₁₂ eq₂₃ - simp only [restrict, DefDomain.comp_ι, DefDomain.comp_π, assoc] - have hι := congr_arg DefDomain.Hom.ι (Subsingleton.elim (i₁₂ ≫ φ₂) (i₂₃ ≫ ψ₂)) - have hπ := congr_arg DefDomain.Hom.π (Subsingleton.elim (i₁₂ ≫ φ₂) (i₂₃ ≫ ψ₂)) - dsimp at hι hπ - rw [reassoc_of% eq₁₂, ← reassoc_of% eq₂₃, reassoc_of% hι, hπ] - · obtain ⟨d₁, f₁, rfl⟩ := x.mk_surjective - obtain ⟨d₂, f₂, rfl⟩ := y.mk_surjective - rintro ⟨d, φ₁, φ₂, h⟩ - trans mk (Hom.restrict φ₁ f₁) - · exact (Quot.sound (by constructor)) - · rw [h] - exact (Quot.sound (by constructor)).symm - -lemma ext_iff {d₁ d₂ : DefDomain X Y} (f₁ : d₁.src ⟶ d₁.tgt) (f₂ : d₂.src ⟶ d₂.tgt) : - mk f₁ = mk f₂ ↔ ∃ (d : DefDomain X Y) (φ₁ : d ⟶ d₁) (φ₂ : d ⟶ d₂), - restrict φ₁ f₁ = restrict φ₂ f₂ := by - apply quotMk_eq_quotMk_iff - -variable (P) in -def ofHom {X Y : C} (f : X ⟶ Y) : Hom (P := P) ⟨X⟩ ⟨Y⟩ := - mk (d := DefDomain.top _ _) f - -variable (X) in -abbrev id : Hom X X := ofHom P (𝟙 X.obj) - -variable {d₁₂ : DefDomain X Y} {d₂₃ : DefDomain Y Z} - (a : d₁₂.src ⟶ d₁₂.tgt) (b : d₂₃.src ⟶ d₂₃.tgt) - -structure CompStruct {d₁₃ : DefDomain X Z} - (h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃) where - α : d₁₃.src ⟶ h.obj - β : h.obj ⟶ d₁₃.tgt - hα : α ≫ h.fromObj = h.ι ≫ a - hβ : h.toObj ≫ β = b ≫ h.π - -namespace CompStruct - -lemma nonempty : ∃ (d₁₃ : DefDomain X Z) - (h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃), Nonempty (CompStruct a b h) := by - sorry - -variable {a b} -def comp {d₁₃ : DefDomain X Z} - {h : DefDomain.CompStruct d₁₂ d₂₃ d₁₃} (γ : CompStruct a b h) : - Hom X Z := - Hom.mk (d := d₁₃) (γ.α ≫ γ.β) - -end CompStruct - -end Hom - -variable {X Y Z} - -namespace Hom' - -variable (f : Hom' X Y) (g : Hom' Y Z) - -noncomputable def comp.defDomain : Hom.DefDomain X Z := - (Hom.CompStruct.nonempty f.2 g.2).choose - -noncomputable def comp.defDomainCompStruct : - Hom.DefDomain.CompStruct f.1 g.1 (defDomain f g) := - (Hom.CompStruct.nonempty f.2 g.2).choose_spec.choose - -noncomputable def comp.compStruct : - Hom.CompStruct f.2 g.2 (defDomainCompStruct f g) := - (Hom.CompStruct.nonempty f.2 g.2).choose_spec.choose_spec.some - -noncomputable def comp : Hom X Z := (comp.compStruct f g).comp - -end Hom' - -namespace Hom - -noncomputable def comp : Hom X Y → Hom Y Z → Hom X Z := - Quot.lift₂ Hom'.comp sorry sorry - -@[simp] -lemma id_comp (f : Hom X Y) : (Hom.id X).comp f = f := sorry - -@[simp] -lemma comp_id (f : Hom X Y) : f.comp (.id Y) = f := sorry - -@[simp] -lemma assoc (f : Hom X Y) (g : Hom Y Z) (h : Hom Z T) : - (f.comp g).comp h = f.comp (g.comp h) := sorry - -end Hom - -noncomputable instance : Category P.SerreClassLocalization where - Hom := Hom - id := Hom.id - comp := Hom.comp - -end SerreClassLocalization - -def toSerreClassLocalization : C ⥤ P.SerreClassLocalization where - obj X := ⟨X⟩ - map f := .ofHom P f - map_id _ := rfl - map_comp := sorry - -/-! Alternative approach, in two steps: -1) Localization w.r.t. `epimorphisms C ⊓ P.isoModSerre` using a left calculus of fractions -2) Localize the resulting category using a right calculus of fractions --/ - -namespace IsSerreClass - -namespace Localization - -instance : (P.isoModSerre ⊓ .epimorphisms _).HasLeftCalculusOfFractions where +lemma exists_isoModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + (∃ (X' : C) (s : X' ⟶ X) (_ : P.isoModSerre s), s ≫ f = 0) ↔ + P (Abelian.image f) := by + refine ⟨?_, fun hf ↦ ?_⟩ + · rintro ⟨X', s, hs, eq⟩ + have := P.epiModSerre.comp_mem s (Abelian.factorThruImage f) hs.2 + (epiModSerre_of_epi _ _) + rwa [show s ≫ Abelian.factorThruImage f = 0 by cat_disch, + epiModSerre_zero_iff] at this + · refine ⟨_, kernel.ι f, ?_, by simp⟩ + rw [isoModSerre_iff_of_mono] + exact P.prop_of_iso (Abelian.coimageIsoImage f).symm hf + +lemma exists_comp_isoModSerre_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + (∃ (Y' : C) (s : Y ⟶ Y') (_ : P.isoModSerre s), f ≫ s = 0) ↔ + P (Abelian.image f) := by + refine ⟨?_, fun hf ↦ ?_⟩ + · rintro ⟨Y', s, hs, eq⟩ + apply P.prop_of_iso (Abelian.coimageIsoImage f) + have := P.monoModSerre.comp_mem (Abelian.factorThruCoimage f) s + (monoModSerre_of_mono _ _) hs.1 + rwa [show Abelian.factorThruCoimage f ≫ s = 0 by cat_disch, + monoModSerre_zero_iff] at this + · exact ⟨_, cokernel.π f, by simpa [isoModSerre_iff_of_epi], by simp⟩ + +instance : P.isoModSerre.HasLeftCalculusOfFractions where exists_leftFraction X Y φ := ⟨{s := pushout.inl φ.f φ.s f := pushout.inr φ.f φ.s, hs := MorphismProperty.pushout_inl _ _ φ.hs}, pushout.condition⟩ - ext _ _ _ f₁ f₂ s hs eq := by - have : Epi s := hs.2 - exact ⟨_, 𝟙 _, MorphismProperty.id_mem _ _, by simpa [cancel_epi] using eq⟩ - -variable {D : Type*} [Category* D] - (L : C ⥤ D) - -def LocEpi := (P.isoModSerre ⊓ .epimorphisms _).Localization - deriving Category - -def QEpi : C ⥤ LocEpi P := (P.isoModSerre ⊓ .epimorphisms _).Q - -variable {P} in -lemma QEpi_obj_surjective : Function.Surjective (QEpi P).obj := - (Localization.Construction.objEquiv _).surjective - -instance : (QEpi P).IsLocalization (P.isoModSerre ⊓ .epimorphisms _) := - inferInstanceAs ((MorphismProperty.Q _).IsLocalization _) - -instance : (QEpi P).EssSurj := - Localization.essSurj _ (P.isoModSerre ⊓ .epimorphisms _) - -def mapIsoModSerreInterEpi : - MorphismProperty (LocEpi P) := - fun ⟨⟨X⟩⟩ ⟨⟨Y⟩⟩ f ↦ ∃ (Z : C) (g : X ⟶ Z) (s : Y ⟶ Z) (_ : P.isoModSerre g) - (_ : (P.isoModSerre ⊓ .epimorphisms _) s), - f ≫ (QEpi P).map s = (QEpi P).map g - -lemma mapIsoModSerreInterEpi_iff {X Y : C} (f : (QEpi P).obj X ⟶ (QEpi P).obj Y) : - mapIsoModSerreInterEpi P f ↔ ∃ (Z : C) (g : X ⟶ Z) (s : Y ⟶ Z) (_ : P.isoModSerre g) - (_ : (P.isoModSerre ⊓ .epimorphisms _) s), f ≫ (QEpi P).map s = (QEpi P).map g := - Iff.rfl - -lemma mapIsoModSerreInterEpi.map {X Y : C} (f : X ⟶ Y) (hf : P.isoModSerre f) : - mapIsoModSerreInterEpi P ((QEpi P).map f) := by - rw [mapIsoModSerreInterEpi_iff] - exact ⟨_, f, 𝟙 _, hf, MorphismProperty.id_mem _ _, by simp⟩ - -instance : (mapIsoModSerreInterEpi P).RespectsIso := by - sorry - -instance : (mapIsoModSerreInterEpi P).IsMultiplicative where - id_mem X := by - obtain ⟨X, rfl⟩ := QEpi_obj_surjective X - rw [← Functor.map_id] - exact mapIsoModSerreInterEpi.map _ _ (MorphismProperty.id_mem _ _) - comp_mem := sorry - -instance : (mapIsoModSerreInterEpi P).HasRightCalculusOfFractions where - exists_rightFraction := by - let L := QEpi P - suffices ∀ {X Y Z : C} (f : L.obj X ⟶ L.obj Z) (s : L.obj Y ⟶ L.obj Z) - (hs : mapIsoModSerreInterEpi P s), - ∃ (ψ : (mapIsoModSerreInterEpi P).RightFraction (L.obj X) (L.obj Y)), - ψ.s ≫ f = ψ.f ≫ s by - intro X Y φ - let eX := L.objObjPreimageIso X - let eY := L.objObjPreimageIso Y - let eY' := L.objObjPreimageIso φ.Y' - obtain ⟨ψ, fac⟩ := this (eX.hom ≫ φ.f ≫ eY'.inv) (eY.hom ≫ φ.s ≫ eY'.inv) - ((MorphismProperty.arrow_mk_iso_iff _ (Arrow.isoMk eY eY')).2 φ.hs) - exact - ⟨{s := ψ.s ≫ eX.hom - f := ψ.f ≫ eY.hom - hs := (MorphismProperty.arrow_mk_iso_iff _ - (by exact Arrow.isoMk (Iso.refl _) eX)).1 ψ.hs }, by simpa [← cancel_mono eY'.inv]⟩ - intro X Y Z f s hs - obtain ⟨φf, rfl⟩ := Localization.exists_leftFraction L (P.isoModSerre ⊓ .epimorphisms _) f - obtain ⟨φs, rfl⟩ := Localization.exists_leftFraction L (P.isoModSerre ⊓ .epimorphisms _) s - let W := pushout φf.s φs.s - let f' : X ⟶ W := φf.f ≫ pushout.inl _ _ - let s' : Y ⟶ W := φs.f ≫ pushout.inr _ _ - refine ⟨{ - X' := L.obj (pullback f' s') - s := L.map (pullback.fst _ _) - hs := by - refine mapIsoModSerreInterEpi.map P _ - (MorphismProperty.pullback_fst _ _ - (MorphismProperty.comp_mem _ _ _ ?_ (MorphismProperty.pushout_inr _ _ φf.hs.1))) - sorry - f := L.map (pullback.snd _ _) }, ?_⟩ - have := Localization.inverts L (P.isoModSerre ⊓ .epimorphisms _) φf.s φf.hs - have := Localization.inverts L (P.isoModSerre ⊓ .epimorphisms _) - (pushout.inl φf.s φs.s) (MorphismProperty.pushout_inl _ _ φs.hs) - rw [← cancel_mono (L.map φf.s), assoc, MorphismProperty.LeftFraction.map_comp_map_s, - ← cancel_mono (L.map (pushout.inl φf.s φs.s)), assoc, assoc, assoc, - ← L.map_comp, ← L.map_comp, pullback.condition, - ← L.map_comp, pushout.condition, L.map_comp, L.map_comp, L.map_comp, - MorphismProperty.LeftFraction.map_comp_map_s_assoc] - ext := sorry - -end Localization - -end IsSerreClass + ext X' X Y f₁ f₂ s hs eq := by + refine ⟨_, cokernel.π (f₁ - f₂), ?_, ?_⟩ + · rw [isoModSerre_iff_of_epi] + exact (exists_isoModSerre_comp_eq_zero_iff P _).1 ⟨_, s, hs, by simpa [sub_eq_zero]⟩ + · simpa only [Preadditive.sub_comp, sub_eq_zero] using cokernel.condition (f₁ - f₂) + +instance : P.isoModSerre.HasRightCalculusOfFractions where + exists_rightFraction X Y φ := + ⟨{s := pullback.fst φ.f φ.s + f := pullback.snd φ.f φ.s, + hs := MorphismProperty.pullback_fst _ _ φ.hs}, pullback.condition⟩ + ext X Y Y' f₁ f₂ s hs eq := by + refine ⟨_, kernel.ι (f₁ - f₂), ?_, ?_⟩ + · rw [isoModSerre_iff_of_mono] + exact P.prop_of_iso (Abelian.coimageIsoImage (f₁ - f₂)).symm + ((exists_comp_isoModSerre_eq_zero_iff P _).1 ⟨_ ,s, hs, by simpa [sub_eq_zero]⟩) + · simpa only [Preadditive.comp_sub, sub_eq_zero] using kernel.condition (f₁ - f₂) + +noncomputable example : Preadditive P.isoModSerre.Localization := inferInstance end ObjectProperty diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean index f92fba29821c25..ddb74e93b5e06b 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -144,6 +144,16 @@ lemma epiModSerre_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] : P.epiModSerre f := P.epimorphisms_le_epiModSerre f (epimorphisms.infer_property f) +@[simp] +lemma epiModSerre_zero_iff (X Y : C) : + P.epiModSerre (0 : X ⟶ Y) ↔ P Y := + P.prop_iff_of_iso cokernelZeroIsoTarget + +@[simp] +lemma monoModSerre_zero_iff (X Y : C) : + P.monoModSerre (0 : X ⟶ Y) ↔ P X := + P.prop_iff_of_iso kernelZeroIsoSource + lemma isoModSerre_iff {X Y : C} (f : X ⟶ Y) : P.isoModSerre f ↔ P.monoModSerre f ∧ P.epiModSerre f := Iff.rfl diff --git a/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean b/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean index 649cf7a3f319c4..624d9f7875f43b 100644 --- a/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean +++ b/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean @@ -8,7 +8,8 @@ module public import Mathlib.Algebra.Group.TransferInstance public import Mathlib.CategoryTheory.Localization.CalculusOfFractions.Fractions public import Mathlib.CategoryTheory.Localization.HasLocalization -public import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor +public import Mathlib.CategoryTheory.Preadditive.Opposite +public import Mathlib.CategoryTheory.Preadditive.Transfer /-! # The preadditive category structure on the localized category @@ -300,6 +301,8 @@ end ImplementationDetails end Preadditive +section + variable [W.HasLeftCalculusOfFractions] /-- The preadditive structure on `D`, when `L : C ⥤ D` is a localization @@ -351,6 +354,37 @@ noncomputable instance : Preadditive W.Localization' := preadditive W.Q' W instance : W.Q'.Additive := functor_additive W.Q' W instance [HasZeroObject C] : HasZeroObject W.Localization' := W.Q'.hasZeroObject_of_additive +end + +section + +variable [W.HasRightCalculusOfFractions] + +/-- The preadditive structure on `D`, when `L : C ⥤ D` is a localization +functor, `C` is preadditive and there is a right calculus of fractions. +If both left and right calculus of fractions are available, it is advisable +to use `Localization.preadditive` instead. -/ +noncomputable def preadditive' : Preadditive D := by + letI := preadditive L.op W.op + exact Preadditive.ofFullyFaithful (opOpEquivalence D).fullyFaithfulInverse + +lemma functor_additive' : + letI := preadditive' L W + L.Additive := by + letI := preadditive L.op W.op + letI := preadditive' L W + have := functor_additive L.op W.op + have : (opOpEquivalence C).inverse.Additive := { } + have : (opOpEquivalence D).functor.Additive := by + have : (opOpEquivalence D).symm.functor.Additive := + (opOpEquivalence D).fullyFaithfulInverse.additive_ofFullyFaithful + exact Equivalence.inverse_additive (opOpEquivalence D).symm + exact Functor.additive_of_iso + (show (opOpEquivalence C).inverse ⋙ L.op.op ⋙ (opOpEquivalence D).functor ≅ L + from Iso.refl _) + +end + end Localization end CategoryTheory From 7f376a4d9fa3296db6b700261bbc287413be2818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 16:00:01 +0100 Subject: [PATCH 32/46] wip --- .../Abelian/SerreClass/Localization.lean | 202 +++++++++++++++++- 1 file changed, 199 insertions(+), 3 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 5c74d8b3c75d34..a3c29e74f354fc 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -6,6 +6,7 @@ Authors: Joël Riou module public import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty +public import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Kernels public import Mathlib.CategoryTheory.Localization.CalculusOfFractions.Preadditive public import Mathlib.CategoryTheory.Localization.Composition @@ -16,19 +17,51 @@ public import Mathlib.CategoryTheory.Localization.Composition @[expose] public section -universe v u +universe v' u' v u namespace CategoryTheory -open Category Limits +open Category Limits ZeroObject variable {C : Type u} [Category.{v} C] + {D : Type u'} [Category.{v'} D] + +-- to be moved +def NormalMono.ofArrowIso [HasZeroMorphisms C] {X Y : C} {f : X ⟶ Y} + (hf : NormalMono f) {X' Y' : C} {f' : X' ⟶ Y'} (e : Arrow.mk f ≅ Arrow.mk f') : + NormalMono f' where + Z := hf.Z + g := e.inv.right ≫ hf.g + w := by + have := Arrow.w e.inv + dsimp at this + rw [← reassoc_of% this, hf.w, comp_zero] + isLimit := by + refine (IsLimit.equivOfNatIsoOfIso ?_ _ _ ?_).1 hf.isLimit + · exact parallelPair.ext (Arrow.rightFunc.mapIso e) (Iso.refl _) + (by cat_disch) (by cat_disch) + · exact Fork.ext (Arrow.leftFunc.mapIso e) + +def NormalEpi.ofArrowIso [HasZeroMorphisms C] {X Y : C} {f : X ⟶ Y} + (hf : NormalEpi f) {X' Y' : C} {f' : X' ⟶ Y'} (e : Arrow.mk f ≅ Arrow.mk f') : + NormalEpi f' where + W := hf.W + g := hf.g ≫ e.hom.left + w := by + have := Arrow.w e.hom + dsimp at this + rw [assoc, this, reassoc_of% hf.w, zero_comp] + isColimit := by + refine (IsColimit.equivOfNatIsoOfIso ?_ _ _ ?_).1 hf.isColimit + · exact parallelPair.ext (Iso.refl _) (Arrow.leftFunc.mapIso e) + (by cat_disch) (by cat_disch) + · exact Cofork.ext (Arrow.rightFunc.mapIso e) (by simp [Cofork.π]) variable [Abelian C] namespace ObjectProperty -variable (P : ObjectProperty C) [P.IsSerreClass] +variable (L : C ⥤ D) (P : ObjectProperty C) [P.IsSerreClass] lemma exists_isoModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : (∃ (X' : C) (s : X' ⟶ X) (_ : P.isoModSerre s), s ≫ f = 0) ↔ @@ -55,6 +88,8 @@ lemma exists_comp_isoModSerre_eq_zero_iff {X Y : C} (f : X ⟶ Y) : monoModSerre_zero_iff] at this · exact ⟨_, cokernel.π f, by simpa [isoModSerre_iff_of_epi], by simp⟩ +namespace SerreClassLocalization + instance : P.isoModSerre.HasLeftCalculusOfFractions where exists_leftFraction X Y φ := ⟨{s := pushout.inl φ.f φ.s @@ -80,6 +115,167 @@ instance : P.isoModSerre.HasRightCalculusOfFractions where noncomputable example : Preadditive P.isoModSerre.Localization := inferInstance +variable [L.IsLocalization P.isoModSerre] [Preadditive D] [L.Additive] + +include L P + +lemma isZero_obj_iff (X : C) : + IsZero (L.obj X) ↔ P X := by + sorry + +lemma hasZeroObject : HasZeroObject D := + ⟨L.obj 0, by simpa [isZero_obj_iff L P] using P.prop_zero⟩ + +lemma mono_map_iff {X Y : C} (f : X ⟶ Y) : + Mono (L.map f) ↔ P.monoModSerre f := by + sorry + +lemma epi_map_iff {X Y : C} (f : X ⟶ Y) : + Epi (L.map f) ↔ P.epiModSerre f := by + sorry + +lemma preservesMonomorphisms : L.PreservesMonomorphisms where + preserves f _ := by simpa only [mono_map_iff _ P] using P.monoModSerre_of_mono f + +lemma preservesEpimorphisms : L.PreservesEpimorphisms where + preserves f _ := by simpa only [epi_map_iff _ P] using P.epiModSerre_of_epi f + +lemma preservesKernel {X Y : C} (f : X ⟶ Y) : + PreservesLimit (parallelPair f 0) L := by + refine preservesLimit_of_preserves_limit_cone (kernelIsKernel f) + ((KernelFork.isLimitMapConeEquiv _ L).2 ?_) + sorry + +lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : + PreservesColimit (parallelPair f 0) L := by + refine preservesColimit_of_preserves_colimit_cocone (cokernelIsCokernel f) + ((CokernelCofork.isColimitMapCoconeEquiv _ L).2 ?_) + sorry + +lemma hasKernels : HasKernels D where + has_limit f := by + obtain ⟨g, ⟨e⟩⟩ := + (Localization.essSurj_mapArrow L P.isoModSerre).mem_essImage (Arrow.mk f) + have := preservesKernel L P g.hom + have : HasLimit (parallelPair (L.map g.hom) 0) := + ⟨_, (KernelFork.isLimitMapConeEquiv _ L).1 + (isLimitOfPreserves L (kernelIsKernel g.hom))⟩ + exact hasLimit_of_iso (show parallelPair (L.map g.hom) 0 ≅ _ from + parallelPair.ext (Arrow.leftFunc.mapIso e) + (Arrow.rightFunc.mapIso e) (by cat_disch) (by cat_disch)) + +lemma hasCokernels : HasCokernels D where + has_colimit f := by + obtain ⟨g, ⟨e⟩⟩ := + (Localization.essSurj_mapArrow L P.isoModSerre).mem_essImage (Arrow.mk f) + have := preservesCokernel L P g.hom + have : HasColimit (parallelPair (L.map g.hom) 0) := + ⟨_, (CokernelCofork.isColimitMapCoconeEquiv _ L).1 + (isColimitOfPreserves L (cokernelIsCokernel g.hom))⟩ + exact hasColimit_of_iso (show _ ≅ parallelPair (L.map g.hom) 0 from + parallelPair.ext (Arrow.leftFunc.mapIso e.symm) + (Arrow.rightFunc.mapIso e.symm) (by cat_disch) (by cat_disch)) + +lemma hasEqualizers : HasEqualizers D := + have := hasKernels L P + have {X Y : D} (f g : X ⟶ Y) : HasEqualizer f g := + Preadditive.hasEqualizer_of_hasKernel _ _ + hasEqualizers_of_hasLimit_parallelPair _ + +lemma hasCoequalizers : HasCoequalizers D := + have := hasCokernels L P + have {X Y : D} (f g : X ⟶ Y) : HasCoequalizer f g := by + exact Preadditive.hasCoequalizer_of_hasCokernel _ _ + hasCoequalizers_of_hasColimit_parallelPair _ + +lemma hasBinaryProducts : HasBinaryProducts D := by + have := L + have := P + sorry + +lemma hasBinaryBiproducts : HasBinaryBiproducts D := + have := hasBinaryProducts L P + .of_hasBinaryProducts + +lemma hasBinaryCoproducts : HasBinaryCoproducts D := + have := hasBinaryBiproducts L P + hasBinaryCoproducts_of_hasBinaryBiproducts + +lemma hasFiniteProducts : HasFiniteProducts D := + have := hasZeroObject L P + have := hasBinaryProducts L P + hasFiniteProducts_of_has_binary_and_terminal + +lemma hasFiniteLimits : HasFiniteLimits D := + have := hasEqualizers L P + have := hasFiniteProducts L P + hasFiniteLimits_of_hasEqualizers_and_finite_products + +lemma hasFiniteCoproducts : HasFiniteCoproducts D := + have := hasZeroObject L P + have := hasBinaryCoproducts L P + hasFiniteCoproducts_of_has_binary_and_initial + +lemma hasFiniteColimits : HasFiniteColimits D := + have := hasCoequalizers L P + have := hasFiniteCoproducts L P + hasFiniteColimits_of_hasCoequalizers_and_finite_coproducts + +lemma mono_iff {X Y : D} (f : X ⟶ Y) : + Mono f ↔ ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Mono f'), + Nonempty (L.mapArrow.obj (Arrow.mk f') ≅ Arrow.mk f) := sorry + +lemma epi_iff {X Y : D} (f : X ⟶ Y) : + Epi f ↔ ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Epi f'), + Nonempty (L.mapArrow.obj (Arrow.mk f') ≅ Arrow.mk f) := sorry + +lemma isNormalMonoCategory : IsNormalMonoCategory D where + normalMonoOfMono f hf := by + rw [mono_iff L P] at hf + obtain ⟨X', Y', f', _, ⟨e⟩⟩ := hf + let hf' := normalMonoOfMono f' + refine ⟨NormalMono.ofArrowIso ?_ e⟩ + exact { + Z := L.obj hf'.Z + g := L.map hf'.g + w := by + rw [← L.map_comp] + simp [hf'.w] + isLimit := + have := preservesKernel L P hf'.g + (KernelFork.isLimitMapConeEquiv _ L).1 + (isLimitOfPreserves L hf'.isLimit) } + +lemma isNormalEpiCategory : IsNormalEpiCategory D where + normalEpiOfEpi f hf := by + rw [epi_iff L P] at hf + obtain ⟨X', Y', f', _, ⟨e⟩⟩ := hf + let hf' := normalEpiOfEpi f' + refine ⟨NormalEpi.ofArrowIso ?_ e⟩ + exact { + W := L.obj hf'.W + g := L.map hf'.g + w := by + rw [← L.map_comp] + simp [hf'.w] + isColimit := + have := preservesCokernel L P hf'.g + (CokernelCofork.isColimitMapCoconeEquiv _ L).1 + (isColimitOfPreserves L hf'.isColimit) } + +def abelian : Abelian D := by + have := hasFiniteProducts L P + have := hasKernels L P + have := hasCokernels L P + have := isNormalMonoCategory L P + have := isNormalEpiCategory L P + constructor + +lemma preservesFiniteLimits : PreservesFiniteLimits L := by + sorry + +end SerreClassLocalization + end ObjectProperty end CategoryTheory From 6d8310e1556f3614c7feaf9e65f0daffe554f270 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 16:10:16 +0100 Subject: [PATCH 33/46] wip --- .../Abelian/SerreClass/Localization.lean | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index a3c29e74f354fc..264958c773c209 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -142,12 +142,14 @@ lemma preservesEpimorphisms : L.PreservesEpimorphisms where lemma preservesKernel {X Y : C} (f : X ⟶ Y) : PreservesLimit (parallelPair f 0) L := by + have := preservesMonomorphisms L P refine preservesLimit_of_preserves_limit_cone (kernelIsKernel f) ((KernelFork.isLimitMapConeEquiv _ L).2 ?_) sorry lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : PreservesColimit (parallelPair f 0) L := by + have := preservesEpimorphisms L P refine preservesColimit_of_preserves_colimit_cocone (cokernelIsCokernel f) ((CokernelCofork.isColimitMapCoconeEquiv _ L).2 ?_) sorry @@ -189,9 +191,11 @@ lemma hasCoequalizers : HasCoequalizers D := hasCoequalizers_of_hasColimit_parallelPair _ lemma hasBinaryProducts : HasBinaryProducts D := by - have := L - have := P - sorry + have := Localization.essSurj L P.isoModSerre + have (X Y : D) : HasBinaryProduct X Y := + hasLimit_of_iso (show Limits.pair _ _ ≅ _ from + mapPairIso (L.objObjPreimageIso X) (L.objObjPreimageIso Y)) + exact hasBinaryProducts_of_hasLimit_pair D lemma hasBinaryBiproducts : HasBinaryBiproducts D := have := hasBinaryProducts L P From a89c2cee1ac9e133ef34bdfc1d16596837814131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 16:17:07 +0100 Subject: [PATCH 34/46] wip --- .../Abelian/SerreClass/Localization.lean | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 264958c773c209..9d2cccf03baab9 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -5,10 +5,9 @@ Authors: Joël Riou -/ module +public import Mathlib.Algebra.Homology.ShortComplex.ExactFunctor public import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty -public import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Kernels public import Mathlib.CategoryTheory.Localization.CalculusOfFractions.Preadditive -public import Mathlib.CategoryTheory.Localization.Composition /-! # Localization with respect to a Serre class @@ -242,9 +241,7 @@ lemma isNormalMonoCategory : IsNormalMonoCategory D where exact { Z := L.obj hf'.Z g := L.map hf'.g - w := by - rw [← L.map_comp] - simp [hf'.w] + w := by rw [← L.map_comp]; simp [hf'.w] isLimit := have := preservesKernel L P hf'.g (KernelFork.isLimitMapConeEquiv _ L).1 @@ -259,9 +256,7 @@ lemma isNormalEpiCategory : IsNormalEpiCategory D where exact { W := L.obj hf'.W g := L.map hf'.g - w := by - rw [← L.map_comp] - simp [hf'.w] + w := by rw [← L.map_comp]; simp [hf'.w] isColimit := have := preservesCokernel L P hf'.g (CokernelCofork.isColimitMapCoconeEquiv _ L).1 @@ -276,7 +271,18 @@ def abelian : Abelian D := by constructor lemma preservesFiniteLimits : PreservesFiniteLimits L := by - sorry + letI := abelian L P + have := (Functor.preservesFiniteLimits_tfae L).out 3 2 + rw [this] + intro _ _ f + exact preservesKernel L P f + +lemma preservesFiniteColimits : PreservesFiniteColimits L := by + letI := abelian L P + have := (Functor.preservesFiniteColimits_tfae L).out 3 2 + rw [this] + intro _ _ f + exact preservesCokernel L P f end SerreClassLocalization From 56788ee1f12d8bc4d0bace83b8e00fb3882b04d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 18:24:35 +0100 Subject: [PATCH 35/46] wip --- .../Abelian/SerreClass/Localization.lean | 111 ++++++++++++------ .../Abelian/SerreClass/MorphismProperty.lean | 26 ++++ 2 files changed, 103 insertions(+), 34 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 9d2cccf03baab9..ae1aa526dc3a89 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -87,6 +87,23 @@ lemma exists_comp_isoModSerre_eq_zero_iff {X Y : C} (f : X ⟶ Y) : monoModSerre_zero_iff] at this · exact ⟨_, cokernel.π f, by simpa [isoModSerre_iff_of_epi], by simp⟩ +variable {P} in +lemma monoModSerre.isoModSerre_factorThruImage + {X Y : C} {f : X ⟶ Y} (hf : P.monoModSerre f) : + P.isoModSerre (Abelian.factorThruImage f) := by + rw [isoModSerre_iff_of_epi] + exact P.prop_of_iso + (asIso (kernel.map _ f (𝟙 _) (Abelian.image.ι f) (by simp))).symm hf + +variable {P} in +lemma epiModSerre.isoModSerre_image_ι + {X Y : C} {f : X ⟶ Y} (hf : P.epiModSerre f) : + P.isoModSerre (Abelian.image.ι f) := by + rw [isoModSerre_iff_of_mono] + dsimp [epiModSerre] at hf ⊢ + exact P.prop_of_iso + (asIso (cokernel.map f _ (Abelian.factorThruImage f) (𝟙 Y) (by simp))) hf + namespace SerreClassLocalization instance : P.isoModSerre.HasLeftCalculusOfFractions where @@ -120,7 +137,12 @@ include L P lemma isZero_obj_iff (X : C) : IsZero (L.obj X) ↔ P X := by - sorry + simp only [IsZero.iff_id_eq_zero, ← L.map_id, ← L.map_zero, + MorphismProperty.map_eq_iff_precomp L P.isoModSerre, + comp_id, comp_zero, exists_prop, exists_eq_right] + refine ⟨?_, fun _ ↦ ⟨X, by simpa⟩⟩ + rintro ⟨Y, h⟩ + simpa using h.2 lemma hasZeroObject : HasZeroObject D := ⟨L.obj 0, by simpa [isZero_obj_iff L P] using P.prop_zero⟩ @@ -139,18 +161,70 @@ lemma preservesMonomorphisms : L.PreservesMonomorphisms where lemma preservesEpimorphisms : L.PreservesEpimorphisms where preserves f _ := by simpa only [epi_map_iff _ P] using P.epiModSerre_of_epi f +lemma mono_iff {X Y : D} (f : X ⟶ Y) : + Mono f ↔ ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Mono f'), + Nonempty (Arrow.mk (L.map f') ≅ Arrow.mk f) := by + have := preservesMonomorphisms L P + have := Localization.essSurj_mapArrow L P.isoModSerre + refine ⟨fun _ ↦ ?_, ?_⟩ + · suffices ∀ ⦃X Y : C⦄ (f : X ⟶ Y) (_ : Mono (L.map f)), + ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Mono f'), + Nonempty (Arrow.mk (L.map f') ≅ Arrow.mk (L.map f)) by + let e := L.mapArrow.objObjPreimageIso (Arrow.mk f) + obtain ⟨X', Y', f', _, ⟨e'⟩⟩ := this _ + (((MorphismProperty.monomorphisms D).arrow_iso_iff e).2 (.infer_property f)) + exact ⟨_, _, f', inferInstance, ⟨e' ≪≫ e⟩⟩ + intro X Y f hf + rw [mono_map_iff L P] at hf + refine ⟨_, _, Abelian.image.ι f, inferInstance, ⟨Iso.symm ?_⟩⟩ + have := Localization.inverts L P.isoModSerre _ hf.isoModSerre_factorThruImage + exact Arrow.isoMk (asIso (L.map (Abelian.factorThruImage f))) (Iso.refl _) + (by simp [← L.map_comp]) + · rintro ⟨X', Y', f', _, ⟨e⟩⟩ + exact ((MorphismProperty.monomorphisms D).arrow_mk_iso_iff e).1 + (by simpa using inferInstanceAs (Mono (L.map f'))) + +lemma epi_iff {X Y : D} (f : X ⟶ Y) : + Epi f ↔ ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Epi f'), + Nonempty (Arrow.mk (L.map f') ≅ Arrow.mk f) := by + have := preservesEpimorphisms L P + have := Localization.essSurj_mapArrow L P.isoModSerre + refine ⟨fun _ ↦ ?_, ?_⟩ + · suffices ∀ ⦃X Y : C⦄ (f : X ⟶ Y) (_ : Epi (L.map f)), + ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Epi f'), + Nonempty (Arrow.mk (L.map f') ≅ Arrow.mk (L.map f)) by + let e := L.mapArrow.objObjPreimageIso (Arrow.mk f) + obtain ⟨X', Y', f', _, ⟨e'⟩⟩ := this _ + (((MorphismProperty.epimorphisms D).arrow_iso_iff e).2 (.infer_property f)) + exact ⟨_, _, f', inferInstance, ⟨e' ≪≫ e⟩⟩ + intro X Y f hf + rw [epi_map_iff L P] at hf + refine ⟨_, _, Abelian.factorThruImage f, inferInstance, ⟨?_⟩⟩ + have := Localization.inverts L P.isoModSerre _ hf.isoModSerre_image_ι + refine Arrow.isoMk (Iso.refl _) (asIso (L.map (Abelian.image.ι f))) (by simp [← L.map_comp]) + · rintro ⟨X', Y', f', _, ⟨e⟩⟩ + exact ((MorphismProperty.epimorphisms D).arrow_mk_iso_iff e).1 + (by simpa using inferInstanceAs (Epi (L.map f'))) + + lemma preservesKernel {X Y : C} (f : X ⟶ Y) : PreservesLimit (parallelPair f 0) L := by have := preservesMonomorphisms L P refine preservesLimit_of_preserves_limit_cone (kernelIsKernel f) - ((KernelFork.isLimitMapConeEquiv _ L).2 ?_) + ((KernelFork.isLimitMapConeEquiv _ L).2 + (Fork.IsLimit.ofExistsUnique + (fun s ↦ existsUnique_of_exists_of_unique ?_ + (fun _ _ h₁ h₂ ↦ by simpa [cancel_mono] using h₁.trans h₂.symm)))) sorry lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : PreservesColimit (parallelPair f 0) L := by have := preservesEpimorphisms L P refine preservesColimit_of_preserves_colimit_cocone (cokernelIsCokernel f) - ((CokernelCofork.isColimitMapCoconeEquiv _ L).2 ?_) + ((CokernelCofork.isColimitMapCoconeEquiv _ L).2 + (Cofork.IsColimit.ofExistsUnique + (fun s ↦ existsUnique_of_exists_of_unique ?_ + (fun _ _ h₁ h₂ ↦ by simpa [cancel_epi] using h₁.trans h₂.symm)))) sorry lemma hasKernels : HasKernels D where @@ -196,42 +270,11 @@ lemma hasBinaryProducts : HasBinaryProducts D := by mapPairIso (L.objObjPreimageIso X) (L.objObjPreimageIso Y)) exact hasBinaryProducts_of_hasLimit_pair D -lemma hasBinaryBiproducts : HasBinaryBiproducts D := - have := hasBinaryProducts L P - .of_hasBinaryProducts - -lemma hasBinaryCoproducts : HasBinaryCoproducts D := - have := hasBinaryBiproducts L P - hasBinaryCoproducts_of_hasBinaryBiproducts - lemma hasFiniteProducts : HasFiniteProducts D := have := hasZeroObject L P have := hasBinaryProducts L P hasFiniteProducts_of_has_binary_and_terminal -lemma hasFiniteLimits : HasFiniteLimits D := - have := hasEqualizers L P - have := hasFiniteProducts L P - hasFiniteLimits_of_hasEqualizers_and_finite_products - -lemma hasFiniteCoproducts : HasFiniteCoproducts D := - have := hasZeroObject L P - have := hasBinaryCoproducts L P - hasFiniteCoproducts_of_has_binary_and_initial - -lemma hasFiniteColimits : HasFiniteColimits D := - have := hasCoequalizers L P - have := hasFiniteCoproducts L P - hasFiniteColimits_of_hasCoequalizers_and_finite_coproducts - -lemma mono_iff {X Y : D} (f : X ⟶ Y) : - Mono f ↔ ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Mono f'), - Nonempty (L.mapArrow.obj (Arrow.mk f') ≅ Arrow.mk f) := sorry - -lemma epi_iff {X Y : D} (f : X ⟶ Y) : - Epi f ↔ ∃ (X' Y' : C) (f' : X' ⟶ Y') (_ : Epi f'), - Nonempty (L.mapArrow.obj (Arrow.mk f') ≅ Arrow.mk f) := sorry - lemma isNormalMonoCategory : IsNormalMonoCategory D where normalMonoOfMono f hf := by rw [mono_iff L P] at hf diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean index ddb74e93b5e06b..2fd01589c8b1bf 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -56,6 +56,27 @@ lemma Abelian.isIso_cokernel_map_of_isPushout [HasCokernel t] [HasCokernel b] end +section -- to be moved + +variable {C : Type*} [Category* C] [HasZeroMorphisms C] + {X₁ X₂ X₃ X₄ : C} (t : X₁ ⟶ X₂) (b : X₃ ⟶ X₄) (l : X₁ ⟶ X₃) (r : X₂ ⟶ X₄) + (fac : t ≫ r = l ≫ b) + +instance isIso_kernel_map_of_isIso_of_mono [HasKernel t] [HasKernel b] + [IsIso l] [Mono r] : + IsIso (kernel.map _ _ _ _ fac) := + ⟨kernel.lift _ (kernel.ι b ≫ inv l) (by simp [← cancel_mono r, fac]), + by cat_disch, by cat_disch⟩ + +instance isIso_cokernel_map_of_isIso_of_epi [HasCokernel t] [HasCokernel b] + [Epi l] [IsIso r] : + IsIso (cokernel.map _ _ _ _ fac) := + ⟨cokernel.desc _ (inv r ≫ cokernel.π t) (by simp [← cancel_epi l, ← reassoc_of% fac]), + by cat_disch, by cat_disch⟩ + +end + + variable {C : Type u} [Category.{v} C] [Abelian C] {D : Type u'} [Category.{v'} D] [Abelian D] @@ -177,6 +198,11 @@ lemma isoModSerre_of_epi {X Y : C} (f : X ⟶ Y) [Epi f] (hf : P.monoModSerre f) P.isoModSerre f := by rwa [isoModSerre_iff_of_epi] +@[simp] +lemma isoModSerre_zero_iff (X Y : C) : + P.isoModSerre (0 : X ⟶ Y) ↔ P X ∧ P Y := by + simp [isoModSerre_iff] + lemma isomorphisms_le_isoModSerre : isomorphisms C ≤ P.isoModSerre := fun _ _ f (_ : IsIso f) ↦ ⟨P.monoModSerre_of_mono f, P.epiModSerre_of_epi f⟩ From c1be2b5895d9ae5ffd95bcc745d0e8a4e390dad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 21:35:21 +0100 Subject: [PATCH 36/46] wip --- .../Abelian/SerreClass/Localization.lean | 73 ++++++++++++++++--- 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index ae1aa526dc3a89..bed6425299a30a 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -62,30 +62,48 @@ namespace ObjectProperty variable (L : C ⥤ D) (P : ObjectProperty C) [P.IsSerreClass] -lemma exists_isoModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : - (∃ (X' : C) (s : X' ⟶ X) (_ : P.isoModSerre s), s ≫ f = 0) ↔ +lemma exists_epiModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + (∃ (X' : C) (s : X' ⟶ X) (_ : P.epiModSerre s), s ≫ f = 0) ↔ P (Abelian.image f) := by refine ⟨?_, fun hf ↦ ?_⟩ · rintro ⟨X', s, hs, eq⟩ - have := P.epiModSerre.comp_mem s (Abelian.factorThruImage f) hs.2 + have := P.epiModSerre.comp_mem s (Abelian.factorThruImage f) hs (epiModSerre_of_epi _ _) rwa [show s ≫ Abelian.factorThruImage f = 0 by cat_disch, epiModSerre_zero_iff] at this + · exact ⟨_, kernel.ι f, P.prop_of_iso (Abelian.coimageIsoImage f).symm hf, by simp⟩ + +lemma exists_isoModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + (∃ (X' : C) (s : X' ⟶ X) (_ : P.isoModSerre s), s ≫ f = 0) ↔ + P (Abelian.image f) := by + refine ⟨?_, fun hf ↦ ?_⟩ + · rintro ⟨Y', s, hs, eq⟩ + rw [← exists_epiModSerre_comp_eq_zero_iff P] + exact ⟨Y', s, hs.2, eq⟩ · refine ⟨_, kernel.ι f, ?_, by simp⟩ - rw [isoModSerre_iff_of_mono] - exact P.prop_of_iso (Abelian.coimageIsoImage f).symm hf + simpa only [isoModSerre_iff_of_mono] using + P.prop_of_iso (Abelian.coimageIsoImage f).symm hf -lemma exists_comp_isoModSerre_eq_zero_iff {X Y : C} (f : X ⟶ Y) : - (∃ (Y' : C) (s : Y ⟶ Y') (_ : P.isoModSerre s), f ≫ s = 0) ↔ +lemma exists_comp_monoModSerre_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + (∃ (Y' : C) (s : Y ⟶ Y') (_ : P.monoModSerre s), f ≫ s = 0) ↔ P (Abelian.image f) := by refine ⟨?_, fun hf ↦ ?_⟩ · rintro ⟨Y', s, hs, eq⟩ apply P.prop_of_iso (Abelian.coimageIsoImage f) have := P.monoModSerre.comp_mem (Abelian.factorThruCoimage f) s - (monoModSerre_of_mono _ _) hs.1 + (monoModSerre_of_mono _ _) hs rwa [show Abelian.factorThruCoimage f ≫ s = 0 by cat_disch, monoModSerre_zero_iff] at this - · exact ⟨_, cokernel.π f, by simpa [isoModSerre_iff_of_epi], by simp⟩ + · exact ⟨_, cokernel.π f, hf, by simp⟩ + +lemma exists_comp_isoModSerre_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + (∃ (Y' : C) (s : Y ⟶ Y') (_ : P.isoModSerre s), f ≫ s = 0) ↔ + P (Abelian.image f) := by + refine ⟨?_, fun hf ↦ ?_⟩ + · rintro ⟨Y', s, hs, eq⟩ + rw [← exists_comp_monoModSerre_eq_zero_iff P] + exact ⟨Y', s, hs.1, eq⟩ + · refine ⟨_, cokernel.π f, by rwa [isoModSerre_iff_of_epi], by simp⟩ variable {P} in lemma monoModSerre.isoModSerre_factorThruImage @@ -147,9 +165,43 @@ lemma isZero_obj_iff (X : C) : lemma hasZeroObject : HasZeroObject D := ⟨L.obj 0, by simpa [isZero_obj_iff L P] using P.prop_zero⟩ +lemma map_eq_zero_iff {X Y : C} (f : X ⟶ Y) : + L.map f = 0 ↔ P (Abelian.image f) := by + rw [← L.map_zero, MorphismProperty.map_eq_iff_precomp L P.isoModSerre] + simp [← exists_isoModSerre_comp_eq_zero_iff P] + +lemma map_comp_eq_zero_iff_of_epi_mono {X Z Y : C} (f : X ⟶ Z) (g : Z ⟶ Y) + [Epi f] [Mono g] : + L.map f ≫ L.map g = 0 ↔ P Z := by + rw [← L.map_comp, map_eq_zero_iff L P] + have := strongEpi_of_epi f + exact P.prop_iff_of_iso (Abelian.imageIsoImage _ ≪≫ (image.isoStrongEpiMono f g rfl).symm) + lemma mono_map_iff {X Y : C} (f : X ⟶ Y) : Mono (L.map f) ↔ P.monoModSerre f := by - sorry + have := Localization.essSurj L P.isoModSerre + refine ⟨fun _ ↦ ?_, fun hf ↦ ?_⟩ + · have hf : L.map (kernel.ι f) = 0 := by + rw [← cancel_mono (L.map f), zero_comp, ← L.map_comp, + kernel.condition, L.map_zero] + simpa [hf] using map_comp_eq_zero_iff_of_epi_mono L P (𝟙 _) (kernel.ι f) + · suffices ∀ ⦃Z : C⦄ (z : Z ⟶ X) (hz : L.map z ≫ L.map f = 0), L.map z = 0 by + rw [Preadditive.mono_iff_cancel_zero] + intro W z hz + obtain ⟨φ, hφ⟩ := Localization.exists_rightFraction L P.isoModSerre + ((L.objObjPreimageIso W).hom ≫ z) + have hs := Localization.inverts L P.isoModSerre φ.s φ.hs + rw [← cancel_epi (L.objObjPreimageIso W).hom, comp_zero, hφ, + ← cancel_epi (L.map φ.s), comp_zero, + MorphismProperty.RightFraction.map_s_comp_map] + apply this φ.f + rw [← show L.map φ.s ≫ (L.objObjPreimageIso W).hom ≫ z = L.map φ.f by cat_disch, + assoc, assoc, hz, comp_zero, comp_zero] + intro Z z hz + rw [← L.map_comp] at hz + rw [map_eq_zero_iff L P, ← exists_comp_monoModSerre_eq_zero_iff P] at hz ⊢ + obtain ⟨W, s, hs, eq⟩ := hz + exact ⟨W, f ≫ s, MorphismProperty.comp_mem _ _ _ hf hs, by simpa using eq⟩ lemma epi_map_iff {X Y : C} (f : X ⟶ Y) : Epi (L.map f) ↔ P.epiModSerre f := by @@ -215,6 +267,7 @@ lemma preservesKernel {X Y : C} (f : X ⟶ Y) : (Fork.IsLimit.ofExistsUnique (fun s ↦ existsUnique_of_exists_of_unique ?_ (fun _ _ h₁ h₂ ↦ by simpa [cancel_mono] using h₁.trans h₂.symm)))) + have := KernelFork.condition s sorry lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : From 12bf57d5e1eaeee38a00d4324a447c728b011bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 22:19:51 +0100 Subject: [PATCH 37/46] wip --- .../Abelian/SerreClass/Localization.lean | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index bed6425299a30a..484ffebdfc34dc 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -258,26 +258,49 @@ lemma epi_iff {X Y : D} (f : X ⟶ Y) : exact ((MorphismProperty.epimorphisms D).arrow_mk_iso_iff e).1 (by simpa using inferInstanceAs (Epi (L.map f'))) - lemma preservesKernel {X Y : C} (f : X ⟶ Y) : PreservesLimit (parallelPair f 0) L := by have := preservesMonomorphisms L P - refine preservesLimit_of_preserves_limit_cone (kernelIsKernel f) - ((KernelFork.isLimitMapConeEquiv _ L).2 - (Fork.IsLimit.ofExistsUnique - (fun s ↦ existsUnique_of_exists_of_unique ?_ - (fun _ _ h₁ h₂ ↦ by simpa [cancel_mono] using h₁.trans h₂.symm)))) - have := KernelFork.condition s - sorry + have := Localization.essSurj L P.isoModSerre + suffices ∀ (W : D) (z : W ⟶ L.obj X) (hz : z ≫ L.map f = 0), + ∃ (l : W ⟶ L.obj (kernel f)), l ≫ L.map (kernel.ι f) = z from + preservesLimit_of_preserves_limit_cone (kernelIsKernel f) + ((KernelFork.isLimitMapConeEquiv _ L).2 + (Fork.IsLimit.ofExistsUnique + (fun s ↦ existsUnique_of_exists_of_unique + (this _ _ (KernelFork.condition s)) + (fun _ _ h₁ h₂ ↦ by simpa [cancel_mono] using h₁.trans h₂.symm)))) + intro W w hw + wlog hw' : ∃ (Z : C) (hZ : W = L.obj Z) (z : Z ⟶ X), w = eqToHom hZ ≫ L.map z + generalizing W + · obtain ⟨φ, hφ⟩ := Localization.exists_rightFraction L P.isoModSerre + ((L.objObjPreimageIso W).hom ≫ w) + have _ := Localization.inverts L P.isoModSerre φ.s φ.hs + rw [← cancel_epi (L.map φ.s), + MorphismProperty.RightFraction.map_s_comp_map] at hφ + obtain ⟨l, hl⟩ := this _ (L.map φ.f) (by + rw [← hφ, assoc, assoc, hw, comp_zero, comp_zero]) ⟨_, rfl, by simp⟩ + exact ⟨(L.objObjPreimageIso W).inv ≫ inv (L.map φ.s) ≫ l, by simp [hl, ← hφ]⟩ + obtain ⟨Z, rfl, z, rfl⟩ := hw' + simp only [eqToHom_refl, id_comp, ← L.map_comp] at hw + rw [map_eq_zero_iff L P, ← exists_isoModSerre_comp_eq_zero_iff P] at hw + obtain ⟨Z', t, ht, fac⟩ := hw + have := Localization.inverts L P.isoModSerre t ht + rw [← assoc] at fac + refine ⟨inv (L.map t) ≫ L.map (kernel.lift _ _ fac), ?_⟩ + simp only [assoc, eqToHom_refl, id_comp, IsIso.inv_comp_eq, ← L.map_comp, kernel.lift_ι] lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : PreservesColimit (parallelPair f 0) L := by have := preservesEpimorphisms L P - refine preservesColimit_of_preserves_colimit_cocone (cokernelIsCokernel f) - ((CokernelCofork.isColimitMapCoconeEquiv _ L).2 - (Cofork.IsColimit.ofExistsUnique - (fun s ↦ existsUnique_of_exists_of_unique ?_ - (fun _ _ h₁ h₂ ↦ by simpa [cancel_epi] using h₁.trans h₂.symm)))) + suffices ∀ (W : D) (z : L.obj Y ⟶ W) (hz : L.map f ≫ z = 0), + ∃ (l : L.obj (cokernel f) ⟶ W), L.map (cokernel.π f) ≫ l = z from + preservesColimit_of_preserves_colimit_cocone (cokernelIsCokernel f) + ((CokernelCofork.isColimitMapCoconeEquiv _ L).2 + (Cofork.IsColimit.ofExistsUnique + (fun s ↦ existsUnique_of_exists_of_unique + (this _ _ (CokernelCofork.condition s)) + (fun _ _ h₁ h₂ ↦ by simpa [cancel_epi] using h₁.trans h₂.symm)))) sorry lemma hasKernels : HasKernels D where From 02ed251242b9affd97298afe014508a07aaf11c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Sun, 25 Jan 2026 22:45:17 +0100 Subject: [PATCH 38/46] wip --- .../Abelian/SerreClass/Localization.lean | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 484ffebdfc34dc..a8ad5d931e12c7 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -195,8 +195,8 @@ lemma mono_map_iff {X Y : C} (f : X ⟶ Y) : ← cancel_epi (L.map φ.s), comp_zero, MorphismProperty.RightFraction.map_s_comp_map] apply this φ.f - rw [← show L.map φ.s ≫ (L.objObjPreimageIso W).hom ≫ z = L.map φ.f by cat_disch, - assoc, assoc, hz, comp_zero, comp_zero] + have : L.map φ.s ≫ (L.objObjPreimageIso W).hom ≫ z = L.map φ.f := by cat_disch + rw [← this, assoc, assoc, hz, comp_zero, comp_zero] intro Z z hz rw [← L.map_comp] at hz rw [map_eq_zero_iff L P, ← exists_comp_monoModSerre_eq_zero_iff P] at hz ⊢ @@ -205,7 +205,30 @@ lemma mono_map_iff {X Y : C} (f : X ⟶ Y) : lemma epi_map_iff {X Y : C} (f : X ⟶ Y) : Epi (L.map f) ↔ P.epiModSerre f := by - sorry + have := Localization.essSurj L P.isoModSerre + refine ⟨fun _ ↦ ?_, fun hf ↦ ?_⟩ + · have hf : L.map (cokernel.π f) = 0 := by + rw [← cancel_epi (L.map f), comp_zero, ← L.map_comp, + cokernel.condition, L.map_zero] + simpa [hf] using map_comp_eq_zero_iff_of_epi_mono L P (cokernel.π f) (𝟙 _) + · suffices ∀ ⦃Z : C⦄ (z : Y ⟶ Z) (hz : L.map f ≫ L.map z = 0), L.map z = 0 by + rw [Preadditive.epi_iff_cancel_zero] + intro W z hz + obtain ⟨φ, hφ⟩ := Localization.exists_leftFraction L P.isoModSerre + (z ≫ (L.objObjPreimageIso W).inv) + have hs := Localization.inverts L P.isoModSerre φ.s φ.hs + rw [← cancel_mono (L.objObjPreimageIso W).inv, zero_comp, hφ, + ← cancel_mono (L.map φ.s), zero_comp, + MorphismProperty.LeftFraction.map_comp_map_s] + apply this φ.f + have : L.map φ.f = z ≫ (L.objObjPreimageIso W).inv ≫ L.map φ.s := by + simp [reassoc_of% hφ] + rw [this, reassoc_of% hz, zero_comp] + intro Z z hz + rw [← L.map_comp] at hz + rw [map_eq_zero_iff L P, ← exists_epiModSerre_comp_eq_zero_iff P] at hz ⊢ + obtain ⟨W, s, hs, eq⟩ := hz + refine ⟨_, s ≫ f, MorphismProperty.comp_mem _ _ _ hs hf, by simpa⟩ lemma preservesMonomorphisms : L.PreservesMonomorphisms where preserves f _ := by simpa only [mono_map_iff _ P] using P.monoModSerre_of_mono f @@ -293,6 +316,7 @@ lemma preservesKernel {X Y : C} (f : X ⟶ Y) : lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : PreservesColimit (parallelPair f 0) L := by have := preservesEpimorphisms L P + have := Localization.essSurj L P.isoModSerre suffices ∀ (W : D) (z : L.obj Y ⟶ W) (hz : L.map f ≫ z = 0), ∃ (l : L.obj (cokernel f) ⟶ W), L.map (cokernel.π f) ≫ l = z from preservesColimit_of_preserves_colimit_cocone (cokernelIsCokernel f) @@ -301,7 +325,23 @@ lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : (fun s ↦ existsUnique_of_exists_of_unique (this _ _ (CokernelCofork.condition s)) (fun _ _ h₁ h₂ ↦ by simpa [cancel_epi] using h₁.trans h₂.symm)))) - sorry + intro W w hw + wlog hw' : ∃ (Z : C) (hZ : L.obj Z = W) (z : Y ⟶ Z), w = L.map z ≫ eqToHom hZ + generalizing W + · obtain ⟨φ, hφ⟩ := Localization.exists_leftFraction L P.isoModSerre + (w ≫ (L.objObjPreimageIso W).inv) + have _ := Localization.inverts L P.isoModSerre φ.s φ.hs + rw [← cancel_mono (L.map φ.s), assoc, + MorphismProperty.LeftFraction.map_comp_map_s] at hφ + obtain ⟨l, hl⟩ := this _ (L.map φ.f) (by rw [← hφ, reassoc_of% hw, zero_comp]) ⟨_, rfl, by simp⟩ + exact ⟨l ≫ inv (L.map φ.s) ≫ (L.objObjPreimageIso W).hom, by simp [reassoc_of% hl, ← hφ]⟩ + obtain ⟨Z, rfl, z, rfl⟩ := hw' + simp only [eqToHom_refl, comp_id, ← L.map_comp] at hw + rw [map_eq_zero_iff L P, ← exists_comp_isoModSerre_eq_zero_iff P] at hw + obtain ⟨Z', t, ht, fac⟩ := hw + rw [assoc] at fac + have := Localization.inverts L P.isoModSerre t ht + exact ⟨L.map (cokernel.desc _ _ fac) ≫ inv (L.map t), by simp [← L.map_comp_assoc]⟩ lemma hasKernels : HasKernels D where has_limit f := by From 3c1c9e0b57efe7d57cdbef27ebb21cfcaec2da13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Mon, 26 Jan 2026 09:22:40 +0100 Subject: [PATCH 39/46] wip --- .../Abelian/SerreClass/Localization.lean | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index a8ad5d931e12c7..f49858315cc3f0 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -230,6 +230,16 @@ lemma epi_map_iff {X Y : C} (f : X ⟶ Y) : obtain ⟨W, s, hs, eq⟩ := hz refine ⟨_, s ≫ f, MorphismProperty.comp_mem _ _ _ hs hf, by simpa⟩ +lemma inverseImage_monomorphisms : + (MorphismProperty.monomorphisms _).inverseImage L = P.monoModSerre := by + ext + simp [mono_map_iff L P] + +lemma inverseImage_epimorphisms : + (MorphismProperty.epimorphisms _).inverseImage L = P.epiModSerre := by + ext + simp [epi_map_iff L P] + lemma preservesMonomorphisms : L.PreservesMonomorphisms where preserves f _ := by simpa only [mono_map_iff _ P] using P.monoModSerre_of_mono f @@ -443,6 +453,16 @@ lemma preservesFiniteColimits : PreservesFiniteColimits L := by intro _ _ f exact preservesCokernel L P f +lemma isIso_map_iff {X Y : C} (f : X ⟶ Y) : + IsIso (L.map f) ↔ P.isoModSerre f := by + letI := abelian L P + rw [isIso_iff_mono_and_epi, mono_map_iff L P, epi_map_iff L P, isoModSerre_iff] + +lemma inverseImage_isomorphisms : + (MorphismProperty.isomorphisms _).inverseImage L = P.isoModSerre := by + ext + simp [isIso_map_iff L P] + end SerreClassLocalization end ObjectProperty From 239b28496e10c30bee339cddf8c511805f97ed28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 18:00:42 +0100 Subject: [PATCH 40/46] removed unnecessary code --- .../CalculusOfFractions/Preadditive.lean | 36 +------------------ 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean b/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean index 624d9f7875f43b..649cf7a3f319c4 100644 --- a/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean +++ b/Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean @@ -8,8 +8,7 @@ module public import Mathlib.Algebra.Group.TransferInstance public import Mathlib.CategoryTheory.Localization.CalculusOfFractions.Fractions public import Mathlib.CategoryTheory.Localization.HasLocalization -public import Mathlib.CategoryTheory.Preadditive.Opposite -public import Mathlib.CategoryTheory.Preadditive.Transfer +public import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor /-! # The preadditive category structure on the localized category @@ -301,8 +300,6 @@ end ImplementationDetails end Preadditive -section - variable [W.HasLeftCalculusOfFractions] /-- The preadditive structure on `D`, when `L : C ⥤ D` is a localization @@ -354,37 +351,6 @@ noncomputable instance : Preadditive W.Localization' := preadditive W.Q' W instance : W.Q'.Additive := functor_additive W.Q' W instance [HasZeroObject C] : HasZeroObject W.Localization' := W.Q'.hasZeroObject_of_additive -end - -section - -variable [W.HasRightCalculusOfFractions] - -/-- The preadditive structure on `D`, when `L : C ⥤ D` is a localization -functor, `C` is preadditive and there is a right calculus of fractions. -If both left and right calculus of fractions are available, it is advisable -to use `Localization.preadditive` instead. -/ -noncomputable def preadditive' : Preadditive D := by - letI := preadditive L.op W.op - exact Preadditive.ofFullyFaithful (opOpEquivalence D).fullyFaithfulInverse - -lemma functor_additive' : - letI := preadditive' L W - L.Additive := by - letI := preadditive L.op W.op - letI := preadditive' L W - have := functor_additive L.op W.op - have : (opOpEquivalence C).inverse.Additive := { } - have : (opOpEquivalence D).functor.Additive := by - have : (opOpEquivalence D).symm.functor.Additive := - (opOpEquivalence D).fullyFaithfulInverse.additive_ofFullyFaithful - exact Equivalence.inverse_additive (opOpEquivalence D).symm - exact Functor.additive_of_iso - (show (opOpEquivalence C).inverse ⋙ L.op.op ⋙ (opOpEquivalence D).functor ≅ L - from Iso.refl _) - -end - end Localization end CategoryTheory From e7b96338010c8e6733902e0d571c8662d2979cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 18:06:46 +0100 Subject: [PATCH 41/46] moved code --- .../Abelian/SerreClass/Localization.lean | 65 +++++-------------- .../Limits/Shapes/NormalMono/Basic.lean | 33 ++++++++++ 2 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index f49858315cc3f0..bb230caaff45ba 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -20,47 +20,13 @@ universe v' u' v u namespace CategoryTheory -open Category Limits ZeroObject - -variable {C : Type u} [Category.{v} C] - {D : Type u'} [Category.{v'} D] - --- to be moved -def NormalMono.ofArrowIso [HasZeroMorphisms C] {X Y : C} {f : X ⟶ Y} - (hf : NormalMono f) {X' Y' : C} {f' : X' ⟶ Y'} (e : Arrow.mk f ≅ Arrow.mk f') : - NormalMono f' where - Z := hf.Z - g := e.inv.right ≫ hf.g - w := by - have := Arrow.w e.inv - dsimp at this - rw [← reassoc_of% this, hf.w, comp_zero] - isLimit := by - refine (IsLimit.equivOfNatIsoOfIso ?_ _ _ ?_).1 hf.isLimit - · exact parallelPair.ext (Arrow.rightFunc.mapIso e) (Iso.refl _) - (by cat_disch) (by cat_disch) - · exact Fork.ext (Arrow.leftFunc.mapIso e) - -def NormalEpi.ofArrowIso [HasZeroMorphisms C] {X Y : C} {f : X ⟶ Y} - (hf : NormalEpi f) {X' Y' : C} {f' : X' ⟶ Y'} (e : Arrow.mk f ≅ Arrow.mk f') : - NormalEpi f' where - W := hf.W - g := hf.g ≫ e.hom.left - w := by - have := Arrow.w e.hom - dsimp at this - rw [assoc, this, reassoc_of% hf.w, zero_comp] - isColimit := by - refine (IsColimit.equivOfNatIsoOfIso ?_ _ _ ?_).1 hf.isColimit - · exact parallelPair.ext (Iso.refl _) (Arrow.leftFunc.mapIso e) - (by cat_disch) (by cat_disch) - · exact Cofork.ext (Arrow.rightFunc.mapIso e) (by simp [Cofork.π]) - -variable [Abelian C] +open Limits ZeroObject namespace ObjectProperty -variable (L : C ⥤ D) (P : ObjectProperty C) [P.IsSerreClass] +variable {C : Type u} [Category.{v} C] [Abelian C] + {D : Type u'} [Category.{v'} D] + (L : C ⥤ D) (P : ObjectProperty C) [P.IsSerreClass] lemma exists_epiModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : (∃ (X' : C) (s : X' ⟶ X) (_ : P.epiModSerre s), s ≫ f = 0) ↔ @@ -157,7 +123,7 @@ lemma isZero_obj_iff (X : C) : IsZero (L.obj X) ↔ P X := by simp only [IsZero.iff_id_eq_zero, ← L.map_id, ← L.map_zero, MorphismProperty.map_eq_iff_precomp L P.isoModSerre, - comp_id, comp_zero, exists_prop, exists_eq_right] + Category.comp_id, comp_zero, exists_prop, exists_eq_right] refine ⟨?_, fun _ ↦ ⟨X, by simpa⟩⟩ rintro ⟨Y, h⟩ simpa using h.2 @@ -196,7 +162,7 @@ lemma mono_map_iff {X Y : C} (f : X ⟶ Y) : MorphismProperty.RightFraction.map_s_comp_map] apply this φ.f have : L.map φ.s ≫ (L.objObjPreimageIso W).hom ≫ z = L.map φ.f := by cat_disch - rw [← this, assoc, assoc, hz, comp_zero, comp_zero] + rw [← this, Category.assoc, Category.assoc, hz, comp_zero, comp_zero] intro Z z hz rw [← L.map_comp] at hz rw [map_eq_zero_iff L P, ← exists_comp_monoModSerre_eq_zero_iff P] at hz ⊢ @@ -312,16 +278,17 @@ lemma preservesKernel {X Y : C} (f : X ⟶ Y) : rw [← cancel_epi (L.map φ.s), MorphismProperty.RightFraction.map_s_comp_map] at hφ obtain ⟨l, hl⟩ := this _ (L.map φ.f) (by - rw [← hφ, assoc, assoc, hw, comp_zero, comp_zero]) ⟨_, rfl, by simp⟩ + rw [← hφ, Category.assoc, Category.assoc, hw, comp_zero, comp_zero]) ⟨_, rfl, by simp⟩ exact ⟨(L.objObjPreimageIso W).inv ≫ inv (L.map φ.s) ≫ l, by simp [hl, ← hφ]⟩ obtain ⟨Z, rfl, z, rfl⟩ := hw' - simp only [eqToHom_refl, id_comp, ← L.map_comp] at hw + simp only [eqToHom_refl, Category.id_comp, ← L.map_comp] at hw rw [map_eq_zero_iff L P, ← exists_isoModSerre_comp_eq_zero_iff P] at hw obtain ⟨Z', t, ht, fac⟩ := hw have := Localization.inverts L P.isoModSerre t ht - rw [← assoc] at fac + rw [← Category.assoc] at fac refine ⟨inv (L.map t) ≫ L.map (kernel.lift _ _ fac), ?_⟩ - simp only [assoc, eqToHom_refl, id_comp, IsIso.inv_comp_eq, ← L.map_comp, kernel.lift_ι] + simp only [Category.assoc, eqToHom_refl, Category.id_comp, IsIso.inv_comp_eq, + ← L.map_comp, kernel.lift_ι] lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : PreservesColimit (parallelPair f 0) L := by @@ -341,15 +308,15 @@ lemma preservesCokernel {X Y : C} (f : X ⟶ Y) : · obtain ⟨φ, hφ⟩ := Localization.exists_leftFraction L P.isoModSerre (w ≫ (L.objObjPreimageIso W).inv) have _ := Localization.inverts L P.isoModSerre φ.s φ.hs - rw [← cancel_mono (L.map φ.s), assoc, + rw [← cancel_mono (L.map φ.s), Category.assoc, MorphismProperty.LeftFraction.map_comp_map_s] at hφ obtain ⟨l, hl⟩ := this _ (L.map φ.f) (by rw [← hφ, reassoc_of% hw, zero_comp]) ⟨_, rfl, by simp⟩ exact ⟨l ≫ inv (L.map φ.s) ≫ (L.objObjPreimageIso W).hom, by simp [reassoc_of% hl, ← hφ]⟩ obtain ⟨Z, rfl, z, rfl⟩ := hw' - simp only [eqToHom_refl, comp_id, ← L.map_comp] at hw + simp only [eqToHom_refl, Category.comp_id, ← L.map_comp] at hw rw [map_eq_zero_iff L P, ← exists_comp_isoModSerre_eq_zero_iff P] at hw obtain ⟨Z', t, ht, fac⟩ := hw - rw [assoc] at fac + rw [Category.assoc] at fac have := Localization.inverts L P.isoModSerre t ht exact ⟨L.map (cokernel.desc _ _ fac) ≫ inv (L.map t), by simp [← L.map_comp_assoc]⟩ @@ -406,13 +373,13 @@ lemma isNormalMonoCategory : IsNormalMonoCategory D where rw [mono_iff L P] at hf obtain ⟨X', Y', f', _, ⟨e⟩⟩ := hf let hf' := normalMonoOfMono f' + have := preservesKernel L P hf'.g refine ⟨NormalMono.ofArrowIso ?_ e⟩ exact { Z := L.obj hf'.Z g := L.map hf'.g w := by rw [← L.map_comp]; simp [hf'.w] isLimit := - have := preservesKernel L P hf'.g (KernelFork.isLimitMapConeEquiv _ L).1 (isLimitOfPreserves L hf'.isLimit) } @@ -421,13 +388,13 @@ lemma isNormalEpiCategory : IsNormalEpiCategory D where rw [epi_iff L P] at hf obtain ⟨X', Y', f', _, ⟨e⟩⟩ := hf let hf' := normalEpiOfEpi f' + have := preservesCokernel L P hf'.g refine ⟨NormalEpi.ofArrowIso ?_ e⟩ exact { W := L.obj hf'.W g := L.map hf'.g w := by rw [← L.map_comp]; simp [hf'.w] isColimit := - have := preservesCokernel L P hf'.g (CokernelCofork.isColimitMapCoconeEquiv _ L).1 (isColimitOfPreserves L hf'.isColimit) } diff --git a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean index 20824588c6ded9..3906c6ddae382b 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/NormalMono/Basic.lean @@ -115,6 +115,22 @@ def normalOfIsPullbackFstOfNormal {P Q R S : C} {f : P ⟶ Q} {g : P ⟶ R} {h : NormalMono f := normalOfIsPullbackSndOfNormal comm.symm (PullbackCone.flipIsLimit t) +/-- Transport a `NormalMono` structure via an isomorphism of arrows. -/ +def NormalMono.ofArrowIso {X Y : C} {f : X ⟶ Y} + (hf : NormalMono f) {X' Y' : C} {f' : X' ⟶ Y'} (e : Arrow.mk f ≅ Arrow.mk f') : + NormalMono f' where + Z := hf.Z + g := e.inv.right ≫ hf.g + w := by + have := Arrow.w e.inv + dsimp at this + rw [← reassoc_of% this, hf.w, comp_zero] + isLimit := by + refine (IsLimit.equivOfNatIsoOfIso ?_ _ _ ?_).1 hf.isLimit + · exact parallelPair.ext (Arrow.rightFunc.mapIso e) (Iso.refl _) + (by cat_disch) (by cat_disch) + · exact Fork.ext (Arrow.leftFunc.mapIso e) + section variable (C) @@ -219,6 +235,23 @@ open Opposite variable [HasZeroMorphisms C] +/-- Transport a `NormalEpi` structure via an isomorphism of arrows. -/ +def NormalEpi.ofArrowIso [HasZeroMorphisms C] {X Y : C} {f : X ⟶ Y} + (hf : NormalEpi f) {X' Y' : C} {f' : X' ⟶ Y'} (e : Arrow.mk f ≅ Arrow.mk f') : + NormalEpi f' where + W := hf.W + g := hf.g ≫ e.hom.left + w := by + have := Arrow.w e.hom + dsimp at this + rw [Category.assoc, this, reassoc_of% hf.w, zero_comp] + isColimit := by + refine (IsColimit.equivOfNatIsoOfIso ?_ _ _ ?_).1 hf.isColimit + · exact parallelPair.ext (Iso.refl _) (Arrow.leftFunc.mapIso e) + (by cat_disch) (by cat_disch) + · exact Cofork.ext (Arrow.rightFunc.mapIso e) (by simp [Cofork.π]) + + /-- A normal mono becomes a normal epi in the opposite category. -/ def normalEpiOfNormalMonoUnop {X Y : Cᵒᵖ} (f : X ⟶ Y) (m : NormalMono f.unop) : NormalEpi f where W := op m.Z From 1ad59db7b23327fb4dd5383068617d98428d050f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 18:28:44 +0100 Subject: [PATCH 42/46] wip --- Mathlib.lean | 1 + Mathlib/CategoryTheory/Abelian/Basic.lean | 7 ++ Mathlib/CategoryTheory/Abelian/CommSq.lean | 42 +++++++++- .../Abelian/SerreClass/MorphismProperty.lean | 84 +------------------ .../CategoryTheory/Limits/Shapes/Kernels.lean | 13 +++ .../Shapes/Pullback/IsPullback/Kernels.lean | 54 ++++++++++++ 6 files changed, 117 insertions(+), 84 deletions(-) create mode 100644 Mathlib/CategoryTheory/Limits/Shapes/Pullback/IsPullback/Kernels.lean diff --git a/Mathlib.lean b/Mathlib.lean index b8cbd0fb434426..e5572e5047c335 100644 --- a/Mathlib.lean +++ b/Mathlib.lean @@ -2720,6 +2720,7 @@ public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.HasPullback public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.IsPullback.Basic public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.IsPullback.BicartesianSq public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.IsPullback.Defs +public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.IsPullback.Kernels public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Iso public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.Pasting diff --git a/Mathlib/CategoryTheory/Abelian/Basic.lean b/Mathlib/CategoryTheory/Abelian/Basic.lean index 87ac2a82a4d69c..05df566065e629 100644 --- a/Mathlib/CategoryTheory/Abelian/Basic.lean +++ b/Mathlib/CategoryTheory/Abelian/Basic.lean @@ -10,6 +10,7 @@ public import Mathlib.CategoryTheory.Preadditive.Biproducts public import Mathlib.CategoryTheory.Limits.Preserves.Shapes.Kernels public import Mathlib.CategoryTheory.Limits.Shapes.Images public import Mathlib.CategoryTheory.Limits.Constructions.LimitsOfProductsAndEqualizers +public import Mathlib.CategoryTheory.MorphismProperty.Limits public import Mathlib.CategoryTheory.Abelian.NonPreadditive /-! @@ -790,6 +791,12 @@ theorem mono_inl_of_factor_thru_epi_mono_factorization (f : X ⟶ Y) (g : X ⟶ end MonoPushout +instance : (MorphismProperty.monomorphisms C).IsStableUnderCobaseChange := + .mk' (fun _ _ _ _ _ _ (_ : Mono _) ↦ inferInstanceAs (Mono _)) + +instance : (MorphismProperty.epimorphisms C).IsStableUnderBaseChange := + .mk' (fun _ _ _ _ _ _ (_ : Epi _) ↦ inferInstanceAs (Epi _)) + end CategoryTheory.Abelian namespace CategoryTheory.NonPreadditiveAbelian diff --git a/Mathlib/CategoryTheory/Abelian/CommSq.lean b/Mathlib/CategoryTheory/Abelian/CommSq.lean index 75dd1d0aed4b64..0a85f00da96ece 100644 --- a/Mathlib/CategoryTheory/Abelian/CommSq.lean +++ b/Mathlib/CategoryTheory/Abelian/CommSq.lean @@ -14,13 +14,16 @@ public import Mathlib.Algebra.Homology.CommSq Consider a pushout square in an abelian category: ``` -X₁ ⟶ X₂ -| | -v v -X₃ ⟶ X₄ + t + X₁ ⟶ X₂ +l| |r + v v + X₃ ⟶ X₄ + b ``` We study the associated exact sequence `X₁ ⟶ X₂ ⊞ X₃ ⟶ X₄ ⟶ 0`. +We also show that the induced morphism `kernel t ⟶ kernel b` is an epimorphism. -/ @@ -113,5 +116,36 @@ statement to `IsPushout.hom_eq_add_up_to_refinements`. end IsPullback +namespace Abelian + +variable {X₁ X₂ X₃ X₄ : C} {t : X₁ ⟶ X₂} {l : X₁ ⟶ X₃} {r : X₂ ⟶ X₄} {b : X₃ ⟶ X₄} + +lemma mono_cokernel_map_of_isPullback (sq : IsPullback t l r b) : + Mono (cokernel.map _ _ _ _ sq.w) := by + rw [Preadditive.mono_iff_cancel_zero] + intro A₀ z hz + obtain ⟨A₁, π₁, _, x₂, hx₂⟩ := + surjective_up_to_refinements_of_epi (cokernel.π t) z + have : (ShortComplex.mk _ _ (cokernel.condition b)).Exact := + ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel b) + obtain ⟨A₂, π₂, _, x₃, hx₃⟩ := this.exact_up_to_refinements (x₂ ≫ r) (by + simpa [hz] using hx₂.symm =≫ cokernel.map _ _ _ _ sq.w) + obtain ⟨x₁, hx₁, rfl⟩ := sq.exists_lift (π₂ ≫ x₂) x₃ (by simpa) + simp [← cancel_epi π₁, ← cancel_epi π₂, hx₂, ← reassoc_of% hx₁] + +lemma epi_kernel_map_of_isPushout (sq : IsPushout t l r b) : + Epi (kernel.map _ _ _ _ sq.w) := by + rw [epi_iff_surjective_up_to_refinements] + intro A₀ z + obtain ⟨A₁, π₁, _, x₁, hx₁⟩ := ((ShortComplex.mk _ _ + sq.cokernelCofork.condition).exact_of_g_is_cokernel + sq.isColimitCokernelCofork).exact_up_to_refinements + (z ≫ kernel.ι _ ≫ biprod.inr) (by simp) + refine ⟨A₁, π₁, inferInstance, -kernel.lift _ x₁ ?_, ?_⟩ + · simpa using hx₁.symm =≫ biprod.fst + · ext + simpa using hx₁ =≫ biprod.snd + +end Abelian end CategoryTheory diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean index 2fd01589c8b1bf..8846c1ecc0f606 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/MorphismProperty.lean @@ -7,7 +7,9 @@ module public import Mathlib.Algebra.Homology.Square public import Mathlib.CategoryTheory.Abelian.SerreClass.Basic +public import Mathlib.CategoryTheory.Abelian.CommSq public import Mathlib.CategoryTheory.Abelian.DiagramLemmas.KernelCokernelComp +public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.IsPullback.Kernels public import Mathlib.CategoryTheory.MorphismProperty.Composition public import Mathlib.CategoryTheory.MorphismProperty.Retract public import Mathlib.CategoryTheory.MorphismProperty.Limits @@ -37,87 +39,9 @@ namespace CategoryTheory open Category Limits ZeroObject MorphismProperty -section -- to be moved - -variable {C : Type*} [Category* C] [HasZeroMorphisms C] - {X₁ X₂ X₃ X₄ : C} {t : X₁ ⟶ X₂} {l : X₁ ⟶ X₃} {r : X₂ ⟶ X₄} {b : X₃ ⟶ X₄} - -lemma Abelian.isIso_kernel_map_of_isPullback [HasKernel t] [HasKernel b] - (sq : IsPullback t l r b) : - IsIso (kernel.map _ _ _ _ sq.w) := - ⟨kernel.lift _ (sq.lift 0 (kernel.ι b) (by simp)) (by simp), - by ext; exact sq.hom_ext (by cat_disch) (by cat_disch), by cat_disch⟩ - -lemma Abelian.isIso_cokernel_map_of_isPushout [HasCokernel t] [HasCokernel b] - (sq : IsPushout t l r b) : - IsIso (cokernel.map _ _ _ _ sq.w) := - ⟨cokernel.desc _ (sq.desc (cokernel.π t) 0 (by simp)) (by simp), - by cat_disch, by ext; exact sq.hom_ext (by cat_disch) (by cat_disch)⟩ - -end - -section -- to be moved - -variable {C : Type*} [Category* C] [HasZeroMorphisms C] - {X₁ X₂ X₃ X₄ : C} (t : X₁ ⟶ X₂) (b : X₃ ⟶ X₄) (l : X₁ ⟶ X₃) (r : X₂ ⟶ X₄) - (fac : t ≫ r = l ≫ b) - -instance isIso_kernel_map_of_isIso_of_mono [HasKernel t] [HasKernel b] - [IsIso l] [Mono r] : - IsIso (kernel.map _ _ _ _ fac) := - ⟨kernel.lift _ (kernel.ι b ≫ inv l) (by simp [← cancel_mono r, fac]), - by cat_disch, by cat_disch⟩ - -instance isIso_cokernel_map_of_isIso_of_epi [HasCokernel t] [HasCokernel b] - [Epi l] [IsIso r] : - IsIso (cokernel.map _ _ _ _ fac) := - ⟨cokernel.desc _ (inv r ≫ cokernel.π t) (by simp [← cancel_epi l, ← reassoc_of% fac]), - by cat_disch, by cat_disch⟩ - -end - - variable {C : Type u} [Category.{v} C] [Abelian C] {D : Type u'} [Category.{v'} D] [Abelian D] -namespace Abelian -- to be moved - -variable {X₁ X₂ X₃ X₄ : C} {t : X₁ ⟶ X₂} {l : X₁ ⟶ X₃} {r : X₂ ⟶ X₄} {b : X₃ ⟶ X₄} - -lemma mono_cokernel_map_of_isPullback (sq : IsPullback t l r b) : - Mono (cokernel.map _ _ _ _ sq.w) := by - rw [Preadditive.mono_iff_cancel_zero] - intro A₀ z hz - obtain ⟨A₁, π₁, _, x₂, hx₂⟩ := - surjective_up_to_refinements_of_epi (cokernel.π t) z - have : (ShortComplex.mk _ _ (cokernel.condition b)).Exact := - ShortComplex.exact_of_g_is_cokernel _ (cokernelIsCokernel b) - obtain ⟨A₂, π₂, _, x₃, hx₃⟩ := this.exact_up_to_refinements (x₂ ≫ r) (by - simpa [hz] using hx₂.symm =≫ cokernel.map _ _ _ _ sq.w) - obtain ⟨x₁, hx₁, rfl⟩ := sq.exists_lift (π₂ ≫ x₂) x₃ (by simpa) - simp [← cancel_epi π₁, ← cancel_epi π₂, hx₂, ← reassoc_of% hx₁] - -lemma epi_kernel_map_of_isPushout (sq : IsPushout t l r b) : - Epi (kernel.map _ _ _ _ sq.w) := by - rw [epi_iff_surjective_up_to_refinements] - intro A₀ z - obtain ⟨A₁, π₁, _, x₁, hx₁⟩ := ((ShortComplex.mk _ _ - sq.cokernelCofork.condition).exact_of_g_is_cokernel - sq.isColimitCokernelCofork).exact_up_to_refinements - (z ≫ kernel.ι _ ≫ biprod.inr) (by simp) - refine ⟨A₁, π₁, inferInstance, -kernel.lift _ x₁ ?_, ?_⟩ - · simpa using hx₁.symm =≫ biprod.fst - · ext - simpa using hx₁ =≫ biprod.snd - -end Abelian - -instance : (monomorphisms C).IsStableUnderCobaseChange := - .mk' (fun _ _ _ _ _ _ (_ : Mono _) ↦ inferInstanceAs (Mono _)) - -instance : (epimorphisms C).IsStableUnderBaseChange := - .mk' (fun _ _ _ _ _ _ (_ : Epi _) ↦ inferInstanceAs (Epi _)) - namespace ObjectProperty variable (P : ObjectProperty C) @@ -266,7 +190,7 @@ lemma isoModSerre_isInvertedBy_iff (F : C ⥤ D) instance : P.monoModSerre.IsStableUnderBaseChange where of_isPullback sq h := - have := Abelian.isIso_kernel_map_of_isPullback sq.flip + have := isIso_kernel_map_of_isPullback sq.flip P.prop_of_iso (asIso (kernel.map _ _ _ _ sq.w.symm)).symm h instance : P.epiModSerre.IsStableUnderBaseChange where @@ -285,7 +209,7 @@ instance : P.monoModSerre.IsStableUnderCobaseChange where instance : P.epiModSerre.IsStableUnderCobaseChange where of_isPushout sq h := - have := Abelian.isIso_cokernel_map_of_isPushout sq.flip + have := isIso_cokernel_map_of_isPushout sq.flip P.prop_of_iso (asIso (cokernel.map _ _ _ _ sq.w.symm)) h instance : P.isoModSerre.IsStableUnderCobaseChange := by diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean index 950aaeea9ce3fd..e3d6cdbdc58aea 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean @@ -314,6 +314,13 @@ lemma kernel.map_id {X Y : C} (f : X ⟶ Y) [HasKernel f] (q : Y ⟶ Y) (w : f ≫ q = 𝟙 _ ≫ f) : kernel.map f f (𝟙 _) q w = 𝟙 _ := by cat_disch +instance {X' Y' : C} (f' : X' ⟶ Y') [HasKernel f'] (p : X ⟶ X') (q : Y ⟶ Y') + (w : f ≫ q = p ≫ f') [IsIso p] [Mono q] : + IsIso (kernel.map _ _ _ _ w) := + ⟨kernel.lift _ (kernel.ι f' ≫ inv p) (by simp [← cancel_mono q, w]), + by cat_disch, by cat_disch⟩ + + /-- Given a commutative diagram ``` X --f--> Y --g--> Z @@ -802,6 +809,12 @@ abbrev cokernel.map {X' Y' : C} (f' : X' ⟶ Y') [HasCokernel f'] (p : X ⟶ X') apply congrArg (· ≫ π f') w simp [this]) +instance {X' Y' : C} (f' : X' ⟶ Y') [HasCokernel f'] (p : X ⟶ X') (q : Y ⟶ Y') + (w : f ≫ q = p ≫ f') [Epi p] [IsIso q] : + IsIso (cokernel.map _ _ _ _ w) := + ⟨cokernel.desc _ (inv q ≫ cokernel.π f) (by simp [← cancel_epi p, ← reassoc_of% w]), + by cat_disch, by cat_disch⟩ + @[simp] lemma cokernel.map_id {X Y : C} (f : X ⟶ Y) [HasCokernel f] (q : X ⟶ X) (w : f ≫ 𝟙 _ = q ≫ f) : cokernel.map f f q (𝟙 _) w = 𝟙 _ := by diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Pullback/IsPullback/Kernels.lean b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/IsPullback/Kernels.lean new file mode 100644 index 00000000000000..c1240541df24f2 --- /dev/null +++ b/Mathlib/CategoryTheory/Limits/Shapes/Pullback/IsPullback/Kernels.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.CategoryTheory.Limits.Shapes.Kernels +public import Mathlib.CategoryTheory.Limits.Shapes.Pullback.IsPullback.Basic + +/-! +# Horizontal maps in a pullback square have the same kernel + +Consider a commutative square: +``` + t + X₁ --> X₂ +l| |r + v v + X₃ --> X₄ + b +``` +* If this is a pullback square, then the induced map `kernel t ⟶ kernel b` +is an isomorphism. +* If this is a pushout square, then the induced map `cokernel t ⟶ cokernel b` +is an isomorphism. + +(Similar results for the (co)kernels of the vertical maps can be obtained +by applying these results to the flipped square.) + +-/ + +@[expose] public section + +universe v v' u u' + +namespace CategoryTheory.Limits + +variable {C : Type*} [Category* C] [HasZeroMorphisms C] + {X₁ X₂ X₃ X₄ : C} {t : X₁ ⟶ X₂} {l : X₁ ⟶ X₃} {r : X₂ ⟶ X₄} {b : X₃ ⟶ X₄} + +lemma isIso_kernel_map_of_isPullback [HasKernel t] [HasKernel b] + (sq : IsPullback t l r b) : + IsIso (kernel.map _ _ _ _ sq.w) := + ⟨kernel.lift _ (sq.lift 0 (kernel.ι b) (by simp)) (by simp), + by ext; exact sq.hom_ext (by cat_disch) (by cat_disch), by cat_disch⟩ + +lemma isIso_cokernel_map_of_isPushout [HasCokernel t] [HasCokernel b] + (sq : IsPushout t l r b) : + IsIso (cokernel.map _ _ _ _ sq.w) := + ⟨cokernel.desc _ (sq.desc (cokernel.π t) 0 (by simp)) (by simp), + by cat_disch, by ext; exact sq.hom_ext (by cat_disch) (by cat_disch)⟩ + +end CategoryTheory.Limits From 45a034c84fb11f284a4791799b01c6735da9f5e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 18:30:32 +0100 Subject: [PATCH 43/46] wip --- Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean | 1 - 1 file changed, 1 deletion(-) diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean index e3d6cdbdc58aea..36ed94d0430dde 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Kernels.lean @@ -320,7 +320,6 @@ instance {X' Y' : C} (f' : X' ⟶ Y') [HasKernel f'] (p : X ⟶ X') (q : Y ⟶ Y ⟨kernel.lift _ (kernel.ι f' ≫ inv p) (by simp [← cancel_mono q, w]), by cat_disch, by cat_disch⟩ - /-- Given a commutative diagram ``` X --f--> Y --g--> Z From 7ec3d6b2ba45f7ca18fd25db14125dfe4c92af29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 19:41:35 +0100 Subject: [PATCH 44/46] wip --- .../Abelian/SerreClass/Localization.lean | 117 +++++++++++++++++- .../CategoryTheory/Limits/ExactFunctor.lean | 15 +++ .../Limits/Shapes/Equalizers.lean | 5 +- .../Localization/Predicate.lean | 7 ++ 4 files changed, 137 insertions(+), 7 deletions(-) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index bb230caaff45ba..1eec33bd0b7643 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -8,15 +8,24 @@ module public import Mathlib.Algebra.Homology.ShortComplex.ExactFunctor public import Mathlib.CategoryTheory.Abelian.SerreClass.MorphismProperty public import Mathlib.CategoryTheory.Localization.CalculusOfFractions.Preadditive +public import Mathlib.CategoryTheory.Limits.ExactFunctor /-! # Localization with respect to a Serre class +The main definition in this file is `ObjectProperty.SerreClassLocalization.abelian` +which shows that if `L : C ⥤ D` is a localization functor with respect to +the class of morphisms `P.isoModSerre` for a Serre class `P : ObjectProperty C` +in the abelian category `C`, then `D` is an abelian category. + +We also show that a functor `G : D ⥤ E` to an abelian category is exact iff +the composition `L ⋙ G` is. + -/ @[expose] public section -universe v' u' v u +universe v'' v' v u'' u' u namespace CategoryTheory @@ -27,6 +36,7 @@ namespace ObjectProperty variable {C : Type u} [Category.{v} C] [Abelian C] {D : Type u'} [Category.{v'} D] (L : C ⥤ D) (P : ObjectProperty C) [P.IsSerreClass] + {E : Type u''} [Category.{v''} E] [Abelian E] lemma exists_epiModSerre_comp_eq_zero_iff {X Y : C} (f : X ⟶ Y) : (∃ (X' : C) (s : X' ⟶ X) (_ : P.epiModSerre s), s ≫ f = 0) ↔ @@ -329,8 +339,7 @@ lemma hasKernels : HasKernels D where ⟨_, (KernelFork.isLimitMapConeEquiv _ L).1 (isLimitOfPreserves L (kernelIsKernel g.hom))⟩ exact hasLimit_of_iso (show parallelPair (L.map g.hom) 0 ≅ _ from - parallelPair.ext (Arrow.leftFunc.mapIso e) - (Arrow.rightFunc.mapIso e) (by cat_disch) (by cat_disch)) + parallelPair.ext (Arrow.leftFunc.mapIso e) (Arrow.rightFunc.mapIso e)) lemma hasCokernels : HasCokernels D where has_colimit f := by @@ -341,8 +350,7 @@ lemma hasCokernels : HasCokernels D where ⟨_, (CokernelCofork.isColimitMapCoconeEquiv _ L).1 (isColimitOfPreserves L (cokernelIsCokernel g.hom))⟩ exact hasColimit_of_iso (show _ ≅ parallelPair (L.map g.hom) 0 from - parallelPair.ext (Arrow.leftFunc.mapIso e.symm) - (Arrow.rightFunc.mapIso e.symm) (by cat_disch) (by cat_disch)) + parallelPair.ext (Arrow.leftFunc.mapIso e.symm) (Arrow.rightFunc.mapIso e.symm)) lemma hasEqualizers : HasEqualizers D := have := hasKernels L P @@ -398,6 +406,12 @@ lemma isNormalEpiCategory : IsNormalEpiCategory D where (CokernelCofork.isColimitMapCoconeEquiv _ L).1 (isColimitOfPreserves L hf'.isColimit) } +/-- If `L : C ⥤ D` is a localization functor with respect to a Serre class `P` in +the abelian category `C`, then `D` is an abelian category. +(Note that we assume that `D` has already been equipped with a preadditive structure, +and that `L` is additive. Otherwise, see the results in the file +`Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean` +which applies because `P.isoModSerre` has a calculus of left and right fractions.) -/ def abelian : Abelian D := by have := hasFiniteProducts L P have := hasKernels L P @@ -430,6 +444,99 @@ lemma inverseImage_isomorphisms : ext simp [isIso_map_iff L P] +variable (G : D ⥤ E) + +lemma preservesFiniteLimits_comp_iff : + PreservesFiniteLimits (L ⋙ G) ↔ PreservesFiniteLimits G := by + letI := abelian L P + have := preservesFiniteLimits L P + refine ⟨fun _ ↦ ?_, fun _ ↦ comp_preservesFiniteLimits _ _⟩ + have := (Localization.functor_additive_iff L P.isoModSerre G).2 + ((L ⋙ G).additive_of_preserves_binary_products) + refine ((Functor.preservesFiniteLimits_tfae G).out 2 3).1 (fun _ _ f ↦ ?_) + obtain ⟨f', ⟨iso⟩⟩ := + (Localization.essSurj_mapArrow L P.isoModSerre).mem_essImage (Arrow.mk f) + have : PreservesLimit (parallelPair (L.map f'.hom) 0) G := + preservesLimit_of_preserves_limit_cone + ((KernelFork.isLimitMapConeEquiv _ _).1 + (isLimitOfPreserves L (kernelIsKernel f'.hom))) + ((KernelFork.isLimitMapConeEquiv _ G).2 + ((KernelFork.isLimitMapConeEquiv _ (L ⋙ G)).1 + (isLimitOfPreserves (L ⋙ G) (kernelIsKernel f'.hom)))) + exact preservesLimit_of_iso_diagram G + (show parallelPair (L.map f'.hom) 0 ≅ parallelPair f 0 from + parallelPair.ext (Arrow.leftFunc.mapIso iso) (Arrow.rightFunc.mapIso iso)) + +lemma preservesFiniteColimits_comp_iff : + PreservesFiniteColimits (L ⋙ G) ↔ PreservesFiniteColimits G := by + letI := abelian L P + have := preservesFiniteColimits L P + refine ⟨fun _ ↦ ?_, fun _ ↦ comp_preservesFiniteColimits _ _⟩ + have := (Localization.functor_additive_iff L P.isoModSerre G).2 (by + have := preservesBinaryBiproducts_of_preservesBinaryCoproducts (L ⋙ G) + exact Functor.additive_of_preservesBinaryBiproducts _) + refine ((Functor.preservesFiniteColimits_tfae G).out 2 3).1 (fun _ _ f ↦ ?_) + obtain ⟨f', ⟨iso⟩⟩ := + (Localization.essSurj_mapArrow L P.isoModSerre).mem_essImage (Arrow.mk f) + have : PreservesColimit (parallelPair (L.map f'.hom) 0) G := + preservesColimit_of_preserves_colimit_cocone + ((CokernelCofork.isColimitMapCoconeEquiv _ _).1 + (isColimitOfPreserves L (cokernelIsCokernel f'.hom))) + ((CokernelCofork.isColimitMapCoconeEquiv _ G).2 + ((CokernelCofork.isColimitMapCoconeEquiv _ (L ⋙ G)).1 + (isColimitOfPreserves (L ⋙ G) (cokernelIsCokernel f'.hom)))) + exact preservesColimit_of_iso_diagram G + (show parallelPair (L.map f'.hom) 0 ≅ parallelPair f 0 from + parallelPair.ext (Arrow.leftFunc.mapIso iso) (Arrow.rightFunc.mapIso iso)) + +lemma exactFunctor_comp_iff : + exactFunctor _ _ (L ⋙ G) ↔ exactFunctor _ _ G := by + simp [preservesFiniteLimits_comp_iff L P, preservesFiniteColimits_comp_iff L P] + +variable (E) + +/-- When `L : C ⥤ D` is a localization functor with respect to a Serre class +in the abelian category `C`, this is the functor `(D ⥤ₑ E) ⥤ C ⥤ₑ E` +obtained by precomposition with `L`. -/ +def whiskeringLeft : (D ⥤ₑ E) ⥤ C ⥤ₑ E := + ObjectProperty.lift _ + (ObjectProperty.ι _ ⋙ (Functor.whiskeringLeft _ _ _).obj L) (fun G ↦ by + dsimp + simpa only [exactFunctor_comp_iff L P] using G.property) + +@[simp] +lemma whiskeringLeft_obj_obj (G : D ⥤ₑ E) : + ((whiskeringLeft L P E).obj G).obj = L ⋙ G.obj := rfl + +/-- When `L : C ⥤ D` is a localization functor with respect to a Serre class +in the abelian category `C`, the functor `whiskeringLeft L P E: (D ⥤ₑ E) ⥤ C ⥤ₑ E` +is fully faithful. -/ +noncomputable def fullyFaithfulWhiskeringLeft : + (whiskeringLeft L P E).FullyFaithful := + Functor.FullyFaithful.ofCompFaithful (G := ObjectProperty.ι _) + ((exactFunctor D E).fullyFaithfulι.comp + (Localization.fullyFaithfulWhiskeringLeft L P.isoModSerre E)) + +instance : (whiskeringLeft L P E).Faithful := + (fullyFaithfulWhiskeringLeft L P E).faithful + +instance : (whiskeringLeft L P E).Full := + (fullyFaithfulWhiskeringLeft L P E).full + +lemma essImage_whiskeringLeft : + (whiskeringLeft L P E).essImage = + fun G ↦ P.isoModSerre.IsInvertedBy G.obj := by + ext F + refine ⟨?_, fun hF ↦ ?_⟩ + · rintro ⟨G, ⟨e⟩⟩ + rw [← MorphismProperty.IsInvertedBy.iff_of_iso _ + (show L ⋙ G.obj ≅ F.obj from (ObjectProperty.ι _).mapIso e)] + exact MorphismProperty.IsInvertedBy.of_comp _ _ (Localization.inverts L _) _ + · refine ⟨⟨Localization.lift F.obj hF L, ?_⟩, + ⟨ObjectProperty.isoMk _ (Localization.fac F.obj hF L)⟩⟩ + rw [← exactFunctor_comp_iff L P] + exact ObjectProperty.prop_of_iso _ (Localization.fac F.obj hF L).symm F.property + end SerreClassLocalization end ObjectProperty diff --git a/Mathlib/CategoryTheory/Limits/ExactFunctor.lean b/Mathlib/CategoryTheory/Limits/ExactFunctor.lean index 48b6f8b8e267e8..d3dfdcab52275d 100644 --- a/Mathlib/CategoryTheory/Limits/ExactFunctor.lean +++ b/Mathlib/CategoryTheory/Limits/ExactFunctor.lean @@ -6,6 +6,7 @@ Authors: Markus Himmel module public import Mathlib.CategoryTheory.Limits.Preserves.Finite +public import Mathlib.CategoryTheory.ObjectProperty.CompleteLattice /-! # Bundled exact functors @@ -41,6 +42,11 @@ variable {C D} in lemma leftExactFunctor_iff (F : C ⥤ D) : leftExactFunctor C D F ↔ PreservesFiniteLimits F := Iff.rfl +instance : (leftExactFunctor C D).IsClosedUnderIsomorphisms where + of_iso e h := by + simp only [leftExactFunctor_iff] at h ⊢ + exact preservesFiniteLimits_of_natIso e + /-- Bundled left-exact functors. -/ abbrev LeftExactFunctor := (leftExactFunctor C D).FullSubcategory @@ -64,6 +70,11 @@ variable {C D} in lemma rightExactFunctor_iff (F : C ⥤ D) : rightExactFunctor C D F ↔ PreservesFiniteColimits F := Iff.rfl +instance : (rightExactFunctor C D).IsClosedUnderIsomorphisms where + of_iso e h := by + simp only [rightExactFunctor_iff] at h ⊢ + exact preservesFiniteColimits_of_natIso e + /-- Bundled right-exact functors. -/ abbrev RightExactFunctor := (rightExactFunctor C D).FullSubcategory @@ -87,6 +98,10 @@ variable {C D} in lemma exactFunctor_iff (F : C ⥤ D) : exactFunctor C D F ↔ PreservesFiniteLimits F ∧ PreservesFiniteColimits F := Iff.rfl +instance : (exactFunctor C D).IsClosedUnderIsomorphisms := by + dsimp [exactFunctor] + infer_instance + /-- Bundled exact functors. -/ abbrev ExactFunctor := (exactFunctor C D).FullSubcategory diff --git a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean index a3edd43e51ac49..0e0836fc58da29 100644 --- a/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean +++ b/Mathlib/CategoryTheory/Limits/Shapes/Equalizers.lean @@ -298,8 +298,9 @@ theorem parallelPairHom_app_one {X' Y' : C} (f g : X ⟶ Y) (f' g' : X' ⟶ Y') its components. -/ @[simps!] def parallelPair.ext {F G : WalkingParallelPair ⥤ C} (zero : F.obj zero ≅ G.obj zero) - (one : F.obj one ≅ G.obj one) (left : F.map left ≫ one.hom = zero.hom ≫ G.map left) - (right : F.map right ≫ one.hom = zero.hom ≫ G.map right) : F ≅ G := + (one : F.obj one ≅ G.obj one) + (left : F.map left ≫ one.hom = zero.hom ≫ G.map left := by cat_disch) + (right : F.map right ≫ one.hom = zero.hom ≫ G.map right := by cat_disch) : F ≅ G := NatIso.ofComponents (by rintro ⟨j⟩ diff --git a/Mathlib/CategoryTheory/Localization/Predicate.lean b/Mathlib/CategoryTheory/Localization/Predicate.lean index 11d7ed522d9044..d0474daa37e0d0 100644 --- a/Mathlib/CategoryTheory/Localization/Predicate.lean +++ b/Mathlib/CategoryTheory/Localization/Predicate.lean @@ -267,6 +267,13 @@ lemma faithful_whiskeringLeft (L : C ⥤ D) (W) [L.IsLocalization W] (E : Type*) ((whiskeringLeft C D E).obj L).Faithful := inferInstanceAs (whiskeringLeftFunctor' L W E).Faithful +/-- The precomposition with a localization functor gives fully faithful functors. -/ +def fullyFaithfulWhiskeringLeft (L : C ⥤ D) (W) [L.IsLocalization W] (E : Type*) [Category* E] : + ((whiskeringLeft C D E).obj L).FullyFaithful := by + have := full_whiskeringLeft L W E + have := faithful_whiskeringLeft L W E + exact FullyFaithful.ofFullyFaithful _ + variable {E} theorem natTrans_ext (L : C ⥤ D) (W) [L.IsLocalization W] {F₁ F₂ : D ⥤ E} {τ τ' : F₁ ⟶ F₂} From 75313faabaa4ed1af7b1eeada873e0df40da28a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 20:29:38 +0100 Subject: [PATCH 45/46] fix --- Mathlib/CategoryTheory/Galois/Examples.lean | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Mathlib/CategoryTheory/Galois/Examples.lean b/Mathlib/CategoryTheory/Galois/Examples.lean index 665b59ce1e70d8..bd451a1e6d323b 100644 --- a/Mathlib/CategoryTheory/Galois/Examples.lean +++ b/Mathlib/CategoryTheory/Galois/Examples.lean @@ -107,7 +107,7 @@ instance : GaloisCategory (Action FintypeCat G) where /-- The `G`-action on a connected finite `G`-set is transitive. -/ theorem Action.pretransitive_of_isConnected (X : Action FintypeCat G) - [IsConnected X] : MulAction.IsPretransitive G X.V where + [PreGaloisCategory.IsConnected X] : MulAction.IsPretransitive G X.V where exists_smul_eq x y := by /- We show that the `G`-orbit of `x` is a non-initial subobject of `X` and hence by connectedness, the orbit equals `X.V`. -/ @@ -131,7 +131,7 @@ theorem Action.pretransitive_of_isConnected (X : Action FintypeCat G) /-- A nonempty `G`-set with transitive `G`-action is connected. -/ theorem Action.isConnected_of_transitive (X : FintypeCat) [MulAction G X] [MulAction.IsPretransitive G X] [h : Nonempty X] : - IsConnected (Action.FintypeCat.ofMulAction G X) where + PreGaloisCategory.IsConnected (Action.FintypeCat.ofMulAction G X) where notInitial := not_initial_of_inhabited (Action.forget _ _) h.some noTrivialComponent Y i hm hni := by /- We show that the induced inclusion `i.hom` of finite sets is surjective, using the @@ -151,7 +151,7 @@ theorem Action.isConnected_of_transitive (X : FintypeCat) [MulAction G X] /-- A nonempty finite `G`-set is connected if and only if the `G`-action is transitive. -/ theorem Action.isConnected_iff_transitive (X : Action FintypeCat G) [Nonempty X.V] : - IsConnected X ↔ MulAction.IsPretransitive G X.V := + PreGaloisCategory.IsConnected X ↔ MulAction.IsPretransitive G X.V := ⟨fun _ ↦ pretransitive_of_isConnected G X, fun _ ↦ isConnected_of_transitive G X.V⟩ variable {G} @@ -159,7 +159,7 @@ variable {G} /-- If `X` is a connected `G`-set and `x` is an element of `X`, `X` is isomorphic to the quotient of `G` by the stabilizer of `x` as `G`-sets. -/ noncomputable def isoQuotientStabilizerOfIsConnected (X : Action FintypeCat G) - [IsConnected X] (x : X.V) [Fintype (G ⧸ (MulAction.stabilizer G x))] : + [PreGaloisCategory.IsConnected X] (x : X.V) [Fintype (G ⧸ (MulAction.stabilizer G x))] : X ≅ G ⧸ₐ MulAction.stabilizer G x := haveI : MulAction.IsPretransitive G X.V := Action.pretransitive_of_isConnected G X let e : X.V ≃ G ⧸ MulAction.stabilizer G x := From 3846bb8fcebee29dcffd0affc178744944e2fa79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Riou?= Date: Tue, 27 Jan 2026 21:17:00 +0100 Subject: [PATCH 46/46] stacks annotation --- Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean | 1 + 1 file changed, 1 insertion(+) diff --git a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean index 1eec33bd0b7643..b91161708e7fd9 100644 --- a/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean +++ b/Mathlib/CategoryTheory/Abelian/SerreClass/Localization.lean @@ -412,6 +412,7 @@ the abelian category `C`, then `D` is an abelian category. and that `L` is additive. Otherwise, see the results in the file `Mathlib/CategoryTheory/Localization/CalculusOfFractions/Preadditive.lean` which applies because `P.isoModSerre` has a calculus of left and right fractions.) -/ +@[stacks 02MS] def abelian : Abelian D := by have := hasFiniteProducts L P have := hasKernels L P