From dcad3591d7f35181bb2f71a206ad4510417d14be Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sat, 8 Jun 2024 15:25:02 +0200
Subject: [PATCH 01/63] feat: small types of morphisms in the localized
 category

---
 Mathlib.lean                                  |   1 +
 Mathlib/CategoryTheory/Equivalence.lean       |  24 ++--
 .../CategoryTheory/Localization/SmallHom.lean | 106 ++++++++++++++++++
 3 files changed, 121 insertions(+), 10 deletions(-)
 create mode 100644 Mathlib/CategoryTheory/Localization/SmallHom.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index 36a068e42db8dd..881fb5542ec08f 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -1483,6 +1483,7 @@ import Mathlib.CategoryTheory.Localization.Pi
 import Mathlib.CategoryTheory.Localization.Predicate
 import Mathlib.CategoryTheory.Localization.Prod
 import Mathlib.CategoryTheory.Localization.Resolution
+import Mathlib.CategoryTheory.Localization.SmallHom
 import Mathlib.CategoryTheory.Localization.Triangulated
 import Mathlib.CategoryTheory.Monad.Adjunction
 import Mathlib.CategoryTheory.Monad.Algebra
diff --git a/Mathlib/CategoryTheory/Equivalence.lean b/Mathlib/CategoryTheory/Equivalence.lean
index 33f44541ceadf8..7434a9f8f3c9d3 100644
--- a/Mathlib/CategoryTheory/Equivalence.lean
+++ b/Mathlib/CategoryTheory/Equivalence.lean
@@ -480,29 +480,33 @@ instance essSurj_functor (e : C ≌ E) : e.functor.EssSurj :=
 instance essSurj_inverse (e : C ≌ E) : e.inverse.EssSurj :=
   e.symm.essSurj_functor
 
+/-- The functor of an equivalence of categories is fully faithful. -/
+def fullyFaithfulFunctor (e : C ≌ E) : e.functor.FullyFaithful where
+  preimage {X Y} f := e.unitIso.hom.app X ≫ e.inverse.map f ≫ e.unitIso.inv.app Y
+
+/-- The inverse of an equivalence of categories is fully faithful. -/
+def fullyFaithfulInverse (e : C ≌ E) : e.inverse.FullyFaithful where
+  preimage {X Y} f := e.counitIso.inv.app X ≫ e.functor.map f ≫ e.counitIso.hom.app Y
+
 /-- The functor of an equivalence of categories is faithful.
 
 See <https://stacks.math.columbia.edu/tag/02C3>.
 -/
-instance faithful_functor (e : C ≌ E) : e.functor.Faithful where
-  map_injective {X Y f g} h := by
-    rw [← cancel_mono (e.unit.app Y), ← cancel_epi (e.unitInv.app X),
-      ← e.inv_fun_map _ _ f, ← e.inv_fun_map _ _ g, h]
+instance faithful_functor (e : C ≌ E) : e.functor.Faithful :=
+  e.fullyFaithfulFunctor.faithful
 
 instance faithful_inverse (e : C ≌ E) : e.inverse.Faithful :=
-  e.symm.faithful_functor
+  e.fullyFaithfulInverse.faithful
 
 /-- The functor of an equivalence of categories is full.
 
 See <https://stacks.math.columbia.edu/tag/02C3>.
 -/
-instance full_functor (e : C ≌ E) : e.functor.Full where
-  map_surjective {X Y} f :=
-    ⟨e.unitIso.hom.app X ≫ e.inverse.map f ≫ e.unitIso.inv.app Y,
-      e.inverse.map_injective (by simp)⟩
+instance full_functor (e : C ≌ E) : e.functor.Full :=
+  e.fullyFaithfulFunctor.full
 
 instance full_inverse (e : C ≌ E) : e.inverse.Full :=
-  e.symm.full_functor
+  e.fullyFaithfulInverse.full
 
 /-- If `e : C ≌ D` is an equivalence of categories, and `iso : e.functor ≅ G` is
 an isomorphism, then there is an equivalence of categories whose functor is `G`. -/
diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
new file mode 100644
index 00000000000000..c5b21f0417f643
--- /dev/null
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -0,0 +1,106 @@
+/-
+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.Localization.HasLocalization
+import Mathlib.Logic.Small.Defs
+
+/-!
+# Shrinking morphisms in localized categories
+
+-/
+
+universe w w' w'' v u u' u''
+
+namespace CategoryTheory
+
+variable {C : Type u} [Category.{v} C]
+
+section
+
+/-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
+`e : X ≅ X'` and `e' : Y ≅ Y'`. -/
+@[simps]
+def homEquivOfIsos {X Y X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
+    (X ⟶ Y) ≃ (X' ⟶ Y') where
+  toFun f := e.inv ≫ f ≫ e'.hom
+  invFun g := e.hom ≫ g ≫ e'.inv
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
+end
+
+variable (W : MorphismProperty C)
+  {D : Type u'} [Category.{w'} D] (L : C ⥤ D) [L.IsLocalization W]
+  {D' : Type u''} [Category.{w''} D'] (L' : C ⥤ D') [L'.IsLocalization W] (X Y Z : C)
+
+namespace MorphismProperty
+
+/-- This property holds if the type of morphisms between `X` and `Y`
+in the localized category with respect to `W : MorphismProperty C`
+is small. -/
+class HasSmallLocalizedHom : Prop where
+  small : Small.{w} (W.Q.obj X ⟶ W.Q.obj Y)
+
+/-- Bijection between types of morphisms in two localized categories
+for the same class of morphisms `W`. -/
+noncomputable def localizationsHomEquiv :
+    (L.obj X ⟶ L.obj Y) ≃ (L'.obj X ⟶ L'.obj Y) :=
+  (Localization.uniq L L' W).fullyFaithfulFunctor.homEquiv.trans
+    (homEquivOfIsos ((Localization.compUniqFunctor L L' W).app X)
+      ((Localization.compUniqFunctor L L' W).app Y))
+
+lemma hasSmallLocalizedHom_iff :
+    HasSmallLocalizedHom.{w} W X Y ↔ Small.{w} (L.obj X ⟶ L.obj Y) := by
+  let e := localizationsHomEquiv W W.Q L X Y
+  constructor
+  · intro h
+    have := h.small
+    exact small_map e.symm
+  · intro h
+    exact ⟨small_map e⟩
+
+lemma hasSmallLocalizedHom_of_isLocalization :
+    HasSmallLocalizedHom.{w'} W X Y := by
+  rw [W.hasSmallLocalizedHom_iff L]
+  infer_instance
+
+lemma small_of_hasSmallLocalizedHom [HasSmallLocalizedHom.{w} W X Y] :
+    Small.{w} (L.obj X ⟶ L.obj Y) := by
+  rwa [← W.hasSmallLocalizedHom_iff]
+
+variable {X Y} in
+lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
+    HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y' := by
+  simp only [W.hasSmallLocalizedHom_iff W.Q]
+  exact small_congr (homEquivOfIsos (W.Q.mapIso e) (W.Q.mapIso e'))
+
+end MorphismProperty
+
+namespace Localization
+
+open MorphismProperty
+
+/-- The type of morphisms from `X` to `Y` in the localized category
+with respect to `W : MorphismProperty C` that is shrunk to `Type w`
+when `HasSmallLocalizedHom.{w} W X Y` holds. -/
+def SmallHom [HasSmallLocalizedHom.{w} W X Y] : Type w :=
+  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
+  Shrink.{w} (W.Q.obj X ⟶ W.Q.obj Y)
+
+namespace SmallHom
+
+/-- The canonical bijection `SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y)`
+when `L` is a localization functor for `W : MorphismProperty C` and
+that `HasSmallLocalizedHom.{w} W X Y` holds. -/
+noncomputable def equiv [HasSmallLocalizedHom.{w} W X Y] :
+    SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y) :=
+  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
+  (equivShrink _).symm.trans (W.localizationsHomEquiv _ _ _ _)
+
+end SmallHom
+
+end Localization
+
+end CategoryTheory

From 9d5cdc18bff2873c5dfd21749b9c96851cdcdb0e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sat, 8 Jun 2024 22:33:16 +0200
Subject: [PATCH 02/63] added compatibilities

---
 .../Localization/Predicate.lean               | 25 ++++++++--
 .../CategoryTheory/Localization/SmallHom.lean | 48 +++++++++++++++++--
 2 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/Predicate.lean b/Mathlib/CategoryTheory/Localization/Predicate.lean
index 2cdb8224e123a6..353a1d670565c7 100644
--- a/Mathlib/CategoryTheory/Localization/Predicate.lean
+++ b/Mathlib/CategoryTheory/Localization/Predicate.lean
@@ -454,13 +454,32 @@ def compUniqInverse : L₂ ⋙ (uniq L₁ L₂ W').inverse ≅ L₁ := compUniqF
 instance : Lifting L₁ W' L₂ (uniq L₁ L₂ W').functor := ⟨compUniqFunctor L₁ L₂ W'⟩
 instance : Lifting L₂ W' L₁ (uniq L₁ L₂ W').inverse := ⟨compUniqInverse L₁ L₂ W'⟩
 
+section
+
+variable (F : D₁ ⥤ D₂) (e : L₁ ⋙ F ≅ L₂)
+
 /-- If `L₁ : C ⥤ D₁` and `L₂ : C ⥤ D₂` are two localization functors for the
 same `MorphismProperty C`, any functor `F : D₁ ⥤ D₂` equipped with an isomorphism
 `L₁ ⋙ F ≅ L₂` is isomorphic to the functor of the equivalence given by `uniq`. -/
-def isoUniqFunctor (F : D₁ ⥤ D₂) (e : L₁ ⋙ F ≅ L₂) :
-    F ≅ (uniq L₁ L₂ W').functor :=
+def uniqFunctorIso  :
+    (uniq L₁ L₂ W').functor ≅ F :=
   letI : Lifting L₁ W' L₂ F := ⟨e⟩
-  liftNatIso L₁ W' L₂ L₂ F (uniq L₁ L₂ W').functor (Iso.refl L₂)
+  liftNatIso L₁ W' L₂ L₂ (uniq L₁ L₂ W').functor F (Iso.refl L₂)
+
+lemma uniqFunctorIso_hom_app (X : C) :
+    (uniqFunctorIso L₁ L₂ W' F e).hom.app (L₁.obj X) =
+      (compUniqFunctor L₁ L₂ W').hom.app X ≫ e.inv.app X := by
+  dsimp [uniqFunctorIso]
+  simp only [liftNatTrans_app, Functor.comp_obj, NatTrans.id_app, id_comp]
+  rfl
+
+lemma compUniqFunctor_eq :
+    compUniqFunctor L₁ L₂ W' =
+      isoWhiskerLeft L₁ (uniqFunctorIso L₁ L₂ W' F e) ≪≫ e := by
+  ext X
+  simp [uniqFunctorIso_hom_app]
+
+end
 
 end Localization
 
diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index c5b21f0417f643..0f1413e1509206 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -43,6 +43,8 @@ is small. -/
 class HasSmallLocalizedHom : Prop where
   small : Small.{w} (W.Q.obj X ⟶ W.Q.obj Y)
 
+variable {X Y Z}
+
 /-- Bijection between types of morphisms in two localized categories
 for the same class of morphisms `W`. -/
 noncomputable def localizationsHomEquiv :
@@ -51,26 +53,36 @@ noncomputable def localizationsHomEquiv :
     (homEquivOfIsos ((Localization.compUniqFunctor L L' W).app X)
       ((Localization.compUniqFunctor L L' W).app Y))
 
+@[simp]
+lemma localizationHomEquiv_refl :
+    localizationsHomEquiv W L L (X := X) (Y := Y) = Equiv.refl _ := by
+  ext f
+  simp [localizationsHomEquiv, Localization.compUniqFunctor_eq L L W (𝟭 _) L.rightUnitor]
+
+lemma localizationHomEquiv_comp (f : L.obj X ⟶ L.obj Y) (g : L.obj Y ⟶ L.obj Z) :
+    localizationsHomEquiv W L L' (f ≫ g) =
+      localizationsHomEquiv W L L' f ≫ localizationsHomEquiv W L L' g := by
+  simp [localizationsHomEquiv]
+
 lemma hasSmallLocalizedHom_iff :
     HasSmallLocalizedHom.{w} W X Y ↔ Small.{w} (L.obj X ⟶ L.obj Y) := by
-  let e := localizationsHomEquiv W W.Q L X Y
   constructor
   · intro h
     have := h.small
-    exact small_map e.symm
+    exact small_map (localizationsHomEquiv W W.Q L).symm
   · intro h
-    exact ⟨small_map e⟩
+    exact ⟨small_map (localizationsHomEquiv W W.Q L)⟩
 
 lemma hasSmallLocalizedHom_of_isLocalization :
     HasSmallLocalizedHom.{w'} W X Y := by
   rw [W.hasSmallLocalizedHom_iff L]
   infer_instance
 
+variable (X Y) in
 lemma small_of_hasSmallLocalizedHom [HasSmallLocalizedHom.{w} W X Y] :
     Small.{w} (L.obj X ⟶ L.obj Y) := by
   rwa [← W.hasSmallLocalizedHom_iff]
 
-variable {X Y} in
 lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
     HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y' := by
   simp only [W.hasSmallLocalizedHom_iff W.Q]
@@ -91,13 +103,39 @@ def SmallHom [HasSmallLocalizedHom.{w} W X Y] : Type w :=
 
 namespace SmallHom
 
+variable {X Y Z}
+
 /-- The canonical bijection `SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y)`
 when `L` is a localization functor for `W : MorphismProperty C` and
 that `HasSmallLocalizedHom.{w} W X Y` holds. -/
 noncomputable def equiv [HasSmallLocalizedHom.{w} W X Y] :
     SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y) :=
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
-  (equivShrink _).symm.trans (W.localizationsHomEquiv _ _ _ _)
+  (equivShrink _).symm.trans (W.localizationsHomEquiv W.Q L)
+
+variable [HasSmallLocalizedHom.{w} W X Y][HasSmallLocalizedHom.{w} W Y Z]
+  [HasSmallLocalizedHom.{w} W X Z]
+
+variable {W}
+
+variable (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z)
+
+/-- The composition on `SmallHom W`. -/
+noncomputable def comp (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
+    SmallHom.{w} W X Z :=
+  (equiv W W.Q).symm (equiv W W.Q α ≫ equiv W W.Q β)
+
+lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
+  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
+  letI := small_of_hasSmallLocalizedHom.{w} W W.Q Y Z
+  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Z
+  obtain ⟨α, rfl⟩ := (equivShrink _).surjective α
+  obtain ⟨β, rfl⟩ := (equivShrink _).surjective β
+  dsimp [equiv, comp]
+  rw [Equiv.symm_apply_apply]
+  erw [(equivShrink _).symm_apply_apply, (equivShrink _).symm_apply_apply]
+  rw [← localizationHomEquiv_comp, localizationHomEquiv_refl, Equiv.refl_symm,
+    Equiv.refl_apply, Equiv.refl_apply, localizationHomEquiv_comp]
 
 end SmallHom
 

From 08077d01f95276ef630c094fdae37594f398627e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 9 Jun 2024 00:22:43 +0200
Subject: [PATCH 03/63] fixed imports

---
 Mathlib/CategoryTheory/Localization/SmallHom.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 0f1413e1509206..847c1217c5be61 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.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.Localization.HasLocalization
+import Mathlib.CategoryTheory.Localization.Predicate
 import Mathlib.Logic.Small.Defs
 
 /-!

From 88d42d844c8ba0a040524a7a6146daf6f58e51d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 9 Jun 2024 15:55:22 +0200
Subject: [PATCH 04/63] added note

---
 Mathlib/CategoryTheory/Localization/SmallHom.lean | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 847c1217c5be61..0fa5cbcae47d4d 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -19,6 +19,7 @@ variable {C : Type u} [Category.{v} C]
 
 section
 
+-- should be moved to CategoryTheory.Iso
 /-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
 `e : X ≅ X'` and `e' : Y ≅ Y'`. -/
 @[simps]

From aa484c12b68c9fc970934103efbd3cee2d497b73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 9 Jun 2024 21:15:35 +0200
Subject: [PATCH 05/63] feat: the mapping cone of a monomorphism, up to a
 quasi-isomorphism

---
 .../Homology/HomologySequenceLemmas.lean      |  2 +-
 .../Homology/HomotopyCategory/ShortExact.lean | 87 +++++++++++++++++++
 .../Triangulated/HomologicalFunctor.lean      | 16 ++++
 3 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean

diff --git a/Mathlib/Algebra/Homology/HomologySequenceLemmas.lean b/Mathlib/Algebra/Homology/HomologySequenceLemmas.lean
index 8ffb3c98e2f884..3964e891d02359 100644
--- a/Mathlib/Algebra/Homology/HomologySequenceLemmas.lean
+++ b/Mathlib/Algebra/Homology/HomologySequenceLemmas.lean
@@ -72,7 +72,7 @@ noncomputable def composableArrows₅ (i j : ι) (hij : c.Rel i j) : ComposableA
   mk₅ (homologyMap S₁.f i) (homologyMap S₁.g i) (hS₁.δ i j hij)
     (homologyMap S₁.f j) (homologyMap S₁.g j)
 
-lemma composableArrows₅_exact (i j : ι) (hij : c.Rel i j):
+lemma composableArrows₅_exact (i j : ι) (hij : c.Rel i j) :
     (composableArrows₅ hS₁ i j hij).Exact :=
   exact_of_δ₀ (hS₁.homology_exact₂ i).exact_toComposableArrows
     (exact_of_δ₀ (hS₁.homology_exact₃ i j hij).exact_toComposableArrows
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
new file mode 100644
index 00000000000000..384174a00e1b0d
--- /dev/null
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
@@ -0,0 +1,87 @@
+/-
+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.Algebra.Homology.HomotopyCategory.HomologicalFunctor
+import Mathlib.Algebra.Homology.HomotopyCategory.ShiftSequence
+import Mathlib.Algebra.Homology.HomologySequenceLemmas
+
+/-!
+# The mapping cone of a monomorphism, up to a quasi-isomophism
+
+If `S` is a short exact short complex of cochain complexes in an abelian category,
+we construct a quasi-isomorphism `descShortComplex S : mappingCone S.f ⟶ S.X₃`.
+
+We obtain this by comparing the homology sequence of `S` and the homology
+sequence of the homology functor on the homotopy category, applied to the triangle
+attached to the mapping cone of `S.f`.
+
+-/
+
+open CategoryTheory Category ComplexShape HomotopyCategory
+  HomologicalComplex.HomologySequence
+
+variable {C : Type*} [Category C] [Abelian C]
+
+namespace CochainComplex
+
+variable (S : ShortComplex (CochainComplex C ℤ)) (hS : S.ShortExact)
+
+namespace mappingCone
+
+/-- The canonical morphism `mappingCone S.f ⟶ S.X₃` when `S` is a short complex
+of cochain complexes. -/
+noncomputable def descShortComplex : mappingCone S.f ⟶ S.X₃ := desc S.f 0 S.g (by simp)
+
+@[reassoc (attr := simp)]
+lemma inr_descShortComplex : inr S.f ≫ descShortComplex S = S.g := by
+  simp [descShortComplex]
+
+variable {S}
+
+lemma homologySequenceδ_triangleh (n₀ : ℤ) (n₁ : ℤ) (h : n₀ + 1 = n₁) :
+    (homologyFunctor C (up ℤ) 0).homologySequenceδ (triangleh S.f) n₀ n₁ h =
+      (homologyFunctorFactors C (up ℤ) n₀).hom.app _ ≫
+        HomologicalComplex.homologyMap (descShortComplex S) n₀ ≫ hS.δ n₀ n₁ h ≫
+          (homologyFunctorFactors C (up ℤ) n₁).inv.app _ := by
+  sorry
+
+open ComposableArrows
+
+set_option simprocs false
+
+lemma quasiIso_descShortComplex : QuasiIso (descShortComplex S) where
+  quasiIsoAt n := by
+    rw [quasiIsoAt_iff_isIso_homologyMap]
+    let φ : ((homologyFunctor C (up ℤ) 0).homologySequenceComposableArrows₅
+        (triangleh S.f) n _ rfl).δlast ⟶ (composableArrows₅ hS n _ rfl).δlast :=
+      homMk₄ ((homologyFunctorFactors C (up ℤ) _).hom.app _)
+        ((homologyFunctorFactors C (up ℤ) _).hom.app _)
+        ((homologyFunctorFactors C (up ℤ) _).hom.app _ ≫
+          HomologicalComplex.homologyMap (descShortComplex S) n)
+        ((homologyFunctorFactors C (up ℤ) _).hom.app _)
+        ((homologyFunctorFactors C (up ℤ) _).hom.app _)
+        ((homologyFunctorFactors C (up ℤ) _).hom.naturality S.f)
+        (by
+          erw [(homologyFunctorFactors C (up ℤ) n).hom.naturality_assoc]
+          dsimp
+          rw [← HomologicalComplex.homologyMap_comp, inr_descShortComplex])
+        (by
+          dsimp
+          erw [homologySequenceδ_triangleh hS]
+          simp only [Functor.comp_obj, HomologicalComplex.homologyFunctor_obj, assoc,
+            Iso.inv_hom_id_app, comp_id])
+        ((homologyFunctorFactors C (up ℤ) _).hom.naturality S.f)
+    have : IsIso ((homologyFunctorFactors C (up ℤ) n).hom.app (mappingCone S.f) ≫
+        HomologicalComplex.homologyMap (descShortComplex S) n) := by
+      apply Abelian.isIso_of_epi_of_isIso_of_isIso_of_mono
+        ((homologyFunctor C (up ℤ) 0).homologySequenceComposableArrows₅_exact _
+          (mappingCone_triangleh_distinguished S.f) n _ rfl).δlast
+        (composableArrows₅_exact hS n _ rfl).δlast φ
+      all_goals dsimp [φ]; infer_instance
+    apply IsIso.of_isIso_comp_left ((homologyFunctorFactors C (up ℤ) n).hom.app (mappingCone S.f))
+
+end mappingCone
+
+end CochainComplex
diff --git a/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean b/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean
index 3d8c1c7c9bb182..e630e1c82993c0 100644
--- a/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean
+++ b/Mathlib/CategoryTheory/Triangulated/HomologicalFunctor.lean
@@ -7,6 +7,7 @@ import Mathlib.Algebra.Homology.ShortComplex.Exact
 import Mathlib.CategoryTheory.Shift.ShiftSequence
 import Mathlib.CategoryTheory.Triangulated.Functor
 import Mathlib.CategoryTheory.Triangulated.Subcategory
+import Mathlib.Algebra.Homology.ExactSequence
 
 /-! # Homological functors
 
@@ -237,6 +238,21 @@ lemma mem_homologicalKernel_W_iff {X Y : C} (f : X ⟶ Y) :
   · intros
     constructor <;> infer_instance
 
+open ComposableArrows
+
+/-- The exact sequence with six terms starting from `(F.shift n₀).obj T.obj₁` until
+`(F.shift n₁).obj T.obj₃` when `T` is a distinguished triangle and `F` a homological functor. -/
+@[simp] noncomputable def homologySequenceComposableArrows₅ : ComposableArrows A 5 :=
+  mk₅ ((F.shift n₀).map T.mor₁) ((F.shift n₀).map T.mor₂)
+    (F.homologySequenceδ T n₀ n₁ h) ((F.shift n₁).map T.mor₁) ((F.shift n₁).map T.mor₂)
+
+lemma homologySequenceComposableArrows₅_exact :
+    (F.homologySequenceComposableArrows₅ T n₀ n₁ h).Exact :=
+  exact_of_δ₀ (F.homologySequence_exact₂ T hT n₀).exact_toComposableArrows
+    (exact_of_δ₀ (F.homologySequence_exact₃ T hT n₀ n₁ h).exact_toComposableArrows
+      (exact_of_δ₀ (F.homologySequence_exact₁ T hT n₀ n₁ h).exact_toComposableArrows
+        (F.homologySequence_exact₂ T hT n₁).exact_toComposableArrows))
+
 end
 
 end Functor

From 467fa14274899cfff49c0c78697717dc2071b81d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 9 Jun 2024 21:22:14 +0200
Subject: [PATCH 06/63] updated Mathlib.lean

---
 Mathlib.lean | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Mathlib.lean b/Mathlib.lean
index 5bbd36285ce929..4c9cdec16d0399 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -312,6 +312,7 @@ import Mathlib.Algebra.Homology.HomotopyCategory.MappingCone
 import Mathlib.Algebra.Homology.HomotopyCategory.Pretriangulated
 import Mathlib.Algebra.Homology.HomotopyCategory.Shift
 import Mathlib.Algebra.Homology.HomotopyCategory.ShiftSequence
+import Mathlib.Algebra.Homology.HomotopyCategory.ShortExact
 import Mathlib.Algebra.Homology.HomotopyCategory.SingleFunctors
 import Mathlib.Algebra.Homology.HomotopyCategory.Triangulated
 import Mathlib.Algebra.Homology.HomotopyCofiber

From b2f24ea6c9fc9be3a61fa43b85616fdd75a2eaaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 9 Jun 2024 23:51:25 +0200
Subject: [PATCH 07/63] wip

---
 Mathlib.lean                                  |  1 +
 .../HomotopyCategory/MappingCone.lean         | 11 ++++
 .../HomotopyCategory/ShiftSequence.lean       |  5 ++
 .../Homology/HomotopyCategory/ShortExact.lean | 62 ++++++++++++++++++-
 Mathlib/Algebra/Homology/Refinements.lean     | 24 +++++++
 .../CategoryTheory/Abelian/Refinements.lean   |  9 +++
 6 files changed, 109 insertions(+), 3 deletions(-)
 create mode 100644 Mathlib/Algebra/Homology/Refinements.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index 4c9cdec16d0399..e9801ad51c351e 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -323,6 +323,7 @@ import Mathlib.Algebra.Homology.Localization
 import Mathlib.Algebra.Homology.ModuleCat
 import Mathlib.Algebra.Homology.Opposite
 import Mathlib.Algebra.Homology.QuasiIso
+import Mathlib.Algebra.Homology.Refinements
 import Mathlib.Algebra.Homology.ShortComplex.Ab
 import Mathlib.Algebra.Homology.ShortComplex.Abelian
 import Mathlib.Algebra.Homology.ShortComplex.Basic
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean
index a210ec80c24cf5..ce44a12d846927 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/MappingCone.lean
@@ -174,6 +174,17 @@ lemma ext_from_iff (i j : ℤ) (hij : j + 1 = i) {A : C} (f g : (mappingCone φ)
   · rintro ⟨h₁, h₂⟩
     exact ext_from φ i j hij h₁ h₂
 
+lemma decomp_to {i : ℤ} {A : C} (f : A ⟶ (mappingCone φ).X i) (j : ℤ) (hij : i + 1 = j) :
+    ∃ (a : A ⟶ F.X j) (b : A ⟶ G.X i), f = a ≫ (inl φ).v j i (by omega) + b ≫ (inr φ).f i :=
+  ⟨f ≫ (fst φ).1.v i j hij, f ≫ (snd φ).v i i (add_zero i),
+    by apply ext_to φ i j hij <;> simp⟩
+
+lemma decomp_from {j : ℤ} {A : C} (f : (mappingCone φ).X j ⟶ A) (i : ℤ) (hij : j + 1 = i) :
+    ∃ (a : F.X i ⟶ A) (b : G.X j ⟶ A),
+      f = (fst φ).1.v j i hij ≫ a + (snd φ).v j j (add_zero j) ≫ b :=
+  ⟨(inl φ).v i j (by omega) ≫ f, (inr φ).f j ≫ f,
+    by apply ext_from φ i j hij <;> simp⟩
+
 lemma ext_cochain_to_iff (i j : ℤ) (hij : i + 1 = j)
     {K : CochainComplex C ℤ} {γ₁ γ₂ : Cochain K (mappingCone φ) i} :
     γ₁ = γ₂ ↔ γ₁.comp (fst φ).1 hij = γ₂.comp (fst φ).1 hij ∧
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
index 16a3bd8aef8812..dbf2335d7d907f 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
@@ -124,6 +124,11 @@ instance {K L : CochainComplex C ℤ} (φ : K ⟶ L) (n : ℤ) [QuasiIso φ] :
     change IsIso (homologyMap φ _)
     infer_instance
 
+variable (C) in
+lemma homologyFunctor_shift (n : ℤ) :
+    (homologyFunctor C (ComplexShape.up ℤ) 0).shift n =
+      homologyFunctor C (ComplexShape.up ℤ) n := rfl
+
 end CochainComplex
 
 namespace HomotopyCategory
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
index 384174a00e1b0d..9379da63b3bf60 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
@@ -6,6 +6,7 @@ Authors: Joël Riou
 import Mathlib.Algebra.Homology.HomotopyCategory.HomologicalFunctor
 import Mathlib.Algebra.Homology.HomotopyCategory.ShiftSequence
 import Mathlib.Algebra.Homology.HomologySequenceLemmas
+import Mathlib.Algebra.Homology.Refinements
 
 /-!
 # The mapping cone of a monomorphism, up to a quasi-isomophism
@@ -19,17 +20,32 @@ attached to the mapping cone of `S.f`.
 
 -/
 
-open CategoryTheory Category ComplexShape HomotopyCategory
-  HomologicalComplex.HomologySequence
+open CategoryTheory Category ComplexShape HomotopyCategory Limits
+  HomologicalComplex.HomologySequence Pretriangulated Preadditive
 
 variable {C : Type*} [Category C] [Abelian C]
 
 namespace CochainComplex
 
-variable (S : ShortComplex (CochainComplex C ℤ)) (hS : S.ShortExact)
+section
+
+variable (T : Triangle (CochainComplex C ℤ)) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁)
+
+@[reassoc]
+lemma homologySequenceδ_quotient_mapTriangle_obj :
+    (homologyFunctor C (up ℤ) 0).homologySequenceδ
+        ((quotient C (up ℤ)).mapTriangle.obj T) n₀ n₁ h =
+      (homologyFunctorFactors C (up ℤ) n₀).hom.app _ ≫
+        (HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftMap T.mor₃ n₀ n₁ (by omega) ≫
+        (homologyFunctorFactors C (up ℤ) n₁).inv.app _ := by
+  sorry
+
+end
 
 namespace mappingCone
 
+variable (S : ShortComplex (CochainComplex C ℤ)) (hS : S.ShortExact)
+
 /-- The canonical morphism `mappingCone S.f ⟶ S.X₃` when `S` is a short complex
 of cochain complexes. -/
 noncomputable def descShortComplex : mappingCone S.f ⟶ S.X₃ := desc S.f 0 S.g (by simp)
@@ -38,6 +54,15 @@ noncomputable def descShortComplex : mappingCone S.f ⟶ S.X₃ := desc S.f 0 S.
 lemma inr_descShortComplex : inr S.f ≫ descShortComplex S = S.g := by
   simp [descShortComplex]
 
+@[reassoc (attr := simp)]
+lemma inr_f_descShortComplex_f (n : ℤ) : (inr S.f).f n ≫ (descShortComplex S).f n = S.g.f n := by
+  simp [descShortComplex]
+
+@[reassoc (attr := simp)]
+lemma inl_v_descShortComplex_f (i j : ℤ) (h : i + (-1) = j) :
+    (inl S.f).v i j h ≫ (descShortComplex S).f j = 0 := by
+  simp [descShortComplex]
+
 variable {S}
 
 lemma homologySequenceδ_triangleh (n₀ : ℤ) (n₁ : ℤ) (h : n₀ + 1 = n₁) :
@@ -45,6 +70,37 @@ lemma homologySequenceδ_triangleh (n₀ : ℤ) (n₁ : ℤ) (h : n₀ + 1 = n
       (homologyFunctorFactors C (up ℤ) n₀).hom.app _ ≫
         HomologicalComplex.homologyMap (descShortComplex S) n₀ ≫ hS.δ n₀ n₁ h ≫
           (homologyFunctorFactors C (up ℤ) n₁).inv.app _ := by
+  dsimp
+  rw [← cancel_mono ((homologyFunctorFactors C (up ℤ) n₁).hom.app _),
+    assoc, assoc, assoc, Iso.inv_hom_id_app,
+    ← cancel_epi ((homologyFunctorFactors C (up ℤ) n₀).inv.app _), Iso.inv_hom_id_app_assoc]
+  dsimp
+  rw [comp_id]
+  apply yoneda.map_injective
+  ext ⟨A⟩ (x : A ⟶ _)
+  dsimp
+  obtain ⟨A', π, _, x', w, hx'⟩ :=
+    (mappingCone S.f).eq_liftCycles_homologyπ_up_to_refinements x n₁ (by simpa using h)
+  erw [homologySequenceδ_quotient_mapTriangle_obj_assoc _ _ _ h]
+  dsimp
+  rw [Iso.inv_hom_id_app_assoc, Iso.inv_hom_id_app]
+  erw [comp_id]
+  rw [← cancel_epi π, reassoc_of% hx', reassoc_of% hx',
+    HomologicalComplex.homologyπ_naturality_assoc,
+    HomologicalComplex.liftCycles_comp_cyclesMap_assoc]
+  obtain ⟨a, b, hab⟩ := decomp_to _ x' n₁ h
+  rw [hab, ext_to_iff _ n₁ (n₁ + 1) rfl, add_comp, assoc, assoc, inr_f_d, add_comp, assoc,
+    assoc, assoc, assoc, inr_f_fst_v, comp_zero, comp_zero, add_zero, zero_comp,
+    d_fst_v _ _ _ _ h, comp_neg, inl_v_fst_v_assoc, comp_neg, neg_eq_zero,
+    add_comp, assoc, assoc, assoc, assoc, inr_f_snd_v, comp_id, zero_comp,
+    d_snd_v _ _ _ h, comp_add, inl_v_fst_v_assoc, inl_v_snd_v_assoc, zero_comp, add_zero] at w
+  conv_rhs => simp only [hab, add_comp, assoc, inr_f_descShortComplex_f,
+    inl_v_descShortComplex_f, comp_zero, zero_add]
+  rw [hS.δ_eq n₀ n₁ (by simpa using h) (b ≫ S.g.f n₀) _ b rfl (-a)
+    (by simp only [neg_comp, neg_eq_iff_add_eq_zero, w.2]) (n₁ + 1) (by simp)]
+  dsimp [Functor.shiftMap, homologyFunctor_shift]
+  rw [HomologicalComplex.homologyπ_naturality_assoc,
+    HomologicalComplex.liftCycles_comp_cyclesMap_assoc]
   sorry
 
 open ComposableArrows
diff --git a/Mathlib/Algebra/Homology/Refinements.lean b/Mathlib/Algebra/Homology/Refinements.lean
new file mode 100644
index 00000000000000..7017233136f955
--- /dev/null
+++ b/Mathlib/Algebra/Homology/Refinements.lean
@@ -0,0 +1,24 @@
+/-
+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.Abelian.Refinements
+import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex
+
+open CategoryTheory
+
+variable {C ι : Type*} [Category C] [Abelian C] {c : ComplexShape ι}
+  (K : HomologicalComplex C c)
+
+namespace HomologicalComplex
+
+lemma eq_liftCycles_homologyπ_up_to_refinements {A : C} {i : ι} (γ : A ⟶ K.homology i)
+  (j : ι) (hj : c.next i = j) :
+    ∃ (A' : C) (π : A' ⟶ A) (_ : Epi π) (z : A' ⟶ K.X i) (hz : z ≫ K.d i j = 0),
+      π ≫ γ = K.liftCycles z j hj hz ≫ K.homologyπ i := by
+  subst hj
+  exact (K.sc i).eq_liftCycles_homologyπ_up_to_refinements γ
+
+end HomologicalComplex
diff --git a/Mathlib/CategoryTheory/Abelian/Refinements.lean b/Mathlib/CategoryTheory/Abelian/Refinements.lean
index f566d9630f585d..feb9cac637814c 100644
--- a/Mathlib/CategoryTheory/Abelian/Refinements.lean
+++ b/Mathlib/CategoryTheory/Abelian/Refinements.lean
@@ -110,4 +110,13 @@ lemma ShortComplex.Exact.exact_up_to_refinements
   rw [ShortComplex.exact_iff_exact_up_to_refinements] at hS
   exact hS x₂ hx₂
 
+lemma ShortComplex.eq_liftCycles_homologyπ_up_to_refinements {A : C} (γ : A ⟶ S.homology) :
+    ∃ (A' : C) (π : A' ⟶ A) (_ : Epi π) (z : A' ⟶ S.X₂) (hz : z ≫ S.g = 0),
+      π ≫ γ = S.liftCycles z hz ≫ S.homologyπ := by
+  obtain ⟨A', π, hπ, z, hz⟩ := surjective_up_to_refinements_of_epi S.homologyπ γ
+  refine' ⟨A', π, hπ, z ≫ S.iCycles, by simp, _⟩
+  rw [hz]
+  congr 1
+  rw [← cancel_mono S.iCycles, liftCycles_i]
+
 end CategoryTheory

From 18af13ed25b48ab8a07d122d4996612ce25ceb21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Mon, 10 Jun 2024 00:01:25 +0200
Subject: [PATCH 08/63] Update Mathlib/Algebra/Homology/Refinements.lean

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 Mathlib/Algebra/Homology/Refinements.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/Algebra/Homology/Refinements.lean b/Mathlib/Algebra/Homology/Refinements.lean
index 7017233136f955..d13765fb130d51 100644
--- a/Mathlib/Algebra/Homology/Refinements.lean
+++ b/Mathlib/Algebra/Homology/Refinements.lean
@@ -15,7 +15,7 @@ variable {C ι : Type*} [Category C] [Abelian C] {c : ComplexShape ι}
 namespace HomologicalComplex
 
 lemma eq_liftCycles_homologyπ_up_to_refinements {A : C} {i : ι} (γ : A ⟶ K.homology i)
-  (j : ι) (hj : c.next i = j) :
+    (j : ι) (hj : c.next i = j) :
     ∃ (A' : C) (π : A' ⟶ A) (_ : Epi π) (z : A' ⟶ K.X i) (hz : z ≫ K.d i j = 0),
       π ≫ γ = K.liftCycles z j hj hz ≫ K.homologyπ i := by
   subst hj

From fab421ac333f59591496969b3470a5fca5b1f713 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 10 Jun 2024 00:53:49 +0200
Subject: [PATCH 09/63] removed a sorry

---
 .../Homology/HomotopyCategory/ShortExact.lean | 40 ++++++++++++++++---
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
index 9379da63b3bf60..1692fe1f0e7898 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
@@ -29,6 +29,26 @@ namespace CochainComplex
 
 section
 
+@[reassoc]
+lemma liftCycles_shift_homologyπ
+    (K : CochainComplex C ℤ) {A : C} {n i : ℤ} (f : A ⟶ (K⟦n⟧).X i) (j : ℤ)
+    (hj : (up ℤ).next i = j) (hf : f ≫ (K⟦n⟧).d i j = 0) (i' : ℤ) (hi' : n + i = i') (j' : ℤ) (hj' : (up ℤ).next i' = j'):
+    (K⟦n⟧).liftCycles f j hj hf ≫ (K⟦n⟧).homologyπ i =
+      K.liftCycles (f ≫ (K.shiftFunctorObjXIso n i i' (by omega)).hom) j' hj' (by
+        simp only [next] at hj hj'
+        obtain rfl : i' = i + n := by omega
+        obtain rfl : j' = j + n := by omega
+        dsimp at hf ⊢
+        simp only [Linear.comp_units_smul] at hf
+        apply (one_smul (M := ℤˣ) _).symm.trans _
+        rw [← Int.units_mul_self n.negOnePow, mul_smul, comp_id, hf, smul_zero]) ≫
+        K.homologyπ i' ≫ ((HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftIso n i i' hi').inv.app K := by
+  sorry
+
+end
+
+section
+
 variable (T : Triangle (CochainComplex C ℤ)) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁)
 
 @[reassoc]
@@ -70,38 +90,46 @@ lemma homologySequenceδ_triangleh (n₀ : ℤ) (n₁ : ℤ) (h : n₀ + 1 = n
       (homologyFunctorFactors C (up ℤ) n₀).hom.app _ ≫
         HomologicalComplex.homologyMap (descShortComplex S) n₀ ≫ hS.δ n₀ n₁ h ≫
           (homologyFunctorFactors C (up ℤ) n₁).inv.app _ := by
+  /- We proceed by diagram chase. We test the identity on
+     cocycles `x' : A' ⟶ (mappingCone S.f).X n₀` -/
   dsimp
   rw [← cancel_mono ((homologyFunctorFactors C (up ℤ) n₁).hom.app _),
     assoc, assoc, assoc, Iso.inv_hom_id_app,
     ← cancel_epi ((homologyFunctorFactors C (up ℤ) n₀).inv.app _), Iso.inv_hom_id_app_assoc]
-  dsimp
-  rw [comp_id]
   apply yoneda.map_injective
   ext ⟨A⟩ (x : A ⟶ _)
-  dsimp
   obtain ⟨A', π, _, x', w, hx'⟩ :=
     (mappingCone S.f).eq_liftCycles_homologyπ_up_to_refinements x n₁ (by simpa using h)
   erw [homologySequenceδ_quotient_mapTriangle_obj_assoc _ _ _ h]
   dsimp
-  rw [Iso.inv_hom_id_app_assoc, Iso.inv_hom_id_app]
+  rw [comp_id, Iso.inv_hom_id_app_assoc, Iso.inv_hom_id_app]
   erw [comp_id]
   rw [← cancel_epi π, reassoc_of% hx', reassoc_of% hx',
     HomologicalComplex.homologyπ_naturality_assoc,
     HomologicalComplex.liftCycles_comp_cyclesMap_assoc]
+  /- We decompose the cocycle `x'` into two morphisms `a : A' ⟶ S.X₁.X n₁`
+     and `b : A' ⟶ S.X₂.X n₀` satisfying certain relations. -/
   obtain ⟨a, b, hab⟩ := decomp_to _ x' n₁ h
   rw [hab, ext_to_iff _ n₁ (n₁ + 1) rfl, add_comp, assoc, assoc, inr_f_d, add_comp, assoc,
     assoc, assoc, assoc, inr_f_fst_v, comp_zero, comp_zero, add_zero, zero_comp,
     d_fst_v _ _ _ _ h, comp_neg, inl_v_fst_v_assoc, comp_neg, neg_eq_zero,
     add_comp, assoc, assoc, assoc, assoc, inr_f_snd_v, comp_id, zero_comp,
     d_snd_v _ _ _ h, comp_add, inl_v_fst_v_assoc, inl_v_snd_v_assoc, zero_comp, add_zero] at w
+  /- We simplify the RHS. -/
   conv_rhs => simp only [hab, add_comp, assoc, inr_f_descShortComplex_f,
     inl_v_descShortComplex_f, comp_zero, zero_add]
   rw [hS.δ_eq n₀ n₁ (by simpa using h) (b ≫ S.g.f n₀) _ b rfl (-a)
     (by simp only [neg_comp, neg_eq_iff_add_eq_zero, w.2]) (n₁ + 1) (by simp)]
+  /- We simplify the LHS. -/
   dsimp [Functor.shiftMap, homologyFunctor_shift]
   rw [HomologicalComplex.homologyπ_naturality_assoc,
-    HomologicalComplex.liftCycles_comp_cyclesMap_assoc]
-  sorry
+    HomologicalComplex.liftCycles_comp_cyclesMap_assoc,
+    S.X₁.liftCycles_shift_homologyπ_assoc _ _ _ _ n₁ (by omega) (n₁ + 1) (by simp),
+    Iso.inv_hom_id_app]
+  dsimp [homologyFunctor_shift]
+  simp only [hab, add_comp, assoc, inl_v_triangle_mor₃_f_assoc,
+    shiftFunctorObjXIso, neg_comp, Iso.inv_hom_id, comp_neg, comp_id,
+    inr_f_triangle_mor₃_f_assoc, zero_comp, comp_zero, add_zero]
 
 open ComposableArrows
 

From 3b5de64041ca3adf5081662aa6c025cce0b9e8e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 10 Jun 2024 08:53:05 +0200
Subject: [PATCH 10/63] removed a sorry

---
 .../Homology/HomotopyCategory/ShiftSequence.lean   | 10 ++++++++++
 .../Homology/HomotopyCategory/ShortExact.lean      | 14 +++++---------
 .../CategoryTheory/Shift/InducedShiftSequence.lean | 12 ++++++++++++
 3 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
index dbf2335d7d907f..801a506a204b67 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
@@ -152,4 +152,14 @@ lemma homologyShiftIso_hom_app (n a a' : ℤ) (ha' : n + a = a') (K : CochainCom
       (homologyFunctorFactors _ _ a').inv.app K := by
   apply Functor.ShiftSequence.induced_shiftIso_hom_app_obj
 
+@[reassoc]
+lemma homologyFunctor_shiftMap
+    {K L : CochainComplex C ℤ} {n : ℤ} (f : K ⟶ L⟦n⟧) (a a' : ℤ) (h : n + a = a') :
+    (homologyFunctor C (ComplexShape.up ℤ) 0).shiftMap
+      ((quotient _ _).map f ≫ ((quotient _ _).commShiftIso n).hom.app _) a a' h =
+        (homologyFunctorFactors _ _ a).hom.app K ≫
+          (HomologicalComplex.homologyFunctor C (ComplexShape.up ℤ) 0).shiftMap f a a' h ≫
+            (homologyFunctorFactors _ _ a').inv.app L := by
+  apply Functor.ShiftSequence.induced_shiftMap
+
 end HomotopyCategory
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
index 1692fe1f0e7898..f11fd02c2033a9 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
@@ -42,25 +42,21 @@ lemma liftCycles_shift_homologyπ
         simp only [Linear.comp_units_smul] at hf
         apply (one_smul (M := ℤˣ) _).symm.trans _
         rw [← Int.units_mul_self n.negOnePow, mul_smul, comp_id, hf, smul_zero]) ≫
-        K.homologyπ i' ≫ ((HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftIso n i i' hi').inv.app K := by
+        K.homologyπ i' ≫
+          ((HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftIso n i i' hi').inv.app K := by
   sorry
 
 end
 
-section
-
-variable (T : Triangle (CochainComplex C ℤ)) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁)
-
 @[reassoc]
-lemma homologySequenceδ_quotient_mapTriangle_obj :
+lemma homologySequenceδ_quotient_mapTriangle_obj
+    (T : Triangle (CochainComplex C ℤ)) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) :
     (homologyFunctor C (up ℤ) 0).homologySequenceδ
         ((quotient C (up ℤ)).mapTriangle.obj T) n₀ n₁ h =
       (homologyFunctorFactors C (up ℤ) n₀).hom.app _ ≫
         (HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftMap T.mor₃ n₀ n₁ (by omega) ≫
         (homologyFunctorFactors C (up ℤ) n₁).inv.app _ := by
-  sorry
-
-end
+  apply homologyFunctor_shiftMap
 
 namespace mappingCone
 
diff --git a/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean b/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean
index 33ad165e1dbd64..6c10c18c70b23e 100644
--- a/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean
+++ b/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean
@@ -119,6 +119,18 @@ lemma induced_shiftIso_hom_app_obj (n a a' : M) (ha' : n + a = a') (X : C) :
         (G.shiftIso n a a' ha').hom.app X ≫ (e' a').inv.app X := by
   apply induced.shiftIso_hom_app_obj
 
+@[reassoc]
+def induced_shiftMap {n : M} {X Y : C} (f : X ⟶ Y⟦n⟧) (a a' : M) (h : n + a = a') :
+    letI := induced e M F' e'
+    F.shiftMap (L.map f ≫ (L.commShiftIso n).hom.app _) a a' h =
+      (e' a).hom.app X ≫ G.shiftMap f a a' h ≫ (e' a').inv.app Y := by
+  dsimp [shiftMap]
+  rw [Functor.map_comp, induced_shiftIso_hom_app_obj, assoc, assoc]
+  nth_rw 2 [← Functor.map_comp_assoc]
+  simp only [comp_obj, Iso.hom_inv_id_app, map_id, id_comp]
+  rw [← NatTrans.naturality_assoc]
+  rfl
+
 end ShiftSequence
 
 end Functor

From 89fe3b0374f7f513d9b5b10f6f89b674a068aa4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 10 Jun 2024 09:14:09 +0200
Subject: [PATCH 11/63] removed sorries

---
 .../HomotopyCategory/ShiftSequence.lean       | 25 ++++++++++++++++++-
 .../Homology/HomotopyCategory/ShortExact.lean | 25 ++-----------------
 2 files changed, 26 insertions(+), 24 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
index 801a506a204b67..dc10431f21fff5 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
@@ -18,7 +18,7 @@ and `HomotopyCategory` namespaces.
 
 -/
 
-open CategoryTheory Category
+open CategoryTheory Category ComplexShape Limits
 
 variable (C : Type*) [Category C] [Preadditive C]
 
@@ -129,6 +129,29 @@ lemma homologyFunctor_shift (n : ℤ) :
     (homologyFunctor C (ComplexShape.up ℤ) 0).shift n =
       homologyFunctor C (ComplexShape.up ℤ) n := rfl
 
+@[reassoc]
+lemma liftCycles_shift_homologyπ
+    (K : CochainComplex C ℤ) {A : C} {n i : ℤ} (f : A ⟶ (K⟦n⟧).X i) (j : ℤ)
+    (hj : (up ℤ).next i = j) (hf : f ≫ (K⟦n⟧).d i j = 0) (i' : ℤ) (hi' : n + i = i') (j' : ℤ)
+    (hj' : (up ℤ).next i' = j') :
+    (K⟦n⟧).liftCycles f j hj hf ≫ (K⟦n⟧).homologyπ i =
+      K.liftCycles (f ≫ (K.shiftFunctorObjXIso n i i' (by omega)).hom) j' hj' (by
+        simp only [next] at hj hj'
+        obtain rfl : i' = i + n := by omega
+        obtain rfl : j' = j + n := by omega
+        dsimp at hf ⊢
+        simp only [Linear.comp_units_smul] at hf
+        apply (one_smul (M := ℤˣ) _).symm.trans _
+        rw [← Int.units_mul_self n.negOnePow, mul_smul, comp_id, hf, smul_zero]) ≫
+        K.homologyπ i' ≫
+          ((HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftIso n i i' hi').inv.app K := by
+  simp only [liftCycles, homologyπ,
+    shiftFunctorObjXIso, Functor.shiftIso, Functor.ShiftSequence.shiftIso,
+    ShiftSequence.shiftIso_inv_app, ShortComplex.homologyπ_naturality,
+    ShortComplex.liftCycles_comp_cyclesMap_assoc, shiftShortComplexFunctorIso_inv_app_τ₂,
+    assoc, Iso.hom_inv_id, comp_id]
+  rfl
+
 end CochainComplex
 
 namespace HomotopyCategory
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
index f11fd02c2033a9..2dc4694c7f66e6 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShortExact.lean
@@ -15,8 +15,8 @@ If `S` is a short exact short complex of cochain complexes in an abelian categor
 we construct a quasi-isomorphism `descShortComplex S : mappingCone S.f ⟶ S.X₃`.
 
 We obtain this by comparing the homology sequence of `S` and the homology
-sequence of the homology functor on the homotopy category, applied to the triangle
-attached to the mapping cone of `S.f`.
+sequence of the homology functor on the homotopy category, applied to the
+distinguished triangle attached to the mapping cone of `S.f`.
 
 -/
 
@@ -27,27 +27,6 @@ variable {C : Type*} [Category C] [Abelian C]
 
 namespace CochainComplex
 
-section
-
-@[reassoc]
-lemma liftCycles_shift_homologyπ
-    (K : CochainComplex C ℤ) {A : C} {n i : ℤ} (f : A ⟶ (K⟦n⟧).X i) (j : ℤ)
-    (hj : (up ℤ).next i = j) (hf : f ≫ (K⟦n⟧).d i j = 0) (i' : ℤ) (hi' : n + i = i') (j' : ℤ) (hj' : (up ℤ).next i' = j'):
-    (K⟦n⟧).liftCycles f j hj hf ≫ (K⟦n⟧).homologyπ i =
-      K.liftCycles (f ≫ (K.shiftFunctorObjXIso n i i' (by omega)).hom) j' hj' (by
-        simp only [next] at hj hj'
-        obtain rfl : i' = i + n := by omega
-        obtain rfl : j' = j + n := by omega
-        dsimp at hf ⊢
-        simp only [Linear.comp_units_smul] at hf
-        apply (one_smul (M := ℤˣ) _).symm.trans _
-        rw [← Int.units_mul_self n.negOnePow, mul_smul, comp_id, hf, smul_zero]) ≫
-        K.homologyπ i' ≫
-          ((HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftIso n i i' hi').inv.app K := by
-  sorry
-
-end
-
 @[reassoc]
 lemma homologySequenceδ_quotient_mapTriangle_obj
     (T : Triangle (CochainComplex C ℤ)) (n₀ n₁ : ℤ) (h : n₀ + 1 = n₁) :

From a0d590b273db6aa53a622958c19a5dabae7f084a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 10 Jun 2024 09:17:20 +0200
Subject: [PATCH 12/63] added docstring

---
 Mathlib/Algebra/Homology/Refinements.lean | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Mathlib/Algebra/Homology/Refinements.lean b/Mathlib/Algebra/Homology/Refinements.lean
index d13765fb130d51..a2c442807fce7b 100644
--- a/Mathlib/Algebra/Homology/Refinements.lean
+++ b/Mathlib/Algebra/Homology/Refinements.lean
@@ -7,6 +7,16 @@ Authors: Joël Riou
 import Mathlib.CategoryTheory.Abelian.Refinements
 import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex
 
+/-!
+# Refinements
+
+This file contains lemmas about "refinements" that are specific to
+the study of the homology of `HomologicalComplex`. General
+lemmas about refinements and the case of `ShortComplex` appear
+in the file `CategoryTheory.Abelian.Refinements`.
+
+-/
+
 open CategoryTheory
 
 variable {C ι : Type*} [Category C] [Abelian C] {c : ComplexShape ι}

From 872879ab557762e8605fadab27fb803ac9e35431 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 10 Jun 2024 09:39:26 +0200
Subject: [PATCH 13/63] fixed def/lemma

---
 Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean b/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean
index 6c10c18c70b23e..79ed69962f8581 100644
--- a/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean
+++ b/Mathlib/CategoryTheory/Shift/InducedShiftSequence.lean
@@ -120,7 +120,7 @@ lemma induced_shiftIso_hom_app_obj (n a a' : M) (ha' : n + a = a') (X : C) :
   apply induced.shiftIso_hom_app_obj
 
 @[reassoc]
-def induced_shiftMap {n : M} {X Y : C} (f : X ⟶ Y⟦n⟧) (a a' : M) (h : n + a = a') :
+lemma induced_shiftMap {n : M} {X Y : C} (f : X ⟶ Y⟦n⟧) (a a' : M) (h : n + a = a') :
     letI := induced e M F' e'
     F.shiftMap (L.map f ≫ (L.commShiftIso n).hom.app _) a a' h =
       (e' a).hom.app X ≫ G.shiftMap f a a' h ≫ (e' a').inv.app Y := by

From 16e77b942e7f1ed4cc26b0c3e6b4f827114615c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 10 Jun 2024 10:34:16 +0200
Subject: [PATCH 14/63] s/refine'/refine/

---
 Mathlib/CategoryTheory/Abelian/Refinements.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Abelian/Refinements.lean b/Mathlib/CategoryTheory/Abelian/Refinements.lean
index feb9cac637814c..90215bae9f07f9 100644
--- a/Mathlib/CategoryTheory/Abelian/Refinements.lean
+++ b/Mathlib/CategoryTheory/Abelian/Refinements.lean
@@ -114,7 +114,7 @@ lemma ShortComplex.eq_liftCycles_homologyπ_up_to_refinements {A : C} (γ : A 
     ∃ (A' : C) (π : A' ⟶ A) (_ : Epi π) (z : A' ⟶ S.X₂) (hz : z ≫ S.g = 0),
       π ≫ γ = S.liftCycles z hz ≫ S.homologyπ := by
   obtain ⟨A', π, hπ, z, hz⟩ := surjective_up_to_refinements_of_epi S.homologyπ γ
-  refine' ⟨A', π, hπ, z ≫ S.iCycles, by simp, _⟩
+  refine ⟨A', π, hπ, z ≫ S.iCycles, by simp, ?_⟩
   rw [hz]
   congr 1
   rw [← cancel_mono S.iCycles, liftCycles_i]

From 683b743b0fc895223361dd67f5c7885316e6f8cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 11 Jun 2024 22:35:18 +0200
Subject: [PATCH 15/63] feat: the distinguished triangle attached to a short
 exact sequence of complexes

---
 Mathlib.lean                                  |   1 +
 .../Homology/DerivedCategory/Basic.lean       |  32 +++-
 .../Homology/DerivedCategory/ShortExact.lean  |  65 +++++++
 Mathlib/CategoryTheory/Shift/CommShift.lean   | 165 +++++++++++++++++-
 .../CategoryTheory/Triangulated/Functor.lean  |  25 ++-
 5 files changed, 281 insertions(+), 7 deletions(-)
 create mode 100644 Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index e9801ad51c351e..34ee496abc28a3 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -288,6 +288,7 @@ import Mathlib.Algebra.Homology.ComplexShape
 import Mathlib.Algebra.Homology.ComplexShapeSigns
 import Mathlib.Algebra.Homology.ConcreteCategory
 import Mathlib.Algebra.Homology.DerivedCategory.Basic
+import Mathlib.Algebra.Homology.DerivedCategory.ShortExact
 import Mathlib.Algebra.Homology.DifferentialObject
 import Mathlib.Algebra.Homology.Embedding.Basic
 import Mathlib.Algebra.Homology.Exact
diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
index 09fba743dcdd7e..c6f37c6b338a1f 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
@@ -48,7 +48,7 @@ instance should be obtained at the beginning of the proof, using the term
 
 - define the induced homological functor `DerivedCategory C ⥤ C`.
 - construct the distinguished triangle associated to a short exact sequence
-of cochain complexes, and compare the associated connecting homomorphism
+of cochain complexes (done), and compare the associated connecting homomorphism
 with the one defined in `Algebra.Homology.HomologySequence`.
 - refactor the definition of Ext groups using morphisms in the derived category
 (which may be shrunk to the universe `v` at least when `C` has enough projectives
@@ -62,7 +62,7 @@ or enough injectives).
 
 universe w v u
 
-open CategoryTheory Limits
+open CategoryTheory Limits Pretriangulated
 
 variable (C : Type u) [Category.{v} C] [Abelian C]
 
@@ -132,6 +132,11 @@ instance : (Q (C := C)).IsLocalization
   dsimp only [Q, DerivedCategory]
   infer_instance
 
+instance {K L : CochainComplex C ℤ} (f : K ⟶ L) [QuasiIso f] :
+    IsIso (Q.map f) :=
+  Localization.inverts Q (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) _
+    (inferInstanceAs (QuasiIso f))
+
 /-- The localization functor `HomotopyCategory C (ComplexShape.up ℤ) ⥤ DerivedCategory C`. -/
 def Qh : HomotopyCategory C (ComplexShape.up ℤ) ⥤ DerivedCategory C :=
   HomologicalComplexUpToQuasiIso.Qh
@@ -168,6 +173,12 @@ noncomputable instance : HasShift (DerivedCategory C) ℤ :=
 noncomputable instance : (Qh (C := C)).CommShift ℤ :=
   Functor.CommShift.localized Qh (HomotopyCategory.subcategoryAcyclic C).W ℤ
 
+noncomputable instance : (Q (C := C)).CommShift ℤ :=
+  Functor.CommShift.ofIso (quotientCompQhIso C) ℤ
+
+instance : NatTrans.CommShift (quotientCompQhIso C).hom ℤ :=
+  Functor.CommShift.ofIso_compatibility (quotientCompQhIso C) ℤ
+
 instance (n : ℤ) : (shiftFunctor (DerivedCategory C) n).Additive := by
   rw [Localization.functor_additive_iff
     Qh (HomotopyCategory.subcategoryAcyclic C).W]
@@ -185,4 +196,21 @@ noncomputable instance : IsTriangulated (DerivedCategory C) :=
   Triangulated.Localization.isTriangulated
     Qh (HomotopyCategory.subcategoryAcyclic C).W
 
+variable {C}
+
+lemma mem_distTriang_iff (T : Triangle (DerivedCategory C)) :
+    (T ∈ distTriang (DerivedCategory C)) ↔ ∃ (X Y : CochainComplex C ℤ) (f : X ⟶ Y),
+      Nonempty (T ≅ Q.mapTriangle.obj (CochainComplex.mappingCone.triangle f)) := by
+  constructor
+  · rintro ⟨T', e, ⟨X, Y, f, ⟨e'⟩⟩⟩
+    refine ⟨_, _, f, ⟨?_⟩⟩
+    exact e ≪≫ Qh.mapTriangle.mapIso e' ≪≫
+      (Functor.mapTriangleCompIso (HomotopyCategory.quotient C _) Qh).symm.app _ ≪≫
+      (Functor.mapTriangleIso (quotientCompQhIso C)).app _
+  · rintro ⟨X, Y, f, ⟨e⟩⟩
+    refine isomorphic_distinguished _ (Qh.map_distinguished _ ?_) _
+      (e ≪≫ (Functor.mapTriangleIso (quotientCompQhIso C)).symm.app _ ≪≫
+      (Functor.mapTriangleCompIso (HomotopyCategory.quotient C _) Qh).app _)
+    exact ⟨_, _, f, ⟨Iso.refl _⟩⟩
+
 end DerivedCategory
diff --git a/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean b/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean
new file mode 100644
index 00000000000000..9d63d714f1f6eb
--- /dev/null
+++ b/Mathlib/Algebra/Homology/DerivedCategory/ShortExact.lean
@@ -0,0 +1,65 @@
+/-
+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.Algebra.Homology.HomotopyCategory.ShortExact
+import Mathlib.Algebra.Homology.DerivedCategory.Basic
+
+/-!
+# The distinguished triangle attached to a short exact sequence of cochain complexes
+
+Given a short exact short complex `S` in the category `CochainComplex C ℤ`,
+we construct a distinguished triangle
+`Q.obj S.X₁ ⟶ Q.obj S.X₂ ⟶  Q.obj S.X₃ ⟶ (Q.obj S.X₃)⟦1⟧`
+in the derived category of `C`.
+(See `triangleOfSES` and `triangleOfSES_distinguished`.)
+
+-/
+
+universe w v u
+
+open CategoryTheory Category Pretriangulated
+
+namespace DerivedCategory
+
+variable {C : Type u} [Category.{v} C] [Abelian C] [HasDerivedCategory.{w} C]
+  {S : ShortComplex (CochainComplex C ℤ)} (hS : S.ShortExact)
+
+/-- The connecting homomorphism `Q.obj (S.X₃) ⟶ (Q.obj S.X₁)⟦(1 : ℤ)⟧`
+in the derived category when `S` is a short exact short complex of
+cochain complexes in an abelian category. -/
+noncomputable def triangleOfSESδ :
+  Q.obj (S.X₃) ⟶ (Q.obj S.X₁)⟦(1 : ℤ)⟧ :=
+    have := CochainComplex.mappingCone.quasiIso_descShortComplex hS
+    inv (Q.map (CochainComplex.mappingCone.descShortComplex S)) ≫
+      Q.map (CochainComplex.mappingCone.triangle S.f).mor₃ ≫
+      (Q.commShiftIso (1 : ℤ)).hom.app S.X₁
+
+/-- The distinguished triangle in the derived category associated to a short
+exact sequence of cochain complexes. -/
+@[simps!]
+noncomputable def triangleOfSES : Triangle (DerivedCategory C) :=
+  Triangle.mk (Q.map S.f) (Q.map S.g) (triangleOfSESδ hS)
+
+/-- The triangle `triangleOfSES` attached to a short exact sequence `S` of cochain
+complexes is isomorphism to the standard distinguished triangle associated to
+the morphism `S.f`. -/
+noncomputable def triangleOfSESIso :
+    triangleOfSES hS ≅ Q.mapTriangle.obj (CochainComplex.mappingCone.triangle S.f) := by
+  have := CochainComplex.mappingCone.quasiIso_descShortComplex hS
+  refine Iso.symm (Triangle.isoMk _ _ (Iso.refl _) (Iso.refl _)
+    (asIso (Q.map (CochainComplex.mappingCone.descShortComplex S))) ?_ ?_ ?_)
+  · dsimp [triangleOfSES]
+    simp only [comp_id, id_comp]
+  · dsimp
+    simp only [← Q.map_comp, CochainComplex.mappingCone.inr_descShortComplex, id_comp]
+  · dsimp [triangleOfSESδ]
+    rw [CategoryTheory.Functor.map_id, comp_id, IsIso.hom_inv_id_assoc]
+
+lemma triangleOfSES_distinguished :
+    triangleOfSES hS ∈ distTriang (DerivedCategory C) := by
+  rw [mem_distTriang_iff]
+  exact ⟨_, _, S.f, ⟨triangleOfSESIso hS⟩⟩
+
+end DerivedCategory
diff --git a/Mathlib/CategoryTheory/Shift/CommShift.lean b/Mathlib/CategoryTheory/Shift/CommShift.lean
index 0fa0f7407f5aa7..92c4f554e2dd3f 100644
--- a/Mathlib/CategoryTheory/Shift/CommShift.lean
+++ b/Mathlib/CategoryTheory/Shift/CommShift.lean
@@ -147,13 +147,39 @@ end
 
 namespace CommShift
 
-variable (C)
-
+variable (C) in
 instance id : CommShift (𝟭 C) A where
   iso := fun a => rightUnitor _ ≪≫ (leftUnitor _).symm
 
+instance comp [F.CommShift A] [G.CommShift A] : (F ⋙ G).CommShift A where
+  iso a := (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight (F.commShiftIso a) _ ≪≫
+    Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ (G.commShiftIso a) ≪≫
+    (Functor.associator _ _ _).symm
+  zero := by
+    ext X
+    dsimp
+    simp only [id_comp, comp_id, commShiftIso_zero, isoZero_hom_app, ← Functor.map_comp_assoc,
+      assoc, Iso.inv_hom_id_app, id_obj, comp_map, comp_obj]
+  add := fun a b => by
+    ext X
+    dsimp
+    simp only [commShiftIso_add, isoAdd_hom_app]
+    dsimp
+    simp only [comp_id, id_comp, assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app, comp_obj]
+    simp only [map_comp, assoc, commShiftIso_hom_naturality_assoc]
+
 end CommShift
 
+lemma commShiftIso_comp_hom_app [F.CommShift A] [G.CommShift A] (a : A) (X : C) :
+    (commShiftIso (F ⋙ G) a).hom.app X =
+      G.map ((commShiftIso F a).hom.app X) ≫ (commShiftIso G a).hom.app (F.obj X) := by
+  simp [commShiftIso, CommShift.iso]
+
+lemma commShiftIso_comp_inv_app [F.CommShift A] [G.CommShift A] (a : A) (X : C) :
+    (commShiftIso (F ⋙ G) a).inv.app X =
+      (commShiftIso G a).inv.app (F.obj X) ≫ G.map ((commShiftIso F a).inv.app X) := by
+  simp [commShiftIso, CommShift.iso]
+
 variable {B}
 
 lemma map_shiftFunctorComm_hom_app [F.CommShift B] (X : C) (a b : B) :
@@ -200,4 +226,139 @@ lemma map_shiftFunctorCompIsoId_inv_app [F.CommShift A] (X : C) (a b : A) (h : a
 
 end Functor
 
+namespace NatTrans
+
+variable {C D E : Type*} [Category C] [Category D] [Category E]
+  {F₁ F₂ F₃ : C ⥤ D} (τ : F₁ ⟶ F₂) (τ' : F₂ ⟶ F₃) (e : F₁ ≅ F₂)
+    (G G' : D ⥤ E) (τ'' : G ⟶ G')
+  (A : Type*) [AddMonoid A] [HasShift C A] [HasShift D A] [HasShift E A]
+  [F₁.CommShift A] [F₂.CommShift A] [F₃.CommShift A]
+    [G.CommShift A] [G'.CommShift A]
+
+/-- If `τ : F₁ ⟶ F₂` is a natural transformation between two functors
+which commute with a shift by an additive monoid `A`, this typeclass
+asserts a compatibility of `τ` with these shifts. -/
+class CommShift : Prop :=
+  comm' (a : A) : (F₁.commShiftIso a).hom ≫ whiskerRight τ _ =
+    whiskerLeft _ τ ≫ (F₂.commShiftIso a).hom
+
+namespace CommShift
+
+section
+
+variable {A}
+variable [NatTrans.CommShift τ A]
+
+lemma comm (a : A) : (F₁.commShiftIso a).hom ≫ whiskerRight τ _ =
+    whiskerLeft _ τ ≫ (F₂.commShiftIso a).hom := by
+  apply comm'
+
+@[reassoc]
+lemma comm_app (a : A) (X : C) :
+    (F₁.commShiftIso a).hom.app X ≫ (τ.app X)⟦a⟧' =
+      τ.app (X⟦a⟧) ≫ (F₂.commShiftIso a).hom.app X :=
+  NatTrans.congr_app (comm τ a) X
+
+lemma shift_app (a : A) (X : C) :
+    (τ.app X)⟦a⟧' = (F₁.commShiftIso a).inv.app X ≫
+      τ.app (X⟦a⟧) ≫ (F₂.commShiftIso a).hom.app X := by
+  rw [← comm_app, Iso.inv_hom_id_app_assoc]
+
+lemma app_shift (a : A) (X : C) :
+    τ.app (X⟦a⟧) = (F₁.commShiftIso a).hom.app X ≫ (τ.app X)⟦a⟧' ≫
+      (F₂.commShiftIso a).inv.app X := by
+  erw [comm_app_assoc, Iso.hom_inv_id_app, Category.comp_id]
+
+end
+
+instance of_iso_inv [NatTrans.CommShift e.hom A] :
+  NatTrans.CommShift e.inv A := ⟨fun a => by
+  ext X
+  dsimp
+  rw [← cancel_epi (e.hom.app (X⟦a⟧)), e.hom_inv_id_app_assoc, ← comm_app_assoc,
+    ← Functor.map_comp, e.hom_inv_id_app, Functor.map_id]
+  rw [Category.comp_id]⟩
+
+lemma of_isIso [IsIso τ] [NatTrans.CommShift τ A] :
+    NatTrans.CommShift (inv τ) A := by
+  haveI : NatTrans.CommShift (asIso τ).hom A := by
+    dsimp
+    infer_instance
+  change NatTrans.CommShift (asIso τ).inv A
+  infer_instance
+
+variable (F₁)
+
+instance id : NatTrans.CommShift (𝟙 F₁) A := ⟨by aesop_cat⟩
+
+instance comp [NatTrans.CommShift τ A] [NatTrans.CommShift τ' A] :
+    NatTrans.CommShift (τ ≫ τ') A := ⟨fun a => by
+  ext X
+  simp [comm_app_assoc, comm_app]⟩
+
+variable {F₁}
+
+instance whiskerRight [NatTrans.CommShift τ A] :
+    NatTrans.CommShift (whiskerRight τ G) A := ⟨fun a => by
+  ext X
+  simp only [Functor.comp_obj, whiskerRight_twice, comp_app,
+    whiskerRight_app, Functor.comp_map, whiskerLeft_app,
+    Functor.commShiftIso_comp_hom_app, Category.assoc]
+  erw [← NatTrans.naturality]
+  dsimp
+  simp only [← G.map_comp_assoc, comm_app]⟩
+
+variable {G G'} (F₁)
+
+instance whiskerLeft [NatTrans.CommShift τ'' A] :
+    NatTrans.CommShift (whiskerLeft F₁ τ'') A := ⟨fun a => by
+  ext X
+  simp only [Functor.comp_obj, comp_app, whiskerRight_app, whiskerLeft_app, whiskerLeft_twice,
+    Functor.commShiftIso_comp_hom_app, Category.assoc, ← NatTrans.naturality_assoc, comm_app]⟩
+
+end CommShift
+
+end NatTrans
+
+namespace Functor
+
+namespace CommShift
+
+variable {C D E : Type*} [Category C] [Category D]
+  {F : C ⥤ D} {G : C ⥤ D} (e : F ≅ G)
+  (A : Type*) [AddMonoid A] [HasShift C A] [HasShift D A]
+  [F.CommShift A]
+
+/-- If `e : F ≅ G` is an isomorphism of functors and if `F` commutes with the
+shift, then `G` also commutes with the shift. -/
+def ofIso : G.CommShift A where
+  iso a := isoWhiskerLeft _ e.symm ≪≫ F.commShiftIso a ≪≫ isoWhiskerRight e _
+  zero := by
+    ext X
+    simp only [comp_obj, F.commShiftIso_zero A, Iso.trans_hom, isoWhiskerLeft_hom,
+      Iso.symm_hom, isoWhiskerRight_hom, NatTrans.comp_app, whiskerLeft_app,
+      isoZero_hom_app, whiskerRight_app, assoc]
+    erw [← e.inv.naturality_assoc, ← NatTrans.naturality,
+      e.inv_hom_id_app_assoc]
+  add a b := by
+    ext X
+    simp only [comp_obj, F.commShiftIso_add, Iso.trans_hom, isoWhiskerLeft_hom,
+      Iso.symm_hom, isoWhiskerRight_hom, NatTrans.comp_app, whiskerLeft_app,
+      isoAdd_hom_app, whiskerRight_app, assoc, map_comp, NatTrans.naturality_assoc,
+      NatIso.cancel_natIso_inv_left]
+    simp only [← Functor.map_comp_assoc, e.hom_inv_id_app_assoc]
+    simp only [← NatTrans.naturality, comp_obj, comp_map, map_comp, assoc]
+
+lemma ofIso_compatibility :
+    letI := ofIso e A
+    NatTrans.CommShift e.hom A := by
+  letI := ofIso e A
+  refine' ⟨fun a => _⟩
+  dsimp [commShiftIso, ofIso]
+  rw [← whiskerLeft_comp_assoc, e.hom_inv_id, whiskerLeft_id', id_comp]
+
+end CommShift
+
+end Functor
+
 end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Triangulated/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Functor.lean
index 09a88da85e00f1..d7be1f2f2f51a6 100644
--- a/Mathlib/CategoryTheory/Triangulated/Functor.lean
+++ b/Mathlib/CategoryTheory/Triangulated/Functor.lean
@@ -25,8 +25,9 @@ open Category Limits Pretriangulated Preadditive
 
 namespace Functor
 
-variable {C D : Type*} [Category C] [Category D] [HasShift C ℤ] [HasShift D ℤ]
-  (F : C ⥤ D) [F.CommShift ℤ]
+variable {C D E : Type*} [Category C] [Category D] [Category E]
+  [HasShift C ℤ] [HasShift D ℤ] [HasShift E ℤ]
+  (F : C ⥤ D) [F.CommShift ℤ] (G : D ⥤ E) [G.CommShift ℤ]
 
 /-- The functor `Triangle C ⥤ Triangle D` that is induced by a functor `F : C ⥤ D`
 which commutes with shift by `ℤ`. -/
@@ -84,7 +85,8 @@ noncomputable def mapTriangleCommShiftIso (n : ℤ) :
       simp only [comp_obj, assoc, Iso.inv_hom_id_app_assoc,
         ← Functor.map_comp, Iso.inv_hom_id_app, map_id, comp_id])) (by aesop_cat)
 
-attribute [local simp] commShiftIso_zero commShiftIso_add
+attribute [local simp] map_zsmul comp_zsmul zsmul_comp
+  commShiftIso_zero commShiftIso_add commShiftIso_comp_hom_app
   shiftFunctorAdd'_eq_shiftFunctorAdd
 
 set_option maxHeartbeats 400000 in
@@ -111,6 +113,23 @@ noncomputable def mapTriangleInvRotateIso [F.Additive] :
     (fun T => Triangle.isoMk _ _ ((F.commShiftIso (-1 : ℤ)).symm.app _) (Iso.refl _) (Iso.refl _)
       (by aesop_cat) (by aesop_cat) (by aesop_cat)) (by aesop_cat)
 
+/-- The canonical isomorphism `(F ⋙ G).mapTriangle ≅ F.mapTriangle ⋙ G.mapTriangle`. -/
+@[simps!]
+def mapTriangleCompIso : (F ⋙ G).mapTriangle ≅ F.mapTriangle ⋙ G.mapTriangle :=
+  NatIso.ofComponents (fun T => Triangle.isoMk _ _ (Iso.refl _) (Iso.refl _) (Iso.refl _))
+
+/-- Two isomorphic functors `F₁` and `F₂` induce isomorphic functor
+`F₁.mapTriangle` and `F₂.mapTriangle` if the isomorphism `F₁ ≅ F₂` is compatible
+with the shifts. -/
+@[simps!]
+def mapTriangleIso {F₁ F₂ : C ⥤ D} (e : F₁ ≅ F₂) [F₁.CommShift ℤ] [F₂.CommShift ℤ]
+    [NatTrans.CommShift e.hom ℤ] : F₁.mapTriangle ≅ F₂.mapTriangle :=
+  NatIso.ofComponents (fun T =>
+    Triangle.isoMk _ _ (e.app _) (e.app _) (e.app _) (by simp) (by simp) (by
+      dsimp
+      simp only [assoc, NatTrans.CommShift.comm_app e.hom (1 : ℤ) T.obj₁,
+        NatTrans.naturality_assoc])) (by aesop_cat)
+
 end Additive
 
 variable [HasZeroObject C] [HasZeroObject D] [Preadditive C] [Preadditive D]

From 42f76c14f44adc8ec7ea4688a21dc8c5bc72c68a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 12 Jun 2024 10:39:24 +0200
Subject: [PATCH 16/63] feat: more API for commutation of functors with shifts

---
 Mathlib/CategoryTheory/Shift/CommShift.lean   | 164 +++++++++++++++++-
 .../CategoryTheory/Triangulated/Functor.lean  |  25 ++-
 2 files changed, 184 insertions(+), 5 deletions(-)

diff --git a/Mathlib/CategoryTheory/Shift/CommShift.lean b/Mathlib/CategoryTheory/Shift/CommShift.lean
index 0fa0f7407f5aa7..0db6d5142bc428 100644
--- a/Mathlib/CategoryTheory/Shift/CommShift.lean
+++ b/Mathlib/CategoryTheory/Shift/CommShift.lean
@@ -147,13 +147,39 @@ end
 
 namespace CommShift
 
-variable (C)
-
+variable (C) in
 instance id : CommShift (𝟭 C) A where
   iso := fun a => rightUnitor _ ≪≫ (leftUnitor _).symm
 
+instance comp [F.CommShift A] [G.CommShift A] : (F ⋙ G).CommShift A where
+  iso a := (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight (F.commShiftIso a) _ ≪≫
+    Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ (G.commShiftIso a) ≪≫
+    (Functor.associator _ _ _).symm
+  zero := by
+    ext X
+    dsimp
+    simp only [id_comp, comp_id, commShiftIso_zero, isoZero_hom_app, ← Functor.map_comp_assoc,
+      assoc, Iso.inv_hom_id_app, id_obj, comp_map, comp_obj]
+  add := fun a b => by
+    ext X
+    dsimp
+    simp only [commShiftIso_add, isoAdd_hom_app]
+    dsimp
+    simp only [comp_id, id_comp, assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app, comp_obj]
+    simp only [map_comp, assoc, commShiftIso_hom_naturality_assoc]
+
 end CommShift
 
+lemma commShiftIso_comp_hom_app [F.CommShift A] [G.CommShift A] (a : A) (X : C) :
+    (commShiftIso (F ⋙ G) a).hom.app X =
+      G.map ((commShiftIso F a).hom.app X) ≫ (commShiftIso G a).hom.app (F.obj X) := by
+  simp [commShiftIso, CommShift.iso]
+
+lemma commShiftIso_comp_inv_app [F.CommShift A] [G.CommShift A] (a : A) (X : C) :
+    (commShiftIso (F ⋙ G) a).inv.app X =
+      (commShiftIso G a).inv.app (F.obj X) ≫ G.map ((commShiftIso F a).inv.app X) := by
+  simp [commShiftIso, CommShift.iso]
+
 variable {B}
 
 lemma map_shiftFunctorComm_hom_app [F.CommShift B] (X : C) (a b : B) :
@@ -200,4 +226,138 @@ lemma map_shiftFunctorCompIsoId_inv_app [F.CommShift A] (X : C) (a b : A) (h : a
 
 end Functor
 
+namespace NatTrans
+
+variable {C D E : Type*} [Category C] [Category D] [Category E]
+  {F₁ F₂ F₃ : C ⥤ D} (τ : F₁ ⟶ F₂) (τ' : F₂ ⟶ F₃) (e : F₁ ≅ F₂)
+    (G G' : D ⥤ E) (τ'' : G ⟶ G')
+  (A : Type*) [AddMonoid A] [HasShift C A] [HasShift D A] [HasShift E A]
+  [F₁.CommShift A] [F₂.CommShift A] [F₃.CommShift A]
+    [G.CommShift A] [G'.CommShift A]
+
+/-- If `τ : F₁ ⟶ F₂` is a natural transformation between two functors
+which commute with a shift by an additive monoid `A`, this typeclass
+asserts a compatibility of `τ` with these shifts. -/
+class CommShift : Prop :=
+  comm' (a : A) : (F₁.commShiftIso a).hom ≫ whiskerRight τ _ =
+    whiskerLeft _ τ ≫ (F₂.commShiftIso a).hom
+
+namespace CommShift
+
+section
+
+variable {A}
+variable [NatTrans.CommShift τ A]
+
+lemma comm (a : A) : (F₁.commShiftIso a).hom ≫ whiskerRight τ _ =
+    whiskerLeft _ τ ≫ (F₂.commShiftIso a).hom := by
+  apply comm'
+
+@[reassoc]
+lemma comm_app (a : A) (X : C) :
+    (F₁.commShiftIso a).hom.app X ≫ (τ.app X)⟦a⟧' =
+      τ.app (X⟦a⟧) ≫ (F₂.commShiftIso a).hom.app X :=
+  NatTrans.congr_app (comm τ a) X
+
+@[reassoc]
+lemma shift_app (a : A) (X : C) :
+    (τ.app X)⟦a⟧' = (F₁.commShiftIso a).inv.app X ≫
+      τ.app (X⟦a⟧) ≫ (F₂.commShiftIso a).hom.app X := by
+  rw [← comm_app, Iso.inv_hom_id_app_assoc]
+
+@[reassoc]
+lemma app_shift (a : A) (X : C) :
+    τ.app (X⟦a⟧) = (F₁.commShiftIso a).hom.app X ≫ (τ.app X)⟦a⟧' ≫
+      (F₂.commShiftIso a).inv.app X := by
+  erw [comm_app_assoc, Iso.hom_inv_id_app, Category.comp_id]
+
+end
+
+instance of_iso_inv [NatTrans.CommShift e.hom A] :
+  NatTrans.CommShift e.inv A := ⟨fun a => by
+  ext X
+  dsimp
+  rw [← cancel_epi (e.hom.app (X⟦a⟧)), e.hom_inv_id_app_assoc, ← comm_app_assoc,
+    ← Functor.map_comp, e.hom_inv_id_app, Functor.map_id]
+  rw [Category.comp_id]⟩
+
+lemma of_isIso [IsIso τ] [NatTrans.CommShift τ A] :
+    NatTrans.CommShift (inv τ) A := by
+  haveI : NatTrans.CommShift (asIso τ).hom A := by
+    dsimp
+    infer_instance
+  change NatTrans.CommShift (asIso τ).inv A
+  infer_instance
+
+variable (F₁) in
+instance id : NatTrans.CommShift (𝟙 F₁) A := ⟨by aesop_cat⟩
+
+instance comp [NatTrans.CommShift τ A] [NatTrans.CommShift τ' A] :
+    NatTrans.CommShift (τ ≫ τ') A := ⟨fun a => by
+  ext X
+  simp [comm_app_assoc, comm_app]⟩
+
+instance whiskerRight [NatTrans.CommShift τ A] :
+    NatTrans.CommShift (whiskerRight τ G) A := ⟨fun a => by
+  ext X
+  simp only [Functor.comp_obj, whiskerRight_twice, comp_app,
+    whiskerRight_app, Functor.comp_map, whiskerLeft_app,
+    Functor.commShiftIso_comp_hom_app, Category.assoc]
+  erw [← NatTrans.naturality]
+  dsimp
+  simp only [← G.map_comp_assoc, comm_app]⟩
+
+variable {G G'} (F₁)
+
+instance whiskerLeft [NatTrans.CommShift τ'' A] :
+    NatTrans.CommShift (whiskerLeft F₁ τ'') A := ⟨fun a => by
+  ext X
+  simp only [Functor.comp_obj, comp_app, whiskerRight_app, whiskerLeft_app, whiskerLeft_twice,
+    Functor.commShiftIso_comp_hom_app, Category.assoc, ← NatTrans.naturality_assoc, comm_app]⟩
+
+end CommShift
+
+end NatTrans
+
+namespace Functor
+
+namespace CommShift
+
+variable {C D E : Type*} [Category C] [Category D]
+  {F : C ⥤ D} {G : C ⥤ D} (e : F ≅ G)
+  (A : Type*) [AddMonoid A] [HasShift C A] [HasShift D A]
+  [F.CommShift A]
+
+/-- If `e : F ≅ G` is an isomorphism of functors and if `F` commutes with the
+shift, then `G` also commutes with the shift. -/
+def ofIso : G.CommShift A where
+  iso a := isoWhiskerLeft _ e.symm ≪≫ F.commShiftIso a ≪≫ isoWhiskerRight e _
+  zero := by
+    ext X
+    simp only [comp_obj, F.commShiftIso_zero A, Iso.trans_hom, isoWhiskerLeft_hom,
+      Iso.symm_hom, isoWhiskerRight_hom, NatTrans.comp_app, whiskerLeft_app,
+      isoZero_hom_app, whiskerRight_app, assoc]
+    erw [← e.inv.naturality_assoc, ← NatTrans.naturality,
+      e.inv_hom_id_app_assoc]
+  add a b := by
+    ext X
+    simp only [comp_obj, F.commShiftIso_add, Iso.trans_hom, isoWhiskerLeft_hom,
+      Iso.symm_hom, isoWhiskerRight_hom, NatTrans.comp_app, whiskerLeft_app,
+      isoAdd_hom_app, whiskerRight_app, assoc, map_comp, NatTrans.naturality_assoc,
+      NatIso.cancel_natIso_inv_left]
+    simp only [← Functor.map_comp_assoc, e.hom_inv_id_app_assoc]
+    simp only [← NatTrans.naturality, comp_obj, comp_map, map_comp, assoc]
+
+lemma ofIso_compatibility :
+    letI := ofIso e A
+    NatTrans.CommShift e.hom A := by
+  letI := ofIso e A
+  refine' ⟨fun a => _⟩
+  dsimp [commShiftIso, ofIso]
+  rw [← whiskerLeft_comp_assoc, e.hom_inv_id, whiskerLeft_id', id_comp]
+
+end CommShift
+
+end Functor
+
 end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Triangulated/Functor.lean b/Mathlib/CategoryTheory/Triangulated/Functor.lean
index 09a88da85e00f1..cde890b2fb7051 100644
--- a/Mathlib/CategoryTheory/Triangulated/Functor.lean
+++ b/Mathlib/CategoryTheory/Triangulated/Functor.lean
@@ -25,8 +25,9 @@ open Category Limits Pretriangulated Preadditive
 
 namespace Functor
 
-variable {C D : Type*} [Category C] [Category D] [HasShift C ℤ] [HasShift D ℤ]
-  (F : C ⥤ D) [F.CommShift ℤ]
+variable {C D E : Type*} [Category C] [Category D] [Category E]
+  [HasShift C ℤ] [HasShift D ℤ] [HasShift E ℤ]
+  (F : C ⥤ D) [F.CommShift ℤ] (G : D ⥤ E) [G.CommShift ℤ]
 
 /-- The functor `Triangle C ⥤ Triangle D` that is induced by a functor `F : C ⥤ D`
 which commutes with shift by `ℤ`. -/
@@ -84,7 +85,8 @@ noncomputable def mapTriangleCommShiftIso (n : ℤ) :
       simp only [comp_obj, assoc, Iso.inv_hom_id_app_assoc,
         ← Functor.map_comp, Iso.inv_hom_id_app, map_id, comp_id])) (by aesop_cat)
 
-attribute [local simp] commShiftIso_zero commShiftIso_add
+attribute [local simp] map_zsmul comp_zsmul zsmul_comp
+  commShiftIso_zero commShiftIso_add commShiftIso_comp_hom_app
   shiftFunctorAdd'_eq_shiftFunctorAdd
 
 set_option maxHeartbeats 400000 in
@@ -111,6 +113,23 @@ noncomputable def mapTriangleInvRotateIso [F.Additive] :
     (fun T => Triangle.isoMk _ _ ((F.commShiftIso (-1 : ℤ)).symm.app _) (Iso.refl _) (Iso.refl _)
       (by aesop_cat) (by aesop_cat) (by aesop_cat)) (by aesop_cat)
 
+/-- The canonical isomorphism `(F ⋙ G).mapTriangle ≅ F.mapTriangle ⋙ G.mapTriangle`. -/
+@[simps!]
+def mapTriangleCompIso : (F ⋙ G).mapTriangle ≅ F.mapTriangle ⋙ G.mapTriangle :=
+  NatIso.ofComponents (fun T => Triangle.isoMk _ _ (Iso.refl _) (Iso.refl _) (Iso.refl _))
+
+/-- Two isomorphic functors `F₁` and `F₂` induce isomorphic functors
+`F₁.mapTriangle` and `F₂.mapTriangle` if the isomorphism `F₁ ≅ F₂` is compatible
+with the shifts. -/
+@[simps!]
+def mapTriangleIso {F₁ F₂ : C ⥤ D} (e : F₁ ≅ F₂) [F₁.CommShift ℤ] [F₂.CommShift ℤ]
+    [NatTrans.CommShift e.hom ℤ] : F₁.mapTriangle ≅ F₂.mapTriangle :=
+  NatIso.ofComponents (fun T =>
+    Triangle.isoMk _ _ (e.app _) (e.app _) (e.app _) (by simp) (by simp) (by
+      dsimp
+      simp only [assoc, NatTrans.CommShift.comm_app e.hom (1 : ℤ) T.obj₁,
+        NatTrans.naturality_assoc])) (by aesop_cat)
+
 end Additive
 
 variable [HasZeroObject C] [HasZeroObject D] [Preadditive C] [Preadditive D]

From 127ca968adaec5c4cf8dbc4c887c2dd95777493e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 16 Jun 2024 13:38:09 +0200
Subject: [PATCH 17/63] feat(Algebra/Homology) the single complex functor
 preserves (co)limits

---
 .../Homology/HomologicalComplexLimits.lean    | 26 ++++++++++++++++++-
 Mathlib/Algebra/Homology/Single.lean          | 16 ++++++++++--
 .../Limits/Preserves/Shapes/Zero.lean         | 25 ++++++++++++++++++
 .../Limits/Shapes/ZeroMorphisms.lean          | 19 ++++++++++++++
 4 files changed, 83 insertions(+), 3 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean b/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
index f46a21f10f8dba..2452418d24fd59 100644
--- a/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
+++ b/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
@@ -3,7 +3,7 @@ Copyright (c) 2023 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.HomologicalComplex
+import Mathlib.Algebra.Homology.Single
 import Mathlib.CategoryTheory.Limits.Shapes.FiniteLimits
 import Mathlib.CategoryTheory.Limits.Preserves.Finite
 
@@ -193,4 +193,28 @@ def preservesColimitsOfShapeOfEval {D : Type*} [Category D]
   ⟨fun {_} => ⟨fun hs ↦ isColimitOfEval _ _
     (fun i => isColimitOfPreserves (G ⋙ eval C c i) hs)⟩⟩
 
+section
+
+variable [HasZeroObject C] [DecidableEq ι] (i : ι)
+
+noncomputable instance : PreservesLimitsOfShape J (single C c i) :=
+  preservesLimitsOfShapeOfEval _ (fun j => by
+    by_cases h : j = i
+    · subst h
+      exact preservesLimitsOfShapeOfNatIso (singleCompEvalIsoSelf C c j).symm
+    · exact Functor.preservesLimitsOfShapeOfIsZero _ (isZero_single_comp_eval C c _ _ h))
+
+noncomputable instance : PreservesColimitsOfShape J (single C c i) :=
+  preservesColimitsOfShapeOfEval _ (fun j => by
+    by_cases h : j = i
+    · subst h
+      exact preservesColimitsOfShapeOfNatIso (singleCompEvalIsoSelf C c j).symm
+    · exact Functor.preservesColimitsOfShapeOfIsZero _ (isZero_single_comp_eval C c _ _ h))
+
+noncomputable instance : PreservesFiniteLimits (single C c i) := ⟨by intros; infer_instance⟩
+
+noncomputable instance : PreservesFiniteColimits (single C c i) := ⟨by intros; infer_instance⟩
+
+end
+
 end HomologicalComplex
diff --git a/Mathlib/Algebra/Homology/Single.lean b/Mathlib/Algebra/Homology/Single.lean
index 85f24d4adf8e7b..857c82a642866c 100644
--- a/Mathlib/Algebra/Homology/Single.lean
+++ b/Mathlib/Algebra/Homology/Single.lean
@@ -96,6 +96,20 @@ theorem single_map_f_self (j : ι) {A B : V} (f : A ⟶ B) :
   rfl
 #align homological_complex.single_map_f_self HomologicalComplex.single_map_f_self
 
+variable (V)
+
+/-- The natural isomorphism `single V c j ⋙ eval V c j ≅ 𝟭 V`. -/
+@[simps!]
+noncomputable def singleCompEvalIsoSelf (j : ι) : single V c j ⋙ eval V c j ≅ 𝟭 V :=
+  NatIso.ofComponents (singleObjXSelf c j) (fun {A B} f => by simp [single_map_f_self])
+
+lemma isZero_single_comp_eval (j i : ι) (hi : i ≠ j) : IsZero (single V c j ⋙ eval V c i) := by
+  rw [Functor.isZero_iff]
+  intro A
+  exact isZero_single_obj_X c _ _ _ hi
+
+variable {V c}
+
 @[ext]
 lemma from_single_hom_ext {K : HomologicalComplex V c} {j : ι} {A : V}
     {f g : (single V c j).obj A ⟶ K} (hfg : f.f j = g.f j) : f = g := by
@@ -126,8 +140,6 @@ instance (j : ι) : (single V c j).Full where
       ext
       simp [single_map_f_self]⟩
 
-variable {c}
-
 /-- Constructor for morphisms to a single homological complex. -/
 noncomputable def mkHomToSingle {K : HomologicalComplex V c} {j : ι} {A : V} (φ : K.X j ⟶ A)
     (hφ : ∀ (i : ι), c.Rel i j → K.d i j ≫ φ = 0) :
diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
index 631d1a633da5e4..804bbf49c249aa 100644
--- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
+++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
@@ -180,4 +180,29 @@ def preservesInitialObjectOfPreservesZeroMorphisms [PreservesZeroMorphisms F] :
 
 end ZeroObject
 
+section
+
+variable {J : Type*} [Category J] [HasZeroObject D] [HasZeroMorphisms D]
+  (G : C ⥤ D) (hG : IsZero G)
+
+/-- A zero functor preserves limits. -/
+def preservesLimitsOfShapeOfIsZero : PreservesLimitsOfShape J G where
+  preservesLimit := ⟨fun hc => by
+    rw [Functor.isZero_iff] at hG
+    refine IsLimit.ofIsZero _ ?_ (hG _)
+    rw [Functor.isZero_iff]
+    intro X
+    apply hG⟩
+
+/-- A zero functor preserves colimits. -/
+def preservesColimitsOfShapeOfIsZero : PreservesColimitsOfShape J G where
+  preservesColimit := ⟨fun hc => by
+    rw [Functor.isZero_iff] at hG
+    refine IsColimit.ofIsZero _ ?_ (hG _)
+    rw [Functor.isZero_iff]
+    intro X
+    apply hG⟩
+
+end
+
 end CategoryTheory.Functor
diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean
index b113825635be68..02356b31d75537 100644
--- a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean
+++ b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean
@@ -665,4 +665,23 @@ instance isSplitEpi_prod_snd [HasZeroMorphisms C] {X Y : C} [HasLimit (pair X Y)
   IsSplitEpi.mk' { section_ := prod.lift 0 (𝟙 Y) }
 #align category_theory.limits.is_split_epi_prod_snd CategoryTheory.Limits.isSplitEpi_prod_snd
 
+
+section
+
+variable [HasZeroMorphisms C] [HasZeroObject C] {F : D ⥤ C}
+
+/-- If a functor `F` is zero, then any cone for `F` with a zero point is limit. -/
+def IsLimit.ofIsZero (c : Cone F) (hF : IsZero F) (hc : IsZero c.pt) : IsLimit c where
+  lift _ := 0
+  fac _ j := (F.isZero_iff.1 hF j).eq_of_tgt _ _
+  uniq _ _ _ := hc.eq_of_tgt _ _
+
+/-- If a functor `F` is zero, then any cocone for `F` with a zero point is colimit. -/
+def IsColimit.ofIsZero (c : Cocone F) (hF : IsZero F) (hc : IsZero c.pt) : IsColimit c where
+  desc _ := 0
+  fac _ j := (F.isZero_iff.1 hF j).eq_of_src _ _
+  uniq _ _ _ := hc.eq_of_src _ _
+
+end
+
 end CategoryTheory.Limits

From 365b9df352562b53f12cab5305f7f45402affd79 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 16 Jun 2024 14:32:35 +0200
Subject: [PATCH 18/63] feat: the distinguished triangle attached to a short
 exact sequence

---
 Mathlib.lean                                  |  1 +
 .../Homology/DerivedCategory/Basic.lean       | 33 ++++++++
 .../DerivedCategory/SingleTriangle.lean       | 80 +++++++++++++++++++
 .../CategoryTheory/Shift/SingleFunctors.lean  | 38 ++++++++-
 4 files changed, 150 insertions(+), 2 deletions(-)
 create mode 100644 Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index abc1ef33f71ec3..4c4555404bb490 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -293,6 +293,7 @@ import Mathlib.Algebra.Homology.ConcreteCategory
 import Mathlib.Algebra.Homology.DerivedCategory.Basic
 import Mathlib.Algebra.Homology.DerivedCategory.HomologySequence
 import Mathlib.Algebra.Homology.DerivedCategory.ShortExact
+import Mathlib.Algebra.Homology.DerivedCategory.SingleTriangle
 import Mathlib.Algebra.Homology.DifferentialObject
 import Mathlib.Algebra.Homology.Embedding.Basic
 import Mathlib.Algebra.Homology.Exact
diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
index cc2bedc6bc998a..6231641a9facfa 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
@@ -5,6 +5,7 @@ Authors: Joël Riou
 -/
 import Mathlib.Algebra.Homology.HomotopyCategory.HomologicalFunctor
 import Mathlib.Algebra.Homology.HomotopyCategory.ShiftSequence
+import Mathlib.Algebra.Homology.HomotopyCategory.SingleFunctors
 import Mathlib.Algebra.Homology.HomotopyCategory.Triangulated
 import Mathlib.Algebra.Homology.Localization
 
@@ -223,4 +224,36 @@ lemma mem_distTriang_iff (T : Triangle (DerivedCategory C)) :
       (Functor.mapTriangleCompIso (HomotopyCategory.quotient C _) Qh).app _)
     exact ⟨_, _, f, ⟨Iso.refl _⟩⟩
 
+variable (C)
+
+/-- The single functors `C ⥤ DerivedCategory C` for all `n : ℤ` along with
+their compatibilities with shifts. -/
+noncomputable def singleFunctors : SingleFunctors C (DerivedCategory C) ℤ :=
+  (HomotopyCategory.singleFunctors C).postcomp Qh
+
+/-- The shift functor `C ⥤ DerivedCategory C` which sends `X : C` to the
+single cochain complex with `X` sitting in degree `n : ℤ`. -/
+noncomputable abbrev singleFunctor (n : ℤ) := (singleFunctors C).functor n
+
+instance (n : ℤ) : (singleFunctor C n).Additive := by
+  dsimp [singleFunctor, singleFunctors]
+  infer_instance
+
+/-- The isomorphism
+`DerivedCategory.singleFunctors C ≅ (HomotopyCategory.singleFunctors C).postcomp Qh` given
+by the definition of `DerivedCategory.singleFunctors`. -/
+noncomputable def singleFunctorsPostcompQhIso :
+    singleFunctors C ≅ (HomotopyCategory.singleFunctors C).postcomp Qh :=
+  Iso.refl _
+
+/-- The isomorphism
+`DerivedCategory.singleFunctors C ≅ (CochainComplex.singleFunctors C).postcomp Q`. -/
+noncomputable def singleFunctorsPostcompQIso :
+    singleFunctors C ≅ (CochainComplex.singleFunctors C).postcomp Q :=
+  (SingleFunctors.postcompFunctor C ℤ (Qh : _ ⥤ DerivedCategory C)).mapIso
+    (HomotopyCategory.singleFunctorsPostcompQuotientIso C) ≪≫
+      (CochainComplex.singleFunctors C).postcompPostcompIso (HomotopyCategory.quotient _ _) Qh ≪≫
+      SingleFunctors.postcompIsoOfIso
+        (CochainComplex.singleFunctors C) (quotientCompQhIso C)
+
 end DerivedCategory
diff --git a/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean b/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean
new file mode 100644
index 00000000000000..c1eaf214e01129
--- /dev/null
+++ b/Mathlib/Algebra/Homology/DerivedCategory/SingleTriangle.lean
@@ -0,0 +1,80 @@
+/-
+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.Algebra.Homology.DerivedCategory.ShortExact
+
+/-!
+# The distinguished triangle of a short exact sequence in an abelian category
+
+Given a short exact short complex `S` in an abelian category, we construct
+the associated distinguished triangle in the derived category:
+`(singleFunctor C 0).obj S.X₁ ⟶ (singleFunctor C 0).obj S.X₂ ⟶ (singleFunctor C 0).obj S.X₃ ⟶ ...`
+
+# TODO
+* when the canonical t-structure on the derived category is formalized, refactor
+this definition to make it a particular case of the triangle induced by a short
+exact sequence in the heart of a t-structure
+
+-/
+
+universe w v u
+
+namespace CategoryTheory
+
+variable {C : Type u} [Category.{v} C] [Abelian C] [HasDerivedCategory.{w} C]
+
+open Category DerivedCategory Pretriangulated
+
+namespace ShortComplex
+
+variable {S : ShortComplex C} (hS : S.ShortExact)
+
+namespace ShortExact
+
+/-- The connecting homomorphism
+`(singleFunctor C 0).obj S.X₃ ⟶ ((singleFunctor C 0).obj S.X₁)⟦(1 : ℤ)⟧` in the derived
+category of `C` when `S` is a short exact short complex in `C`. -/
+noncomputable def singleδ : (singleFunctor C 0).obj S.X₃ ⟶
+    ((singleFunctor C 0).obj S.X₁)⟦(1 : ℤ)⟧ :=
+  (((SingleFunctors.evaluation _ _ 0).mapIso (singleFunctorsPostcompQIso C)).hom.app S.X₃) ≫
+    triangleOfSESδ (hS.map_of_exact (HomologicalComplex.single C (ComplexShape.up ℤ) 0)) ≫
+    (((SingleFunctors.evaluation _ _ 0).mapIso
+      (singleFunctorsPostcompQIso C)).inv.app S.X₁)⟦(1 : ℤ)⟧'
+
+/-- The (distinguished) triangle in the derived category of `C` given by a
+short exact short complex in `C`. -/
+@[simps!]
+noncomputable def singleTriangle : Triangle (DerivedCategory C) :=
+  Triangle.mk ((singleFunctor C 0).map S.f)
+    ((singleFunctor C 0).map S.g) hS.singleδ
+
+/-- Given a short exact complex `S` in `C` that is short exact (`hS`), this is the
+canonical isomorphism between the triangle `hS.singleTriangle` in the derived category
+and the triangle attached to the corresponding short exact sequence of cochain complexes
+after the application of the single functor. -/
+@[simps!]
+noncomputable def singleTriangleIso :
+    hS.singleTriangle ≅
+      triangleOfSES (hS.map_of_exact (HomologicalComplex.single C (ComplexShape.up ℤ) 0)) := by
+  let e := (SingleFunctors.evaluation _ _ 0).mapIso (singleFunctorsPostcompQIso C)
+  refine Triangle.isoMk _ _ (e.app S.X₁) (e.app S.X₂) (e.app S.X₃) ?_ ?_ ?_
+  · aesop_cat
+  · aesop_cat
+  · dsimp [singleδ, e]
+    rw [Category.assoc, Category.assoc, ← Functor.map_comp, SingleFunctors.inv_hom_id_hom_app]
+    erw [Functor.map_id, comp_id]
+
+/-- The distinguished triangle in the derived category of `C` given by a
+short exact short complex in `C`. -/
+lemma singleTriangle_distinguished :
+    hS.singleTriangle ∈ distTriang (DerivedCategory C) :=
+  isomorphic_distinguished _ (triangleOfSES_distinguished (hS.map_of_exact
+    (HomologicalComplex.single C (ComplexShape.up ℤ) 0))) _ (singleTriangleIso hS)
+
+end ShortExact
+
+end ShortComplex
+
+end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Shift/SingleFunctors.lean b/Mathlib/CategoryTheory/Shift/SingleFunctors.lean
index c295fa9bb659b1..45c7c745c80073 100644
--- a/Mathlib/CategoryTheory/Shift/SingleFunctors.lean
+++ b/Mathlib/CategoryTheory/Shift/SingleFunctors.lean
@@ -27,8 +27,8 @@ which sends an object `X : C` to a complex where `X` sits in a single degree.
 
 open CategoryTheory Category ZeroObject Limits
 
-variable (C D E E' : Type*) [Category C] [Category D] [Category E]
-  (A : Type*) [AddMonoid A] [HasShift D A] [HasShift E A]
+variable (C D E E' : Type*) [Category C] [Category D] [Category E] [Category E']
+  (A : Type*) [AddMonoid A] [HasShift D A] [HasShift E A] [HasShift E' A]
 
 namespace CategoryTheory
 
@@ -218,6 +218,40 @@ def postcomp (G : D ⥤ E) [G.CommShift A] :
       Functor.commShiftIso_inv_naturality_assoc]
     simp only [← G.map_comp, Iso.inv_hom_id_app_assoc]
 
+variable (C A)
+
+/-- The functor `SingleFunctors C D A ⥤ SingleFunctors C E A` given by the postcomposition
+by a functor `G : D ⥤ E` which commutes with the shift. -/
+def postcompFunctor (G : D ⥤ E) [G.CommShift A] :
+    SingleFunctors C D A ⥤ SingleFunctors C E A where
+  obj F := F.postcomp G
+  map {F₁ F₂} φ :=
+    { hom := fun a => whiskerRight (φ.hom a) G
+      comm := fun n a a' ha' => by
+        ext X
+        simpa using G.congr_map (congr_app (φ.comm n a a' ha') X) }
+
+variable {C E' A}
+
+/-- The canonical isomorphism `(F.postcomp G).postcomp G' ≅ F.postcomp (G ⋙ G')`. -/
+@[simps!]
+def postcompPostcompIso (G : D ⥤ E) (G' : E ⥤ E') [G.CommShift A] [G'.CommShift A] :
+    (F.postcomp G).postcomp G' ≅ F.postcomp (G ⋙ G') :=
+  isoMk (fun a => Functor.associator _ _ _) (fun n a a' ha' => by
+    ext X
+    simp [Functor.commShiftIso_comp_inv_app])
+
+/-- The isomorphism `F.postcomp G ≅ F.postcomp G'` induced by an isomorphism `e : G ≅ G'`
+which commutes with the shift. -/
+@[simps!]
+def postcompIsoOfIso {G G' : D ⥤ E} (e : G ≅ G') [G.CommShift A] [G'.CommShift A]
+    [NatTrans.CommShift e.hom A]:
+    F.postcomp G ≅ F.postcomp G' :=
+  isoMk (fun a => isoWhiskerLeft (F.functor a) e) (fun n a a' ha' => by
+    ext X
+    dsimp
+    simp [NatTrans.CommShift.shift_app e.hom n])
+
 end SingleFunctors
 
 end CategoryTheory

From 285e3e7355dfe4b8ee7062572d8a3ce4a663da34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 18 Jun 2024 09:02:54 +0200
Subject: [PATCH 19/63] added docstring

---
 Mathlib/CategoryTheory/Iso.lean               | 10 ++++++
 .../CategoryTheory/Localization/SmallHom.lean | 35 +++++++------------
 2 files changed, 23 insertions(+), 22 deletions(-)

diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean
index fc4210cac733e7..0f112448d3c9ce 100644
--- a/Mathlib/CategoryTheory/Iso.lean
+++ b/Mathlib/CategoryTheory/Iso.lean
@@ -250,6 +250,16 @@ theorem hom_eq_inv (α : X ≅ Y) (β : Y ≅ X) : α.hom = β.inv ↔ β.hom =
   rfl
 #align category_theory.iso.hom_eq_inv CategoryTheory.Iso.hom_eq_inv
 
+/-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
+`e : X ≅ X'` and `e' : Y ≅ Y'`. -/
+@[simps]
+def homEquiv {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
+    (X ⟶ Y) ≃ (X' ⟶ Y') where
+  toFun f := e.inv ≫ f ≫ e'.hom
+  invFun g := e.hom ≫ g ≫ e'.inv
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
 end Iso
 
 /-- `IsIso` typeclass expressing that a morphism is invertible. -/
diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 0fa5cbcae47d4d..2310d15ce04175 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -9,30 +9,22 @@ import Mathlib.Logic.Small.Defs
 /-!
 # Shrinking morphisms in localized categories
 
+Given a class of morphisms `W : MorphismProperty C`, and two objects `X` and `Y`,
+we introduce a type-class `HasSmallLocalizedHom.{w} W X Y` which expresses
+that in the localized category with respect to `W`, the type of morphisms from `X`
+to `Y` is `w`-small for a certain universe `w`. Under this assumption,
+we define `SmallHom.{w} W X Y : Type w` as the shrunk type. For any localization
+functor `L : C ⥤ D` for `W`, we provide a bijection
+`SmallHom.equiv.{w} W L : SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y)` that is compatible
+with the composition of morphisms.
+
 -/
 
 universe w w' w'' v u u' u''
 
 namespace CategoryTheory
 
-variable {C : Type u} [Category.{v} C]
-
-section
-
--- should be moved to CategoryTheory.Iso
-/-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
-`e : X ≅ X'` and `e' : Y ≅ Y'`. -/
-@[simps]
-def homEquivOfIsos {X Y X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
-    (X ⟶ Y) ≃ (X' ⟶ Y') where
-  toFun f := e.inv ≫ f ≫ e'.hom
-  invFun g := e.hom ≫ g ≫ e'.inv
-  left_inv := by aesop_cat
-  right_inv := by aesop_cat
-
-end
-
-variable (W : MorphismProperty C)
+variable {C : Type u} [Category.{v} C] (W : MorphismProperty C)
   {D : Type u'} [Category.{w'} D] (L : C ⥤ D) [L.IsLocalization W]
   {D' : Type u''} [Category.{w''} D'] (L' : C ⥤ D') [L'.IsLocalization W] (X Y Z : C)
 
@@ -51,7 +43,7 @@ for the same class of morphisms `W`. -/
 noncomputable def localizationsHomEquiv :
     (L.obj X ⟶ L.obj Y) ≃ (L'.obj X ⟶ L'.obj Y) :=
   (Localization.uniq L L' W).fullyFaithfulFunctor.homEquiv.trans
-    (homEquivOfIsos ((Localization.compUniqFunctor L L' W).app X)
+    (Iso.homEquiv ((Localization.compUniqFunctor L L' W).app X)
       ((Localization.compUniqFunctor L L' W).app Y))
 
 @[simp]
@@ -87,7 +79,7 @@ lemma small_of_hasSmallLocalizedHom [HasSmallLocalizedHom.{w} W X Y] :
 lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
     HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y' := by
   simp only [W.hasSmallLocalizedHom_iff W.Q]
-  exact small_congr (homEquivOfIsos (W.Q.mapIso e) (W.Q.mapIso e'))
+  exact small_congr (Iso.homEquiv (W.Q.mapIso e) (W.Q.mapIso e'))
 
 end MorphismProperty
 
@@ -114,7 +106,7 @@ noncomputable def equiv [HasSmallLocalizedHom.{w} W X Y] :
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   (equivShrink _).symm.trans (W.localizationsHomEquiv W.Q L)
 
-variable [HasSmallLocalizedHom.{w} W X Y][HasSmallLocalizedHom.{w} W Y Z]
+variable [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Z]
   [HasSmallLocalizedHom.{w} W X Z]
 
 variable {W}
@@ -129,7 +121,6 @@ noncomputable def comp (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
 lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q Y Z
-  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Z
   obtain ⟨α, rfl⟩ := (equivShrink _).surjective α
   obtain ⟨β, rfl⟩ := (equivShrink _).surjective β
   dsimp [equiv, comp]

From e11918576c1a977475c872ee93f9631ada77b79a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 18 Jun 2024 10:16:55 +0200
Subject: [PATCH 20/63] more API

---
 .../CategoryTheory/Localization/SmallHom.lean | 70 ++++++++++++++++++-
 1 file changed, 68 insertions(+), 2 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 2310d15ce04175..7a9e42479421df 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -46,6 +46,19 @@ noncomputable def localizationsHomEquiv :
     (Iso.homEquiv ((Localization.compUniqFunctor L L' W).app X)
       ((Localization.compUniqFunctor L L' W).app Y))
 
+@[simp]
+lemma localizationsHomEquiv_map (f : X ⟶ Y) :
+    localizationsHomEquiv W L L' (L.map f) = L'.map f := by
+  dsimp [localizationsHomEquiv]
+  erw [← NatTrans.naturality_assoc]
+  simp
+
+variable (X) in
+@[simp]
+lemma localizationsHomEquiv_id :
+    localizationsHomEquiv W L L' (𝟙 (L.obj X)) = 𝟙 (L'.obj X) := by
+  simpa using localizationsHomEquiv_map W L L' (𝟙 X)
+
 @[simp]
 lemma localizationHomEquiv_refl :
     localizationsHomEquiv W L L (X := X) (Y := Y) = Equiv.refl _ := by
@@ -57,6 +70,14 @@ lemma localizationHomEquiv_comp (f : L.obj X ⟶ L.obj Y) (g : L.obj Y ⟶ L.obj
       localizationsHomEquiv W L L' f ≫ localizationsHomEquiv W L L' g := by
   simp [localizationsHomEquiv]
 
+lemma localizationsHomEquiv_isoOfHom_inv (f : X ⟶ Y) (hf : W f):
+    localizationsHomEquiv W L L' ((Localization.isoOfHom L W f hf).inv) =
+      (Localization.isoOfHom L' W f hf).inv := by
+  rw [← cancel_mono (Localization.isoOfHom L' W f hf).hom, Iso.inv_hom_id,
+    Localization.isoOfHom_hom, ← localizationsHomEquiv_map W L,
+    ← localizationHomEquiv_comp, Localization.isoOfHom_inv, IsIso.inv_hom_id,
+    localizationsHomEquiv_id]
+
 lemma hasSmallLocalizedHom_iff :
     HasSmallLocalizedHom.{w} W X Y ↔ Small.{w} (L.obj X ⟶ L.obj Y) := by
   constructor
@@ -106,8 +127,31 @@ noncomputable def equiv [HasSmallLocalizedHom.{w} W X Y] :
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   (equivShrink _).symm.trans (W.localizationsHomEquiv W.Q L)
 
-variable [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Z]
-  [HasSmallLocalizedHom.{w} W X Z]
+variable [HasSmallLocalizedHom.{w} W X Y]
+
+/-- The element in `SmallHom W X Y` induced by `f : X ⟶ Y`. -/
+noncomputable def mk (f : X ⟶ Y) : SmallHom.{w} W X Y :=
+  (equiv.{w} W W.Q).symm (W.Q.map f)
+
+@[simp]
+lemma equiv_mk (f : X ⟶ Y) : equiv.{w} W L (mk W f) = L.map f := by
+  simp [equiv, mk]
+
+variable {W} in
+/-- The formal inverse in `SmallHom W X Y` of a morphism `f : Y ⟶ X` such that `W f`. -/
+noncomputable def mkInv (f : Y ⟶ X) (hf : W f) : SmallHom.{w} W X Y :=
+  (equiv.{w} W W.Q).symm (Localization.isoOfHom W.Q W f hf).inv
+
+@[simp]
+lemma equiv_mkInv (f : Y ⟶ X) (hf : W f) :
+    equiv.{w} W L (mkInv f hf) = (Localization.isoOfHom L W f hf).inv := by
+  dsimp only [equiv, mkInv]
+  simp only [localizationHomEquiv_refl, Equiv.trans_refl, Equiv.symm_symm,
+    Equiv.trans_apply, Equiv.symm_apply_apply, localizationsHomEquiv_isoOfHom_inv]
+
+section
+
+variable [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
 
 variable {W}
 
@@ -129,6 +173,28 @@ lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
   rw [← localizationHomEquiv_comp, localizationHomEquiv_refl, Equiv.refl_symm,
     Equiv.refl_apply, Equiv.refl_apply, localizationHomEquiv_comp]
 
+lemma mk_comp_mk (f : X ⟶ Y) (g : Y ⟶ Z) :
+    (mk W f).comp (mk W g) = mk W (f ≫ g) :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
+
+end
+
+section
+
+variable [HasSmallLocalizedHom.{w} W Y X]
+
+@[simp]
+lemma mk_comp_mkInv (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W Y Y] :
+    (mk W f).comp (mkInv f hf) = mk W (𝟙 Y) :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
+
+@[simp]
+lemma mkInv_comp_mk (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X X] :
+    (mkInv f hf).comp (mk W f)= mk W (𝟙 X) :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
+
+end
+
 end SmallHom
 
 end Localization

From 7ebda0baf1894518e2db2fce3ca0ebe7fb7b6cf3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 18 Jun 2024 12:38:26 +0200
Subject: [PATCH 21/63] wip

---
 Mathlib.lean                                  |   1 +
 Mathlib/CategoryTheory/Iso.lean               |  16 +++
 .../Localization/SmallShiftedHom.lean         | 108 ++++++++++++++++++
 Mathlib/CategoryTheory/Shift/ShiftedHom.lean  |  28 ++++-
 4 files changed, 150 insertions(+), 3 deletions(-)
 create mode 100644 Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index 552a6a9134ec06..71d9e7489a9705 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -1502,6 +1502,7 @@ import Mathlib.CategoryTheory.Localization.Predicate
 import Mathlib.CategoryTheory.Localization.Prod
 import Mathlib.CategoryTheory.Localization.Resolution
 import Mathlib.CategoryTheory.Localization.SmallHom
+import Mathlib.CategoryTheory.Localization.SmallShiftedHom
 import Mathlib.CategoryTheory.Localization.Triangulated
 import Mathlib.CategoryTheory.Monad.Adjunction
 import Mathlib.CategoryTheory.Monad.Algebra
diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean
index 0f112448d3c9ce..0a609f5f659c37 100644
--- a/Mathlib/CategoryTheory/Iso.lean
+++ b/Mathlib/CategoryTheory/Iso.lean
@@ -250,6 +250,22 @@ theorem hom_eq_inv (α : X ≅ Y) (β : Y ≅ X) : α.hom = β.inv ↔ β.hom =
   rfl
 #align category_theory.iso.hom_eq_inv CategoryTheory.Iso.hom_eq_inv
 
+/-- The bijection `(Z ⟶ X) ≃ (Z ⟶ Y)` induced by `α : X ≅ Y`. -/
+@[simps]
+def homToEquiv (α : X ≅ Y) {Z : C} : (Z ⟶ X) ≃ (Z ⟶ Y) where
+  toFun f := f ≫ α.hom
+  invFun g := g ≫ α.inv
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
+/-- The bijection `(X ⟶ Z) ≃ (Y ⟶ Z)` induced by `α : X ≅ Y`. -/
+@[simps]
+def homFromEquiv (α : X ≅ Y) {Z : C} : (X ⟶ Z) ≃ (Y ⟶ Z) where
+  toFun f := α.inv ≫ f
+  invFun g := α.hom ≫ g
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
 /-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
 `e : X ≅ X'` and `e' : Y ≅ Y'`. -/
 @[simps]
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
new file mode 100644
index 00000000000000..ed9837b885c33a
--- /dev/null
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -0,0 +1,108 @@
+/-
+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.Localization.LocalizerMorphism
+import Mathlib.CategoryTheory.Localization.SmallHom
+import Mathlib.CategoryTheory.Shift.ShiftedHom
+import Mathlib.CategoryTheory.Shift.Localization
+
+universe w w' v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
+
+namespace CategoryTheory
+
+namespace Localization
+
+variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
+  {C' : Type u₂} [Category.{v₂} C'] (W' : MorphismProperty C')
+  {D : Type u₃} [Category.{v₃} D]
+  {D' : Type u₄} [Category.{v₄} D']
+  {M : Type w'} [AddMonoid M] [HasShift C M] [HasShift C' M]
+  [W.IsCompatibleWithShift M]
+  [W'.IsCompatibleWithShift M] (X Y Z : C)
+
+variable (M) in
+abbrev HasSmallLocalizedShiftedHom : Prop :=
+  ∀ (m : M), MorphismProperty.HasSmallLocalizedHom.{w} W X (Y⟦m⟧)
+
+def SmallShiftedHom [HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) : Type w :=
+  SmallHom W X (Y⟦m⟧)
+
+namespace SmallShiftedHom
+
+variable {X Y Z}
+section
+
+variable [HasSmallLocalizedShiftedHom.{w} W M X Y]
+
+section
+
+variable (L : C ⥤ D) [L.IsLocalization W] [HasShift D M] [L.CommShift M]
+
+noncomputable def equiv {m : M} :
+    SmallShiftedHom.{w} W X Y m ≃ ShiftedHom (L.obj X) (L.obj Y) m :=
+  (SmallHom.equiv W L).trans ((L.commShiftIso m).app Y).homToEquiv
+
+variable [HasSmallLocalizedShiftedHom.{w} W M Y Z]
+  [HasSmallLocalizedShiftedHom.{w} W M X Z]
+
+variable {a b c : M} (f : SmallShiftedHom.{w} W X Y a)
+  (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c)
+
+noncomputable def comp' : SmallShiftedHom.{w} W X Z c :=
+  (equiv W L).symm ((equiv W L f).comp (equiv W L g) h)
+
+
+end
+
+variable [HasSmallLocalizedShiftedHom.{w} W M Y Z]
+  [HasSmallLocalizedShiftedHom.{w} W M X Z]
+
+variable {a b c : M} (f : SmallShiftedHom.{w} W X Y a)
+  (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c)
+
+noncomputable def comp : SmallShiftedHom.{w} W X Z c :=
+  comp' W W.Q f g h
+
+end
+
+section
+
+variable {W W'}
+
+section
+
+noncomputable def map' [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    {a : M} (f : SmallShiftedHom.{w} W X Y a)
+    (Φ : LocalizerMorphism W W')
+    [HasSmallLocalizedShiftedHom.{w} W' M (Φ.functor.obj X) (Φ.functor.obj Y)]
+    (L : C ⥤ D) [L.IsLocalization W] [HasShift D M] [L.CommShift M]
+    (L' : C' ⥤ D') [L'.IsLocalization W'] [HasShift D' M] [L'.CommShift M]
+    (G : D ⥤ D') [G.CommShift M] (e : Φ.functor ⋙ L' ≅ L ⋙ G) :
+    SmallShiftedHom.{w} W' (Φ.functor.obj X) (Φ.functor.obj Y) a :=
+  (equiv W' L').symm
+    ((ShiftedHom.mk₀ (0 : M) rfl (e.hom.app X)).comp
+      (((equiv W L f).map G).comp
+      (ShiftedHom.mk₀ (0 : M) rfl (e.inv.app Y)) (zero_add a)) (add_zero a))
+
+noncomputable def map [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    {a : M} (f : SmallShiftedHom.{w} W X Y a)
+    (Φ : LocalizerMorphism W W')
+    [HasSmallLocalizedShiftedHom.{w} W' M (Φ.functor.obj X) (Φ.functor.obj Y)] :
+    SmallShiftedHom.{w} W' (Φ.functor.obj X) (Φ.functor.obj Y) a := by
+  have : (Φ.localizedFunctor W.Q W'.Q).CommShift M := sorry
+  exact f.map' Φ W.Q W'.Q (Φ.localizedFunctor W.Q W'.Q)
+    (CatCommSq.iso _ _ _ _)
+
+-- TODO: show that `comp'` and `map'` do not depend on `L`, `L'`, etc.
+
+end
+
+end
+
+end SmallShiftedHom
+
+end Localization
+
+end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
index 7211367069a8f3..f6cf58e5e79dbd 100644
--- a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Shift/ShiftedHom.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.Shift.Basic
+import Mathlib.CategoryTheory.Shift.CommShift
 import Mathlib.CategoryTheory.Preadditive.AdditiveFunctor
 
 /-! Shifted morphisms
@@ -24,8 +24,8 @@ namespace CategoryTheory
 
 open Category
 
-variable {C : Type*} [Category C]
-  {M : Type*} [AddMonoid M] [HasShift C M]
+variable {C : Type*} [Category C] {D : Type*} [Category D] {E : Type*} [Category E]
+  {M : Type*} [AddMonoid M] [HasShift C M] [HasShift D M] [HasShift E M]
 
 /-- In a category `C` equipped with a shift by an additive monoid,
 this is the type of morphisms `X ⟶ (Y⟦n⟧)` for `m : M`.  -/
@@ -121,6 +121,28 @@ lemma zero_comp (a : M) {b c : M} (β : ShiftedHom Y Z b) (h : b + a = c) :
 
 end Preadditive
 
+/-- The action on `ShiftedHom` of a functor which commutes with the shift. -/
+def map {a : M} (f : ShiftedHom X Y a) (F : C ⥤ D) [F.CommShift M] :
+    ShiftedHom (F.obj X) (F.obj Y) a :=
+  F.map f ≫ (F.commShiftIso a).hom.app Y
+
+@[simp]
+lemma id_map {a : M} (f : ShiftedHom X Y a) : f.map (𝟭 C) = f := by
+  simp [map, Functor.commShiftIso, Functor.CommShift.iso]
+
+--lemma comp_map {a : M} (f : ShiftedHom X Y a) (F : C ⥤ D) [F.CommShift M]
+--    (G : D ⥤ E) [G.CommShift M] : f.map (F ⋙ G) = (f.map F).map G := by
+--  sorry
+
+lemma map_comp {a b c : M} (f : ShiftedHom X Y a) (g : ShiftedHom Y Z b)
+    (h : b + a = c) (F : C ⥤ D) [F.CommShift M] :
+    (f.comp g h).map F = (f.map F).comp (g.map F) h := by
+  dsimp [comp, map]
+  simp only [Functor.map_comp, assoc]
+  erw [← NatTrans.naturality_assoc]
+  simp only [Functor.comp_map, F.commShiftIso_add' h, Functor.CommShift.isoAdd'_hom_app,
+    ← Functor.map_comp_assoc, Iso.inv_hom_id_app, Functor.comp_obj, comp_id, assoc]
+
 end ShiftedHom
 
 end CategoryTheory

From bcdfe45eb7c5f18fa92c3779ed0615a7eaffaf20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 18 Jun 2024 15:48:04 +0200
Subject: [PATCH 22/63] wip

---
 .../CategoryTheory/Localization/SmallHom.lean | 91 +++++++++++++++++--
 .../Localization/SmallShiftedHom.lean         |  7 +-
 Mathlib/CategoryTheory/Shift/ShiftedHom.lean  |  6 +-
 3 files changed, 93 insertions(+), 11 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 7a9e42479421df..17adbb6e4f3d91 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.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.Localization.Predicate
+import Mathlib.CategoryTheory.Localization.LocalizerMorphism
 import Mathlib.Logic.Small.Defs
 
 /-!
@@ -20,16 +20,50 @@ with the composition of morphisms.
 
 -/
 
-universe w w' w'' v u u' u''
+universe w w' v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
 
 namespace CategoryTheory
 
-variable {C : Type u} [Category.{v} C] (W : MorphismProperty C)
-  {D : Type u'} [Category.{w'} D] (L : C ⥤ D) [L.IsLocalization W]
-  {D' : Type u''} [Category.{w''} D'] (L' : C ⥤ D') [L'.IsLocalization W] (X Y Z : C)
+variable {C : Type u₁} [Category.{v₁} C] {W : MorphismProperty C}
+  {C' : Type u₂} [Category.{v₂} C'] {W' : MorphismProperty C'}
+  {D : Type u₃} [Category.{v₃} D]
+  {D' : Type u₄} [Category.{v₄} D']
+
+namespace LocalizerMorphism
+
+variable (Φ : LocalizerMorphism W W')
+  (L : C ⥤ D) [L.IsLocalization W]
+  (L' : C' ⥤ D') [L'.IsLocalization W'] {X Y : C}
+
+noncomputable def homMap (f : L.obj X ⟶ L.obj Y) :
+    L'.obj (Φ.functor.obj X) ⟶ L'.obj (Φ.functor.obj Y) :=
+  Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
+    ((Φ.localizedFunctor L L').map f)
+
+lemma homMap_apply (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : L.obj X ⟶ L.obj Y) :
+    Φ.homMap L L' f = e.hom.app X ≫ G.map f ≫ e.inv.app Y := by
+  let G' := Φ.localizedFunctor L L'
+  let e' := CatCommSq.iso Φ.functor L L' G'
+  change e'.hom.app X ≫ G'.map f ≫ e'.inv.app Y = _
+  letI : Localization.Lifting L W (Φ.functor ⋙ L') G := ⟨e.symm⟩
+  let α : G' ≅ G := Localization.liftNatIso L W (L ⋙ G') (Φ.functor ⋙ L') _ _ e'.symm
+  have : e = e' ≪≫ isoWhiskerLeft _ α := by
+    ext X
+    dsimp [α]
+    rw [Localization.liftNatTrans_app]
+    erw [Category.id_comp]
+    rw [Iso.hom_inv_id_app_assoc]
+    rfl
+  simp [this]
+
+end LocalizerMorphism
+
+variable (W)
 
 namespace MorphismProperty
 
+variable (L : C ⥤ D) [L.IsLocalization W] (L' : C ⥤ D') [L'.IsLocalization W] (X Y Z : C)
+
 /-- This property holds if the type of morphisms between `X` and `Y`
 in the localized category with respect to `W : MorphismProperty C`
 is small. -/
@@ -46,6 +80,16 @@ noncomputable def localizationsHomEquiv :
     (Iso.homEquiv ((Localization.compUniqFunctor L L' W).app X)
       ((Localization.compUniqFunctor L L' W).app Y))
 
+lemma localizationsHomEquiv_eq_homMap (f : L.obj X ⟶ L.obj Y) :
+    localizationsHomEquiv W L L' f = (LocalizerMorphism.id W).homMap L L' f :=
+  ((LocalizerMorphism.id W).homMap_apply L L' (Localization.uniq L L' W).functor
+    (Localization.compUniqFunctor L L' W).symm f).symm
+
+lemma localizationsHomEquiv_eq (G : D ⥤ D') (e : L ⋙ G ≅ L') (f : L.obj X ⟶ L.obj Y) :
+    localizationsHomEquiv W L L' f = e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
+  rw [localizationsHomEquiv_eq_homMap]
+  exact (LocalizerMorphism.id W).homMap_apply L L' G e.symm f
+
 @[simp]
 lemma localizationsHomEquiv_map (f : X ⟶ Y) :
     localizationsHomEquiv W L L' (L.map f) = L'.map f := by
@@ -63,7 +107,7 @@ lemma localizationsHomEquiv_id :
 lemma localizationHomEquiv_refl :
     localizationsHomEquiv W L L (X := X) (Y := Y) = Equiv.refl _ := by
   ext f
-  simp [localizationsHomEquiv, Localization.compUniqFunctor_eq L L W (𝟭 _) L.rightUnitor]
+  simpa using localizationsHomEquiv_eq W L L (𝟭 _) (Iso.refl _) f
 
 lemma localizationHomEquiv_comp (f : L.obj X ⟶ L.obj Y) (g : L.obj Y ⟶ L.obj Z) :
     localizationsHomEquiv W L L' (f ≫ g) =
@@ -88,7 +132,7 @@ lemma hasSmallLocalizedHom_iff :
     exact ⟨small_map (localizationsHomEquiv W W.Q L)⟩
 
 lemma hasSmallLocalizedHom_of_isLocalization :
-    HasSmallLocalizedHom.{w'} W X Y := by
+    HasSmallLocalizedHom.{v₃} W X Y := by
   rw [W.hasSmallLocalizedHom_iff L]
   infer_instance
 
@@ -106,6 +150,9 @@ end MorphismProperty
 
 namespace Localization
 
+variable (Φ : LocalizerMorphism W W') (L : C ⥤ D) [L.IsLocalization W]
+  (L' : C' ⥤ D') [L'.IsLocalization W'] (X Y Z : C)
+
 open MorphismProperty
 
 /-- The type of morphisms from `X` to `Y` in the localized category
@@ -195,6 +242,36 @@ lemma mkInv_comp_mk (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X X] :
 
 end
 
+variable {W}
+
+section
+
+variable [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
+
+/-- The action of a localizer morphism on `SmallHom`. -/
+noncomputable def map (f : SmallHom.{w} W X Y) :
+    SmallHom.{w'} W' (Φ.functor.obj X) (Φ.functor.obj Y) :=
+  (equiv W' W'.Q).symm
+    (Iso.homEquiv ((CatCommSq.iso Φ.functor W.Q W'.Q _).symm.app _)
+      ((CatCommSq.iso Φ.functor W.Q W'.Q _).symm.app _)
+      ((Φ.localizedFunctor W.Q W'.Q).map ((equiv W W.Q) f)))
+
+lemma equiv_map (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : SmallHom.{w} W X Y) :
+    (equiv W' L') (f.map Φ) = e.hom.app X ≫ G.map (equiv W L f) ≫ e.inv.app Y := by
+  sorry
+
+end
+
+variable [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
+  [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
+  [W'.HasSmallLocalizedHom (Φ.functor.obj Y) (Φ.functor.obj Z)]
+  [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Z)]
+
+lemma map_comp (f : SmallHom.{w} W X Y) (g : SmallHom.{w} W Y Z) :
+    (f.comp g).map Φ = (f.map Φ).comp (g.map Φ) := by
+  apply (equiv W' W'.Q).injective
+  simp [equiv_map Φ W.Q W'.Q (Φ.localizedFunctor W.Q W'.Q) (CatCommSq.iso _ _ _ _), equiv_comp]
+
 end SmallHom
 
 end Localization
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index ed9837b885c33a..13d8fa3439fdc5 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -24,7 +24,12 @@ variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
 
 variable (M) in
 abbrev HasSmallLocalizedShiftedHom : Prop :=
-  ∀ (m : M), MorphismProperty.HasSmallLocalizedHom.{w} W X (Y⟦m⟧)
+  ∀ (a b : M), MorphismProperty.HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧)
+
+instance [HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) :
+    MorphismProperty.HasSmallLocalizedHom.{w} W X (Y⟦m⟧) :=
+  (MorphismProperty.hasSmallLocalizedHom_iff_of_isos W
+    ((shiftFunctorZero C M).app X) (Iso.refl (Y⟦m⟧))).1 inferInstance
 
 def SmallShiftedHom [HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) : Type w :=
   SmallHom W X (Y⟦m⟧)
diff --git a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
index f6cf58e5e79dbd..072953d2897270 100644
--- a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
@@ -130,9 +130,9 @@ def map {a : M} (f : ShiftedHom X Y a) (F : C ⥤ D) [F.CommShift M] :
 lemma id_map {a : M} (f : ShiftedHom X Y a) : f.map (𝟭 C) = f := by
   simp [map, Functor.commShiftIso, Functor.CommShift.iso]
 
---lemma comp_map {a : M} (f : ShiftedHom X Y a) (F : C ⥤ D) [F.CommShift M]
---    (G : D ⥤ E) [G.CommShift M] : f.map (F ⋙ G) = (f.map F).map G := by
---  sorry
+lemma comp_map {a : M} (f : ShiftedHom X Y a) (F : C ⥤ D) [F.CommShift M]
+    (G : D ⥤ E) [G.CommShift M] : f.map (F ⋙ G) = (f.map F).map G := by
+  simp [map, Functor.commShiftIso_comp_hom_app]
 
 lemma map_comp {a b c : M} (f : ShiftedHom X Y a) (g : ShiftedHom Y Z b)
     (h : b + a = c) (F : C ⥤ D) [F.CommShift M] :

From 95c8bdf3a195ce2a1aafa6b8b9bc25debe2944a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 18 Jun 2024 17:43:43 +0200
Subject: [PATCH 23/63] removed a sorry

---
 .../CategoryTheory/Localization/SmallHom.lean | 66 ++++++++++++++++---
 1 file changed, 57 insertions(+), 9 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 17adbb6e4f3d91..3adc4e1f2541ac 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -35,6 +35,10 @@ variable (Φ : LocalizerMorphism W W')
   (L : C ⥤ D) [L.IsLocalization W]
   (L' : C' ⥤ D') [L'.IsLocalization W'] {X Y : C}
 
+/-- If `Φ : LocalizerMorphism W W'` is a morphism of localizer, `L` and `L'`
+are localization functors for `W` and `W'`, then this is the induced map
+`(L.obj X ⟶ L.obj Y) → (L'.obj (Φ.functor.obj X) ⟶ L'.obj (Φ.functor.obj Y))`
+for all objects `X` and `Y`. -/
 noncomputable def homMap (f : L.obj X ⟶ L.obj Y) :
     L'.obj (Φ.functor.obj X) ⟶ L'.obj (Φ.functor.obj Y) :=
   Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
@@ -151,30 +155,35 @@ end MorphismProperty
 namespace Localization
 
 variable (Φ : LocalizerMorphism W W') (L : C ⥤ D) [L.IsLocalization W]
-  (L' : C' ⥤ D') [L'.IsLocalization W'] (X Y Z : C)
 
 open MorphismProperty
 
 /-- The type of morphisms from `X` to `Y` in the localized category
 with respect to `W : MorphismProperty C` that is shrunk to `Type w`
 when `HasSmallLocalizedHom.{w} W X Y` holds. -/
-def SmallHom [HasSmallLocalizedHom.{w} W X Y] : Type w :=
+def SmallHom (X Y : C) [HasSmallLocalizedHom.{w} W X Y] : Type w :=
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   Shrink.{w} (W.Q.obj X ⟶ W.Q.obj Y)
 
 namespace SmallHom
 
-variable {X Y Z}
-
 /-- The canonical bijection `SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y)`
 when `L` is a localization functor for `W : MorphismProperty C` and
 that `HasSmallLocalizedHom.{w} W X Y` holds. -/
-noncomputable def equiv [HasSmallLocalizedHom.{w} W X Y] :
+noncomputable def equiv {X Y : C} [HasSmallLocalizedHom.{w} W X Y] :
     SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y) :=
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   (equivShrink _).symm.trans (W.localizationsHomEquiv W.Q L)
 
-variable [HasSmallLocalizedHom.{w} W X Y]
+lemma equiv_equiv_symm (L' : C ⥤ D') [L'.IsLocalization W] (G : D ⥤ D')
+    (e : L ⋙ G ≅ L') {X Y : C} (f : L.obj X ⟶ L.obj Y)
+    [HasSmallLocalizedHom.{w} W X Y] : equiv W L' ((equiv W L).symm f) =
+      e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
+  sorry
+
+section
+
+variable {X Y Z : C} [HasSmallLocalizedHom.{w} W X Y]
 
 /-- The element in `SmallHom W X Y` induced by `f : X ⟶ Y`. -/
 noncomputable def mk (f : X ⟶ Y) : SmallHom.{w} W X Y :=
@@ -242,11 +251,17 @@ lemma mkInv_comp_mk (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X X] :
 
 end
 
+end
+
 variable {W}
 
 section
 
-variable [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
+variable (L' : C' ⥤ D') [L'.IsLocalization W']
+variable {X Y Z : C}
+
+variable [W.HasSmallLocalizedHom X Y]
+  [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
 
 /-- The action of a localizer morphism on `SmallHom`. -/
 noncomputable def map (f : SmallHom.{w} W X Y) :
@@ -258,11 +273,44 @@ noncomputable def map (f : SmallHom.{w} W X Y) :
 
 lemma equiv_map (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : SmallHom.{w} W X Y) :
     (equiv W' L') (f.map Φ) = e.hom.app X ≫ G.map (equiv W L f) ≫ e.inv.app Y := by
-  sorry
+  obtain ⟨g, rfl⟩ := (equiv W W.Q).symm.surjective f
+  simp only [map, Equiv.apply_symm_apply]
+  let G' := Φ.localizedFunctor W.Q W'.Q
+  let β := CatCommSq.iso Φ.functor W.Q W'.Q G'
+  let E := (uniq W.Q L W).functor
+  let α : W.Q ⋙ E ≅ L := compUniqFunctor W.Q L W
+  let E' := (uniq W'.Q L' W').functor
+  let α' : W'.Q ⋙ E' ≅ L' := compUniqFunctor W'.Q L' W'
+  rw [equiv_equiv_symm W W.Q L E α, equiv_equiv_symm W' W'.Q L' E' α']
+  change α'.inv.app _ ≫ E'.map (β.hom.app X ≫ G'.map g ≫ β.inv.app Y) ≫ _ = _
+  let γ : G' ⋙ E' ≅ E ⋙ G := liftNatIso W.Q W (W.Q ⋙ G' ⋙ E') (W.Q ⋙ E ⋙ G) _ _
+    ((Functor.associator _ _ _).symm ≪≫ isoWhiskerRight β.symm E' ≪≫
+      Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ α' ≪≫ e ≪≫
+      isoWhiskerRight α.symm G ≪≫ Functor.associator _ _ _)
+  have hγ : ∀ (X : C), γ.hom.app (W.Q.obj X) =
+      E'.map (β.inv.app X) ≫ α'.hom.app (Φ.functor.obj X) ≫
+        e.hom.app X ≫ G.map (α.inv.app X) := fun X ↦ by
+    dsimp [γ]
+    rw [liftNatTrans_app]
+    dsimp
+    rw [Category.id_comp, Category.id_comp, Category.comp_id]
+    erw [Category.id_comp, Category.comp_id]
+  simp only [Functor.map_comp, Category.assoc]
+  erw [← NatIso.naturality_1 γ]
+  simp only [Functor.comp_map, ← cancel_epi (e.inv.app X), ← cancel_epi (G.map (α.hom.app X)),
+    ← cancel_epi (γ.hom.app (W.Q.obj X)), Category.assoc, Iso.inv_hom_id_app_assoc,
+    ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.map_id, Category.id_comp,
+    Iso.hom_inv_id_app_assoc]
+  simp only [hγ, Category.assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app,
+    Functor.map_id, Category.id_comp, Iso.hom_inv_id_app_assoc,
+    Iso.inv_hom_id_app_assoc, Iso.hom_inv_id_app, Functor.comp_obj, Category.comp_id]
 
 end
 
-variable [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
+variable {X Y Z : C}
+
+variable [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Z]
+  [HasSmallLocalizedHom.{w} W X Z]
   [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
   [W'.HasSmallLocalizedHom (Φ.functor.obj Y) (Φ.functor.obj Z)]
   [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Z)]

From 586efe3aae4fabac3a9776cdcf9f09373f3c128d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 18 Jun 2024 21:06:02 +0200
Subject: [PATCH 24/63] removed sorries

---
 .../CategoryTheory/Localization/SmallHom.lean | 56 +++++++++++++++----
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 3adc4e1f2541ac..890b8550b1d28f 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -20,14 +20,17 @@ with the composition of morphisms.
 
 -/
 
-universe w w' v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
+universe w w' v₁ v₂ v₃ v₄ v₅ u₁ u₂ u₃ u₄ u₅
 
 namespace CategoryTheory
 
+open Category
+
 variable {C : Type u₁} [Category.{v₁} C] {W : MorphismProperty C}
   {C' : Type u₂} [Category.{v₂} C'] {W' : MorphismProperty C'}
   {D : Type u₃} [Category.{v₃} D]
   {D' : Type u₄} [Category.{v₄} D']
+  {D'' : Type u₅} [Category.{v₅} D'']
 
 namespace LocalizerMorphism
 
@@ -55,7 +58,7 @@ lemma homMap_apply (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : L.obj
     ext X
     dsimp [α]
     rw [Localization.liftNatTrans_app]
-    erw [Category.id_comp]
+    erw [id_comp]
     rw [Iso.hom_inv_id_app_assoc]
     rfl
   simp [this]
@@ -66,7 +69,8 @@ variable (W)
 
 namespace MorphismProperty
 
-variable (L : C ⥤ D) [L.IsLocalization W] (L' : C ⥤ D') [L'.IsLocalization W] (X Y Z : C)
+variable (L : C ⥤ D) [L.IsLocalization W] (L' : C ⥤ D') [L'.IsLocalization W]
+  (L'' : C ⥤ D'') [L''.IsLocalization W] (X Y Z : C)
 
 /-- This property holds if the type of morphisms between `X` and `Y`
 in the localized category with respect to `W : MorphismProperty C`
@@ -113,6 +117,32 @@ lemma localizationHomEquiv_refl :
   ext f
   simpa using localizationsHomEquiv_eq W L L (𝟭 _) (Iso.refl _) f
 
+lemma localizationHomEquiv_symm (f : L.obj X ⟶ L.obj Y) :
+    (localizationsHomEquiv W L' L).symm f = localizationsHomEquiv W L L' f := by
+  apply (W.localizationsHomEquiv L' L).injective
+  let E := Localization.uniq L L' W
+  let α : L ⋙ E.functor ≅ L' := (Localization.compUniqFunctor L L' W)
+  rw [Equiv.apply_symm_apply, localizationsHomEquiv_eq W L L' E.functor α f,
+    localizationsHomEquiv_eq W L' L E.inverse
+      (isoWhiskerRight α.symm E.inverse ≪≫ Functor.associator _ _ _ ≪≫
+        isoWhiskerLeft L E.unitIso.symm ≪≫ L.rightUnitor)]
+  dsimp
+  simp only [assoc, id_comp, comp_id, Functor.map_comp, Equivalence.inv_fun_map]
+  simp only [← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.comp_obj, Functor.map_id,
+    id_comp, Iso.hom_inv_id_app_assoc, Functor.id_obj, comp_id]
+
+lemma localizationHomEquiv_trans (f : L.obj X ⟶ L.obj Y) :
+    (localizationsHomEquiv W L' L'') (localizationsHomEquiv W L L' f) =
+      localizationsHomEquiv W L L'' f := by
+  let E := Localization.uniq L L' W
+  let α : L ⋙ E.functor ≅ L' := (Localization.compUniqFunctor L L' W)
+  let E' := Localization.uniq L' L'' W
+  let α' : L' ⋙ E'.functor ≅ L'' := (Localization.compUniqFunctor L' L'' W)
+  simp [localizationsHomEquiv_eq W L L' E.functor α,
+    localizationsHomEquiv_eq W L' L'' E'.functor α',
+    localizationsHomEquiv_eq W L L'' (E.functor ⋙ E'.functor)
+      ((Functor.associator _ _ _).symm ≪≫ isoWhiskerRight α E'.functor ≪≫ α')]
+
 lemma localizationHomEquiv_comp (f : L.obj X ⟶ L.obj Y) (g : L.obj Y ⟶ L.obj Z) :
     localizationsHomEquiv W L L' (f ≫ g) =
       localizationsHomEquiv W L L' f ≫ localizationsHomEquiv W L L' g := by
@@ -179,7 +209,9 @@ lemma equiv_equiv_symm (L' : C ⥤ D') [L'.IsLocalization W] (G : D ⥤ D')
     (e : L ⋙ G ≅ L') {X Y : C} (f : L.obj X ⟶ L.obj Y)
     [HasSmallLocalizedHom.{w} W X Y] : equiv W L' ((equiv W L).symm f) =
       e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
-  sorry
+  dsimp [equiv]
+  rw [Equiv.symm_apply_apply, localizationHomEquiv_symm, localizationHomEquiv_trans]
+  apply localizationsHomEquiv_eq
 
 section
 
@@ -293,17 +325,17 @@ lemma equiv_map (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : SmallHom
     dsimp [γ]
     rw [liftNatTrans_app]
     dsimp
-    rw [Category.id_comp, Category.id_comp, Category.comp_id]
-    erw [Category.id_comp, Category.comp_id]
-  simp only [Functor.map_comp, Category.assoc]
+    rw [id_comp, id_comp, comp_id]
+    erw [id_comp, comp_id]
+  simp only [Functor.map_comp, assoc]
   erw [← NatIso.naturality_1 γ]
   simp only [Functor.comp_map, ← cancel_epi (e.inv.app X), ← cancel_epi (G.map (α.hom.app X)),
-    ← cancel_epi (γ.hom.app (W.Q.obj X)), Category.assoc, Iso.inv_hom_id_app_assoc,
-    ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.map_id, Category.id_comp,
+    ← cancel_epi (γ.hom.app (W.Q.obj X)), assoc, Iso.inv_hom_id_app_assoc,
+    ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.map_id, id_comp,
     Iso.hom_inv_id_app_assoc]
-  simp only [hγ, Category.assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app,
-    Functor.map_id, Category.id_comp, Iso.hom_inv_id_app_assoc,
-    Iso.inv_hom_id_app_assoc, Iso.hom_inv_id_app, Functor.comp_obj, Category.comp_id]
+  simp only [hγ, assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app,
+    Functor.map_id, id_comp, Iso.hom_inv_id_app_assoc,
+    Iso.inv_hom_id_app_assoc, Iso.hom_inv_id_app, Functor.comp_obj, comp_id]
 
 end
 

From e89f5b5db33b8ad2732295f4f853dc1c55151a05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 11:28:55 +0200
Subject: [PATCH 25/63] fixed sorries

---
 .../CategoryTheory/Localization/SmallHom.lean |  22 +-
 .../Localization/SmallShiftedHom.lean         | 188 ++++++++++++------
 2 files changed, 150 insertions(+), 60 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 890b8550b1d28f..a0270fa9fb4765 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -215,7 +215,7 @@ lemma equiv_equiv_symm (L' : C ⥤ D') [L'.IsLocalization W] (G : D ⥤ D')
 
 section
 
-variable {X Y Z : C} [HasSmallLocalizedHom.{w} W X Y]
+variable {X Y Z T : C} [HasSmallLocalizedHom.{w} W X Y]
 
 /-- The element in `SmallHom W X Y` induced by `f : X ⟶ Y`. -/
 noncomputable def mk (f : X ⟶ Y) : SmallHom.{w} W X Y :=
@@ -265,6 +265,26 @@ lemma mk_comp_mk (f : X ⟶ Y) (g : Y ⟶ Z) :
     (mk W f).comp (mk W g) = mk W (f ≫ g) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
+@[simp]
+lemma comp_mk_id (α : SmallHom.{w} W X Y) [HasSmallLocalizedHom.{w} W Y Y] :
+    α.comp (mk W (𝟙 Y)) = α :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
+
+@[simp]
+lemma mk_id_comp (α : SmallHom.{w} W X Y) [HasSmallLocalizedHom.{w} W X X] :
+    (mk W (𝟙 X)).comp α = α :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
+
+variable [HasSmallLocalizedHom.{w} W Z T] [HasSmallLocalizedHom.{w} W X T]
+  [HasSmallLocalizedHom.{w} W Y T]
+
+@[simp]
+lemma comp_assoc (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z)
+    (γ : SmallHom.{w} W Z T) :
+    (α.comp β).comp γ = α.comp (β.comp γ) := by
+  apply (equiv W W.Q).injective
+  simp only [equiv_comp, assoc]
+
 end
 
 section
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 13d8fa3439fdc5..433d6e9ae75f94 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -12,99 +12,169 @@ universe w w' v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
 
 namespace CategoryTheory
 
-namespace Localization
+open Category
 
 variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
   {C' : Type u₂} [Category.{v₂} C'] (W' : MorphismProperty C')
   {D : Type u₃} [Category.{v₃} D]
   {D' : Type u₄} [Category.{v₄} D']
-  {M : Type w'} [AddMonoid M] [HasShift C M] [HasShift C' M]
-  [W.IsCompatibleWithShift M]
-  [W'.IsCompatibleWithShift M] (X Y Z : C)
+  {M : Type w'} [AddMonoid M] [HasShift C M] [HasShift C' M] [HasShift D M]
+  [W.IsCompatibleWithShift M] [W'.IsCompatibleWithShift M]
+
+namespace MorphismProperty
+
+variable (X Y : C)
 
 variable (M) in
 abbrev HasSmallLocalizedShiftedHom : Prop :=
-  ∀ (a b : M), MorphismProperty.HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧)
+  ∀ (a b : M), HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧)
 
-instance [HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) :
-    MorphismProperty.HasSmallLocalizedHom.{w} W X (Y⟦m⟧) :=
-  (MorphismProperty.hasSmallLocalizedHom_iff_of_isos W
-    ((shiftFunctorZero C M).app X) (Iso.refl (Y⟦m⟧))).1 inferInstance
+variable [HasSmallLocalizedShiftedHom.{w} W M X Y]
 
-def SmallShiftedHom [HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) : Type w :=
-  SmallHom W X (Y⟦m⟧)
+variable (M) in
+lemma hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ :
+    HasSmallLocalizedHom.{w} W X Y :=
+  (hasSmallLocalizedHom_iff_of_isos W
+    ((shiftFunctorZero C M).app X) ((shiftFunctorZero C M).app Y)).1 inferInstance
+
+instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₁ (m : M) :
+    HasSmallLocalizedHom.{w} W X (Y⟦m⟧) :=
+  (hasSmallLocalizedHom_iff_of_isos W
+    ((shiftFunctorZero C M).app X) (Iso.refl (Y⟦m⟧))).1 inferInstance
 
-namespace SmallShiftedHom
+instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₂ (m m' n : M) :
+    HasSmallLocalizedHom.{w} W (X⟦m⟧⟦m'⟧) (Y⟦n⟧) :=
+  (hasSmallLocalizedHom_iff_of_isos W
+    ((shiftFunctorAdd C m m').app X) (Iso.refl (Y⟦n⟧))).1 inferInstance
 
-variable {X Y Z}
-section
+instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₃ (m n n' : M) :
+    HasSmallLocalizedHom.{w} W (X⟦m⟧) (Y⟦n⟧⟦n'⟧) :=
+  (hasSmallLocalizedHom_iff_of_isos W
+    (Iso.refl (X⟦m⟧)) ((shiftFunctorAdd C n n').app Y)).1 inferInstance
 
-variable [HasSmallLocalizedShiftedHom.{w} W M X Y]
+instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₄ (m : M) :
+    HasSmallLocalizedHom.{w} W (X⟦m⟧) Y :=
+  (hasSmallLocalizedHom_iff_of_isos W
+    (Iso.refl (X⟦m⟧)) ((shiftFunctorZero C M).app Y)).1 inferInstance
 
-section
+end MorphismProperty
 
-variable (L : C ⥤ D) [L.IsLocalization W] [HasShift D M] [L.CommShift M]
+namespace Localization
 
-noncomputable def equiv {m : M} :
-    SmallShiftedHom.{w} W X Y m ≃ ShiftedHom (L.obj X) (L.obj Y) m :=
-  (SmallHom.equiv W L).trans ((L.commShiftIso m).app Y).homToEquiv
+namespace SmallHom
 
-variable [HasSmallLocalizedShiftedHom.{w} W M Y Z]
-  [HasSmallLocalizedShiftedHom.{w} W M X Z]
+variable {W}
+variable (L : C ⥤ D) [L.IsLocalization W] [L.CommShift M]
+variable {X Y : C} [MorphismProperty.HasSmallLocalizedHom.{w} W X Y]
+    (f : SmallHom.{w} W X Y) (a : M) [MorphismProperty.HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦a⟧)]
 
-variable {a b c : M} (f : SmallShiftedHom.{w} W X Y a)
-  (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c)
+noncomputable def shift : SmallHom.{w} W (X⟦a⟧) (Y⟦a⟧) :=
+  f.map (LocalizerMorphism.mk (shiftFunctor C a)
+    (by rw [MorphismProperty.IsCompatibleWithShift.condition]))
 
-noncomputable def comp' : SmallShiftedHom.{w} W X Z c :=
-  (equiv W L).symm ((equiv W L f).comp (equiv W L g) h)
+lemma equiv_shift : equiv W L (f.shift a) =
+    (L.commShiftIso a).hom.app X ≫ (equiv W L f)⟦a⟧' ≫ (L.commShiftIso a).inv.app Y :=
+  equiv_map (LocalizerMorphism.mk (shiftFunctor C a) _) _ _ _ (L.commShiftIso a) f
 
+end SmallHom
 
-end
+def SmallShiftedHom (X Y : C)
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) : Type w :=
+  SmallHom W X (Y⟦m⟧)
 
-variable [HasSmallLocalizedShiftedHom.{w} W M Y Z]
-  [HasSmallLocalizedShiftedHom.{w} W M X Z]
+namespace SmallShiftedHom
 
-variable {a b c : M} (f : SmallShiftedHom.{w} W X Y a)
-  (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c)
+section
 
-noncomputable def comp : SmallShiftedHom.{w} W X Z c :=
-  comp' W W.Q f g h
+variable {W}
+variable {X Y Z : C}
+
+noncomputable def shift {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y]
+  (f : SmallShiftedHom.{w} W X Y a) (n a' : M) (h : a + n = a') :
+    SmallHom.{w} W (X⟦n⟧) (Y⟦a'⟧) :=
+  (SmallHom.shift f n).comp (SmallHom.mk W ((shiftFunctorAdd' C a n a' h).inv.app Y))
+
+noncomputable def comp {a b c : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z Z]
+    (f : SmallShiftedHom.{w} W X Y a) (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c) :
+    SmallShiftedHom.{w} W X Z c :=
+  SmallHom.comp f (g.shift a c h)
+
+noncomputable def equiv₀ [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y] :
+    SmallShiftedHom.{w} W X Y (0 : M) ≃
+      letI := W.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ M X Y; SmallHom.{w} W X Y :=
+  letI := W.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ M X Y
+  letI := W.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ M Y Y
+  { toFun := fun f ↦ SmallHom.comp f (SmallHom.mk W ((shiftFunctorZero C M).hom.app Y))
+    invFun := fun g ↦ SmallHom.comp g (SmallHom.mk W ((shiftFunctorZero C M).inv.app Y))
+    left_inv := fun f ↦ by simp [SmallHom.mk_comp_mk]
+    right_inv := fun g ↦ by simp [SmallHom.mk_comp_mk] }
 
 end
 
 section
 
-variable {W W'}
+variable (L : C ⥤ D) [L.IsLocalization W] [HasShift D M] [L.CommShift M]
+  {X Y Z T : C}
 
-section
+noncomputable def equiv [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y] {m : M} :
+    SmallShiftedHom.{w} W X Y m ≃ ShiftedHom (L.obj X) (L.obj Y) m :=
+  (SmallHom.equiv W L).trans ((L.commShiftIso m).app Y).homToEquiv
 
-noncomputable def map' [HasSmallLocalizedShiftedHom.{w} W M X Y]
-    {a : M} (f : SmallShiftedHom.{w} W X Y a)
-    (Φ : LocalizerMorphism W W')
-    [HasSmallLocalizedShiftedHom.{w} W' M (Φ.functor.obj X) (Φ.functor.obj Y)]
-    (L : C ⥤ D) [L.IsLocalization W] [HasShift D M] [L.CommShift M]
-    (L' : C' ⥤ D') [L'.IsLocalization W'] [HasShift D' M] [L'.CommShift M]
-    (G : D ⥤ D') [G.CommShift M] (e : Φ.functor ⋙ L' ≅ L ⋙ G) :
-    SmallShiftedHom.{w} W' (Φ.functor.obj X) (Φ.functor.obj Y) a :=
-  (equiv W' L').symm
-    ((ShiftedHom.mk₀ (0 : M) rfl (e.hom.app X)).comp
-      (((equiv W L f).map G).comp
-      (ShiftedHom.mk₀ (0 : M) rfl (e.inv.app Y)) (zero_add a)) (add_zero a))
-
-noncomputable def map [HasSmallLocalizedShiftedHom.{w} W M X Y]
-    {a : M} (f : SmallShiftedHom.{w} W X Y a)
-    (Φ : LocalizerMorphism W W')
-    [HasSmallLocalizedShiftedHom.{w} W' M (Φ.functor.obj X) (Φ.functor.obj Y)] :
-    SmallShiftedHom.{w} W' (Φ.functor.obj X) (Φ.functor.obj Y) a := by
-  have : (Φ.localizedFunctor W.Q W'.Q).CommShift M := sorry
-  exact f.map' Φ W.Q W'.Q (Φ.localizedFunctor W.Q W'.Q)
-    (CatCommSq.iso _ _ _ _)
-
--- TODO: show that `comp'` and `map'` do not depend on `L`, `L'`, etc.
+lemma equiv_shift' {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y]
+    (f : SmallShiftedHom.{w} W X Y a) (n a' : M) (h : a + n = a') :
+    SmallHom.equiv W L (f.shift n a' h) = (L.commShiftIso n).hom.app X ≫
+        (SmallHom.equiv W L f)⟦n⟧' ≫ ((L.commShiftIso a).hom.app Y)⟦n⟧' ≫
+        (shiftFunctorAdd' D a n a' h).inv.app (L.obj Y) ≫ (L.commShiftIso a').inv.app Y := by
+  simp only [shift, SmallHom.equiv_comp, SmallHom.equiv_shift, SmallHom.equiv_mk, assoc,
+    L.commShiftIso_add' h, Functor.CommShift.isoAdd'_inv_app, Iso.inv_hom_id_app_assoc,
+    ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.comp_obj, comp_id]
+
+lemma equiv_shift {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y]
+    (f : SmallShiftedHom.{w} W X Y a) (n a' : M) (h : a + n = a') :
+    equiv W L (f.shift n a' h) = (L.commShiftIso n).hom.app X ≫ (equiv W L f)⟦n⟧' ≫
+      (shiftFunctorAdd' D a n a' h).inv.app (L.obj Y) := by
+  dsimp [equiv]
+  erw [Iso.homToEquiv_apply, Iso.homToEquiv_apply, equiv_shift']
+  simp only [Functor.comp_obj, Iso.app_hom, assoc, Iso.inv_hom_id_app, comp_id, Functor.map_comp]
+  rfl
+
+lemma equiv_comp [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z Z] {a b c : M}
+    (f : SmallShiftedHom.{w} W X Y a) (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c) :
+    equiv W L (f.comp g h) = (equiv W L f).comp (equiv W L g) h := by
+  dsimp [comp, equiv, ShiftedHom.comp]
+  erw [Iso.homToEquiv_apply, Iso.homToEquiv_apply, Iso.homToEquiv_apply, SmallHom.equiv_comp]
+  simp only [equiv_shift', Functor.comp_obj, Iso.app_hom, assoc, Iso.inv_hom_id_app,
+    comp_id, Functor.map_comp]
+  rfl
 
 end
 
-end
+lemma comp_assoc {X Y Z T : C} {a₁ a₂ a₃ a₁₂ a₂₃ a : M}
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X T]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y T]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z T]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z Z]
+    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M T T]
+    (α : SmallShiftedHom.{w} W X Y a₁)
+    (β : SmallShiftedHom.{w} W Y Z a₂) (γ : SmallShiftedHom.{w} W Z T a₃)
+    (h₁₂ : a₂ + a₁ = a₁₂) (h₂₃ : a₃ + a₂ = a₂₃) (h : a₃ + a₂ + a₁ = a) :
+    (α.comp β h₁₂).comp γ (show a₃ + a₁₂ = a by rw [← h₁₂, ← add_assoc, h]) =
+      α.comp (β.comp γ h₂₃) (by rw [← h₂₃, h]) := by
+  apply (equiv W W.Q).injective
+  simp only [equiv_comp, ShiftedHom.comp_assoc _ _ _ h₁₂ h₂₃ h]
 
 end SmallShiftedHom
 

From 7ee3dfb98ea37eb2dea791a3fa9a49d73025142a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Wed, 19 Jun 2024 13:16:42 +0200
Subject: [PATCH 26/63] Update
 Mathlib/CategoryTheory/Localization/SmallHom.lean

Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com>
---
 Mathlib/CategoryTheory/Localization/SmallHom.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 7a9e42479421df..399027a19a5e17 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -190,7 +190,7 @@ lemma mk_comp_mkInv (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W Y Y] :
 
 @[simp]
 lemma mkInv_comp_mk (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X X] :
-    (mkInv f hf).comp (mk W f)= mk W (𝟙 X) :=
+    (mkInv f hf).comp (mk W f) = mk W (𝟙 X) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
 end

From 9c91e8d8407879cb37f1970f10c5ca2b4cc543d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 15:14:20 +0200
Subject: [PATCH 27/63] wip

---
 Mathlib.lean                                  |   1 +
 .../CategoryTheory/Localization/HomEquiv.lean | 167 +++++++++
 .../CategoryTheory/Localization/SmallHom.lean | 350 ++++++------------
 .../Localization/SmallShiftedHom.lean         |  12 +-
 4 files changed, 296 insertions(+), 234 deletions(-)
 create mode 100644 Mathlib/CategoryTheory/Localization/HomEquiv.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index 71d9e7489a9705..fd0564987964b5 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -1495,6 +1495,7 @@ import Mathlib.CategoryTheory.Localization.DerivabilityStructure.Basic
 import Mathlib.CategoryTheory.Localization.Equivalence
 import Mathlib.CategoryTheory.Localization.FiniteProducts
 import Mathlib.CategoryTheory.Localization.HasLocalization
+import Mathlib.CategoryTheory.Localization.HomEquiv
 import Mathlib.CategoryTheory.Localization.LocalizerMorphism
 import Mathlib.CategoryTheory.Localization.Opposite
 import Mathlib.CategoryTheory.Localization.Pi
diff --git a/Mathlib/CategoryTheory/Localization/HomEquiv.lean b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
new file mode 100644
index 00000000000000..14ae6ff8233d07
--- /dev/null
+++ b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
@@ -0,0 +1,167 @@
+/-
+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.Localization.LocalizerMorphism
+
+/-!
+# Bijections between morphisms in two localized categories
+
+Given two localization functors `L₁ : C ⥤ D₁` and `L₂ : C ⥤ D₂` for the same
+class of morphisms `W : MorphismProperty C`, we define a bijection
+`Localization.homEquiv W L₁ L₂ : (L₁.obj X ⟶ L₁.obj Y) ≃ (L₂.obj X ⟶ L₂.obj Y)`
+between the types of morphisms in the two localized categories.
+
+More generally, given a localizer morphism `Φ : LocalizerMorphism W₁ W₂`, we define a map
+`Φ.homMap L₁ L₂ : (L₁.obj X ⟶ L₁.obj Y) ⟶ (L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y))`.
+The definition `Localization.homEquiv` is obtained by applying the construction
+to the identity localizer morphism.
+
+-/
+
+namespace CategoryTheory
+
+open Category
+
+variable {C C₁ C₂ C₃ D₁ D₂ D₃ : Type*} [Category C]
+  [Category C₁] [Category C₂] [Category C₃]
+  [Category D₁] [Category D₂] [Category D₃]
+
+namespace LocalizerMorphism
+
+variable {W₁ : MorphismProperty C₁} {W₂ : MorphismProperty C₂} {W₃ : MorphismProperty C₃}
+  (Φ : LocalizerMorphism W₁ W₂) (Ψ : LocalizerMorphism W₂ W₃)
+  (L₁ : C₁ ⥤ D₁) [L₁.IsLocalization W₁]
+  (L₂ : C₂ ⥤ D₂) [L₂.IsLocalization W₂]
+  (L₃ : C₃ ⥤ D₃) [L₃.IsLocalization W₃]
+  {X Y Z : C₁}
+
+/-- If `Φ : LocalizerMorphism W₁ W₂` is a morphism of localizers, `L₁` and `L₂`
+are localization functors for `W₁` and `W₂`, then this is the induced map
+`(L₁.obj X ⟶ L₁.obj Y) ⟶ (L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y))`
+for all objects `X` and `Y`. -/
+noncomputable def homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y) :=
+  Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
+    ((Φ.localizedFunctor L₁ L₂).map f)
+
+@[simp]
+lemma homMap_map (f : X ⟶ Y) :
+    Φ.homMap L₁ L₂ (L₁.map f) = L₂.map (Φ.functor.map f) := by
+  dsimp [homMap]
+  erw [← NatTrans.naturality_assoc]
+  simp
+
+variable (X) in
+@[simp]
+lemma homMap_id  :
+    Φ.homMap L₁ L₂ (𝟙 (L₁.obj X)) = 𝟙 (L₂.obj (Φ.functor.obj X)) := by
+  simpa using Φ.homMap_map L₁ L₂ (𝟙 X)
+
+@[reassoc]
+lemma homMap_comp (f : L₁.obj X ⟶ L₁.obj Y) (g : L₁.obj Y ⟶ L₁.obj Z) :
+    Φ.homMap L₁ L₂ (f ≫ g) = Φ.homMap L₁ L₂ f ≫ Φ.homMap L₁ L₂ g := by
+  simp [homMap]
+
+@[reassoc]
+lemma homMap_apply (G : D₁ ⥤ D₂) (e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G) (f : L₁.obj X ⟶ L₁.obj Y) :
+    Φ.homMap L₁ L₂ f = e.hom.app X ≫ G.map f ≫ e.inv.app Y := by
+  let G' := Φ.localizedFunctor L₁ L₂
+  let e' := CatCommSq.iso Φ.functor L₁ L₂ G'
+  change e'.hom.app X ≫ G'.map f ≫ e'.inv.app Y = _
+  letI : Localization.Lifting L₁ W₁ (Φ.functor ⋙ L₂) G := ⟨e.symm⟩
+  let α : G' ≅ G := Localization.liftNatIso L₁ W₁ (L₁ ⋙ G') (Φ.functor ⋙ L₂) _ _ e'.symm
+  have : e = e' ≪≫ isoWhiskerLeft _ α := by
+    ext X
+    dsimp [α]
+    rw [Localization.liftNatTrans_app]
+    erw [id_comp]
+    rw [Iso.hom_inv_id_app_assoc]
+    rfl
+  simp [this]
+
+@[simp]
+lemma id_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    (id W₁).homMap L₁ L₁ f = f := by
+  simpa using (id W₁).homMap_apply L₁ L₁ (𝟭 D₁) (Iso.refl _) f
+
+@[simp]
+lemma homMap_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    Ψ.homMap L₂ L₃ (Φ.homMap L₁ L₂ f) = (Φ.comp Ψ).homMap L₁ L₃ f := by
+  let G := Φ.localizedFunctor L₁ L₂
+  let G' := Ψ.localizedFunctor L₂ L₃
+  let e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G := CatCommSq.iso _ _ _ _
+  let e' : Ψ.functor ⋙ L₃ ≅ L₂ ⋙ G' := CatCommSq.iso _ _ _ _
+  rw [Φ.homMap_apply L₁ L₂ G e, Ψ.homMap_apply L₂ L₃ G' e',
+    (Φ.comp Ψ).homMap_apply L₁ L₃ (G ⋙ G')
+    (Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ e' ≪≫
+      (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight e _ ≪≫
+      Functor.associator _ _ _)]
+  dsimp
+  simp only [Functor.map_comp, assoc, comp_id, id_comp]
+
+end LocalizerMorphism
+
+namespace Localization
+
+variable (W : MorphismProperty C) (L₁ : C ⥤ D₁) [L₁.IsLocalization W]
+  (L₂ : C ⥤ D₂) [L₂.IsLocalization W] (L₃ : C ⥤ D₃) [L₃.IsLocalization W]
+  {X Y Z : C}
+
+/-- Bijection between types of morphisms in two localized categories
+for the same class of morphisms `W`. -/
+@[simps (config := .lemmasOnly) apply]
+noncomputable def homEquiv :
+    (L₁.obj X ⟶ L₁.obj Y) ≃ (L₂.obj X ⟶ L₂.obj Y) where
+  toFun := (LocalizerMorphism.id W).homMap L₁ L₂
+  invFun := (LocalizerMorphism.id W).homMap L₂ L₁
+  left_inv f := by
+    rw [LocalizerMorphism.homMap_homMap]
+    apply LocalizerMorphism.id_homMap
+  right_inv g := by
+    rw [LocalizerMorphism.homMap_homMap]
+    apply LocalizerMorphism.id_homMap
+
+@[simp]
+lemma homEquiv_symm_apply (g : L₂.obj X ⟶ L₂.obj Y) :
+    (homEquiv W L₁ L₂).symm g = homEquiv W L₂ L₁ g := rfl
+
+lemma homEquiv_eq (G : D₁ ⥤ D₂) (e : L₁ ⋙ G ≅ L₂) (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₁ L₂ f = e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
+  rw [homEquiv_apply, LocalizerMorphism.homMap_apply (LocalizerMorphism.id W) L₁ L₂ G e.symm,
+    Iso.symm_hom, Iso.symm_inv]
+
+@[simp]
+lemma homEquiv_refl (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₁ L₁ f = f := by
+  apply LocalizerMorphism.id_homMap
+
+lemma homEquiv_trans (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₂ L₃ (homEquiv W L₁ L₂ f) = homEquiv W L₁ L₃ f := by
+  dsimp only [homEquiv_apply]
+  apply LocalizerMorphism.homMap_homMap
+
+lemma homEquiv_comp (f : L₁.obj X ⟶ L₁.obj Y) (g : L₁.obj Y ⟶ L₁.obj Z) :
+    homEquiv W L₁ L₂ (f ≫ g) = homEquiv W L₁ L₂ f ≫ homEquiv W L₁ L₂ g := by
+  apply LocalizerMorphism.homMap_comp
+
+@[simp]
+lemma homEquiv_map (f : X ⟶ Y) : homEquiv W L₁ L₂ (L₁.map f) = L₂.map f := by
+  simp [homEquiv_apply]
+
+variable (X) in
+@[simp]
+lemma homEquiv_id : homEquiv W L₁ L₂ (𝟙 (L₁.obj X)) = 𝟙 (L₂.obj X) := by
+  simp [homEquiv_apply]
+
+lemma homEquiv_isoOfHom_inv (f : Y ⟶ X) (hf : W f) :
+    homEquiv W L₁ L₂ (isoOfHom L₁ W f hf).inv = (isoOfHom L₂ W f hf).inv := by
+  rw [← cancel_mono (isoOfHom L₂ W f hf).hom, Iso.inv_hom_id, isoOfHom_hom,
+    ← homEquiv_map W L₁ L₂ f, ← homEquiv_comp, isoOfHom_inv,
+    IsIso.inv_hom_id, homEquiv_id]
+
+end Localization
+
+end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index a0270fa9fb4765..c1dd485238f1e6 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.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.Localization.LocalizerMorphism
+import Mathlib.CategoryTheory.Localization.HomEquiv
 import Mathlib.Logic.Small.Defs
 
 /-!
@@ -26,51 +26,15 @@ namespace CategoryTheory
 
 open Category
 
-variable {C : Type u₁} [Category.{v₁} C] {W : MorphismProperty C}
-  {C' : Type u₂} [Category.{v₂} C'] {W' : MorphismProperty C'}
-  {D : Type u₃} [Category.{v₃} D]
-  {D' : Type u₄} [Category.{v₄} D']
-  {D'' : Type u₅} [Category.{v₅} D'']
-
-namespace LocalizerMorphism
-
-variable (Φ : LocalizerMorphism W W')
-  (L : C ⥤ D) [L.IsLocalization W]
-  (L' : C' ⥤ D') [L'.IsLocalization W'] {X Y : C}
-
-/-- If `Φ : LocalizerMorphism W W'` is a morphism of localizer, `L` and `L'`
-are localization functors for `W` and `W'`, then this is the induced map
-`(L.obj X ⟶ L.obj Y) → (L'.obj (Φ.functor.obj X) ⟶ L'.obj (Φ.functor.obj Y))`
-for all objects `X` and `Y`. -/
-noncomputable def homMap (f : L.obj X ⟶ L.obj Y) :
-    L'.obj (Φ.functor.obj X) ⟶ L'.obj (Φ.functor.obj Y) :=
-  Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
-    ((Φ.localizedFunctor L L').map f)
-
-lemma homMap_apply (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : L.obj X ⟶ L.obj Y) :
-    Φ.homMap L L' f = e.hom.app X ≫ G.map f ≫ e.inv.app Y := by
-  let G' := Φ.localizedFunctor L L'
-  let e' := CatCommSq.iso Φ.functor L L' G'
-  change e'.hom.app X ≫ G'.map f ≫ e'.inv.app Y = _
-  letI : Localization.Lifting L W (Φ.functor ⋙ L') G := ⟨e.symm⟩
-  let α : G' ≅ G := Localization.liftNatIso L W (L ⋙ G') (Φ.functor ⋙ L') _ _ e'.symm
-  have : e = e' ≪≫ isoWhiskerLeft _ α := by
-    ext X
-    dsimp [α]
-    rw [Localization.liftNatTrans_app]
-    erw [id_comp]
-    rw [Iso.hom_inv_id_app_assoc]
-    rfl
-  simp [this]
-
-end LocalizerMorphism
+namespace Localization
 
-variable (W)
+variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
+  {D : Type u₂} [Category.{v₂} D]
+  {D' : Type u₃} [Category.{v₃} D']
 
-namespace MorphismProperty
+section
 
-variable (L : C ⥤ D) [L.IsLocalization W] (L' : C ⥤ D') [L'.IsLocalization W]
-  (L'' : C ⥤ D'') [L''.IsLocalization W] (X Y Z : C)
+variable (L : C ⥤ D) [L.IsLocalization W] (X Y Z : C)
 
 /-- This property holds if the type of morphisms between `X` and `Y`
 in the localized category with respect to `W : MorphismProperty C`
@@ -78,121 +42,40 @@ is small. -/
 class HasSmallLocalizedHom : Prop where
   small : Small.{w} (W.Q.obj X ⟶ W.Q.obj Y)
 
-variable {X Y Z}
-
-/-- Bijection between types of morphisms in two localized categories
-for the same class of morphisms `W`. -/
-noncomputable def localizationsHomEquiv :
-    (L.obj X ⟶ L.obj Y) ≃ (L'.obj X ⟶ L'.obj Y) :=
-  (Localization.uniq L L' W).fullyFaithfulFunctor.homEquiv.trans
-    (Iso.homEquiv ((Localization.compUniqFunctor L L' W).app X)
-      ((Localization.compUniqFunctor L L' W).app Y))
-
-lemma localizationsHomEquiv_eq_homMap (f : L.obj X ⟶ L.obj Y) :
-    localizationsHomEquiv W L L' f = (LocalizerMorphism.id W).homMap L L' f :=
-  ((LocalizerMorphism.id W).homMap_apply L L' (Localization.uniq L L' W).functor
-    (Localization.compUniqFunctor L L' W).symm f).symm
-
-lemma localizationsHomEquiv_eq (G : D ⥤ D') (e : L ⋙ G ≅ L') (f : L.obj X ⟶ L.obj Y) :
-    localizationsHomEquiv W L L' f = e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
-  rw [localizationsHomEquiv_eq_homMap]
-  exact (LocalizerMorphism.id W).homMap_apply L L' G e.symm f
+attribute [instance] HasSmallLocalizedHom.small
 
-@[simp]
-lemma localizationsHomEquiv_map (f : X ⟶ Y) :
-    localizationsHomEquiv W L L' (L.map f) = L'.map f := by
-  dsimp [localizationsHomEquiv]
-  erw [← NatTrans.naturality_assoc]
-  simp
-
-variable (X) in
-@[simp]
-lemma localizationsHomEquiv_id :
-    localizationsHomEquiv W L L' (𝟙 (L.obj X)) = 𝟙 (L'.obj X) := by
-  simpa using localizationsHomEquiv_map W L L' (𝟙 X)
-
-@[simp]
-lemma localizationHomEquiv_refl :
-    localizationsHomEquiv W L L (X := X) (Y := Y) = Equiv.refl _ := by
-  ext f
-  simpa using localizationsHomEquiv_eq W L L (𝟭 _) (Iso.refl _) f
-
-lemma localizationHomEquiv_symm (f : L.obj X ⟶ L.obj Y) :
-    (localizationsHomEquiv W L' L).symm f = localizationsHomEquiv W L L' f := by
-  apply (W.localizationsHomEquiv L' L).injective
-  let E := Localization.uniq L L' W
-  let α : L ⋙ E.functor ≅ L' := (Localization.compUniqFunctor L L' W)
-  rw [Equiv.apply_symm_apply, localizationsHomEquiv_eq W L L' E.functor α f,
-    localizationsHomEquiv_eq W L' L E.inverse
-      (isoWhiskerRight α.symm E.inverse ≪≫ Functor.associator _ _ _ ≪≫
-        isoWhiskerLeft L E.unitIso.symm ≪≫ L.rightUnitor)]
-  dsimp
-  simp only [assoc, id_comp, comp_id, Functor.map_comp, Equivalence.inv_fun_map]
-  simp only [← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.comp_obj, Functor.map_id,
-    id_comp, Iso.hom_inv_id_app_assoc, Functor.id_obj, comp_id]
-
-lemma localizationHomEquiv_trans (f : L.obj X ⟶ L.obj Y) :
-    (localizationsHomEquiv W L' L'') (localizationsHomEquiv W L L' f) =
-      localizationsHomEquiv W L L'' f := by
-  let E := Localization.uniq L L' W
-  let α : L ⋙ E.functor ≅ L' := (Localization.compUniqFunctor L L' W)
-  let E' := Localization.uniq L' L'' W
-  let α' : L' ⋙ E'.functor ≅ L'' := (Localization.compUniqFunctor L' L'' W)
-  simp [localizationsHomEquiv_eq W L L' E.functor α,
-    localizationsHomEquiv_eq W L' L'' E'.functor α',
-    localizationsHomEquiv_eq W L L'' (E.functor ⋙ E'.functor)
-      ((Functor.associator _ _ _).symm ≪≫ isoWhiskerRight α E'.functor ≪≫ α')]
-
-lemma localizationHomEquiv_comp (f : L.obj X ⟶ L.obj Y) (g : L.obj Y ⟶ L.obj Z) :
-    localizationsHomEquiv W L L' (f ≫ g) =
-      localizationsHomEquiv W L L' f ≫ localizationsHomEquiv W L L' g := by
-  simp [localizationsHomEquiv]
-
-lemma localizationsHomEquiv_isoOfHom_inv (f : X ⟶ Y) (hf : W f):
-    localizationsHomEquiv W L L' ((Localization.isoOfHom L W f hf).inv) =
-      (Localization.isoOfHom L' W f hf).inv := by
-  rw [← cancel_mono (Localization.isoOfHom L' W f hf).hom, Iso.inv_hom_id,
-    Localization.isoOfHom_hom, ← localizationsHomEquiv_map W L,
-    ← localizationHomEquiv_comp, Localization.isoOfHom_inv, IsIso.inv_hom_id,
-    localizationsHomEquiv_id]
+variable {X Y Z}
 
 lemma hasSmallLocalizedHom_iff :
     HasSmallLocalizedHom.{w} W X Y ↔ Small.{w} (L.obj X ⟶ L.obj Y) := by
   constructor
   · intro h
     have := h.small
-    exact small_map (localizationsHomEquiv W W.Q L).symm
+    exact small_map (homEquiv W W.Q L).symm
   · intro h
-    exact ⟨small_map (localizationsHomEquiv W W.Q L)⟩
+    exact ⟨small_map (homEquiv W W.Q L)⟩
 
 lemma hasSmallLocalizedHom_of_isLocalization :
-    HasSmallLocalizedHom.{v₃} W X Y := by
-  rw [W.hasSmallLocalizedHom_iff L]
+    HasSmallLocalizedHom.{v₂} W X Y := by
+  rw [hasSmallLocalizedHom_iff W L]
   infer_instance
 
 variable (X Y) in
 lemma small_of_hasSmallLocalizedHom [HasSmallLocalizedHom.{w} W X Y] :
     Small.{w} (L.obj X ⟶ L.obj Y) := by
-  rwa [← W.hasSmallLocalizedHom_iff]
+  rwa [← hasSmallLocalizedHom_iff W]
 
 lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
     HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y' := by
-  simp only [W.hasSmallLocalizedHom_iff W.Q]
+  simp only [hasSmallLocalizedHom_iff W W.Q]
   exact small_congr (Iso.homEquiv (W.Q.mapIso e) (W.Q.mapIso e'))
 
-end MorphismProperty
-
-namespace Localization
-
-variable (Φ : LocalizerMorphism W W') (L : C ⥤ D) [L.IsLocalization W]
-
-open MorphismProperty
+end
 
 /-- The type of morphisms from `X` to `Y` in the localized category
 with respect to `W : MorphismProperty C` that is shrunk to `Type w`
 when `HasSmallLocalizedHom.{w} W X Y` holds. -/
 def SmallHom (X Y : C) [HasSmallLocalizedHom.{w} W X Y] : Type w :=
-  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   Shrink.{w} (W.Q.obj X ⟶ W.Q.obj Y)
 
 namespace SmallHom
@@ -200,57 +83,58 @@ namespace SmallHom
 /-- The canonical bijection `SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y)`
 when `L` is a localization functor for `W : MorphismProperty C` and
 that `HasSmallLocalizedHom.{w} W X Y` holds. -/
-noncomputable def equiv {X Y : C} [HasSmallLocalizedHom.{w} W X Y] :
+noncomputable def equiv (L : C ⥤ D) [L.IsLocalization W] {X Y : C}
+    [HasSmallLocalizedHom.{w} W X Y] :
     SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y) :=
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
-  (equivShrink _).symm.trans (W.localizationsHomEquiv W.Q L)
+  (equivShrink _).symm.trans (homEquiv W W.Q L)
 
-lemma equiv_equiv_symm (L' : C ⥤ D') [L'.IsLocalization W] (G : D ⥤ D')
-    (e : L ⋙ G ≅ L') {X Y : C} (f : L.obj X ⟶ L.obj Y)
-    [HasSmallLocalizedHom.{w} W X Y] : equiv W L' ((equiv W L).symm f) =
+lemma equiv_equiv_symm (L : C ⥤ D) [L.IsLocalization W]
+    (L' : C ⥤ D') [L'.IsLocalization W] (G : D ⥤ D')
+    (e : L ⋙ G ≅ L') {X Y : C} [HasSmallLocalizedHom.{w} W X Y]
+    (f : L.obj X ⟶ L.obj Y) :
+    equiv W L' ((equiv W L).symm f) =
       e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
   dsimp [equiv]
-  rw [Equiv.symm_apply_apply, localizationHomEquiv_symm, localizationHomEquiv_trans]
-  apply localizationsHomEquiv_eq
-
-section
-
-variable {X Y Z T : C} [HasSmallLocalizedHom.{w} W X Y]
+  rw [Equiv.symm_apply_apply, homEquiv_trans]
+  apply homEquiv_eq
 
 /-- The element in `SmallHom W X Y` induced by `f : X ⟶ Y`. -/
-noncomputable def mk (f : X ⟶ Y) : SmallHom.{w} W X Y :=
+noncomputable def mk {X Y : C} [HasSmallLocalizedHom.{w} W X Y] (f : X ⟶ Y) :
+    SmallHom.{w} W X Y :=
   (equiv.{w} W W.Q).symm (W.Q.map f)
 
 @[simp]
-lemma equiv_mk (f : X ⟶ Y) : equiv.{w} W L (mk W f) = L.map f := by
+lemma equiv_mk (L : C ⥤ D) [L.IsLocalization W] {X Y : C}
+    [HasSmallLocalizedHom.{w} W X Y] (f : X ⟶ Y) :
+    equiv.{w} W L (mk W f) = L.map f := by
   simp [equiv, mk]
 
-variable {W} in
+variable {W}
+
 /-- The formal inverse in `SmallHom W X Y` of a morphism `f : Y ⟶ X` such that `W f`. -/
-noncomputable def mkInv (f : Y ⟶ X) (hf : W f) : SmallHom.{w} W X Y :=
+noncomputable def mkInv {X Y : C} (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X Y] :
+    SmallHom.{w} W X Y :=
   (equiv.{w} W W.Q).symm (Localization.isoOfHom W.Q W f hf).inv
 
 @[simp]
-lemma equiv_mkInv (f : Y ⟶ X) (hf : W f) :
+lemma equiv_mkInv (L : C ⥤ D) [L.IsLocalization W] {X Y : C} (f : Y ⟶ X) (hf : W f)
+    [HasSmallLocalizedHom.{w} W X Y] :
     equiv.{w} W L (mkInv f hf) = (Localization.isoOfHom L W f hf).inv := by
-  dsimp only [equiv, mkInv]
-  simp only [localizationHomEquiv_refl, Equiv.trans_refl, Equiv.symm_symm,
-    Equiv.trans_apply, Equiv.symm_apply_apply, localizationsHomEquiv_isoOfHom_inv]
-
-section
-
-variable [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
-
-variable {W}
-
-variable (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z)
+  simp only [equiv, mkInv, Equiv.symm_trans_apply, Equiv.symm_symm, homEquiv_symm_apply,
+    Equiv.trans_apply, Equiv.symm_apply_apply, homEquiv_isoOfHom_inv]
 
 /-- The composition on `SmallHom W`. -/
-noncomputable def comp (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
+noncomputable def comp {X Y Z : C} [HasSmallLocalizedHom.{w} W X Y]
+    [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
+    (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
     SmallHom.{w} W X Z :=
   (equiv W W.Q).symm (equiv W W.Q α ≫ equiv W W.Q β)
 
-lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
+lemma equiv_comp (L : C ⥤ D) [L.IsLocalization W] {X Y Z : C} [HasSmallLocalizedHom.{w} W X Y]
+    [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
+    (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
+    equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q Y Z
   obtain ⟨α, rfl⟩ := (equivShrink _).surjective α
@@ -258,90 +142,101 @@ lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
   dsimp [equiv, comp]
   rw [Equiv.symm_apply_apply]
   erw [(equivShrink _).symm_apply_apply, (equivShrink _).symm_apply_apply]
-  rw [← localizationHomEquiv_comp, localizationHomEquiv_refl, Equiv.refl_symm,
-    Equiv.refl_apply, Equiv.refl_apply, localizationHomEquiv_comp]
+  simp only [homEquiv_refl, homEquiv_comp]
 
-lemma mk_comp_mk (f : X ⟶ Y) (g : Y ⟶ Z) :
+variable {X Y Z T : C}
+
+lemma mk_comp_mk [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Z]
+    [HasSmallLocalizedHom.{w} W X Z] (f : X ⟶ Y) (g : Y ⟶ Z) :
     (mk W f).comp (mk W g) = mk W (f ≫ g) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
 @[simp]
-lemma comp_mk_id (α : SmallHom.{w} W X Y) [HasSmallLocalizedHom.{w} W Y Y] :
+lemma comp_mk_id [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Y]
+    (α : SmallHom.{w} W X Y)  :
     α.comp (mk W (𝟙 Y)) = α :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
 @[simp]
-lemma mk_id_comp (α : SmallHom.{w} W X Y) [HasSmallLocalizedHom.{w} W X X] :
+lemma mk_id_comp [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W X X]
+    (α : SmallHom.{w} W X Y) :
     (mk W (𝟙 X)).comp α = α :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
-variable [HasSmallLocalizedHom.{w} W Z T] [HasSmallLocalizedHom.{w} W X T]
-  [HasSmallLocalizedHom.{w} W Y T]
-
 @[simp]
-lemma comp_assoc (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z)
-    (γ : SmallHom.{w} W Z T) :
+lemma comp_assoc [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W X Z]
+    [HasSmallLocalizedHom.{w} W X T] [HasSmallLocalizedHom.{w} W Y Z]
+    [HasSmallLocalizedHom.{w} W Y T] [HasSmallLocalizedHom.{w} W Z T]
+    (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) (γ : SmallHom.{w} W Z T) :
     (α.comp β).comp γ = α.comp (β.comp γ) := by
   apply (equiv W W.Q).injective
   simp only [equiv_comp, assoc]
 
-end
-
-section
-
-variable [HasSmallLocalizedHom.{w} W Y X]
-
 @[simp]
-lemma mk_comp_mkInv (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W Y Y] :
+lemma mk_comp_mkInv [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y X]
+    [HasSmallLocalizedHom.{w} W Y Y] (f : Y ⟶ X) (hf : W f) :
     (mk W f).comp (mkInv f hf) = mk W (𝟙 Y) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
 @[simp]
-lemma mkInv_comp_mk (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X X] :
-    (mkInv f hf).comp (mk W f)= mk W (𝟙 X) :=
+lemma mkInv_comp_mk [HasSmallLocalizedHom.{w} W X X] [HasSmallLocalizedHom.{w} W X Y]
+    [HasSmallLocalizedHom.{w} W Y X] (f : Y ⟶ X) (hf : W f) :
+    (mkInv f hf).comp (mk W f) = mk W (𝟙 X) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
-end
+end SmallHom
 
-end
+end Localization
+
+namespace LocalizerMorphism
+
+open Localization
+
+variable {C₁ : Type u₁} [Category.{v₁} C₁] {W₁ : MorphismProperty C₁}
+  {C₂ : Type u₂} [Category.{v₂} C₂] {W₂ : MorphismProperty C₂}
+  {D₁ : Type u₃} [Category.{v₃} D₁] {D₂ : Type u₄} [Category.{v₄} D₂]
+  (Φ : LocalizerMorphism W₁ W₂) (L₁ : C₁ ⥤ D₁) [L₁.IsLocalization W₁]
+  (L₂ : C₂ ⥤ D₂) [L₂.IsLocalization W₂]
 
 variable {W}
 
 section
 
-variable (L' : C' ⥤ D') [L'.IsLocalization W']
-variable {X Y Z : C}
+variable {X Y Z : C₁}
 
-variable [W.HasSmallLocalizedHom X Y]
-  [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
+variable [HasSmallLocalizedHom.{w} W₁ X Y]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y)]
 
 /-- The action of a localizer morphism on `SmallHom`. -/
-noncomputable def map (f : SmallHom.{w} W X Y) :
-    SmallHom.{w'} W' (Φ.functor.obj X) (Φ.functor.obj Y) :=
-  (equiv W' W'.Q).symm
-    (Iso.homEquiv ((CatCommSq.iso Φ.functor W.Q W'.Q _).symm.app _)
-      ((CatCommSq.iso Φ.functor W.Q W'.Q _).symm.app _)
-      ((Φ.localizedFunctor W.Q W'.Q).map ((equiv W W.Q) f)))
-
-lemma equiv_map (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : SmallHom.{w} W X Y) :
-    (equiv W' L') (f.map Φ) = e.hom.app X ≫ G.map (equiv W L f) ≫ e.inv.app Y := by
-  obtain ⟨g, rfl⟩ := (equiv W W.Q).symm.surjective f
-  simp only [map, Equiv.apply_symm_apply]
-  let G' := Φ.localizedFunctor W.Q W'.Q
-  let β := CatCommSq.iso Φ.functor W.Q W'.Q G'
-  let E := (uniq W.Q L W).functor
-  let α : W.Q ⋙ E ≅ L := compUniqFunctor W.Q L W
-  let E' := (uniq W'.Q L' W').functor
-  let α' : W'.Q ⋙ E' ≅ L' := compUniqFunctor W'.Q L' W'
-  rw [equiv_equiv_symm W W.Q L E α, equiv_equiv_symm W' W'.Q L' E' α']
-  change α'.inv.app _ ≫ E'.map (β.hom.app X ≫ G'.map g ≫ β.inv.app Y) ≫ _ = _
-  let γ : G' ⋙ E' ≅ E ⋙ G := liftNatIso W.Q W (W.Q ⋙ G' ⋙ E') (W.Q ⋙ E ⋙ G) _ _
-    ((Functor.associator _ _ _).symm ≪≫ isoWhiskerRight β.symm E' ≪≫
-      Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ α' ≪≫ e ≪≫
-      isoWhiskerRight α.symm G ≪≫ Functor.associator _ _ _)
-  have hγ : ∀ (X : C), γ.hom.app (W.Q.obj X) =
-      E'.map (β.inv.app X) ≫ α'.hom.app (Φ.functor.obj X) ≫
-        e.hom.app X ≫ G.map (α.inv.app X) := fun X ↦ by
+noncomputable def smallHomMap (f : SmallHom.{w} W₁ X Y) :
+    SmallHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y) :=
+  (SmallHom.equiv W₂ W₂.Q).symm
+    (Iso.homEquiv ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
+      ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
+      ((Φ.localizedFunctor W₁.Q W₂.Q).map ((SmallHom.equiv W₁ W₁.Q) f)))
+
+lemma equiv_smallHomMap (G : D₁ ⥤ D₂) (e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G)
+    (f : SmallHom.{w} W₁ X Y) :
+    (SmallHom.equiv W₂ L₂) (Φ.smallHomMap f) =
+      e.hom.app X ≫ G.map (SmallHom.equiv W₁ L₁ f) ≫ e.inv.app Y := by
+  obtain ⟨g, rfl⟩ := (SmallHom.equiv W₁ W₁.Q).symm.surjective f
+  simp only [smallHomMap, Equiv.apply_symm_apply]
+  let G' := Φ.localizedFunctor W₁.Q W₂.Q
+  let β := CatCommSq.iso Φ.functor W₁.Q W₂.Q G'
+  let E₁ := (uniq W₁.Q L₁ W₁).functor
+  let α₁ : W₁.Q ⋙ E₁ ≅ L₁ := compUniqFunctor W₁.Q L₁ W₁
+  let E₂ := (uniq W₂.Q L₂ W₂).functor
+  let α₂ : W₂.Q ⋙ E₂ ≅ L₂ := compUniqFunctor W₂.Q L₂ W₂
+  rw [SmallHom.equiv_equiv_symm W₁ W₁.Q L₁ E₁ α₁,
+    SmallHom.equiv_equiv_symm W₂ W₂.Q L₂ E₂ α₂]
+  change α₂.inv.app _ ≫ E₂.map (β.hom.app X ≫ G'.map g ≫ β.inv.app Y) ≫ _ = _
+  let γ : G' ⋙ E₂ ≅ E₁ ⋙ G := liftNatIso W₁.Q W₁ (W₁.Q ⋙ G' ⋙ E₂) (W₁.Q ⋙ E₁ ⋙ G) _ _
+    ((Functor.associator _ _ _).symm ≪≫ isoWhiskerRight β.symm E₂ ≪≫
+      Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ α₂ ≪≫ e ≪≫
+      isoWhiskerRight α₁.symm G ≪≫ Functor.associator _ _ _)
+  have hγ : ∀ (X : C₁), γ.hom.app (W₁.Q.obj X) =
+      E₂.map (β.inv.app X) ≫ α₂.hom.app (Φ.functor.obj X) ≫
+        e.hom.app X ≫ G.map (α₁.inv.app X) := fun X ↦ by
     dsimp [γ]
     rw [liftNatTrans_app]
     dsimp
@@ -349,8 +244,8 @@ lemma equiv_map (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : SmallHom
     erw [id_comp, comp_id]
   simp only [Functor.map_comp, assoc]
   erw [← NatIso.naturality_1 γ]
-  simp only [Functor.comp_map, ← cancel_epi (e.inv.app X), ← cancel_epi (G.map (α.hom.app X)),
-    ← cancel_epi (γ.hom.app (W.Q.obj X)), assoc, Iso.inv_hom_id_app_assoc,
+  simp only [Functor.comp_map, ← cancel_epi (e.inv.app X), ← cancel_epi (G.map (α₁.hom.app X)),
+    ← cancel_epi (γ.hom.app (W₁.Q.obj X)), assoc, Iso.inv_hom_id_app_assoc,
     ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.map_id, id_comp,
     Iso.hom_inv_id_app_assoc]
   simp only [hγ, assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app,
@@ -359,21 +254,20 @@ lemma equiv_map (G : D ⥤ D') (e : Φ.functor ⋙ L' ≅ L ⋙ G) (f : SmallHom
 
 end
 
-variable {X Y Z : C}
-
-variable [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Z]
-  [HasSmallLocalizedHom.{w} W X Z]
-  [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Y)]
-  [W'.HasSmallLocalizedHom (Φ.functor.obj Y) (Φ.functor.obj Z)]
-  [W'.HasSmallLocalizedHom (Φ.functor.obj X) (Φ.functor.obj Z)]
+variable {X Y Z : C₁}
 
-lemma map_comp (f : SmallHom.{w} W X Y) (g : SmallHom.{w} W Y Z) :
-    (f.comp g).map Φ = (f.map Φ).comp (g.map Φ) := by
-  apply (equiv W' W'.Q).injective
-  simp [equiv_map Φ W.Q W'.Q (Φ.localizedFunctor W.Q W'.Q) (CatCommSq.iso _ _ _ _), equiv_comp]
+variable [HasSmallLocalizedHom.{w} W₁ X Y] [HasSmallLocalizedHom.{w} W₁ Y Z]
+  [HasSmallLocalizedHom.{w} W₁ X Z]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y)]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj Y) (Φ.functor.obj Z)]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Z)]
 
-end SmallHom
+lemma smallHomMap_comp (f : SmallHom.{w} W₁ X Y) (g : SmallHom.{w} W₁ Y Z) :
+    Φ.smallHomMap (f.comp g) = (Φ.smallHomMap f).comp (Φ.smallHomMap g) := by
+  apply (SmallHom.equiv W₂ W₂.Q).injective
+  simp [Φ.equiv_smallHomMap W₁.Q W₂.Q (Φ.localizedFunctor W₁.Q W₂.Q) (CatCommSq.iso _ _ _ _),
+    SmallHom.equiv_comp]
 
-end Localization
+end LocalizerMorphism
 
 end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 433d6e9ae75f94..f6b2c7455f4e87 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -21,7 +21,9 @@ variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
   {M : Type w'} [AddMonoid M] [HasShift C M] [HasShift C' M] [HasShift D M]
   [W.IsCompatibleWithShift M] [W'.IsCompatibleWithShift M]
 
-namespace MorphismProperty
+namespace Localization
+
+section
 
 variable (X Y : C)
 
@@ -57,16 +59,14 @@ instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₄ (m : M) :
   (hasSmallLocalizedHom_iff_of_isos W
     (Iso.refl (X⟦m⟧)) ((shiftFunctorZero C M).app Y)).1 inferInstance
 
-end MorphismProperty
-
-namespace Localization
+end
 
 namespace SmallHom
 
 variable {W}
 variable (L : C ⥤ D) [L.IsLocalization W] [L.CommShift M]
-variable {X Y : C} [MorphismProperty.HasSmallLocalizedHom.{w} W X Y]
-    (f : SmallHom.{w} W X Y) (a : M) [MorphismProperty.HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦a⟧)]
+variable {X Y : C} [HasSmallLocalizedHom.{w} W X Y]
+    (f : SmallHom.{w} W X Y) (a : M) [HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦a⟧)]
 
 noncomputable def shift : SmallHom.{w} W (X⟦a⟧) (Y⟦a⟧) :=
   f.map (LocalizerMorphism.mk (shiftFunctor C a)

From 83d8c13e9fc66b9beb48bbd6f18ddc549b7359ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 15:32:30 +0200
Subject: [PATCH 28/63] feat: bijections between morphisms in two localized
 categories

---
 Mathlib.lean                                  |   1 +
 Mathlib/CategoryTheory/Iso.lean               |  26 +++
 .../CategoryTheory/Localization/HomEquiv.lean | 167 ++++++++++++++++++
 3 files changed, 194 insertions(+)
 create mode 100644 Mathlib/CategoryTheory/Localization/HomEquiv.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index e92f90027d1d00..f2cf9aab8e9846 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -1496,6 +1496,7 @@ import Mathlib.CategoryTheory.Localization.DerivabilityStructure.Basic
 import Mathlib.CategoryTheory.Localization.Equivalence
 import Mathlib.CategoryTheory.Localization.FiniteProducts
 import Mathlib.CategoryTheory.Localization.HasLocalization
+import Mathlib.CategoryTheory.Localization.HomEquiv
 import Mathlib.CategoryTheory.Localization.LocalizerMorphism
 import Mathlib.CategoryTheory.Localization.Opposite
 import Mathlib.CategoryTheory.Localization.Pi
diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean
index fc4210cac733e7..0a609f5f659c37 100644
--- a/Mathlib/CategoryTheory/Iso.lean
+++ b/Mathlib/CategoryTheory/Iso.lean
@@ -250,6 +250,32 @@ theorem hom_eq_inv (α : X ≅ Y) (β : Y ≅ X) : α.hom = β.inv ↔ β.hom =
   rfl
 #align category_theory.iso.hom_eq_inv CategoryTheory.Iso.hom_eq_inv
 
+/-- The bijection `(Z ⟶ X) ≃ (Z ⟶ Y)` induced by `α : X ≅ Y`. -/
+@[simps]
+def homToEquiv (α : X ≅ Y) {Z : C} : (Z ⟶ X) ≃ (Z ⟶ Y) where
+  toFun f := f ≫ α.hom
+  invFun g := g ≫ α.inv
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
+/-- The bijection `(X ⟶ Z) ≃ (Y ⟶ Z)` induced by `α : X ≅ Y`. -/
+@[simps]
+def homFromEquiv (α : X ≅ Y) {Z : C} : (X ⟶ Z) ≃ (Y ⟶ Z) where
+  toFun f := α.inv ≫ f
+  invFun g := α.hom ≫ g
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
+/-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
+`e : X ≅ X'` and `e' : Y ≅ Y'`. -/
+@[simps]
+def homEquiv {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
+    (X ⟶ Y) ≃ (X' ⟶ Y') where
+  toFun f := e.inv ≫ f ≫ e'.hom
+  invFun g := e.hom ≫ g ≫ e'.inv
+  left_inv := by aesop_cat
+  right_inv := by aesop_cat
+
 end Iso
 
 /-- `IsIso` typeclass expressing that a morphism is invertible. -/
diff --git a/Mathlib/CategoryTheory/Localization/HomEquiv.lean b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
new file mode 100644
index 00000000000000..14ae6ff8233d07
--- /dev/null
+++ b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
@@ -0,0 +1,167 @@
+/-
+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.Localization.LocalizerMorphism
+
+/-!
+# Bijections between morphisms in two localized categories
+
+Given two localization functors `L₁ : C ⥤ D₁` and `L₂ : C ⥤ D₂` for the same
+class of morphisms `W : MorphismProperty C`, we define a bijection
+`Localization.homEquiv W L₁ L₂ : (L₁.obj X ⟶ L₁.obj Y) ≃ (L₂.obj X ⟶ L₂.obj Y)`
+between the types of morphisms in the two localized categories.
+
+More generally, given a localizer morphism `Φ : LocalizerMorphism W₁ W₂`, we define a map
+`Φ.homMap L₁ L₂ : (L₁.obj X ⟶ L₁.obj Y) ⟶ (L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y))`.
+The definition `Localization.homEquiv` is obtained by applying the construction
+to the identity localizer morphism.
+
+-/
+
+namespace CategoryTheory
+
+open Category
+
+variable {C C₁ C₂ C₃ D₁ D₂ D₃ : Type*} [Category C]
+  [Category C₁] [Category C₂] [Category C₃]
+  [Category D₁] [Category D₂] [Category D₃]
+
+namespace LocalizerMorphism
+
+variable {W₁ : MorphismProperty C₁} {W₂ : MorphismProperty C₂} {W₃ : MorphismProperty C₃}
+  (Φ : LocalizerMorphism W₁ W₂) (Ψ : LocalizerMorphism W₂ W₃)
+  (L₁ : C₁ ⥤ D₁) [L₁.IsLocalization W₁]
+  (L₂ : C₂ ⥤ D₂) [L₂.IsLocalization W₂]
+  (L₃ : C₃ ⥤ D₃) [L₃.IsLocalization W₃]
+  {X Y Z : C₁}
+
+/-- If `Φ : LocalizerMorphism W₁ W₂` is a morphism of localizers, `L₁` and `L₂`
+are localization functors for `W₁` and `W₂`, then this is the induced map
+`(L₁.obj X ⟶ L₁.obj Y) ⟶ (L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y))`
+for all objects `X` and `Y`. -/
+noncomputable def homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y) :=
+  Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
+    ((Φ.localizedFunctor L₁ L₂).map f)
+
+@[simp]
+lemma homMap_map (f : X ⟶ Y) :
+    Φ.homMap L₁ L₂ (L₁.map f) = L₂.map (Φ.functor.map f) := by
+  dsimp [homMap]
+  erw [← NatTrans.naturality_assoc]
+  simp
+
+variable (X) in
+@[simp]
+lemma homMap_id  :
+    Φ.homMap L₁ L₂ (𝟙 (L₁.obj X)) = 𝟙 (L₂.obj (Φ.functor.obj X)) := by
+  simpa using Φ.homMap_map L₁ L₂ (𝟙 X)
+
+@[reassoc]
+lemma homMap_comp (f : L₁.obj X ⟶ L₁.obj Y) (g : L₁.obj Y ⟶ L₁.obj Z) :
+    Φ.homMap L₁ L₂ (f ≫ g) = Φ.homMap L₁ L₂ f ≫ Φ.homMap L₁ L₂ g := by
+  simp [homMap]
+
+@[reassoc]
+lemma homMap_apply (G : D₁ ⥤ D₂) (e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G) (f : L₁.obj X ⟶ L₁.obj Y) :
+    Φ.homMap L₁ L₂ f = e.hom.app X ≫ G.map f ≫ e.inv.app Y := by
+  let G' := Φ.localizedFunctor L₁ L₂
+  let e' := CatCommSq.iso Φ.functor L₁ L₂ G'
+  change e'.hom.app X ≫ G'.map f ≫ e'.inv.app Y = _
+  letI : Localization.Lifting L₁ W₁ (Φ.functor ⋙ L₂) G := ⟨e.symm⟩
+  let α : G' ≅ G := Localization.liftNatIso L₁ W₁ (L₁ ⋙ G') (Φ.functor ⋙ L₂) _ _ e'.symm
+  have : e = e' ≪≫ isoWhiskerLeft _ α := by
+    ext X
+    dsimp [α]
+    rw [Localization.liftNatTrans_app]
+    erw [id_comp]
+    rw [Iso.hom_inv_id_app_assoc]
+    rfl
+  simp [this]
+
+@[simp]
+lemma id_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    (id W₁).homMap L₁ L₁ f = f := by
+  simpa using (id W₁).homMap_apply L₁ L₁ (𝟭 D₁) (Iso.refl _) f
+
+@[simp]
+lemma homMap_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    Ψ.homMap L₂ L₃ (Φ.homMap L₁ L₂ f) = (Φ.comp Ψ).homMap L₁ L₃ f := by
+  let G := Φ.localizedFunctor L₁ L₂
+  let G' := Ψ.localizedFunctor L₂ L₃
+  let e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G := CatCommSq.iso _ _ _ _
+  let e' : Ψ.functor ⋙ L₃ ≅ L₂ ⋙ G' := CatCommSq.iso _ _ _ _
+  rw [Φ.homMap_apply L₁ L₂ G e, Ψ.homMap_apply L₂ L₃ G' e',
+    (Φ.comp Ψ).homMap_apply L₁ L₃ (G ⋙ G')
+    (Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ e' ≪≫
+      (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight e _ ≪≫
+      Functor.associator _ _ _)]
+  dsimp
+  simp only [Functor.map_comp, assoc, comp_id, id_comp]
+
+end LocalizerMorphism
+
+namespace Localization
+
+variable (W : MorphismProperty C) (L₁ : C ⥤ D₁) [L₁.IsLocalization W]
+  (L₂ : C ⥤ D₂) [L₂.IsLocalization W] (L₃ : C ⥤ D₃) [L₃.IsLocalization W]
+  {X Y Z : C}
+
+/-- Bijection between types of morphisms in two localized categories
+for the same class of morphisms `W`. -/
+@[simps (config := .lemmasOnly) apply]
+noncomputable def homEquiv :
+    (L₁.obj X ⟶ L₁.obj Y) ≃ (L₂.obj X ⟶ L₂.obj Y) where
+  toFun := (LocalizerMorphism.id W).homMap L₁ L₂
+  invFun := (LocalizerMorphism.id W).homMap L₂ L₁
+  left_inv f := by
+    rw [LocalizerMorphism.homMap_homMap]
+    apply LocalizerMorphism.id_homMap
+  right_inv g := by
+    rw [LocalizerMorphism.homMap_homMap]
+    apply LocalizerMorphism.id_homMap
+
+@[simp]
+lemma homEquiv_symm_apply (g : L₂.obj X ⟶ L₂.obj Y) :
+    (homEquiv W L₁ L₂).symm g = homEquiv W L₂ L₁ g := rfl
+
+lemma homEquiv_eq (G : D₁ ⥤ D₂) (e : L₁ ⋙ G ≅ L₂) (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₁ L₂ f = e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
+  rw [homEquiv_apply, LocalizerMorphism.homMap_apply (LocalizerMorphism.id W) L₁ L₂ G e.symm,
+    Iso.symm_hom, Iso.symm_inv]
+
+@[simp]
+lemma homEquiv_refl (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₁ L₁ f = f := by
+  apply LocalizerMorphism.id_homMap
+
+lemma homEquiv_trans (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₂ L₃ (homEquiv W L₁ L₂ f) = homEquiv W L₁ L₃ f := by
+  dsimp only [homEquiv_apply]
+  apply LocalizerMorphism.homMap_homMap
+
+lemma homEquiv_comp (f : L₁.obj X ⟶ L₁.obj Y) (g : L₁.obj Y ⟶ L₁.obj Z) :
+    homEquiv W L₁ L₂ (f ≫ g) = homEquiv W L₁ L₂ f ≫ homEquiv W L₁ L₂ g := by
+  apply LocalizerMorphism.homMap_comp
+
+@[simp]
+lemma homEquiv_map (f : X ⟶ Y) : homEquiv W L₁ L₂ (L₁.map f) = L₂.map f := by
+  simp [homEquiv_apply]
+
+variable (X) in
+@[simp]
+lemma homEquiv_id : homEquiv W L₁ L₂ (𝟙 (L₁.obj X)) = 𝟙 (L₂.obj X) := by
+  simp [homEquiv_apply]
+
+lemma homEquiv_isoOfHom_inv (f : Y ⟶ X) (hf : W f) :
+    homEquiv W L₁ L₂ (isoOfHom L₁ W f hf).inv = (isoOfHom L₂ W f hf).inv := by
+  rw [← cancel_mono (isoOfHom L₂ W f hf).hom, Iso.inv_hom_id, isoOfHom_hom,
+    ← homEquiv_map W L₁ L₂ f, ← homEquiv_comp, isoOfHom_inv,
+    IsIso.inv_hom_id, homEquiv_id]
+
+end Localization
+
+end CategoryTheory

From 212683adb49d0024ff7146abd73d5db697988334 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 15:46:23 +0200
Subject: [PATCH 29/63] merge with localization-homequiv

---
 Mathlib.lean                                  |   1 +
 .../CategoryTheory/Localization/HomEquiv.lean | 167 ++++++++++++
 .../CategoryTheory/Localization/SmallHom.lean | 257 +++++++++++-------
 3 files changed, 332 insertions(+), 93 deletions(-)
 create mode 100644 Mathlib/CategoryTheory/Localization/HomEquiv.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index 552a6a9134ec06..118ab512c43349 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -1495,6 +1495,7 @@ import Mathlib.CategoryTheory.Localization.DerivabilityStructure.Basic
 import Mathlib.CategoryTheory.Localization.Equivalence
 import Mathlib.CategoryTheory.Localization.FiniteProducts
 import Mathlib.CategoryTheory.Localization.HasLocalization
+import Mathlib.CategoryTheory.Localization.HomEquiv
 import Mathlib.CategoryTheory.Localization.LocalizerMorphism
 import Mathlib.CategoryTheory.Localization.Opposite
 import Mathlib.CategoryTheory.Localization.Pi
diff --git a/Mathlib/CategoryTheory/Localization/HomEquiv.lean b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
new file mode 100644
index 00000000000000..14ae6ff8233d07
--- /dev/null
+++ b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
@@ -0,0 +1,167 @@
+/-
+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.Localization.LocalizerMorphism
+
+/-!
+# Bijections between morphisms in two localized categories
+
+Given two localization functors `L₁ : C ⥤ D₁` and `L₂ : C ⥤ D₂` for the same
+class of morphisms `W : MorphismProperty C`, we define a bijection
+`Localization.homEquiv W L₁ L₂ : (L₁.obj X ⟶ L₁.obj Y) ≃ (L₂.obj X ⟶ L₂.obj Y)`
+between the types of morphisms in the two localized categories.
+
+More generally, given a localizer morphism `Φ : LocalizerMorphism W₁ W₂`, we define a map
+`Φ.homMap L₁ L₂ : (L₁.obj X ⟶ L₁.obj Y) ⟶ (L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y))`.
+The definition `Localization.homEquiv` is obtained by applying the construction
+to the identity localizer morphism.
+
+-/
+
+namespace CategoryTheory
+
+open Category
+
+variable {C C₁ C₂ C₃ D₁ D₂ D₃ : Type*} [Category C]
+  [Category C₁] [Category C₂] [Category C₃]
+  [Category D₁] [Category D₂] [Category D₃]
+
+namespace LocalizerMorphism
+
+variable {W₁ : MorphismProperty C₁} {W₂ : MorphismProperty C₂} {W₃ : MorphismProperty C₃}
+  (Φ : LocalizerMorphism W₁ W₂) (Ψ : LocalizerMorphism W₂ W₃)
+  (L₁ : C₁ ⥤ D₁) [L₁.IsLocalization W₁]
+  (L₂ : C₂ ⥤ D₂) [L₂.IsLocalization W₂]
+  (L₃ : C₃ ⥤ D₃) [L₃.IsLocalization W₃]
+  {X Y Z : C₁}
+
+/-- If `Φ : LocalizerMorphism W₁ W₂` is a morphism of localizers, `L₁` and `L₂`
+are localization functors for `W₁` and `W₂`, then this is the induced map
+`(L₁.obj X ⟶ L₁.obj Y) ⟶ (L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y))`
+for all objects `X` and `Y`. -/
+noncomputable def homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y) :=
+  Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
+    ((Φ.localizedFunctor L₁ L₂).map f)
+
+@[simp]
+lemma homMap_map (f : X ⟶ Y) :
+    Φ.homMap L₁ L₂ (L₁.map f) = L₂.map (Φ.functor.map f) := by
+  dsimp [homMap]
+  erw [← NatTrans.naturality_assoc]
+  simp
+
+variable (X) in
+@[simp]
+lemma homMap_id  :
+    Φ.homMap L₁ L₂ (𝟙 (L₁.obj X)) = 𝟙 (L₂.obj (Φ.functor.obj X)) := by
+  simpa using Φ.homMap_map L₁ L₂ (𝟙 X)
+
+@[reassoc]
+lemma homMap_comp (f : L₁.obj X ⟶ L₁.obj Y) (g : L₁.obj Y ⟶ L₁.obj Z) :
+    Φ.homMap L₁ L₂ (f ≫ g) = Φ.homMap L₁ L₂ f ≫ Φ.homMap L₁ L₂ g := by
+  simp [homMap]
+
+@[reassoc]
+lemma homMap_apply (G : D₁ ⥤ D₂) (e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G) (f : L₁.obj X ⟶ L₁.obj Y) :
+    Φ.homMap L₁ L₂ f = e.hom.app X ≫ G.map f ≫ e.inv.app Y := by
+  let G' := Φ.localizedFunctor L₁ L₂
+  let e' := CatCommSq.iso Φ.functor L₁ L₂ G'
+  change e'.hom.app X ≫ G'.map f ≫ e'.inv.app Y = _
+  letI : Localization.Lifting L₁ W₁ (Φ.functor ⋙ L₂) G := ⟨e.symm⟩
+  let α : G' ≅ G := Localization.liftNatIso L₁ W₁ (L₁ ⋙ G') (Φ.functor ⋙ L₂) _ _ e'.symm
+  have : e = e' ≪≫ isoWhiskerLeft _ α := by
+    ext X
+    dsimp [α]
+    rw [Localization.liftNatTrans_app]
+    erw [id_comp]
+    rw [Iso.hom_inv_id_app_assoc]
+    rfl
+  simp [this]
+
+@[simp]
+lemma id_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    (id W₁).homMap L₁ L₁ f = f := by
+  simpa using (id W₁).homMap_apply L₁ L₁ (𝟭 D₁) (Iso.refl _) f
+
+@[simp]
+lemma homMap_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
+    Ψ.homMap L₂ L₃ (Φ.homMap L₁ L₂ f) = (Φ.comp Ψ).homMap L₁ L₃ f := by
+  let G := Φ.localizedFunctor L₁ L₂
+  let G' := Ψ.localizedFunctor L₂ L₃
+  let e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G := CatCommSq.iso _ _ _ _
+  let e' : Ψ.functor ⋙ L₃ ≅ L₂ ⋙ G' := CatCommSq.iso _ _ _ _
+  rw [Φ.homMap_apply L₁ L₂ G e, Ψ.homMap_apply L₂ L₃ G' e',
+    (Φ.comp Ψ).homMap_apply L₁ L₃ (G ⋙ G')
+    (Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ e' ≪≫
+      (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight e _ ≪≫
+      Functor.associator _ _ _)]
+  dsimp
+  simp only [Functor.map_comp, assoc, comp_id, id_comp]
+
+end LocalizerMorphism
+
+namespace Localization
+
+variable (W : MorphismProperty C) (L₁ : C ⥤ D₁) [L₁.IsLocalization W]
+  (L₂ : C ⥤ D₂) [L₂.IsLocalization W] (L₃ : C ⥤ D₃) [L₃.IsLocalization W]
+  {X Y Z : C}
+
+/-- Bijection between types of morphisms in two localized categories
+for the same class of morphisms `W`. -/
+@[simps (config := .lemmasOnly) apply]
+noncomputable def homEquiv :
+    (L₁.obj X ⟶ L₁.obj Y) ≃ (L₂.obj X ⟶ L₂.obj Y) where
+  toFun := (LocalizerMorphism.id W).homMap L₁ L₂
+  invFun := (LocalizerMorphism.id W).homMap L₂ L₁
+  left_inv f := by
+    rw [LocalizerMorphism.homMap_homMap]
+    apply LocalizerMorphism.id_homMap
+  right_inv g := by
+    rw [LocalizerMorphism.homMap_homMap]
+    apply LocalizerMorphism.id_homMap
+
+@[simp]
+lemma homEquiv_symm_apply (g : L₂.obj X ⟶ L₂.obj Y) :
+    (homEquiv W L₁ L₂).symm g = homEquiv W L₂ L₁ g := rfl
+
+lemma homEquiv_eq (G : D₁ ⥤ D₂) (e : L₁ ⋙ G ≅ L₂) (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₁ L₂ f = e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
+  rw [homEquiv_apply, LocalizerMorphism.homMap_apply (LocalizerMorphism.id W) L₁ L₂ G e.symm,
+    Iso.symm_hom, Iso.symm_inv]
+
+@[simp]
+lemma homEquiv_refl (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₁ L₁ f = f := by
+  apply LocalizerMorphism.id_homMap
+
+lemma homEquiv_trans (f : L₁.obj X ⟶ L₁.obj Y) :
+    homEquiv W L₂ L₃ (homEquiv W L₁ L₂ f) = homEquiv W L₁ L₃ f := by
+  dsimp only [homEquiv_apply]
+  apply LocalizerMorphism.homMap_homMap
+
+lemma homEquiv_comp (f : L₁.obj X ⟶ L₁.obj Y) (g : L₁.obj Y ⟶ L₁.obj Z) :
+    homEquiv W L₁ L₂ (f ≫ g) = homEquiv W L₁ L₂ f ≫ homEquiv W L₁ L₂ g := by
+  apply LocalizerMorphism.homMap_comp
+
+@[simp]
+lemma homEquiv_map (f : X ⟶ Y) : homEquiv W L₁ L₂ (L₁.map f) = L₂.map f := by
+  simp [homEquiv_apply]
+
+variable (X) in
+@[simp]
+lemma homEquiv_id : homEquiv W L₁ L₂ (𝟙 (L₁.obj X)) = 𝟙 (L₂.obj X) := by
+  simp [homEquiv_apply]
+
+lemma homEquiv_isoOfHom_inv (f : Y ⟶ X) (hf : W f) :
+    homEquiv W L₁ L₂ (isoOfHom L₁ W f hf).inv = (isoOfHom L₂ W f hf).inv := by
+  rw [← cancel_mono (isoOfHom L₂ W f hf).hom, Iso.inv_hom_id, isoOfHom_hom,
+    ← homEquiv_map W L₁ L₂ f, ← homEquiv_comp, isoOfHom_inv,
+    IsIso.inv_hom_id, homEquiv_id]
+
+end Localization
+
+end CategoryTheory
diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index 399027a19a5e17..c1dd485238f1e6 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.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.Localization.Predicate
+import Mathlib.CategoryTheory.Localization.HomEquiv
 import Mathlib.Logic.Small.Defs
 
 /-!
@@ -20,15 +20,21 @@ with the composition of morphisms.
 
 -/
 
-universe w w' w'' v u u' u''
+universe w w' v₁ v₂ v₃ v₄ v₅ u₁ u₂ u₃ u₄ u₅
 
 namespace CategoryTheory
 
-variable {C : Type u} [Category.{v} C] (W : MorphismProperty C)
-  {D : Type u'} [Category.{w'} D] (L : C ⥤ D) [L.IsLocalization W]
-  {D' : Type u''} [Category.{w''} D'] (L' : C ⥤ D') [L'.IsLocalization W] (X Y Z : C)
+open Category
 
-namespace MorphismProperty
+namespace Localization
+
+variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
+  {D : Type u₂} [Category.{v₂} D]
+  {D' : Type u₃} [Category.{v₃} D']
+
+section
+
+variable (L : C ⥤ D) [L.IsLocalization W] (X Y Z : C)
 
 /-- This property holds if the type of morphisms between `X` and `Y`
 in the localized category with respect to `W : MorphismProperty C`
@@ -36,133 +42,99 @@ is small. -/
 class HasSmallLocalizedHom : Prop where
   small : Small.{w} (W.Q.obj X ⟶ W.Q.obj Y)
 
-variable {X Y Z}
-
-/-- Bijection between types of morphisms in two localized categories
-for the same class of morphisms `W`. -/
-noncomputable def localizationsHomEquiv :
-    (L.obj X ⟶ L.obj Y) ≃ (L'.obj X ⟶ L'.obj Y) :=
-  (Localization.uniq L L' W).fullyFaithfulFunctor.homEquiv.trans
-    (Iso.homEquiv ((Localization.compUniqFunctor L L' W).app X)
-      ((Localization.compUniqFunctor L L' W).app Y))
+attribute [instance] HasSmallLocalizedHom.small
 
-@[simp]
-lemma localizationsHomEquiv_map (f : X ⟶ Y) :
-    localizationsHomEquiv W L L' (L.map f) = L'.map f := by
-  dsimp [localizationsHomEquiv]
-  erw [← NatTrans.naturality_assoc]
-  simp
-
-variable (X) in
-@[simp]
-lemma localizationsHomEquiv_id :
-    localizationsHomEquiv W L L' (𝟙 (L.obj X)) = 𝟙 (L'.obj X) := by
-  simpa using localizationsHomEquiv_map W L L' (𝟙 X)
-
-@[simp]
-lemma localizationHomEquiv_refl :
-    localizationsHomEquiv W L L (X := X) (Y := Y) = Equiv.refl _ := by
-  ext f
-  simp [localizationsHomEquiv, Localization.compUniqFunctor_eq L L W (𝟭 _) L.rightUnitor]
-
-lemma localizationHomEquiv_comp (f : L.obj X ⟶ L.obj Y) (g : L.obj Y ⟶ L.obj Z) :
-    localizationsHomEquiv W L L' (f ≫ g) =
-      localizationsHomEquiv W L L' f ≫ localizationsHomEquiv W L L' g := by
-  simp [localizationsHomEquiv]
-
-lemma localizationsHomEquiv_isoOfHom_inv (f : X ⟶ Y) (hf : W f):
-    localizationsHomEquiv W L L' ((Localization.isoOfHom L W f hf).inv) =
-      (Localization.isoOfHom L' W f hf).inv := by
-  rw [← cancel_mono (Localization.isoOfHom L' W f hf).hom, Iso.inv_hom_id,
-    Localization.isoOfHom_hom, ← localizationsHomEquiv_map W L,
-    ← localizationHomEquiv_comp, Localization.isoOfHom_inv, IsIso.inv_hom_id,
-    localizationsHomEquiv_id]
+variable {X Y Z}
 
 lemma hasSmallLocalizedHom_iff :
     HasSmallLocalizedHom.{w} W X Y ↔ Small.{w} (L.obj X ⟶ L.obj Y) := by
   constructor
   · intro h
     have := h.small
-    exact small_map (localizationsHomEquiv W W.Q L).symm
+    exact small_map (homEquiv W W.Q L).symm
   · intro h
-    exact ⟨small_map (localizationsHomEquiv W W.Q L)⟩
+    exact ⟨small_map (homEquiv W W.Q L)⟩
 
 lemma hasSmallLocalizedHom_of_isLocalization :
-    HasSmallLocalizedHom.{w'} W X Y := by
-  rw [W.hasSmallLocalizedHom_iff L]
+    HasSmallLocalizedHom.{v₂} W X Y := by
+  rw [hasSmallLocalizedHom_iff W L]
   infer_instance
 
 variable (X Y) in
 lemma small_of_hasSmallLocalizedHom [HasSmallLocalizedHom.{w} W X Y] :
     Small.{w} (L.obj X ⟶ L.obj Y) := by
-  rwa [← W.hasSmallLocalizedHom_iff]
+  rwa [← hasSmallLocalizedHom_iff W]
 
 lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
     HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y' := by
-  simp only [W.hasSmallLocalizedHom_iff W.Q]
+  simp only [hasSmallLocalizedHom_iff W W.Q]
   exact small_congr (Iso.homEquiv (W.Q.mapIso e) (W.Q.mapIso e'))
 
-end MorphismProperty
-
-namespace Localization
-
-open MorphismProperty
+end
 
 /-- The type of morphisms from `X` to `Y` in the localized category
 with respect to `W : MorphismProperty C` that is shrunk to `Type w`
 when `HasSmallLocalizedHom.{w} W X Y` holds. -/
-def SmallHom [HasSmallLocalizedHom.{w} W X Y] : Type w :=
-  letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
+def SmallHom (X Y : C) [HasSmallLocalizedHom.{w} W X Y] : Type w :=
   Shrink.{w} (W.Q.obj X ⟶ W.Q.obj Y)
 
 namespace SmallHom
 
-variable {X Y Z}
-
 /-- The canonical bijection `SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y)`
 when `L` is a localization functor for `W : MorphismProperty C` and
 that `HasSmallLocalizedHom.{w} W X Y` holds. -/
-noncomputable def equiv [HasSmallLocalizedHom.{w} W X Y] :
+noncomputable def equiv (L : C ⥤ D) [L.IsLocalization W] {X Y : C}
+    [HasSmallLocalizedHom.{w} W X Y] :
     SmallHom.{w} W X Y ≃ (L.obj X ⟶ L.obj Y) :=
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
-  (equivShrink _).symm.trans (W.localizationsHomEquiv W.Q L)
-
-variable [HasSmallLocalizedHom.{w} W X Y]
+  (equivShrink _).symm.trans (homEquiv W W.Q L)
+
+lemma equiv_equiv_symm (L : C ⥤ D) [L.IsLocalization W]
+    (L' : C ⥤ D') [L'.IsLocalization W] (G : D ⥤ D')
+    (e : L ⋙ G ≅ L') {X Y : C} [HasSmallLocalizedHom.{w} W X Y]
+    (f : L.obj X ⟶ L.obj Y) :
+    equiv W L' ((equiv W L).symm f) =
+      e.inv.app X ≫ G.map f ≫ e.hom.app Y := by
+  dsimp [equiv]
+  rw [Equiv.symm_apply_apply, homEquiv_trans]
+  apply homEquiv_eq
 
 /-- The element in `SmallHom W X Y` induced by `f : X ⟶ Y`. -/
-noncomputable def mk (f : X ⟶ Y) : SmallHom.{w} W X Y :=
+noncomputable def mk {X Y : C} [HasSmallLocalizedHom.{w} W X Y] (f : X ⟶ Y) :
+    SmallHom.{w} W X Y :=
   (equiv.{w} W W.Q).symm (W.Q.map f)
 
 @[simp]
-lemma equiv_mk (f : X ⟶ Y) : equiv.{w} W L (mk W f) = L.map f := by
+lemma equiv_mk (L : C ⥤ D) [L.IsLocalization W] {X Y : C}
+    [HasSmallLocalizedHom.{w} W X Y] (f : X ⟶ Y) :
+    equiv.{w} W L (mk W f) = L.map f := by
   simp [equiv, mk]
 
-variable {W} in
+variable {W}
+
 /-- The formal inverse in `SmallHom W X Y` of a morphism `f : Y ⟶ X` such that `W f`. -/
-noncomputable def mkInv (f : Y ⟶ X) (hf : W f) : SmallHom.{w} W X Y :=
+noncomputable def mkInv {X Y : C} (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X Y] :
+    SmallHom.{w} W X Y :=
   (equiv.{w} W W.Q).symm (Localization.isoOfHom W.Q W f hf).inv
 
 @[simp]
-lemma equiv_mkInv (f : Y ⟶ X) (hf : W f) :
+lemma equiv_mkInv (L : C ⥤ D) [L.IsLocalization W] {X Y : C} (f : Y ⟶ X) (hf : W f)
+    [HasSmallLocalizedHom.{w} W X Y] :
     equiv.{w} W L (mkInv f hf) = (Localization.isoOfHom L W f hf).inv := by
-  dsimp only [equiv, mkInv]
-  simp only [localizationHomEquiv_refl, Equiv.trans_refl, Equiv.symm_symm,
-    Equiv.trans_apply, Equiv.symm_apply_apply, localizationsHomEquiv_isoOfHom_inv]
-
-section
-
-variable [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
-
-variable {W}
-
-variable (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z)
+  simp only [equiv, mkInv, Equiv.symm_trans_apply, Equiv.symm_symm, homEquiv_symm_apply,
+    Equiv.trans_apply, Equiv.symm_apply_apply, homEquiv_isoOfHom_inv]
 
 /-- The composition on `SmallHom W`. -/
-noncomputable def comp (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
+noncomputable def comp {X Y Z : C} [HasSmallLocalizedHom.{w} W X Y]
+    [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
+    (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
     SmallHom.{w} W X Z :=
   (equiv W W.Q).symm (equiv W W.Q α ≫ equiv W W.Q β)
 
-lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
+lemma equiv_comp (L : C ⥤ D) [L.IsLocalization W] {X Y Z : C} [HasSmallLocalizedHom.{w} W X Y]
+    [HasSmallLocalizedHom.{w} W Y Z] [HasSmallLocalizedHom.{w} W X Z]
+    (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) :
+    equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q X Y
   letI := small_of_hasSmallLocalizedHom.{w} W W.Q Y Z
   obtain ⟨α, rfl⟩ := (equivShrink _).surjective α
@@ -170,33 +142,132 @@ lemma equiv_comp : equiv W L (α.comp β) = equiv W L α ≫ equiv W L β := by
   dsimp [equiv, comp]
   rw [Equiv.symm_apply_apply]
   erw [(equivShrink _).symm_apply_apply, (equivShrink _).symm_apply_apply]
-  rw [← localizationHomEquiv_comp, localizationHomEquiv_refl, Equiv.refl_symm,
-    Equiv.refl_apply, Equiv.refl_apply, localizationHomEquiv_comp]
+  simp only [homEquiv_refl, homEquiv_comp]
 
-lemma mk_comp_mk (f : X ⟶ Y) (g : Y ⟶ Z) :
+variable {X Y Z T : C}
+
+lemma mk_comp_mk [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Z]
+    [HasSmallLocalizedHom.{w} W X Z] (f : X ⟶ Y) (g : Y ⟶ Z) :
     (mk W f).comp (mk W g) = mk W (f ≫ g) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
-end
+@[simp]
+lemma comp_mk_id [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y Y]
+    (α : SmallHom.{w} W X Y)  :
+    α.comp (mk W (𝟙 Y)) = α :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
 
-section
+@[simp]
+lemma mk_id_comp [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W X X]
+    (α : SmallHom.{w} W X Y) :
+    (mk W (𝟙 X)).comp α = α :=
+  (equiv W W.Q).injective (by simp [equiv_comp])
 
-variable [HasSmallLocalizedHom.{w} W Y X]
+@[simp]
+lemma comp_assoc [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W X Z]
+    [HasSmallLocalizedHom.{w} W X T] [HasSmallLocalizedHom.{w} W Y Z]
+    [HasSmallLocalizedHom.{w} W Y T] [HasSmallLocalizedHom.{w} W Z T]
+    (α : SmallHom.{w} W X Y) (β : SmallHom.{w} W Y Z) (γ : SmallHom.{w} W Z T) :
+    (α.comp β).comp γ = α.comp (β.comp γ) := by
+  apply (equiv W W.Q).injective
+  simp only [equiv_comp, assoc]
 
 @[simp]
-lemma mk_comp_mkInv (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W Y Y] :
+lemma mk_comp_mkInv [HasSmallLocalizedHom.{w} W X Y] [HasSmallLocalizedHom.{w} W Y X]
+    [HasSmallLocalizedHom.{w} W Y Y] (f : Y ⟶ X) (hf : W f) :
     (mk W f).comp (mkInv f hf) = mk W (𝟙 Y) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
 @[simp]
-lemma mkInv_comp_mk (f : Y ⟶ X) (hf : W f) [HasSmallLocalizedHom.{w} W X X] :
+lemma mkInv_comp_mk [HasSmallLocalizedHom.{w} W X X] [HasSmallLocalizedHom.{w} W X Y]
+    [HasSmallLocalizedHom.{w} W Y X] (f : Y ⟶ X) (hf : W f) :
     (mkInv f hf).comp (mk W f) = mk W (𝟙 X) :=
   (equiv W W.Q).injective (by simp [equiv_comp])
 
-end
-
 end SmallHom
 
 end Localization
 
+namespace LocalizerMorphism
+
+open Localization
+
+variable {C₁ : Type u₁} [Category.{v₁} C₁] {W₁ : MorphismProperty C₁}
+  {C₂ : Type u₂} [Category.{v₂} C₂] {W₂ : MorphismProperty C₂}
+  {D₁ : Type u₃} [Category.{v₃} D₁] {D₂ : Type u₄} [Category.{v₄} D₂]
+  (Φ : LocalizerMorphism W₁ W₂) (L₁ : C₁ ⥤ D₁) [L₁.IsLocalization W₁]
+  (L₂ : C₂ ⥤ D₂) [L₂.IsLocalization W₂]
+
+variable {W}
+
+section
+
+variable {X Y Z : C₁}
+
+variable [HasSmallLocalizedHom.{w} W₁ X Y]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y)]
+
+/-- The action of a localizer morphism on `SmallHom`. -/
+noncomputable def smallHomMap (f : SmallHom.{w} W₁ X Y) :
+    SmallHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y) :=
+  (SmallHom.equiv W₂ W₂.Q).symm
+    (Iso.homEquiv ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
+      ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
+      ((Φ.localizedFunctor W₁.Q W₂.Q).map ((SmallHom.equiv W₁ W₁.Q) f)))
+
+lemma equiv_smallHomMap (G : D₁ ⥤ D₂) (e : Φ.functor ⋙ L₂ ≅ L₁ ⋙ G)
+    (f : SmallHom.{w} W₁ X Y) :
+    (SmallHom.equiv W₂ L₂) (Φ.smallHomMap f) =
+      e.hom.app X ≫ G.map (SmallHom.equiv W₁ L₁ f) ≫ e.inv.app Y := by
+  obtain ⟨g, rfl⟩ := (SmallHom.equiv W₁ W₁.Q).symm.surjective f
+  simp only [smallHomMap, Equiv.apply_symm_apply]
+  let G' := Φ.localizedFunctor W₁.Q W₂.Q
+  let β := CatCommSq.iso Φ.functor W₁.Q W₂.Q G'
+  let E₁ := (uniq W₁.Q L₁ W₁).functor
+  let α₁ : W₁.Q ⋙ E₁ ≅ L₁ := compUniqFunctor W₁.Q L₁ W₁
+  let E₂ := (uniq W₂.Q L₂ W₂).functor
+  let α₂ : W₂.Q ⋙ E₂ ≅ L₂ := compUniqFunctor W₂.Q L₂ W₂
+  rw [SmallHom.equiv_equiv_symm W₁ W₁.Q L₁ E₁ α₁,
+    SmallHom.equiv_equiv_symm W₂ W₂.Q L₂ E₂ α₂]
+  change α₂.inv.app _ ≫ E₂.map (β.hom.app X ≫ G'.map g ≫ β.inv.app Y) ≫ _ = _
+  let γ : G' ⋙ E₂ ≅ E₁ ⋙ G := liftNatIso W₁.Q W₁ (W₁.Q ⋙ G' ⋙ E₂) (W₁.Q ⋙ E₁ ⋙ G) _ _
+    ((Functor.associator _ _ _).symm ≪≫ isoWhiskerRight β.symm E₂ ≪≫
+      Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ α₂ ≪≫ e ≪≫
+      isoWhiskerRight α₁.symm G ≪≫ Functor.associator _ _ _)
+  have hγ : ∀ (X : C₁), γ.hom.app (W₁.Q.obj X) =
+      E₂.map (β.inv.app X) ≫ α₂.hom.app (Φ.functor.obj X) ≫
+        e.hom.app X ≫ G.map (α₁.inv.app X) := fun X ↦ by
+    dsimp [γ]
+    rw [liftNatTrans_app]
+    dsimp
+    rw [id_comp, id_comp, comp_id]
+    erw [id_comp, comp_id]
+  simp only [Functor.map_comp, assoc]
+  erw [← NatIso.naturality_1 γ]
+  simp only [Functor.comp_map, ← cancel_epi (e.inv.app X), ← cancel_epi (G.map (α₁.hom.app X)),
+    ← cancel_epi (γ.hom.app (W₁.Q.obj X)), assoc, Iso.inv_hom_id_app_assoc,
+    ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.map_id, id_comp,
+    Iso.hom_inv_id_app_assoc]
+  simp only [hγ, assoc, ← Functor.map_comp_assoc, Iso.inv_hom_id_app,
+    Functor.map_id, id_comp, Iso.hom_inv_id_app_assoc,
+    Iso.inv_hom_id_app_assoc, Iso.hom_inv_id_app, Functor.comp_obj, comp_id]
+
+end
+
+variable {X Y Z : C₁}
+
+variable [HasSmallLocalizedHom.{w} W₁ X Y] [HasSmallLocalizedHom.{w} W₁ Y Z]
+  [HasSmallLocalizedHom.{w} W₁ X Z]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y)]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj Y) (Φ.functor.obj Z)]
+  [HasSmallLocalizedHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Z)]
+
+lemma smallHomMap_comp (f : SmallHom.{w} W₁ X Y) (g : SmallHom.{w} W₁ Y Z) :
+    Φ.smallHomMap (f.comp g) = (Φ.smallHomMap f).comp (Φ.smallHomMap g) := by
+  apply (SmallHom.equiv W₂ W₂.Q).injective
+  simp [Φ.equiv_smallHomMap W₁.Q W₂.Q (Φ.localizedFunctor W₁.Q W₂.Q) (CatCommSq.iso _ _ _ _),
+    SmallHom.equiv_comp]
+
+end LocalizerMorphism
+
 end CategoryTheory

From 69e5969a5caacb7d9aca2fde2b846873b889c703 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 15:49:32 +0200
Subject: [PATCH 30/63] whitespace

---
 Mathlib/CategoryTheory/Localization/HomEquiv.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Localization/HomEquiv.lean b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
index 14ae6ff8233d07..1f66d431eec3ff 100644
--- a/Mathlib/CategoryTheory/Localization/HomEquiv.lean
+++ b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
@@ -96,7 +96,7 @@ lemma homMap_homMap (f : L₁.obj X ⟶ L₁.obj Y) :
   let e' : Ψ.functor ⋙ L₃ ≅ L₂ ⋙ G' := CatCommSq.iso _ _ _ _
   rw [Φ.homMap_apply L₁ L₂ G e, Ψ.homMap_apply L₂ L₃ G' e',
     (Φ.comp Ψ).homMap_apply L₁ L₃ (G ⋙ G')
-    (Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ e' ≪≫
+      (Functor.associator _ _ _ ≪≫ isoWhiskerLeft _ e' ≪≫
       (Functor.associator _ _ _).symm ≪≫ isoWhiskerRight e _ ≪≫
       Functor.associator _ _ _)]
   dsimp

From 40d4490da39f54b6a98e603f0118655112ff8f9a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 17:59:46 +0200
Subject: [PATCH 31/63] cleaning up

---
 .../Localization/SmallShiftedHom.lean         | 131 +++++++++---------
 1 file changed, 68 insertions(+), 63 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index f6b2c7455f4e87..9c6eb93a22fe72 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -3,23 +3,34 @@ 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.Localization.LocalizerMorphism
 import Mathlib.CategoryTheory.Localization.SmallHom
 import Mathlib.CategoryTheory.Shift.ShiftedHom
 import Mathlib.CategoryTheory.Shift.Localization
 
-universe w w' v₁ v₂ v₃ v₄ u₁ u₂ u₃ u₄
+/-!
+# Shrinking morphisms in localized categories equipped with shifts
+
+If `C` is a category equipped with a shift by an additive monoid `M`,
+and `W : MorphismProperty C` is compatible with the shift,
+we define a type-class `HasSmallLocalizedShiftedHom.{w} W X Y` which
+says that all the types of morphisms from `X⟦a⟧` to `Y⟦b⟧` in the
+localized category are `w`-small for a certain universe. Then,
+we define types `SmallShiftedHom.{w} W X Y m : Type w` for all `m : M`,
+and endow these with a composition which transports the composition
+on the types `ShiftedHom (L.obj X) (L.obj Y) m` when `L : C ⥤ D` is
+any localization functor for `W`.
+
+-/
+
+universe w w' v₁ v₂ u₁ u₂
 
 namespace CategoryTheory
 
 open Category
 
-variable {C : Type u₁} [Category.{v₁} C] (W : MorphismProperty C)
-  {C' : Type u₂} [Category.{v₂} C'] (W' : MorphismProperty C')
-  {D : Type u₃} [Category.{v₃} D]
-  {D' : Type u₄} [Category.{v₄} D']
-  {M : Type w'} [AddMonoid M] [HasShift C M] [HasShift C' M] [HasShift D M]
-  [W.IsCompatibleWithShift M] [W'.IsCompatibleWithShift M]
+variable {C : Type u₁} [Category.{v₁} C] {D : Type u₂} [Category.{v₂} D]
+  (W : MorphismProperty C) {M : Type w'} [AddMonoid M] [HasShift C M] [HasShift D M]
+  [W.IsCompatibleWithShift M]
 
 namespace Localization
 
@@ -28,6 +39,9 @@ section
 variable (X Y : C)
 
 variable (M) in
+/-- Given objects `X` and `Y` in a category `C`, this is the property that
+all the types of morphisms from `X⟦a⟧` to `Y⟦b⟧` are `w`-small
+in the localized category with respect to a class of morphisms `W`. -/
 abbrev HasSmallLocalizedShiftedHom : Prop :=
   ∀ (a b : M), HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧)
 
@@ -39,25 +53,21 @@ lemma hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ :
   (hasSmallLocalizedHom_iff_of_isos W
     ((shiftFunctorZero C M).app X) ((shiftFunctorZero C M).app Y)).1 inferInstance
 
-instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₁ (m : M) :
-    HasSmallLocalizedHom.{w} W X (Y⟦m⟧) :=
+instance (m : M) : HasSmallLocalizedHom.{w} W X (Y⟦m⟧) :=
   (hasSmallLocalizedHom_iff_of_isos W
     ((shiftFunctorZero C M).app X) (Iso.refl (Y⟦m⟧))).1 inferInstance
 
-instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₂ (m m' n : M) :
-    HasSmallLocalizedHom.{w} W (X⟦m⟧⟦m'⟧) (Y⟦n⟧) :=
+instance (m : M) : HasSmallLocalizedHom.{w} W (X⟦m⟧) Y :=
   (hasSmallLocalizedHom_iff_of_isos W
-    ((shiftFunctorAdd C m m').app X) (Iso.refl (Y⟦n⟧))).1 inferInstance
+    (Iso.refl (X⟦m⟧)) ((shiftFunctorZero C M).app Y)).1 inferInstance
 
-instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₃ (m n n' : M) :
-    HasSmallLocalizedHom.{w} W (X⟦m⟧) (Y⟦n⟧⟦n'⟧) :=
+instance (m m' n : M) : HasSmallLocalizedHom.{w} W (X⟦m⟧⟦m'⟧) (Y⟦n⟧) :=
   (hasSmallLocalizedHom_iff_of_isos W
-    (Iso.refl (X⟦m⟧)) ((shiftFunctorAdd C n n').app Y)).1 inferInstance
+    ((shiftFunctorAdd C m m').app X) (Iso.refl (Y⟦n⟧))).1 inferInstance
 
-instance hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₄ (m : M) :
-    HasSmallLocalizedHom.{w} W (X⟦m⟧) Y :=
+instance (m n n' : M) : HasSmallLocalizedHom.{w} W (X⟦m⟧) (Y⟦n⟧⟦n'⟧) :=
   (hasSmallLocalizedHom_iff_of_isos W
-    (Iso.refl (X⟦m⟧)) ((shiftFunctorZero C M).app Y)).1 inferInstance
+    (Iso.refl (X⟦m⟧)) ((shiftFunctorAdd C n n').app Y)).1 inferInstance
 
 end
 
@@ -65,21 +75,25 @@ namespace SmallHom
 
 variable {W}
 variable (L : C ⥤ D) [L.IsLocalization W] [L.CommShift M]
-variable {X Y : C} [HasSmallLocalizedHom.{w} W X Y]
-    (f : SmallHom.{w} W X Y) (a : M) [HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦a⟧)]
+  {X Y : C} [HasSmallLocalizedHom.{w} W X Y]
+  (f : SmallHom.{w} W X Y) (a : M) [HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦a⟧)]
 
+/-- Given `f : SmallHom W X Y` and `a : M`, this is the element
+in `SmallHom W (X⟦a⟧) (Y⟦a⟧)` obtained by shifting by `a`. -/
 noncomputable def shift : SmallHom.{w} W (X⟦a⟧) (Y⟦a⟧) :=
-  f.map (LocalizerMorphism.mk (shiftFunctor C a)
-    (by rw [MorphismProperty.IsCompatibleWithShift.condition]))
+  (LocalizerMorphism.mk (shiftFunctor C a)
+    (by rw [MorphismProperty.IsCompatibleWithShift.condition])).smallHomMap f
 
 lemma equiv_shift : equiv W L (f.shift a) =
     (L.commShiftIso a).hom.app X ≫ (equiv W L f)⟦a⟧' ≫ (L.commShiftIso a).inv.app Y :=
-  equiv_map (LocalizerMorphism.mk (shiftFunctor C a) _) _ _ _ (L.commShiftIso a) f
+  (LocalizerMorphism.mk (shiftFunctor C a) _).equiv_smallHomMap _ _ _ (L.commShiftIso a) f
 
 end SmallHom
 
-def SmallShiftedHom (X Y : C)
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) : Type w :=
+/-- The type of morphisms from `X` to `Y⟦m⟧` in the localized category
+with respect to `W : MorphismProperty C` that is shrunk to `Type w`
+when `HasSmallLocalizedShiftedHom.{w} W X Y` holds. -/
+def SmallShiftedHom (X Y : C) [HasSmallLocalizedShiftedHom.{w} W M X Y] (m : M) : Type w :=
   SmallHom W X (Y⟦m⟧)
 
 namespace SmallShiftedHom
@@ -89,31 +103,23 @@ section
 variable {W}
 variable {X Y Z : C}
 
-noncomputable def shift {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y]
+/-- Given `f : SmallShiftedHom.{w} W X Y a`, this is the element in
+`SmallHom.{w} W (X⟦n⟧) (Y⟦a'⟧)` that is obtained by shifting by `n`
+when `a + n = a'`. -/
+noncomputable def shift {a : M} [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [HasSmallLocalizedShiftedHom.{w} W M Y Y]
   (f : SmallShiftedHom.{w} W X Y a) (n a' : M) (h : a + n = a') :
     SmallHom.{w} W (X⟦n⟧) (Y⟦a'⟧) :=
   (SmallHom.shift f n).comp (SmallHom.mk W ((shiftFunctorAdd' C a n a' h).inv.app Y))
 
-noncomputable def comp {a b c : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z Z]
+/-- The composition on `SmallShiftedHom W`. -/
+noncomputable def comp {a b c : M} [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [HasSmallLocalizedShiftedHom.{w} W M Y Z] [HasSmallLocalizedShiftedHom.{w} W M X Z]
+    [HasSmallLocalizedShiftedHom.{w} W M Z Z]
     (f : SmallShiftedHom.{w} W X Y a) (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c) :
     SmallShiftedHom.{w} W X Z c :=
   SmallHom.comp f (g.shift a c h)
 
-noncomputable def equiv₀ [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y] :
-    SmallShiftedHom.{w} W X Y (0 : M) ≃
-      letI := W.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ M X Y; SmallHom.{w} W X Y :=
-  letI := W.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ M X Y
-  letI := W.hasSmallLocalizedHom_of_hasSmallLocalizedShiftedHom₀ M Y Y
-  { toFun := fun f ↦ SmallHom.comp f (SmallHom.mk W ((shiftFunctorZero C M).hom.app Y))
-    invFun := fun g ↦ SmallHom.comp g (SmallHom.mk W ((shiftFunctorZero C M).inv.app Y))
-    left_inv := fun f ↦ by simp [SmallHom.mk_comp_mk]
-    right_inv := fun g ↦ by simp [SmallHom.mk_comp_mk] }
-
 end
 
 section
@@ -121,22 +127,26 @@ section
 variable (L : C ⥤ D) [L.IsLocalization W] [HasShift D M] [L.CommShift M]
   {X Y Z T : C}
 
-noncomputable def equiv [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y] {m : M} :
+/-- The bijection `SmallShiftedHom.{w} W X Y m ≃ ShiftedHom (L.obj X) (L.obj Y) m`
+for all `m : M`, and `X` and `Y` in `C`m when `L : C ⥤ D` is a localization functor for
+`W : MorphismProperty C` such that the category `D` is equipped with a shift by `M`
+and `L` commutes with the shifts. -/
+noncomputable def equiv [HasSmallLocalizedShiftedHom.{w} W M X Y] {m : M} :
     SmallShiftedHom.{w} W X Y m ≃ ShiftedHom (L.obj X) (L.obj Y) m :=
   (SmallHom.equiv W L).trans ((L.commShiftIso m).app Y).homToEquiv
 
-lemma equiv_shift' {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y]
+lemma equiv_shift' {a : M} [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [HasSmallLocalizedShiftedHom.{w} W M Y Y]
     (f : SmallShiftedHom.{w} W X Y a) (n a' : M) (h : a + n = a') :
     SmallHom.equiv W L (f.shift n a' h) = (L.commShiftIso n).hom.app X ≫
-        (SmallHom.equiv W L f)⟦n⟧' ≫ ((L.commShiftIso a).hom.app Y)⟦n⟧' ≫
+      (SmallHom.equiv W L f)⟦n⟧' ≫ ((L.commShiftIso a).hom.app Y)⟦n⟧' ≫
         (shiftFunctorAdd' D a n a' h).inv.app (L.obj Y) ≫ (L.commShiftIso a').inv.app Y := by
   simp only [shift, SmallHom.equiv_comp, SmallHom.equiv_shift, SmallHom.equiv_mk, assoc,
     L.commShiftIso_add' h, Functor.CommShift.isoAdd'_inv_app, Iso.inv_hom_id_app_assoc,
     ← Functor.map_comp_assoc, Iso.hom_inv_id_app, Functor.comp_obj, comp_id]
 
-lemma equiv_shift {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Y]
+lemma equiv_shift {a : M} [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [HasSmallLocalizedShiftedHom.{w} W M Y Y]
     (f : SmallShiftedHom.{w} W X Y a) (n a' : M) (h : a + n = a') :
     equiv W L (f.shift n a' h) = (L.commShiftIso n).hom.app X ≫ (equiv W L f)⟦n⟧' ≫
       (shiftFunctorAdd' D a n a' h).inv.app (L.obj Y) := by
@@ -145,10 +155,9 @@ lemma equiv_shift {a : M} [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M
   simp only [Functor.comp_obj, Iso.app_hom, assoc, Iso.inv_hom_id_app, comp_id, Functor.map_comp]
   rfl
 
-lemma equiv_comp [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z Z] {a b c : M}
+lemma equiv_comp [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    [HasSmallLocalizedShiftedHom.{w} W M Y Z] [HasSmallLocalizedShiftedHom.{w} W M X Z]
+    [HasSmallLocalizedShiftedHom.{w} W M Z Z] {a b c : M}
     (f : SmallShiftedHom.{w} W X Y a) (g : SmallShiftedHom.{w} W Y Z b) (h : b + a = c) :
     equiv W L (f.comp g h) = (equiv W L f).comp (equiv W L g) h := by
   dsimp [comp, equiv, ShiftedHom.comp]
@@ -160,16 +169,12 @@ lemma equiv_comp [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
 end
 
 lemma comp_assoc {X Y Z T : C} {a₁ a₂ a₃ a₁₂ a₂₃ a : M}
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Y]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M X T]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Y T]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z T]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M Z Z]
-    [MorphismProperty.HasSmallLocalizedShiftedHom.{w} W M T T]
-    (α : SmallShiftedHom.{w} W X Y a₁)
-    (β : SmallShiftedHom.{w} W Y Z a₂) (γ : SmallShiftedHom.{w} W Z T a₃)
+    [HasSmallLocalizedShiftedHom.{w} W M X Y] [HasSmallLocalizedShiftedHom.{w} W M X Z]
+    [HasSmallLocalizedShiftedHom.{w} W M X T] [HasSmallLocalizedShiftedHom.{w} W M Y Z]
+    [HasSmallLocalizedShiftedHom.{w} W M Y T] [HasSmallLocalizedShiftedHom.{w} W M Z T]
+    [HasSmallLocalizedShiftedHom.{w} W M Z Z] [HasSmallLocalizedShiftedHom.{w} W M T T]
+    (α : SmallShiftedHom.{w} W X Y a₁) (β : SmallShiftedHom.{w} W Y Z a₂)
+    (γ : SmallShiftedHom.{w} W Z T a₃)
     (h₁₂ : a₂ + a₁ = a₁₂) (h₂₃ : a₃ + a₂ = a₂₃) (h : a₃ + a₂ + a₁ = a) :
     (α.comp β h₁₂).comp γ (show a₃ + a₁₂ = a by rw [← h₁₂, ← add_assoc, h]) =
       α.comp (β.comp γ h₂₃) (by rw [← h₂₃, h]) := by

From 2d3bae935f36ee57648aa3f56eed0a1fc7d6bce7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 19:10:03 +0200
Subject: [PATCH 32/63] feat: definition of Ext-groups

---
 Mathlib.lean                                  |  1 +
 .../Homology/DerivedCategory/Basic.lean       | 14 +++
 .../Algebra/Homology/DerivedCategory/Ext.lean | 91 +++++++++++++++++++
 3 files changed, 106 insertions(+)
 create mode 100644 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean

diff --git a/Mathlib.lean b/Mathlib.lean
index 74bbfe8c789d62..af826c1aff3c38 100644
--- a/Mathlib.lean
+++ b/Mathlib.lean
@@ -292,6 +292,7 @@ import Mathlib.Algebra.Homology.ComplexShape
 import Mathlib.Algebra.Homology.ComplexShapeSigns
 import Mathlib.Algebra.Homology.ConcreteCategory
 import Mathlib.Algebra.Homology.DerivedCategory.Basic
+import Mathlib.Algebra.Homology.DerivedCategory.Ext
 import Mathlib.Algebra.Homology.DerivedCategory.HomologySequence
 import Mathlib.Algebra.Homology.DifferentialObject
 import Mathlib.Algebra.Homology.Embedding.Basic
diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
index 274b876538225c..a9a31a4848aa7d 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
@@ -5,6 +5,7 @@ Authors: Joël Riou
 -/
 import Mathlib.Algebra.Homology.HomotopyCategory.HomologicalFunctor
 import Mathlib.Algebra.Homology.HomotopyCategory.ShiftSequence
+import Mathlib.Algebra.Homology.HomotopyCategory.SingleFunctors
 import Mathlib.Algebra.Homology.HomotopyCategory.Triangulated
 import Mathlib.Algebra.Homology.Localization
 
@@ -195,4 +196,17 @@ instance {D : Type*} [Category D] : ((whiskeringLeft _ _ D).obj (Qh (C := C))).F
   inferInstanceAs
     (Localization.whiskeringLeftFunctor' _ (HomotopyCategory.quasiIso _ _) D).Faithful
 
+/-- The single functors `C ⥤ DerivedCategory C` for all `n : ℤ` along with
+their compatibilities with shifts. -/
+noncomputable def singleFunctors : SingleFunctors C (DerivedCategory C) ℤ :=
+  (HomotopyCategory.singleFunctors C).postcomp Qh
+
+/-- The shift functor `C ⥤ DerivedCategory C` which sends `X : C` to the
+single cochain complex with `X` sitting in degree `n : ℤ`. -/
+noncomputable abbrev singleFunctor (n : ℤ) := (singleFunctors C).functor n
+
+instance (n : ℤ) : (singleFunctor C n).Additive := by
+  dsimp [singleFunctor, singleFunctors]
+  infer_instance
+
 end DerivedCategory
diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
new file mode 100644
index 00000000000000..5710595c213c5d
--- /dev/null
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -0,0 +1,91 @@
+/-
+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.Algebra.Homology.DerivedCategory.Basic
+import Mathlib.CategoryTheory.Localization.SmallShiftedHom
+
+/-!
+# Ext groups in abelian categories
+
+...
+TODO
+...
+
+-/
+
+universe w' w v u
+
+namespace CategoryTheory
+
+variable (C : Type u) [Category.{v} C] [Abelian C]
+
+instance : (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)).IsCompatibleWithShift ℤ := sorry
+
+open Localization
+
+abbrev HasSmallExt : Prop :=
+  ∀ (X Y : C), HasSmallLocalizedShiftedHom.{w} (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) ℤ
+    ((CochainComplex.singleFunctor C 0).obj X) ((CochainComplex.singleFunctor C 0).obj Y)
+
+variable {C}
+
+variable [HasSmallExt.{w} C]
+
+namespace Abelian
+
+/-- The Ext-groups in an abelian category `C`, defined as a `Type w` when
+`[HasSmallExt.{w} C]`. -/
+def Ext (X Y : C) (n : ℕ) : Type w :=
+  SmallShiftedHom.{w} (HomologicalComplex.quasiIso C (ComplexShape.up ℤ))
+    ((CochainComplex.singleFunctor C 0).obj X)
+    ((CochainComplex.singleFunctor C 0).obj Y) (n : ℤ)
+
+namespace Ext
+
+variable {X Y Z T : C}
+
+/-- The composition of `Ext`. -/
+noncomputable def comp {a b : ℕ} (α : Ext X Y a) (β : Ext Y Z b) {c : ℕ} (h : a + b = c) :
+    Ext X Z c :=
+  SmallShiftedHom.comp α β (by omega)
+
+lemma comp_assoc {a₁ a₂ a₃ a₁₂ a₂₃ a : ℕ} (α : Ext X Y a₁) (β : Ext Y Z a₂) (γ : Ext Z T a₃)
+    (h₁₂ : a₁ + a₂ = a₁₂) (h₂₃ : a₂ + a₃ = a₂₃) (h : a₁ + a₂ + a₃ = a) :
+    (α.comp β h₁₂).comp γ (show a₁₂ + a₃ = a by omega) =
+      α.comp (β.comp γ h₂₃) (by omega) :=
+  SmallShiftedHom.comp_assoc _ _ _ _ _ _ (by omega)
+
+section
+
+variable [HasDerivedCategory.{w'} C]
+
+instance : (DerivedCategory.Q (C := C)).CommShift ℤ := sorry
+
+noncomputable def homEquiv {n : ℕ} :
+    Ext.{w} X Y n ≃ ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X)
+      ((DerivedCategory.singleFunctor C 0).obj Y) (n : ℤ) :=
+  SmallShiftedHom.equiv (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) DerivedCategory.Q
+
+noncomputable abbrev hom {a : ℕ} (α : Ext X Y a) :
+    ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X)
+      ((DerivedCategory.singleFunctor C 0).obj Y) (a : ℤ) :=
+  homEquiv α
+
+@[simp]
+lemma comp_hom {a b : ℕ} (α : Ext X Y a) (β : Ext Y Z b) {c : ℕ} (h : a + b = c) :
+    (α.comp β h).hom = α.hom.comp β.hom (by omega) := by
+  apply SmallShiftedHom.equiv_comp
+
+@[ext]
+lemma ext {n : ℕ} {α β : Ext X Y n} (h : α.hom = β.hom) : α = β :=
+  homEquiv.injective h
+
+end
+
+end Ext
+
+end Abelian
+
+end CategoryTheory

From b9de9d844becb5d1e7662a00b60c033204dfc735 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Wed, 19 Jun 2024 19:46:25 +0200
Subject: [PATCH 33/63] wip

---
 .../Algebra/Homology/DerivedCategory/Ext.lean | 48 ++++++++++++++++---
 1 file changed, 41 insertions(+), 7 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 5710595c213c5d..ed09f20b309a0e 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -9,9 +9,36 @@ import Mathlib.CategoryTheory.Localization.SmallShiftedHom
 /-!
 # Ext groups in abelian categories
 
-...
-TODO
-...
+Let `C` be an abelian category (with `C : Type u` and `Category.{v} C`).
+In this file, we introduce the assumption `HasExt.{w} C` which asserts
+that morphisms between single complexes in arbitrary degrees in
+the derived category of `C` are `w`-small. Under this assumption,
+we define `Ext.{w} X Y n : Type w` as shrunk versions of suitable
+types of morphisms in the derived category. In particular, when `C` has
+enough projectives or enough injectives, the property `HasExt.{v} C`
+shall hold (TODO).
+
+Note: in certain situations, `w := v` shall be the preferred
+choice of universe (e.g. if `C := ModuleCat.{v} R` with `R : Type v`).
+However, in the development of the API for Ext-groups, it is important
+to keep a larger degree of generality for universes, as `w < v`
+may happen in certain situations. Indeed, if `X : Scheme.{u}`,
+then the underlying category of the étale site of `X` shall be a large
+category. However, the category `Sheaf X.Etale AddCommGroupCat.{u}`
+shall have good properties (because there is a small category of affine
+schemes with the same category of sheaves), and even though the type of
+morphisms in `Sheaf X.Etale AddCommGroupCat.{u}` shall be
+in `Type (u + 1)`, these types are going to be `u`-small.
+Then, for `C := Sheaf X.etale AddCommGroupCat.{u}`, we will have
+`Category.{u + 1} C`, but `HasExt.{u} C` will hold
+(as `C` has enough injectives). Then, the `Ext` groups between étale
+sheaves over `X` shall be in `Type u`.
+
+## TODO
+* construct the additive structure on `Ext`
+* compute `Ext X Y 0`
+* define the class in `Ext S.X₃ S.X₁ 1` of a short exact short complex `S`
+* construct the long exact sequences of `Ext`.
 
 -/
 
@@ -25,18 +52,21 @@ instance : (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)).IsCompatibleWit
 
 open Localization
 
-abbrev HasSmallExt : Prop :=
+/-- The property that morphisms between single complexes in arbitrary degrees are `w`-small
+in the derived category. -/
+abbrev HasExt : Prop :=
   ∀ (X Y : C), HasSmallLocalizedShiftedHom.{w} (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) ℤ
     ((CochainComplex.singleFunctor C 0).obj X) ((CochainComplex.singleFunctor C 0).obj Y)
 
+lemma hasExt_of_hasDerivedCategory [HasDerivedCategory.{w} C] : HasExt.{w} C := sorry
+
 variable {C}
 
-variable [HasSmallExt.{w} C]
+variable [HasExt.{w} C]
 
 namespace Abelian
 
-/-- The Ext-groups in an abelian category `C`, defined as a `Type w` when
-`[HasSmallExt.{w} C]`. -/
+/-- The Ext-groups in an abelian category `C`, defined as a `Type w` when `[HasExt.{w} C]`. -/
 def Ext (X Y : C) (n : ℕ) : Type w :=
   SmallShiftedHom.{w} (HomologicalComplex.quasiIso C (ComplexShape.up ℤ))
     ((CochainComplex.singleFunctor C 0).obj X)
@@ -61,13 +91,17 @@ section
 
 variable [HasDerivedCategory.{w'} C]
 
+-- this is defined in #13876
 instance : (DerivedCategory.Q (C := C)).CommShift ℤ := sorry
 
+/-- When an instance of `[HasDerivedCategory.{w'} C]` is available, this is the bijection
+between `Ext.{w} X Y n` and a type of morphisms in the derived category. -/
 noncomputable def homEquiv {n : ℕ} :
     Ext.{w} X Y n ≃ ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X)
       ((DerivedCategory.singleFunctor C 0).obj Y) (n : ℤ) :=
   SmallShiftedHom.equiv (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) DerivedCategory.Q
 
+/-- The morphism in the derived category which corresponds to an element in `Ext X Y a`. -/
 noncomputable abbrev hom {a : ℕ} (α : Ext X Y a) :
     ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X)
       ((DerivedCategory.singleFunctor C 0).obj Y) (a : ℤ) :=

From 9217693c4b698fd0dccdbad4db6fcd03978d003f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 09:18:19 +0200
Subject: [PATCH 34/63] wip

---
 .../Algebra/Homology/DerivedCategory/Ext.lean | 26 ++++++++++++++++---
 .../Localization/SmallShiftedHom.lean         |  6 +++++
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index ed09f20b309a0e..494916a319a868 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -48,17 +48,37 @@ namespace CategoryTheory
 
 variable (C : Type u) [Category.{v} C] [Abelian C]
 
-instance : (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)).IsCompatibleWithShift ℤ := sorry
-
 open Localization
 
+instance : (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)).IsCompatibleWithShift ℤ := by
+  sorry
+
 /-- The property that morphisms between single complexes in arbitrary degrees are `w`-small
 in the derived category. -/
 abbrev HasExt : Prop :=
   ∀ (X Y : C), HasSmallLocalizedShiftedHom.{w} (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)) ℤ
     ((CochainComplex.singleFunctor C 0).obj X) ((CochainComplex.singleFunctor C 0).obj Y)
 
-lemma hasExt_of_hasDerivedCategory [HasDerivedCategory.{w} C] : HasExt.{w} C := sorry
+-- TODO: when the canonical t-structure is formalized, replace `n : ℤ` by `n : ℕ`
+lemma hasExt_iff [HasDerivedCategory.{w'} C] :
+    HasExt.{w} C ↔ ∀ (X Y : C) (n : ℤ), Small.{w}
+      ((DerivedCategory.singleFunctor C 0).obj X ⟶
+        (((DerivedCategory.singleFunctor C 0).obj Y)⟦n⟧)) := by
+  dsimp [HasExt]
+  simp only [hasSmallLocalizedShiftedHom_iff _ _ DerivedCategory.Q]
+  constructor
+  · intro h X Y n
+    exact (small_congr ((shiftFunctorZero _ ℤ).app
+      ((DerivedCategory.singleFunctor C 0).obj X)).homFromEquiv).1 (h X Y 0 n)
+  · intro h X Y a b
+    refine (small_congr ?_).1 (h X Y (b - a))
+    exact (Functor.FullyFaithful.ofFullyFaithful
+      (shiftFunctor _ a)).homEquiv.trans
+      ((shiftFunctorAdd' _ _ _ _ (Int.sub_add_cancel b a)).symm.app _).homToEquiv
+
+lemma hasExt_of_hasDerivedCategory [HasDerivedCategory.{w} C] : HasExt.{w} C := by
+  rw [hasExt_iff.{w}]
+  infer_instance
 
 variable {C}
 
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 9c6eb93a22fe72..17fc921ad5f72c 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -45,6 +45,12 @@ in the localized category with respect to a class of morphisms `W`. -/
 abbrev HasSmallLocalizedShiftedHom : Prop :=
   ∀ (a b : M), HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧)
 
+variable (M) in
+lemma hasSmallLocalizedShiftedHom_iff (L : C ⥤ D) [L.IsLocalization W] (X Y : C) :
+    HasSmallLocalizedShiftedHom.{w} W M X Y ↔
+      ∀ (a b : M), Small.{w} ((L.obj X)⟦a⟧ ⟶ (L.obj Y)⟦b⟧) := by
+  sorry
+
 variable [HasSmallLocalizedShiftedHom.{w} W M X Y]
 
 variable (M) in

From 8d7c85f41cf1d905e7a48fba220f8281e571b2d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 09:22:41 +0200
Subject: [PATCH 35/63] better docstring

---
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 494916a319a868..647af5ab23c49f 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -86,7 +86,7 @@ variable [HasExt.{w} C]
 
 namespace Abelian
 
-/-- The Ext-groups in an abelian category `C`, defined as a `Type w` when `[HasExt.{w} C]`. -/
+/-- A Ext-group in an abelian category `C`, defined as a `Type w` when `[HasExt.{w} C]`. -/
 def Ext (X Y : C) (n : ℕ) : Type w :=
   SmallShiftedHom.{w} (HomologicalComplex.quasiIso C (ComplexShape.up ℤ))
     ((CochainComplex.singleFunctor C 0).obj X)

From 8f13fb1cebbd58b36442fb3628ca65dbb68b748d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 09:36:38 +0200
Subject: [PATCH 36/63] added additive structure

---
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 86337e3e34d13b..173ed8a302ee10 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -135,6 +135,12 @@ lemma ext {n : ℕ} {α β : Ext X Y n} (h : α.hom = β.hom) : α = β :=
 
 end
 
+-- TODO: promote `homEquiv` above as `homAddEquiv` with the same
+-- degree of generality, i.e. for any `[HasDerivedCategory.{w'} C]`
+noncomputable instance {n : ℕ} : AddCommGroup (Ext X Y n) :=
+  letI := HasDerivedCategory.standard C
+  homEquiv.addCommGroup
+
 end Ext
 
 end Abelian

From ecf4779db7ddb84301995186fa42752c744f718f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 10:07:21 +0200
Subject: [PATCH 37/63] added lemma about IsCompatibleWithShift

---
 Mathlib/CategoryTheory/Shift/Localization.lean | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Mathlib/CategoryTheory/Shift/Localization.lean b/Mathlib/CategoryTheory/Shift/Localization.lean
index eb48490ff207f0..4708b9a646f629 100644
--- a/Mathlib/CategoryTheory/Shift/Localization.lean
+++ b/Mathlib/CategoryTheory/Shift/Localization.lean
@@ -49,6 +49,13 @@ lemma shiftFunctor_comp_inverts (a : A) :
     W.IsInvertedBy (shiftFunctor C a ⋙ L) := fun _ _ f hf =>
   Localization.inverts L W _ (by simpa only [iff] using hf)
 
+lemma inverseImage (F : D ⥤ C) [HasShift D A] [F.CommShift A] (hW : W.RespectsIso) :
+    (W.inverseImage F).IsCompatibleWithShift A where
+  condition a := by
+    ext X Y f
+    simp only [inverseImage_iff, ← iff W (F.map f) a]
+    exact hW.arrow_mk_iso_iff (Arrow.isoOfNatIso (F.commShiftIso a) f)
+
 end IsCompatibleWithShift
 
 end MorphismProperty

From 66d20aa327466e3dc24f5f1c8ad28626be1cda31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 10:46:45 +0200
Subject: [PATCH 38/63] remove sorries

---
 .../Algebra/Homology/DerivedCategory/Ext.lean |  3 --
 .../HomotopyCategory/ShiftSequence.lean       | 30 ++++++++++++++-----
 .../CategoryTheory/Shift/Localization.lean    |  7 -----
 3 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 173ed8a302ee10..5af5f708a4f569 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -50,9 +50,6 @@ variable (C : Type u) [Category.{v} C] [Abelian C]
 
 open Localization
 
-instance : (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)).IsCompatibleWithShift ℤ := by
-  sorry
-
 /-- The property that morphisms between single complexes in arbitrary degrees are `w`-small
 in the derived category. -/
 abbrev HasExt : Prop :=
diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
index dc10431f21fff5..3bf108549cb32d 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
 Authors: Joël Riou
 -/
 import Mathlib.CategoryTheory.Shift.InducedShiftSequence
+import Mathlib.CategoryTheory.Shift.Localization
 import Mathlib.Algebra.Homology.HomotopyCategory.Shift
 import Mathlib.Algebra.Homology.ShortComplex.HomologicalComplex
 import Mathlib.Algebra.Homology.QuasiIso
@@ -115,14 +116,29 @@ noncomputable instance :
       ← ShortComplex.homologyMap_comp, shiftFunctorAdd'_eq_shiftFunctorAdd,
       shiftShortComplexFunctorIso_add'_hom_app n m _ rfl a a' a'' ha' ha'' K]
 
+lemma quasiIsoAt_shift_iff {K L : CochainComplex C ℤ} (φ : K ⟶ L) (n i j : ℤ) (h : n + i = j) :
+    QuasiIsoAt (φ⟦n⟧') i ↔ QuasiIsoAt φ j := by
+  simp only [quasiIsoAt_iff_isIso_homologyMap]
+  exact (NatIso.isIso_map_iff
+    ((homologyFunctor C (ComplexShape.up ℤ) 0).shiftIso n i j h) φ)
+
+lemma quasiIso_shift_iff {K L : CochainComplex C ℤ} (φ : K ⟶ L) (n : ℤ) :
+    QuasiIso (φ⟦n⟧') ↔ QuasiIso φ := by
+  simp only [quasiIso_iff, fun i ↦ quasiIsoAt_shift_iff φ n i _ rfl]
+  constructor
+  · intro h j
+    obtain ⟨i, rfl⟩ : ∃ i, j = n + i := ⟨j - n, by omega⟩
+    exact h i
+  · intro h i
+    exact h (n + i)
+
 instance {K L : CochainComplex C ℤ} (φ : K ⟶ L) (n : ℤ) [QuasiIso φ] :
-    QuasiIso (φ⟦n⟧') where
-  quasiIsoAt a := by
-    rw [quasiIsoAt_iff_isIso_homologyMap]
-    apply (NatIso.isIso_map_iff
-      ((homologyFunctor C (ComplexShape.up ℤ) 0).shiftIso n a (n + a) rfl) φ).2 ?_
-    change IsIso (homologyMap φ _)
-    infer_instance
+    QuasiIso (φ⟦n⟧') := by
+  rw [quasiIso_shift_iff]
+  infer_instance
+
+instance : (HomologicalComplex.quasiIso C (ComplexShape.up ℤ)).IsCompatibleWithShift ℤ where
+  condition n := by ext; apply quasiIso_shift_iff
 
 variable (C) in
 lemma homologyFunctor_shift (n : ℤ) :
diff --git a/Mathlib/CategoryTheory/Shift/Localization.lean b/Mathlib/CategoryTheory/Shift/Localization.lean
index 4708b9a646f629..eb48490ff207f0 100644
--- a/Mathlib/CategoryTheory/Shift/Localization.lean
+++ b/Mathlib/CategoryTheory/Shift/Localization.lean
@@ -49,13 +49,6 @@ lemma shiftFunctor_comp_inverts (a : A) :
     W.IsInvertedBy (shiftFunctor C a ⋙ L) := fun _ _ f hf =>
   Localization.inverts L W _ (by simpa only [iff] using hf)
 
-lemma inverseImage (F : D ⥤ C) [HasShift D A] [F.CommShift A] (hW : W.RespectsIso) :
-    (W.inverseImage F).IsCompatibleWithShift A where
-  condition a := by
-    ext X Y f
-    simp only [inverseImage_iff, ← iff W (F.map f) a]
-    exact hW.arrow_mk_iso_iff (Arrow.isoOfNatIso (F.commShiftIso a) f)
-
 end IsCompatibleWithShift
 
 end MorphismProperty

From f92c48b95fbdaf74c33141ca3662b5d11fe72eb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 11:22:56 +0200
Subject: [PATCH 39/63] fixed sorries

---
 Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 17fc921ad5f72c..3870fd1a7697e6 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -46,10 +46,14 @@ abbrev HasSmallLocalizedShiftedHom : Prop :=
   ∀ (a b : M), HasSmallLocalizedHom.{w} W (X⟦a⟧) (Y⟦b⟧)
 
 variable (M) in
-lemma hasSmallLocalizedShiftedHom_iff (L : C ⥤ D) [L.IsLocalization W] (X Y : C) :
+lemma hasSmallLocalizedShiftedHom_iff
+    (L : C ⥤ D) [L.IsLocalization W] [L.CommShift M] (X Y : C) :
     HasSmallLocalizedShiftedHom.{w} W M X Y ↔
       ∀ (a b : M), Small.{w} ((L.obj X)⟦a⟧ ⟶ (L.obj Y)⟦b⟧) := by
-  sorry
+  dsimp [HasSmallLocalizedShiftedHom]
+  have eq := fun (a b : M) ↦ small_congr.{_, _, w} (Iso.homEquiv ((L.commShiftIso a).app X) ((L.commShiftIso b).app Y))
+  dsimp at eq
+  simp only [hasSmallLocalizedHom_iff _ L, eq]
 
 variable [HasSmallLocalizedShiftedHom.{w} W M X Y]
 

From b5a08f509540e6e55c9f95fc4b1b0b5e449b521b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Thu, 20 Jun 2024 13:20:17 +0200
Subject: [PATCH 40/63] fixed long line

---
 Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 3870fd1a7697e6..2a7553324c7b60 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -51,7 +51,8 @@ lemma hasSmallLocalizedShiftedHom_iff
     HasSmallLocalizedShiftedHom.{w} W M X Y ↔
       ∀ (a b : M), Small.{w} ((L.obj X)⟦a⟧ ⟶ (L.obj Y)⟦b⟧) := by
   dsimp [HasSmallLocalizedShiftedHom]
-  have eq := fun (a b : M) ↦ small_congr.{_, _, w} (Iso.homEquiv ((L.commShiftIso a).app X) ((L.commShiftIso b).app Y))
+  have eq := fun (a b : M) ↦ small_congr.{_, _, w}
+    (Iso.homEquiv ((L.commShiftIso a).app X) ((L.commShiftIso b).app Y))
   dsimp at eq
   simp only [hasSmallLocalizedHom_iff _ L, eq]
 

From 03a28f051a9e33cc08d54043efcab5ba4ec4b28d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Sat, 22 Jun 2024 18:36:10 +0200
Subject: [PATCH 41/63] Update Mathlib/Algebra/Homology/Single.lean
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Calle Sönne <calle.sonne@gmail.com>
---
 Mathlib/Algebra/Homology/Single.lean | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/Mathlib/Algebra/Homology/Single.lean b/Mathlib/Algebra/Homology/Single.lean
index 857c82a642866c..fbd28a4727fdaa 100644
--- a/Mathlib/Algebra/Homology/Single.lean
+++ b/Mathlib/Algebra/Homology/Single.lean
@@ -103,10 +103,8 @@ variable (V)
 noncomputable def singleCompEvalIsoSelf (j : ι) : single V c j ⋙ eval V c j ≅ 𝟭 V :=
   NatIso.ofComponents (singleObjXSelf c j) (fun {A B} f => by simp [single_map_f_self])
 
-lemma isZero_single_comp_eval (j i : ι) (hi : i ≠ j) : IsZero (single V c j ⋙ eval V c i) := by
-  rw [Functor.isZero_iff]
-  intro A
-  exact isZero_single_obj_X c _ _ _ hi
+lemma isZero_single_comp_eval (j i : ι) (hi : i ≠ j) : IsZero (single V c j ⋙ eval V c i) :=
+  Functor.isZero _ (fun _ ↦ isZero_single_obj_X c _ _ _ hi)
 
 variable {V c}
 

From 4b47afd21add40d0e885f1b889099af54cbe4fc8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Sat, 22 Jun 2024 18:37:49 +0200
Subject: [PATCH 42/63] Update
 Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Calle Sönne <calle.sonne@gmail.com>
---
 Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
index 804bbf49c249aa..27cd63a887d67e 100644
--- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
+++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
@@ -182,7 +182,7 @@ end ZeroObject
 
 section
 
-variable {J : Type*} [Category J] [HasZeroObject D] [HasZeroMorphisms D]
+variable (J : Type*) [Category J] [HasZeroObject D] [HasZeroMorphisms D]
   (G : C ⥤ D) (hG : IsZero G)
 
 /-- A zero functor preserves limits. -/

From f9a0d7ff7c8b7ad4cea87821e6048aaa888bf797 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Sat, 22 Jun 2024 18:40:10 +0200
Subject: [PATCH 43/63] Update
 Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Calle Sönne <calle.sonne@gmail.com>
---
 Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
index 27cd63a887d67e..e5f4589301389e 100644
--- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
+++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
@@ -187,12 +187,10 @@ variable (J : Type*) [Category J] [HasZeroObject D] [HasZeroMorphisms D]
 
 /-- A zero functor preserves limits. -/
 def preservesLimitsOfShapeOfIsZero : PreservesLimitsOfShape J G where
-  preservesLimit := ⟨fun hc => by
+  preservesLimit {K} := ⟨fun hc => by
     rw [Functor.isZero_iff] at hG
     refine IsLimit.ofIsZero _ ?_ (hG _)
-    rw [Functor.isZero_iff]
-    intro X
-    apply hG⟩
+    apply (K ⋙ G).isZero (fun X ↦ hG _)⟩
 
 /-- A zero functor preserves colimits. -/
 def preservesColimitsOfShapeOfIsZero : PreservesColimitsOfShape J G where

From e8998eb98dbfadc27f84844a30f6c42d47a1bcff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sat, 22 Jun 2024 18:47:51 +0200
Subject: [PATCH 44/63] golfing proofs

---
 .../CategoryTheory/Limits/Preserves/Shapes/Zero.lean   | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
index e5f4589301389e..8230985d88f27d 100644
--- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
+++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
@@ -189,17 +189,13 @@ variable (J : Type*) [Category J] [HasZeroObject D] [HasZeroMorphisms D]
 def preservesLimitsOfShapeOfIsZero : PreservesLimitsOfShape J G where
   preservesLimit {K} := ⟨fun hc => by
     rw [Functor.isZero_iff] at hG
-    refine IsLimit.ofIsZero _ ?_ (hG _)
-    apply (K ⋙ G).isZero (fun X ↦ hG _)⟩
+    exact IsLimit.ofIsZero _ ((K ⋙ G).isZero (fun X ↦ hG _)) (hG _)⟩
 
 /-- A zero functor preserves colimits. -/
 def preservesColimitsOfShapeOfIsZero : PreservesColimitsOfShape J G where
-  preservesColimit := ⟨fun hc => by
+  preservesColimit {K} := ⟨fun hc => by
     rw [Functor.isZero_iff] at hG
-    refine IsColimit.ofIsZero _ ?_ (hG _)
-    rw [Functor.isZero_iff]
-    intro X
-    apply hG⟩
+    exact IsColimit.ofIsZero _ ((K ⋙ G).isZero (fun X ↦ hG _)) (hG _)⟩
 
 end
 

From d45bcf73143843f652ba2cfa9915ca18e6385f2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sat, 22 Jun 2024 18:52:43 +0200
Subject: [PATCH 45/63] fixing the build

---
 Mathlib/Algebra/Homology/HomologicalComplexLimits.lean | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean b/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
index 2452418d24fd59..1435ddc2d99004 100644
--- a/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
+++ b/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
@@ -202,14 +202,14 @@ noncomputable instance : PreservesLimitsOfShape J (single C c i) :=
     by_cases h : j = i
     · subst h
       exact preservesLimitsOfShapeOfNatIso (singleCompEvalIsoSelf C c j).symm
-    · exact Functor.preservesLimitsOfShapeOfIsZero _ (isZero_single_comp_eval C c _ _ h))
+    · exact Functor.preservesLimitsOfShapeOfIsZero _ _ (isZero_single_comp_eval C c _ _ h))
 
 noncomputable instance : PreservesColimitsOfShape J (single C c i) :=
   preservesColimitsOfShapeOfEval _ (fun j => by
     by_cases h : j = i
     · subst h
       exact preservesColimitsOfShapeOfNatIso (singleCompEvalIsoSelf C c j).symm
-    · exact Functor.preservesColimitsOfShapeOfIsZero _ (isZero_single_comp_eval C c _ _ h))
+    · exact Functor.preservesColimitsOfShapeOfIsZero _ _ (isZero_single_comp_eval C c _ _ h))
 
 noncomputable instance : PreservesFiniteLimits (single C c i) := ⟨by intros; infer_instance⟩
 

From bb61444dc5231929bb4da2321dc2c5c8782b3a8a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 23 Jun 2024 19:38:29 +0200
Subject: [PATCH 46/63] removed duplicate Iso.homEquiv

---
 Mathlib/CategoryTheory/Iso.lean                   | 10 ----------
 Mathlib/CategoryTheory/Localization/HomEquiv.lean |  3 ++-
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/Mathlib/CategoryTheory/Iso.lean b/Mathlib/CategoryTheory/Iso.lean
index 0a609f5f659c37..80c9b60bbafb55 100644
--- a/Mathlib/CategoryTheory/Iso.lean
+++ b/Mathlib/CategoryTheory/Iso.lean
@@ -266,16 +266,6 @@ def homFromEquiv (α : X ≅ Y) {Z : C} : (X ⟶ Z) ≃ (Y ⟶ Z) where
   left_inv := by aesop_cat
   right_inv := by aesop_cat
 
-/-- The bijection `(X ⟶ Y) ≃ (X' ⟶ Y')` that is induced by isomorphisms
-`e : X ≅ X'` and `e' : Y ≅ Y'`. -/
-@[simps]
-def homEquiv {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
-    (X ⟶ Y) ≃ (X' ⟶ Y') where
-  toFun f := e.inv ≫ f ≫ e'.hom
-  invFun g := e.hom ≫ g ≫ e'.inv
-  left_inv := by aesop_cat
-  right_inv := by aesop_cat
-
 end Iso
 
 /-- `IsIso` typeclass expressing that a morphism is invertible. -/
diff --git a/Mathlib/CategoryTheory/Localization/HomEquiv.lean b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
index 1f66d431eec3ff..259b4a3b426d83 100644
--- a/Mathlib/CategoryTheory/Localization/HomEquiv.lean
+++ b/Mathlib/CategoryTheory/Localization/HomEquiv.lean
@@ -5,6 +5,7 @@ Authors: Joël Riou
 -/
 
 import Mathlib.CategoryTheory.Localization.LocalizerMorphism
+import Mathlib.CategoryTheory.Conj
 
 /-!
 # Bijections between morphisms in two localized categories
@@ -44,7 +45,7 @@ are localization functors for `W₁` and `W₂`, then this is the induced map
 for all objects `X` and `Y`. -/
 noncomputable def homMap (f : L₁.obj X ⟶ L₁.obj Y) :
     L₂.obj (Φ.functor.obj X) ⟶ L₂.obj (Φ.functor.obj Y) :=
-  Iso.homEquiv ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
+  Iso.homCongr ((CatCommSq.iso _ _ _ _).symm.app _) ((CatCommSq.iso _ _ _ _).symm.app _)
     ((Φ.localizedFunctor L₁ L₂).map f)
 
 @[simp]

From 2f8d8c8c16a92136af64c210650f5d0129a08fb9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 23 Jun 2024 19:41:58 +0200
Subject: [PATCH 47/63] fixing the build

---
 Mathlib/CategoryTheory/Localization/SmallHom.lean | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallHom.lean b/Mathlib/CategoryTheory/Localization/SmallHom.lean
index c1dd485238f1e6..ded70ab0264006 100644
--- a/Mathlib/CategoryTheory/Localization/SmallHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallHom.lean
@@ -68,7 +68,7 @@ lemma small_of_hasSmallLocalizedHom [HasSmallLocalizedHom.{w} W X Y] :
 lemma hasSmallLocalizedHom_iff_of_isos {X' Y' : C} (e : X ≅ X') (e' : Y ≅ Y') :
     HasSmallLocalizedHom.{w} W X Y ↔ HasSmallLocalizedHom.{w} W X' Y' := by
   simp only [hasSmallLocalizedHom_iff W W.Q]
-  exact small_congr (Iso.homEquiv (W.Q.mapIso e) (W.Q.mapIso e'))
+  exact small_congr (Iso.homCongr (W.Q.mapIso e) (W.Q.mapIso e'))
 
 end
 
@@ -211,7 +211,7 @@ variable [HasSmallLocalizedHom.{w} W₁ X Y]
 noncomputable def smallHomMap (f : SmallHom.{w} W₁ X Y) :
     SmallHom.{w'} W₂ (Φ.functor.obj X) (Φ.functor.obj Y) :=
   (SmallHom.equiv W₂ W₂.Q).symm
-    (Iso.homEquiv ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
+    (Iso.homCongr ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
       ((CatCommSq.iso Φ.functor W₁.Q W₂.Q _).symm.app _)
       ((Φ.localizedFunctor W₁.Q W₂.Q).map ((SmallHom.equiv W₁ W₁.Q) f)))
 

From 5b005a55dad3c71da8dba72e7cefda0b0782065d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 24 Jun 2024 09:17:37 +0200
Subject: [PATCH 48/63] added preservesLimitsOfSize variants

---
 .../Limits/Preserves/Shapes/Zero.lean              | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
index 8230985d88f27d..170f299c92cae7 100644
--- a/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
+++ b/Mathlib/CategoryTheory/Limits/Preserves/Shapes/Zero.lean
@@ -25,7 +25,7 @@ We provide the following results:
 -/
 
 
-universe v₁ v₂ v₃ u₁ u₂ u₃
+universe v u v₁ v₂ v₃ u₁ u₂ u₃
 
 noncomputable section
 
@@ -182,8 +182,8 @@ end ZeroObject
 
 section
 
-variable (J : Type*) [Category J] [HasZeroObject D] [HasZeroMorphisms D]
-  (G : C ⥤ D) (hG : IsZero G)
+variable [HasZeroObject D] [HasZeroMorphisms D]
+  (G : C ⥤ D) (hG : IsZero G) (J : Type*) [Category J]
 
 /-- A zero functor preserves limits. -/
 def preservesLimitsOfShapeOfIsZero : PreservesLimitsOfShape J G where
@@ -197,6 +197,14 @@ def preservesColimitsOfShapeOfIsZero : PreservesColimitsOfShape J G where
     rw [Functor.isZero_iff] at hG
     exact IsColimit.ofIsZero _ ((K ⋙ G).isZero (fun X ↦ hG _)) (hG _)⟩
 
+/-- A zero functor preserves limits. -/
+def preservesLimitsOfSizeOfIsZero : PreservesLimitsOfSize.{v, u} G where
+  preservesLimitsOfShape := G.preservesLimitsOfShapeOfIsZero hG _
+
+/-- A zero functor preserves colimits. -/
+def preservesColimitsOfSizeOfIsZero : PreservesColimitsOfSize.{v, u} G where
+  preservesColimitsOfShape := G.preservesColimitsOfShapeOfIsZero hG _
+
 end
 
 end CategoryTheory.Functor

From 7f136b507cdf182d77c49facb625411bd8af11b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 24 Jun 2024 09:28:52 +0200
Subject: [PATCH 49/63] added converse statements

---
 Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean
index 02356b31d75537..03bcd8a556b772 100644
--- a/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean
+++ b/Mathlib/CategoryTheory/Limits/Shapes/ZeroMorphisms.lean
@@ -682,6 +682,14 @@ def IsColimit.ofIsZero (c : Cocone F) (hF : IsZero F) (hc : IsZero c.pt) : IsCol
   fac _ j := (F.isZero_iff.1 hF j).eq_of_src _ _
   uniq _ _ _ := hc.eq_of_src _ _
 
+lemma IsLimit.isZero_pt {c : Cone F} (hc : IsLimit c) (hF : IsZero F) : IsZero c.pt :=
+  (isZero_zero C).of_iso (IsLimit.conePointUniqueUpToIso hc
+    (IsLimit.ofIsZero (Cone.mk 0 0) hF (isZero_zero C)))
+
+lemma IsColimit.isZero_pt {c : Cocone F} (hc : IsColimit c) (hF : IsZero F) : IsZero c.pt :=
+  (isZero_zero C).of_iso (IsColimit.coconePointUniqueUpToIso hc
+    (IsColimit.ofIsZero (Cocone.mk 0 0) hF (isZero_zero C)))
+
 end
 
 end CategoryTheory.Limits

From 2f5b8401d8f650a81a22c27d7e25a71b793e5e3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 24 Jun 2024 09:34:12 +0200
Subject: [PATCH 50/63] fixing the build

---
 Mathlib/Algebra/Homology/HomologicalComplexLimits.lean | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean b/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
index 1435ddc2d99004..e0220f3bc2aa32 100644
--- a/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
+++ b/Mathlib/Algebra/Homology/HomologicalComplexLimits.lean
@@ -202,14 +202,14 @@ noncomputable instance : PreservesLimitsOfShape J (single C c i) :=
     by_cases h : j = i
     · subst h
       exact preservesLimitsOfShapeOfNatIso (singleCompEvalIsoSelf C c j).symm
-    · exact Functor.preservesLimitsOfShapeOfIsZero _ _ (isZero_single_comp_eval C c _ _ h))
+    · exact Functor.preservesLimitsOfShapeOfIsZero _ (isZero_single_comp_eval C c _ _ h) _)
 
 noncomputable instance : PreservesColimitsOfShape J (single C c i) :=
   preservesColimitsOfShapeOfEval _ (fun j => by
     by_cases h : j = i
     · subst h
       exact preservesColimitsOfShapeOfNatIso (singleCompEvalIsoSelf C c j).symm
-    · exact Functor.preservesColimitsOfShapeOfIsZero _ _ (isZero_single_comp_eval C c _ _ h))
+    · exact Functor.preservesColimitsOfShapeOfIsZero _ (isZero_single_comp_eval C c _ _ h) _)
 
 noncomputable instance : PreservesFiniteLimits (single C c i) := ⟨by intros; infer_instance⟩
 

From 051d1295d0e4dcc7772d2c3ac8b1a0647207b702 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Tue, 25 Jun 2024 07:53:49 +0200
Subject: [PATCH 51/63] reverted unnecessary change

---
 .../Localization/Predicate.lean               | 25 +++----------------
 1 file changed, 3 insertions(+), 22 deletions(-)

diff --git a/Mathlib/CategoryTheory/Localization/Predicate.lean b/Mathlib/CategoryTheory/Localization/Predicate.lean
index 353a1d670565c7..2cdb8224e123a6 100644
--- a/Mathlib/CategoryTheory/Localization/Predicate.lean
+++ b/Mathlib/CategoryTheory/Localization/Predicate.lean
@@ -454,32 +454,13 @@ def compUniqInverse : L₂ ⋙ (uniq L₁ L₂ W').inverse ≅ L₁ := compUniqF
 instance : Lifting L₁ W' L₂ (uniq L₁ L₂ W').functor := ⟨compUniqFunctor L₁ L₂ W'⟩
 instance : Lifting L₂ W' L₁ (uniq L₁ L₂ W').inverse := ⟨compUniqInverse L₁ L₂ W'⟩
 
-section
-
-variable (F : D₁ ⥤ D₂) (e : L₁ ⋙ F ≅ L₂)
-
 /-- If `L₁ : C ⥤ D₁` and `L₂ : C ⥤ D₂` are two localization functors for the
 same `MorphismProperty C`, any functor `F : D₁ ⥤ D₂` equipped with an isomorphism
 `L₁ ⋙ F ≅ L₂` is isomorphic to the functor of the equivalence given by `uniq`. -/
-def uniqFunctorIso  :
-    (uniq L₁ L₂ W').functor ≅ F :=
+def isoUniqFunctor (F : D₁ ⥤ D₂) (e : L₁ ⋙ F ≅ L₂) :
+    F ≅ (uniq L₁ L₂ W').functor :=
   letI : Lifting L₁ W' L₂ F := ⟨e⟩
-  liftNatIso L₁ W' L₂ L₂ (uniq L₁ L₂ W').functor F (Iso.refl L₂)
-
-lemma uniqFunctorIso_hom_app (X : C) :
-    (uniqFunctorIso L₁ L₂ W' F e).hom.app (L₁.obj X) =
-      (compUniqFunctor L₁ L₂ W').hom.app X ≫ e.inv.app X := by
-  dsimp [uniqFunctorIso]
-  simp only [liftNatTrans_app, Functor.comp_obj, NatTrans.id_app, id_comp]
-  rfl
-
-lemma compUniqFunctor_eq :
-    compUniqFunctor L₁ L₂ W' =
-      isoWhiskerLeft L₁ (uniqFunctorIso L₁ L₂ W' F e) ≪≫ e := by
-  ext X
-  simp [uniqFunctorIso_hom_app]
-
-end
+  liftNatIso L₁ W' L₂ L₂ F (uniq L₁ L₂ W').functor (Iso.refl L₂)
 
 end Localization
 

From bc508a5f4577cdd69d65dde0e915818cfb01ef25 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 30 Jun 2024 11:30:17 +0200
Subject: [PATCH 52/63] removed duplicate lemmas

---
 .../HomotopyCategory/ShiftSequence.lean       | 28 -------------------
 .../Localization/SmallShiftedHom.lean         |  2 +-
 2 files changed, 1 insertion(+), 29 deletions(-)

diff --git a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
index 199072c572a9e7..3bf108549cb32d 100644
--- a/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
+++ b/Mathlib/Algebra/Homology/HomotopyCategory/ShiftSequence.lean
@@ -168,34 +168,6 @@ lemma liftCycles_shift_homologyπ
     assoc, Iso.hom_inv_id, comp_id]
   rfl
 
-variable (C) in
-lemma homologyFunctor_shift (n : ℤ) :
-    (homologyFunctor C (ComplexShape.up ℤ) 0).shift n =
-      homologyFunctor C (ComplexShape.up ℤ) n := rfl
-
-@[reassoc]
-lemma liftCycles_shift_homologyπ
-    (K : CochainComplex C ℤ) {A : C} {n i : ℤ} (f : A ⟶ (K⟦n⟧).X i) (j : ℤ)
-    (hj : (up ℤ).next i = j) (hf : f ≫ (K⟦n⟧).d i j = 0) (i' : ℤ) (hi' : n + i = i') (j' : ℤ)
-    (hj' : (up ℤ).next i' = j') :
-    (K⟦n⟧).liftCycles f j hj hf ≫ (K⟦n⟧).homologyπ i =
-      K.liftCycles (f ≫ (K.shiftFunctorObjXIso n i i' (by omega)).hom) j' hj' (by
-        simp only [next] at hj hj'
-        obtain rfl : i' = i + n := by omega
-        obtain rfl : j' = j + n := by omega
-        dsimp at hf ⊢
-        simp only [Linear.comp_units_smul] at hf
-        apply (one_smul (M := ℤˣ) _).symm.trans _
-        rw [← Int.units_mul_self n.negOnePow, mul_smul, comp_id, hf, smul_zero]) ≫
-        K.homologyπ i' ≫
-          ((HomologicalComplex.homologyFunctor C (up ℤ) 0).shiftIso n i i' hi').inv.app K := by
-  simp only [liftCycles, homologyπ,
-    shiftFunctorObjXIso, Functor.shiftIso, Functor.ShiftSequence.shiftIso,
-    ShiftSequence.shiftIso_inv_app, ShortComplex.homologyπ_naturality,
-    ShortComplex.liftCycles_comp_cyclesMap_assoc, shiftShortComplexFunctorIso_inv_app_τ₂,
-    assoc, Iso.hom_inv_id, comp_id]
-  rfl
-
 end CochainComplex
 
 namespace HomotopyCategory
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 2a7553324c7b60..eccdb71c6948c8 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -52,7 +52,7 @@ lemma hasSmallLocalizedShiftedHom_iff
       ∀ (a b : M), Small.{w} ((L.obj X)⟦a⟧ ⟶ (L.obj Y)⟦b⟧) := by
   dsimp [HasSmallLocalizedShiftedHom]
   have eq := fun (a b : M) ↦ small_congr.{_, _, w}
-    (Iso.homEquiv ((L.commShiftIso a).app X) ((L.commShiftIso b).app Y))
+    (Iso.homCongr ((L.commShiftIso a).app X) ((L.commShiftIso b).app Y))
   dsimp at eq
   simp only [hasSmallLocalizedHom_iff _ L, eq]
 

From 3e944a40bfe6c6c9d7c35a6c98d82250cc25b976 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Mon, 1 Jul 2024 18:35:23 +0200
Subject: [PATCH 53/63] fixing the build

---
 Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index eccdb71c6948c8..9c79e0011faade 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -51,7 +51,7 @@ lemma hasSmallLocalizedShiftedHom_iff
     HasSmallLocalizedShiftedHom.{w} W M X Y ↔
       ∀ (a b : M), Small.{w} ((L.obj X)⟦a⟧ ⟶ (L.obj Y)⟦b⟧) := by
   dsimp [HasSmallLocalizedShiftedHom]
-  have eq := fun (a b : M) ↦ small_congr.{_, _, w}
+  have eq := fun (a b : M) ↦ small_congr.{w}
     (Iso.homCongr ((L.commShiftIso a).app X) ((L.commShiftIso b).app Y))
   dsimp at eq
   simp only [hasSmallLocalizedHom_iff _ L, eq]

From a3189611dda076c0afc2d9b7c585682e88365629 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Fri, 5 Jul 2024 13:30:04 +0200
Subject: [PATCH 54/63] fixing the build

---
 Mathlib/Algebra/Homology/DerivedCategory/Basic.lean | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
index 5a32ccb4877f81..8bad5e612fdbeb 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
@@ -223,11 +223,8 @@ lemma mem_distTriang_iff (T : Triangle (DerivedCategory C)) :
       (Functor.mapTriangleCompIso (HomotopyCategory.quotient C _) Qh).app _)
     exact ⟨_, _, f, ⟨Iso.refl _⟩⟩
 
-<<<<<<< HEAD
-=======
 variable (C)
 
->>>>>>> origin
 /-- The single functors `C ⥤ DerivedCategory C` for all `n : ℤ` along with
 their compatibilities with shifts. -/
 noncomputable def singleFunctors : SingleFunctors C (DerivedCategory C) ℤ :=

From a379d849b487503922fef69ab00d4ae3af192fb8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Fri, 5 Jul 2024 21:26:38 +0200
Subject: [PATCH 55/63] fixing the build

---
 Mathlib/Algebra/Homology/DerivedCategory/Basic.lean | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
index 8bad5e612fdbeb..c04665c5b4098e 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Basic.lean
@@ -223,8 +223,6 @@ lemma mem_distTriang_iff (T : Triangle (DerivedCategory C)) :
       (Functor.mapTriangleCompIso (HomotopyCategory.quotient C _) Qh).app _)
     exact ⟨_, _, f, ⟨Iso.refl _⟩⟩
 
-variable (C)
-
 /-- The single functors `C ⥤ DerivedCategory C` for all `n : ℤ` along with
 their compatibilities with shifts. -/
 noncomputable def singleFunctors : SingleFunctors C (DerivedCategory C) ℤ :=

From 3c4c02692d3d8049761349ba74d7fd711611fa00 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 7 Jul 2024 09:34:28 +0200
Subject: [PATCH 56/63] removed AddCommGroup instance

---
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 5af5f708a4f569..a81e902f94d313 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -132,12 +132,6 @@ lemma ext {n : ℕ} {α β : Ext X Y n} (h : α.hom = β.hom) : α = β :=
 
 end
 
--- TODO: promote `homEquiv` above as `homAddEquiv` with the same
--- degree of generality, i.e. for any `[HasDerivedCategory.{w'} C]`
-noncomputable instance {n : ℕ} : AddCommGroup (Ext X Y n) :=
-  letI := HasDerivedCategory.standard C
-  homEquiv.addCommGroup
-
 end Ext
 
 end Abelian

From a7739c7ed0c043c0a0b5f705d624b5212f7172c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 7 Jul 2024 11:49:03 +0200
Subject: [PATCH 57/63] wip

---
 .../Algebra/Homology/DerivedCategory/Ext.lean | 46 ++++++++++++++++++-
 .../Localization/SmallShiftedHom.lean         | 18 ++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index a81e902f94d313..000870b278b3c8 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -48,7 +48,7 @@ namespace CategoryTheory
 
 variable (C : Type u) [Category.{v} C] [Abelian C]
 
-open Localization
+open Localization Limits
 
 /-- The property that morphisms between single complexes in arbitrary degrees are `w`-small
 in the derived category. -/
@@ -130,8 +130,52 @@ lemma comp_hom {a b : ℕ} (α : Ext X Y a) (β : Ext Y Z b) {c : ℕ} (h : a +
 lemma ext {n : ℕ} {α β : Ext X Y n} (h : α.hom = β.hom) : α = β :=
   homEquiv.injective h
 
+lemma ext_iff {n : ℕ} {α β : Ext X Y n} : α = β ↔ α.hom = β.hom :=
+  ⟨fun h ↦ by rw [h], ext⟩
+
+end
+
+noncomputable def mk₀ (f : X ⟶ Y) : Ext X Y 0 := SmallShiftedHom.mk₀ _ _ (by simp)
+  ((CochainComplex.singleFunctor C 0).map f)
+
+@[simp]
+lemma mk₀_hom [HasDerivedCategory.{w'} C] (f : X ⟶ Y) :
+    (mk₀ f).hom = ShiftedHom.mk₀ _ (by simp) ((DerivedCategory.singleFunctor C 0).map f) :=
+  sorry
+
+section
+
+variable {n : ℕ} {X₁ X₂ : C}
+
+lemma biprod_ext {α β : Ext (X₁ ⊞ X₂) Y n}
+    (h : (mk₀ biprod.inl).comp α (zero_add n) = (mk₀ biprod.inl).comp β (zero_add n)): α = β := by
+  letI := HasDerivedCategory.standard C
+  rw [ext_iff] at h ⊢
+  simp at h
+  sorry
+
+variable (α₁ : Ext X₁ Y n) (α₂ : Ext X₂ Y n)
+
+def descBiprod : Ext (X₁ ⊞ X₂) Y n := by
+  have := α₁
+  have := α₂
+  sorry
+
+@[simp]
+lemma inl_descBiprod : (mk₀ biprod.inl).comp (descBiprod α₁ α₂) (zero_add n) = α₁ := sorry
+
+@[simp]
+lemma inr_descBiprod : (mk₀ biprod.inr).comp (descBiprod α₁ α₂) (zero_add n) = α₂ := sorry
+
 end
 
+noncomputable instance {n : ℕ} : Add (Ext X Y n) where
+  add α₁ α₂ := (mk₀ (biprod.lift (𝟙 X) (𝟙 X))).comp (descBiprod α₁ α₂) (zero_add n)
+
+lemma add_hom [HasDerivedCategory.{w'} C] {n : ℕ} (α₁ α₂ : Ext X Y n) :
+    (α₁ + α₂).hom = α₁.hom + α₂.hom :=
+  sorry
+
 end Ext
 
 end Abelian
diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 83f5c1afa323e2..4670d1799a5fac 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -130,6 +130,12 @@ noncomputable def comp {a b c : M} [HasSmallLocalizedShiftedHom.{w} W M X Y]
     SmallShiftedHom.{w} W X Z c :=
   SmallHom.comp f (g.shift a c h)
 
+variable (W) in
+noncomputable def mk₀ [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    (m₀ : M) (hm₀ : m₀ = 0) (f : X ⟶ Y) :
+    SmallShiftedHom.{w} W X Y m₀ :=
+  SmallHom.mk W (f ≫ (shiftFunctorZero' C m₀ hm₀).inv.app Y)
+
 end
 
 section
@@ -176,6 +182,18 @@ lemma equiv_comp [HasSmallLocalizedShiftedHom.{w} W M X Y]
     comp_id, Functor.map_comp]
   rfl
 
+@[simp]
+lemma equiv_mk₀ [HasSmallLocalizedShiftedHom.{w} W M X Y]
+    (m₀ : M) (hm₀ : m₀ = 0) (f : X ⟶ Y) :
+    equiv W L (SmallShiftedHom.mk₀ W m₀ hm₀ f) =
+      ShiftedHom.mk₀ m₀ hm₀ (L.map f) := by
+  subst hm₀
+  dsimp [equiv, mk₀]
+  erw [SmallHom.equiv_mk, Iso.homToEquiv_apply, Functor.map_comp]
+  dsimp [equiv, mk₀, ShiftedHom.mk₀, shiftFunctorZero']
+  simp only [comp_id, L.commShiftIso_zero, Functor.CommShift.isoZero_hom_app, assoc,
+    ← Functor.map_comp_assoc, Iso.inv_hom_id_app, Functor.id_obj, Functor.map_id, id_comp]
+
 end
 
 lemma comp_assoc {X Y Z T : C} {a₁ a₂ a₃ a₁₂ a₂₃ a : M}

From d522cdc400c40d2e1579defe53d55f0bdf282cf6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 7 Jul 2024 16:26:25 +0200
Subject: [PATCH 58/63] wip

---
 .../Algebra/Homology/DerivedCategory/Ext.lean | 49 +++++++++++++++----
 1 file changed, 39 insertions(+), 10 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 000870b278b3c8..0ddb1cc0fb8939 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -147,25 +147,54 @@ section
 
 variable {n : ℕ} {X₁ X₂ : C}
 
+instance [HasDerivedCategory C] :
+    PreservesBinaryBiproduct X₁ X₂ (DerivedCategory.singleFunctor C 0) :=
+  sorry
+
 lemma biprod_ext {α β : Ext (X₁ ⊞ X₂) Y n}
-    (h : (mk₀ biprod.inl).comp α (zero_add n) = (mk₀ biprod.inl).comp β (zero_add n)): α = β := by
+    (h₁ : (mk₀ biprod.inl).comp α (zero_add n) = (mk₀ biprod.inl).comp β (zero_add n))
+    (h₂ : (mk₀ biprod.inr).comp α (zero_add n) = (mk₀ biprod.inr).comp β (zero_add n)) :
+    α = β := by
   letI := HasDerivedCategory.standard C
-  rw [ext_iff] at h ⊢
-  simp at h
-  sorry
+  rw [ext_iff] at h₁ h₂ ⊢
+  simp only [comp_hom, mk₀_hom, ShiftedHom.mk₀_comp] at h₁ h₂
+  apply BinaryCofan.IsColimit.hom_ext
+    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
+      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit
+  all_goals assumption
 
 variable (α₁ : Ext X₁ Y n) (α₂ : Ext X₂ Y n)
 
-def descBiprod : Ext (X₁ ⊞ X₂) Y n := by
-  have := α₁
-  have := α₂
-  sorry
+noncomputable def descBiprod : Ext (X₁ ⊞ X₂) Y n := by
+  letI := HasDerivedCategory.standard C
+  exact homEquiv.symm (Cofan.IsColimit.desc
+    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
+      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit (by
+        rintro ⟨_|_⟩
+        · exact α₁.hom
+        · exact α₂.hom))
 
 @[simp]
-lemma inl_descBiprod : (mk₀ biprod.inl).comp (descBiprod α₁ α₂) (zero_add n) = α₁ := sorry
+lemma inl_descBiprod : (mk₀ biprod.inl).comp (descBiprod α₁ α₂) (zero_add n) = α₁ := by
+  letI := HasDerivedCategory.standard C
+  ext
+  dsimp [descBiprod]
+  simp only [comp_hom, Int.Nat.cast_ofNat_Int, mk₀_hom, Equiv.apply_symm_apply,
+    ShiftedHom.mk₀_comp]
+  exact Cofan.IsColimit.fac
+    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
+      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit _ WalkingPair.left
 
 @[simp]
-lemma inr_descBiprod : (mk₀ biprod.inr).comp (descBiprod α₁ α₂) (zero_add n) = α₂ := sorry
+lemma inr_descBiprod : (mk₀ biprod.inr).comp (descBiprod α₁ α₂) (zero_add n) = α₂ := by
+  letI := HasDerivedCategory.standard C
+  ext
+  dsimp [descBiprod]
+  simp only [comp_hom, Int.Nat.cast_ofNat_Int, mk₀_hom, Equiv.apply_symm_apply,
+    ShiftedHom.mk₀_comp]
+  exact Cofan.IsColimit.fac
+    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
+      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit _ WalkingPair.right
 
 end
 

From aafd4ca515161f562fc3cecaf982267bff389646 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 7 Jul 2024 18:57:57 +0200
Subject: [PATCH 59/63] wip

---
 .../Algebra/Homology/DerivedCategory/Ext.lean | 165 +++++++++++++-----
 Mathlib/CategoryTheory/Shift/ShiftedHom.lean  |  36 ++++
 2 files changed, 157 insertions(+), 44 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 0ddb1cc0fb8939..480811ee935e1c 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -48,7 +48,7 @@ namespace CategoryTheory
 
 variable (C : Type u) [Category.{v} C] [Abelian C]
 
-open Localization Limits
+open Localization Limits ZeroObject
 
 /-- The property that morphisms between single complexes in arbitrary degrees are `w`-small
 in the derived category. -/
@@ -140,18 +140,110 @@ noncomputable def mk₀ (f : X ⟶ Y) : Ext X Y 0 := SmallShiftedHom.mk₀ _ _ (
 
 @[simp]
 lemma mk₀_hom [HasDerivedCategory.{w'} C] (f : X ⟶ Y) :
-    (mk₀ f).hom = ShiftedHom.mk₀ _ (by simp) ((DerivedCategory.singleFunctor C 0).map f) :=
-  sorry
+    (mk₀ f).hom = ShiftedHom.mk₀ _ (by simp) ((DerivedCategory.singleFunctor C 0).map f) := by
+  apply SmallShiftedHom.equiv_mk₀
+
+@[simp 1100]
+lemma mk₀_comp_mk₀ (f : X ⟶ Y) (g : Y ⟶ Z) :
+    (mk₀ f).comp (mk₀ g) (zero_add 0) = mk₀ (f ≫ g) := by
+  letI := HasDerivedCategory.standard C; ext; simp
+
+@[simp 1100]
+lemma mk₀_comp_mk₀_assoc (f : X ⟶ Y) (g : Y ⟶ Z) {n : ℕ} (α : Ext Z T n) :
+    (mk₀ f).comp ((mk₀ g).comp α (zero_add n)) (zero_add n) =
+      (mk₀ (f ≫ g)).comp α (zero_add n) := by
+  rw [← mk₀_comp_mk₀, comp_assoc]
+  omega
+
+variable {n : ℕ}
+
+noncomputable abbrev hom' (α : Ext X Y n) :
+  letI := HasDerivedCategory.standard C
+  ShiftedHom ((DerivedCategory.singleFunctor C 0).obj X)
+      ((DerivedCategory.singleFunctor C 0).obj Y) (n : ℤ) :=
+  letI := HasDerivedCategory.standard C
+  α.hom
+
+noncomputable instance : AddCommGroup (Ext X Y n) :=
+  letI := HasDerivedCategory.standard C
+  homEquiv.addCommGroup
+
+lemma add_hom' (α β : Ext X Y n) : (α + β).hom' = α.hom' + β.hom' :=
+  letI := HasDerivedCategory.standard C
+  homEquiv.symm.injective (Equiv.symm_apply_apply _ _)
+
+lemma neg_hom' (α : Ext X Y n) : (-α).hom' = -α.hom' :=
+  letI := HasDerivedCategory.standard C
+  homEquiv.symm.injective (Equiv.symm_apply_apply _ _)
+
+variable (X Y n) in
+lemma zero_hom' : (0 : Ext X Y n).hom' = 0 :=
+  letI := HasDerivedCategory.standard C
+  homEquiv.symm.injective (Equiv.symm_apply_apply _ _)
+
+@[simp]
+lemma add_comp (α₁ α₂ : Ext X Y n) {m : ℕ} (β : Ext Y Z m) {p : ℕ} (h : n + m = p) :
+    (α₁ + α₂).comp β h = α₁.comp β h + α₂.comp β h := by
+  letI := HasDerivedCategory.standard C; ext; simp [add_hom']
+
+@[simp]
+lemma comp_add (α : Ext X Y n) {m : ℕ} (β₁ β₂ : Ext Y Z m) {p : ℕ} (h : n + m = p) :
+    α.comp (β₁ + β₂) h = α.comp β₁ h + α.comp β₂ h := by
+  letI := HasDerivedCategory.standard C; ext; simp [add_hom']
+
+@[simp]
+lemma neg_comp (α : Ext X Y n) {m : ℕ} (β : Ext Y Z m) {p : ℕ} (h : n + m = p) :
+    (-α).comp β h = -α.comp β h := by
+  letI := HasDerivedCategory.standard C; ext; simp [neg_hom']
+
+@[simp]
+lemma comp_neg (α : Ext X Y n) {m : ℕ} (β : Ext Y Z m) {p : ℕ} (h : n + m = p) :
+    α.comp (-β) h = -α.comp β h := by
+  letI := HasDerivedCategory.standard C; ext; simp [neg_hom']
+
+variable (X n) in
+@[simp]
+lemma zero_comp {m : ℕ} (β : Ext Y Z m) (p : ℕ) (h : n + m = p) :
+    (0 : Ext X Y n).comp β h = 0 := by
+  letI := HasDerivedCategory.standard C; ext; simp [zero_hom']
+
+@[simp]
+lemma comp_zero (α : Ext X Y n) (Z : C) (m : ℕ) (p : ℕ) (h : n + m = p) :
+    α.comp (0 : Ext Y Z m) h = 0 := by
+  letI := HasDerivedCategory.standard C; ext; simp [zero_hom']
+
+@[simp]
+lemma mk₀_id_comp (α : Ext X Y n) :
+    (mk₀ (𝟙 X)).comp α (zero_add n) = α := by
+  letI := HasDerivedCategory.standard C; ext; simp
+
+@[simp]
+lemma comp_mk₀_id (α : Ext X Y n) :
+    α.comp (mk₀ (𝟙 Y)) (add_zero n) = α := by
+  letI := HasDerivedCategory.standard C; ext; simp
+
+variable (X Y) in
+@[simp]
+lemma mk₀_zero : mk₀ (0 : X ⟶ Y) = 0 := by
+  letI := HasDerivedCategory.standard C; ext; simp [zero_hom']
 
 section
 
-variable {n : ℕ} {X₁ X₂ : C}
+variable [HasDerivedCategory.{w'} C]
+
+variable (X Y n) in
+@[simp]
+lemma zero_hom : (0 : Ext X Y n).hom = 0 := by
+  let β : Ext 0 Y n := 0
+  have hβ : β.hom = 0 := by apply (Functor.map_isZero _ (isZero_zero C)).eq_of_src
+  have : (0 : Ext X Y n) = (0 : Ext X 0 0).comp β (zero_add n) := by simp [β]
+  rw [this, comp_hom, hβ, ShiftedHom.comp_zero]
 
-instance [HasDerivedCategory C] :
+instance {X₁ X₂ : C} [HasDerivedCategory C] :
     PreservesBinaryBiproduct X₁ X₂ (DerivedCategory.singleFunctor C 0) :=
   sorry
 
-lemma biprod_ext {α β : Ext (X₁ ⊞ X₂) Y n}
+lemma biprod_ext {X₁ X₂ : C} {α β : Ext (X₁ ⊞ X₂) Y n}
     (h₁ : (mk₀ biprod.inl).comp α (zero_add n) = (mk₀ biprod.inl).comp β (zero_add n))
     (h₂ : (mk₀ biprod.inr).comp α (zero_add n) = (mk₀ biprod.inr).comp β (zero_add n)) :
     α = β := by
@@ -163,48 +255,33 @@ lemma biprod_ext {α β : Ext (X₁ ⊞ X₂) Y n}
       (BinaryBiproduct.isBilimit X₁ X₂)).isColimit
   all_goals assumption
 
-variable (α₁ : Ext X₁ Y n) (α₂ : Ext X₂ Y n)
-
-noncomputable def descBiprod : Ext (X₁ ⊞ X₂) Y n := by
-  letI := HasDerivedCategory.standard C
-  exact homEquiv.symm (Cofan.IsColimit.desc
-    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
-      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit (by
-        rintro ⟨_|_⟩
-        · exact α₁.hom
-        · exact α₂.hom))
-
-@[simp]
-lemma inl_descBiprod : (mk₀ biprod.inl).comp (descBiprod α₁ α₂) (zero_add n) = α₁ := by
-  letI := HasDerivedCategory.standard C
-  ext
-  dsimp [descBiprod]
-  simp only [comp_hom, Int.Nat.cast_ofNat_Int, mk₀_hom, Equiv.apply_symm_apply,
-    ShiftedHom.mk₀_comp]
-  exact Cofan.IsColimit.fac
-    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
-      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit _ WalkingPair.left
-
 @[simp]
-lemma inr_descBiprod : (mk₀ biprod.inr).comp (descBiprod α₁ α₂) (zero_add n) = α₂ := by
-  letI := HasDerivedCategory.standard C
-  ext
-  dsimp [descBiprod]
-  simp only [comp_hom, Int.Nat.cast_ofNat_Int, mk₀_hom, Equiv.apply_symm_apply,
-    ShiftedHom.mk₀_comp]
-  exact Cofan.IsColimit.fac
-    (isBinaryBilimitOfPreserves (DerivedCategory.singleFunctor C 0)
-      (BinaryBiproduct.isBilimit X₁ X₂)).isColimit _ WalkingPair.right
+lemma add_hom (α β : Ext X Y n) : (α + β).hom = α.hom + β.hom := by
+  let α' : Ext (X ⊞ X) Y n := (mk₀ biprod.fst).comp α (zero_add n)
+  let β' : Ext (X ⊞ X) Y n := (mk₀ biprod.snd).comp β (zero_add n)
+  have eq₁ : α + β = (mk₀ (biprod.lift (𝟙 X) (𝟙 X))).comp (α' + β') (zero_add n) :=
+    by simp [α', β']
+  have eq₂ : α' + β' = homEquiv.symm (α'.hom + β'.hom) := by
+    apply biprod_ext
+    all_goals ext; simp [α', β', ← Functor.map_comp]
+  simp only [eq₁, eq₂, comp_hom, Equiv.apply_symm_apply, ShiftedHom.comp_add]
+  congr
+  · dsimp [α']
+    rw [comp_hom, mk₀_hom, mk₀_hom]
+    dsimp
+    rw [ShiftedHom.mk₀_comp_mk₀_assoc, ← Functor.map_comp,
+      biprod.lift_fst, Functor.map_id, ShiftedHom.mk₀_id_comp]
+  · dsimp [β']
+    rw [comp_hom, mk₀_hom, mk₀_hom]
+    dsimp
+    rw [ShiftedHom.mk₀_comp_mk₀_assoc, ← Functor.map_comp,
+      biprod.lift_snd, Functor.map_id, ShiftedHom.mk₀_id_comp]
+
+lemma neg_hom (α : Ext X Y n) : (-α).hom = -α.hom := by
+  rw [← add_right_inj α.hom, ← add_hom, add_right_neg, add_right_neg, zero_hom]
 
 end
 
-noncomputable instance {n : ℕ} : Add (Ext X Y n) where
-  add α₁ α₂ := (mk₀ (biprod.lift (𝟙 X) (𝟙 X))).comp (descBiprod α₁ α₂) (zero_add n)
-
-lemma add_hom [HasDerivedCategory.{w'} C] {n : ℕ} (α₁ α₂ : Ext X Y n) :
-    (α₁ + α₂).hom = α₁.hom + α₂.hom :=
-  sorry
-
 end Ext
 
 end Abelian
diff --git a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
index 072953d2897270..9df10e34100953 100644
--- a/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Shift/ShiftedHom.lean
@@ -92,10 +92,32 @@ lemma comp_mk₀_id {a : M} (f : ShiftedHom X Y a) (m₀ : M) (hm₀ : m₀ = 0)
     f.comp (mk₀ m₀ hm₀ (𝟙 Y)) (by rw [hm₀, zero_add]) = f := by
   simp [comp_mk₀]
 
+@[simp 1100]
+lemma mk₀_comp_mk₀ (f : X ⟶ Y) (g : Y ⟶ Z) {a b c : M} (h : b + a = c)
+    (ha : a = 0) (hb : b = 0) :
+    (mk₀ a ha f).comp (mk₀ b hb g) h = mk₀ c (by rw [← h, ha, hb, add_zero]) (f ≫ g) := by
+  subst ha hb
+  obtain rfl : c = 0 := by rw [← h, zero_add]
+  rw [mk₀_comp, mk₀, mk₀, assoc]
+
+@[simp]
+lemma mk₀_comp_mk₀_assoc (f : X ⟶ Y) (g : Y ⟶ Z) {a : M}
+    (ha : a = 0) {d : M} (h : ShiftedHom Z T d) :
+    (mk₀ a ha f).comp ((mk₀ a ha g).comp h
+        (show _ = d by rw [ha, add_zero])) (show _ = d by rw [ha, add_zero]) =
+      (mk₀ a ha (f ≫ g)).comp h (by rw [ha, add_zero]) := by
+  subst ha
+  rw [← comp_assoc, mk₀_comp_mk₀]
+  all_goals simp
+
 section Preadditive
 
 variable [Preadditive C]
 
+variable (X Y) in
+@[simp]
+lemma mk₀_zero (m₀ : M) (hm₀ : m₀ = 0) : mk₀ m₀ hm₀ (0 : X ⟶ Y) = 0 := by simp [mk₀]
+
 @[simp]
 lemma comp_add [∀ (a : M), (shiftFunctor C a).Additive]
     {a b c : M} (α : ShiftedHom X Y a) (β₁ β₂ : ShiftedHom Y Z b) (h : b + a = c) :
@@ -108,13 +130,27 @@ lemma add_comp
     (α₁ + α₂).comp β h = α₁.comp β h + α₂.comp β h := by
   rw [comp, comp, comp, Preadditive.add_comp]
 
+@[simp]
+lemma comp_neg [∀ (a : M), (shiftFunctor C a).Additive]
+    {a b c : M} (α : ShiftedHom X Y a) (β : ShiftedHom Y Z b) (h : b + a = c) :
+    α.comp (-β) h = -α.comp β h := by
+  rw [comp, comp, Functor.map_neg, Preadditive.neg_comp, Preadditive.comp_neg]
+
+@[simp]
+lemma neg_comp
+    {a b c : M} (α : ShiftedHom X Y a) (β : ShiftedHom Y Z b) (h : b + a = c) :
+    (-α).comp β h = -α.comp β h := by
+  rw [comp, comp, Preadditive.neg_comp]
+
 variable (Z) in
+@[simp]
 lemma comp_zero [∀ (a : M), (shiftFunctor C a).PreservesZeroMorphisms]
     {a : M} (β : ShiftedHom X Y a) {b c : M} (h : b + a = c) :
     β.comp (0 : ShiftedHom Y Z b) h = 0 := by
   rw [comp, Functor.map_zero, Limits.zero_comp, Limits.comp_zero]
 
 variable (X) in
+@[simp]
 lemma zero_comp (a : M) {b c : M} (β : ShiftedHom Y Z b) (h : b + a = c) :
     (0 : ShiftedHom X Y a).comp β h = 0 := by
   rw [comp, Limits.zero_comp]

From deefeb7dc7b726d093c30ea31ece402cf1a57594 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Sun, 7 Jul 2024 20:42:05 +0200
Subject: [PATCH 60/63] Update
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
---
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 91c0b9e37f2708..5dce47f5b7bd9a 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -269,8 +269,8 @@ lemma biprod_ext {X₁ X₂ : C} {α β : Ext (X₁ ⊞ X₂) Y n}
 lemma add_hom (α β : Ext X Y n) : (α + β).hom = α.hom + β.hom := by
   let α' : Ext (X ⊞ X) Y n := (mk₀ biprod.fst).comp α (zero_add n)
   let β' : Ext (X ⊞ X) Y n := (mk₀ biprod.snd).comp β (zero_add n)
-  have eq₁ : α + β = (mk₀ (biprod.lift (𝟙 X) (𝟙 X))).comp (α' + β') (zero_add n) :=
-    by simp [α', β']
+  have eq₁ : α + β = (mk₀ (biprod.lift (𝟙 X) (𝟙 X))).comp (α' + β') (zero_add n) := by
+    simp [α', β']
   have eq₂ : α' + β' = homEquiv.symm (α'.hom + β'.hom) := by
     apply biprod_ext
     all_goals ext; simp [α', β', ← Functor.map_comp]

From c684ad688b388501eddce2c41cf2e4eb169af8ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 7 Jul 2024 21:01:20 +0200
Subject: [PATCH 61/63] added docstring

---
 Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
index 4670d1799a5fac..712b539adf8cc4 100644
--- a/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
+++ b/Mathlib/CategoryTheory/Localization/SmallShiftedHom.lean
@@ -131,6 +131,8 @@ noncomputable def comp {a b c : M} [HasSmallLocalizedShiftedHom.{w} W M X Y]
   SmallHom.comp f (g.shift a c h)
 
 variable (W) in
+/-- The canonical map `(X ⟶ Y) → SmallShiftedHom.{w} W X Y m₀` when `m₀ = 0` and
+`[HasSmallLocalizedShiftedHom.{w} W M X Y]` holds. -/
 noncomputable def mk₀ [HasSmallLocalizedShiftedHom.{w} W M X Y]
     (m₀ : M) (hm₀ : m₀ = 0) (f : X ⟶ Y) :
     SmallShiftedHom.{w} W X Y m₀ :=

From 4894c9f7ac4498ac6d93be42cf5f4425aec843c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?= <joel.riou@universite-paris-saclay.fr>
Date: Sun, 7 Jul 2024 21:15:22 +0200
Subject: [PATCH 62/63] better docstring

---
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index 5dce47f5b7bd9a..b3d03f3c498da1 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -134,7 +134,7 @@ lemma ext_iff {n : ℕ} {α β : Ext X Y n} : α = β ↔ α.hom = β.hom :=
 
 end
 
-/-- The canonical map `(X ⟶ Y) → (Ext X Y 0)`. -/
+/-- The canonical map `(X ⟶ Y) → Ext X Y 0`. -/
 noncomputable def mk₀ (f : X ⟶ Y) : Ext X Y 0 := SmallShiftedHom.mk₀ _ _ (by simp)
   ((CochainComplex.singleFunctor C 0).map f)
 

From 69ce8aaff2dbf697fc49efe7f54dc486abe1fb23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=ABl=20Riou?=
 <37772949+joelriou@users.noreply.github.com>
Date: Mon, 8 Jul 2024 16:37:20 +0200
Subject: [PATCH 63/63] Update
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean

Co-authored-by: Julian-Kuelshammer <68201724+Julian-Kuelshammer@users.noreply.github.com>
---
 Mathlib/Algebra/Homology/DerivedCategory/Ext.lean | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
index b3d03f3c498da1..c71945ae3a1468 100644
--- a/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
+++ b/Mathlib/Algebra/Homology/DerivedCategory/Ext.lean
@@ -163,7 +163,7 @@ abelian group structure on the constructed derived category
 is used in order to obtain most of the compatibilities satisfied by
 this abelian group structure. It is then shown that the bijection
 `homEquiv` between `Ext X Y n` and Hom-types in the derived category
-cane be promoted to an additive equivalence for any `[HasDerivedCategory C]` instance. -/
+can be promoted to an additive equivalence for any `[HasDerivedCategory C]` instance. -/
 
 noncomputable instance : AddCommGroup (Ext X Y n) :=
   letI := HasDerivedCategory.standard C