Pith. sign in

IndisputableMonolith.Foundation.SingularMayerVietoris

IndisputableMonolith/Foundation/SingularMayerVietoris.lean · 1792 lines · 147 declarations

show as:
view math explainer →

open module explainer GitHub source

Explainer status: pending

   1/-
   2Mayer-Vietoris for Mathlib's singular homology (with `ℤ` coefficients).
   3
   4Layer 4 of the excision spine (layer 1: `SingularPrism`, homotopy invariance;
   5layer 2: `SingularPair`, the LES of a pair; layer 3: `SingularSubdivision`,
   6barycentric subdivision and the small-simplices theorem).
   7
   8## Contents (staged)
   9
  10* Stage 1: for `U V : Set X`, the small-chains subcomplex `SSC U V` of the
  11  singular chain complex `SC X`, generated in each degree by the singular
  12  simplices whose range lies in `U` or in `V`; the degreewise split-mono
  13  inclusion `smallι : SSC U V ⟶ SC X`.
  14* Stage 2: the small-chains theorem (Hatcher, Prop 2.21): for open `U, V`
  15  covering `X` the inclusion induces an isomorphism on homology in every
  16  degree (`smallι_isIso_homologyMap`, `smallChainsHomologyIso`), via the
  17  subdivision operators and the telescoped homotopies of
  18  `SingularSubdivision`.
  19* Stage 3: the Mayer-Vietoris short exact sequence of chain complexes
  20  `0 ⟶ C_*(U ∩ V) ⟶ C_*(U) ⊞ C_*(V) ⟶ C^{U,V}_*(X) ⟶ 0` (`mvSES`,
  21  `mvSES_shortExact`; no openness/covering hypotheses needed).  Left map
  22  `x ↦ (i_* x, −j_* x)` (`mvα`), right map `(a, b) ↦ k_* a + l_* b`
  23  (`mvβ`); degreewise exactness by coordinate tracking on the free basis
  24  (`coordAt`, `suppOf`, `mv_middle_exact`).
  25* Stage 4: the honest Mayer-Vietoris long exact sequence on Mathlib
  26  singular homology of the spaces, with `H_n(SSC)` transported to `H_n(X)`
  27  across the Stage-2 isomorphism and `H_n(C(U) ⊞ C(V))` split by additivity
  28  of the homology functor (`homologyBiprodIso`):
  29  `⋯ → H_n(U ∩ V) → H_n(U) ⊞ H_n(V) → H_n(X) → H_{n−1}(U ∩ V) → ⋯`.
  30  Maps `mvPair` (from the space-level inclusions `U ∩ V ↪ U, V`), `mvSum`
  31  (from `U, V ↪ X`), connecting map `mvδ`; exactness `mv_exact₁/₂/₃`;
  32  degree-0 tail `mvSum_epi_zero`; sanity lock `mvSum_epi_of_left_univ`
  33  (for `U = univ` the sum map is epi in every degree, since its first
  34  component comes from the homeomorphism `univ ≃ X`).
  35
  36## Frontier (layer 5, not yet formalized)
  37
  38* `H_*(Sⁿ)` by Mayer-Vietoris induction: cover `Sⁿ` by two open
  39  hemispheres `U, V` (each contractible, `U ∩ V ≃ Sⁿ⁻¹` up to homotopy),
  40  use layer-1 homotopy invariance to evaluate the `H_*(U)`, `H_*(V)` spots
  41  and this file's `mv_exact₁/₂/₃` + `mvδ` to walk the induction.  Missing
  42  ingredients: `H_*(pt)` (a direct computation on the singular complex of
  43  a point), homotopy equivalences between the hemispheres/pt and
  44  `U ∩ V`/`Sⁿ⁻¹`, and the two-space case split in degree `0`
  45  (`mvSum_epi_zero` supplies the tail).
  46
  47## Instance-diamond note (load-bearing)
  48
  49For `R = ℤ` every `ModuleCat ℤ` carrier has two `Module ℤ` instances
  50(`isModule` and `AddCommGroup.toIntModule`), propositionally but not
  51definitionally equal, and synthesis prefers the generic one. This file
  52deprioritizes `AddCommGroup.toIntModule` and `SubNegMonoid.toZSMul` locally;
  53any continuation working elementwise in these chain groups must keep those
  54two local-attribute lines.
  55-/
  56import Mathlib.Algebra.Homology.HomologicalComplexAbelian
  57import Mathlib.Algebra.Homology.HomologicalComplexBiprod
  58import Mathlib.Algebra.Homology.HomologySequence
  59import Mathlib.Algebra.Homology.ShortComplex.ModuleCat
  60import Mathlib.Algebra.Category.ModuleCat.Products
  61import Mathlib.Algebra.Category.ModuleCat.Biproducts
  62import IndisputableMonolith.Foundation.SingularPrism
  63import IndisputableMonolith.Foundation.SingularPair
  64import IndisputableMonolith.Foundation.SingularSubdivision
  65
  66namespace IndisputableMonolith
  67namespace Foundation
  68namespace SingularMayerVietoris
  69
  70open CategoryTheory Category Limits AlgebraicTopology Simplicial Opposite
  71open SingularPrism SingularSubdivision
  72
  73attribute [local instance 10] Classical.decEq
  74
  75/- For `R = ℤ` every carrier has two `Module ℤ` instances: the canonical one
  76recorded in the `ModuleCat` structure and the generic
  77`AddCommGroup.toIntModule`. They are propositionally but not definitionally
  78equal, and instance synthesis prefers the generic one, which breaks
  79elementwise reasoning. Deprioritizing the generic instance restores the
  80canonical one everywhere in this file. -/
  81attribute [local instance 0] AddCommGroup.toIntModule
  82attribute [local instance 0] SubNegMonoid.toZSMul
  83
  84/-! ## Stage 1: the small-chains subcomplex -/
  85
  86variable {X : TopCat.{0}}
  87
  88/-- A singular `n`-simplex of `X` is *small* (relative to the pair of subsets
  89`U, V`) when its range lies in `U` or in `V`. -/
  90def Small (U V : Set X) {n : ℕ} (s : Idx X n) : Prop :=
  91  Set.range ⇑(simplexEquiv X n s) ⊆ U ∨ Set.range ⇑(simplexEquiv X n s) ⊆ V
  92
  93/-- Faces of small simplices are small. -/
  94lemma Small.δ {U V : Set X} {n : ℕ} {s : Idx X (n + 1)} (hs : Small U V s)
  95    (k : Fin (n + 2)) : Small U V ((TopCat.toSSet.obj X).δ k s) := by
  96  have hrange : Set.range ⇑(simplexEquiv X n ((TopCat.toSSet.obj X).δ k s)) ⊆
  97      Set.range ⇑(simplexEquiv X (n + 1) s) := by
  98    rw [simplexEquiv_δ, ContinuousMap.coe_comp]
  99    exact Set.range_comp_subset_range _ _
 100  rcases hs with h | h
 101  · exact Or.inl (hrange.trans h)
 102  · exact Or.inr (hrange.trans h)
 103
 104variable (U V : Set X)
 105
 106/-- The index type of the degree-`n` small chain group: small singular
 107`n`-simplices. -/
 108def SIdx (n : ℕ) : Type := { s : Idx X n // Small U V s }
 109
 110/-- The degree-`n` small chain group: the free `ℤ`-module on the small
 111singular `n`-simplices, presented as a coproduct. -/
 112noncomputable abbrev sCgrp (n : ℕ) : ModuleCat.{0} ℤ :=
 113  ∐ fun _ : SIdx U V n => ModuleCat.of ℤ ℤ
 114
 115/-- The generator of the small chain group attached to a small simplex. -/
 116noncomputable def sgen (n : ℕ) (t : SIdx U V n) : ModuleCat.of ℤ ℤ ⟶ sCgrp U V n :=
 117  Sigma.ι (fun _ : SIdx U V n => ModuleCat.of ℤ ℤ) t
 118
 119/-- The degree-`n` inclusion of the small chain group into the singular
 120chain group. -/
 121noncomputable def sInc (n : ℕ) : sCgrp U V n ⟶ Cgrp X n :=
 122  Sigma.desc fun t => gen X n t.1
 123
 124lemma sgen_sInc {n : ℕ} (t : SIdx U V n) :
 125    sgen U V n t ≫ sInc U V n = gen X n t.1 :=
 126  Sigma.ι_desc _ _
 127
 128open Classical in
 129/-- The retraction of the degree-`n` inclusion: a small simplex goes to its
 130small generator, everything else goes to `0`. -/
 131noncomputable def sRet (n : ℕ) : Cgrp X n ⟶ sCgrp U V n :=
 132  Sigma.desc fun s =>
 133    if h : Small U V s then sgen U V n ⟨s, h⟩ else 0
 134
 135lemma sInc_comp_sRet (n : ℕ) : sInc U V n ≫ sRet U V n = 𝟙 (sCgrp U V n) := by
 136  apply Sigma.hom_ext
 137  intro t
 138  show sgen U V n t ≫ sInc U V n ≫ sRet U V n = sgen U V n t ≫ 𝟙 (sCgrp U V n)
 139  rw [Category.comp_id, ← assoc, sgen_sInc]
 140  show Sigma.ι (fun _ : Idx X n => ModuleCat.of ℤ ℤ) t.1 ≫ sRet U V n = sgen U V n t
 141  unfold sRet
 142  rw [Sigma.ι_desc, dif_pos t.2]
 143  congr 1
 144
 145/-- The degree-`n` inclusion is a (split) monomorphism. -/
 146lemma sInc_mono (n : ℕ) : Mono (sInc U V n) :=
 147  mono_of_mono_fac (sInc_comp_sRet U V n)
 148
 149/-- The boundary of the small chain complex: the alternating sum of faces,
 150which are small by `Small.δ`. -/
 151noncomputable def sBnd (n : ℕ) : sCgrp U V (n + 1) ⟶ sCgrp U V n :=
 152  Sigma.desc fun t => ∑ k : Fin (n + 2),
 153    (-1 : ℤ) ^ (k : ℕ) • sgen U V n ⟨(TopCat.toSSet.obj X).δ k t.1, t.2.δ k⟩
 154
 155lemma sgen_sBnd {n : ℕ} (t : SIdx U V (n + 1)) :
 156    sgen U V (n + 1) t ≫ sBnd U V n = ∑ k : Fin (n + 2),
 157      (-1 : ℤ) ^ (k : ℕ) • sgen U V n ⟨(TopCat.toSSet.obj X).δ k t.1, t.2.δ k⟩ :=
 158  Sigma.ι_desc _ _
 159
 160/-- The inclusion intertwines the small boundary and the singular boundary. -/
 161lemma sBnd_comp_sInc (n : ℕ) :
 162    sBnd U V n ≫ sInc U V n = sInc U V (n + 1) ≫ bnd X n := by
 163  apply Sigma.hom_ext
 164  intro t
 165  rw [← assoc, ← assoc]
 166  show (sgen U V (n + 1) t ≫ sBnd U V n) ≫ sInc U V n =
 167    (sgen U V (n + 1) t ≫ sInc U V (n + 1)) ≫ bnd X n
 168  rw [sgen_sBnd, sgen_sInc, gen_d, Preadditive.sum_comp]
 169  refine Finset.sum_congr rfl fun k _ => ?_
 170  rw [Preadditive.zsmul_comp]
 171  congr 1
 172  exact sgen_sInc U V _
 173
 174/-- The small boundary squares to zero. -/
 175lemma sBnd_comp_sBnd (n : ℕ) : sBnd U V (n + 1) ≫ sBnd U V n = 0 := by
 176  have := sInc_mono U V n
 177  rw [← cancel_mono (sInc U V n), zero_comp, assoc, sBnd_comp_sInc,
 178    ← assoc, sBnd_comp_sInc, assoc]
 179  show sInc U V (n + 2) ≫ (SC X).d (n + 2) (n + 1) ≫ (SC X).d (n + 1) n = 0
 180  rw [HomologicalComplex.d_comp_d, comp_zero]
 181
 182/-- **Stage 1.** The small-chains subcomplex `C^{U,V}_*(X)`: the chain
 183complex of chains generated by singular simplices landing in `U` or in
 184`V`. -/
 185noncomputable def SSC : ChainComplex (ModuleCat.{0} ℤ) ℕ :=
 186  ChainComplex.of (sCgrp U V) (sBnd U V) (sBnd_comp_sBnd U V)
 187
 188@[simp] lemma SSC_X (n : ℕ) : (SSC U V).X n = sCgrp U V n := rfl
 189
 190lemma SSC_d (n : ℕ) : (SSC U V).d (n + 1) n = sBnd U V n :=
 191  ChainComplex.of_d _ _ _ _
 192
 193/-- The inclusion of the small-chains subcomplex into the singular chain
 194complex, as a chain map. -/
 195noncomputable def smallι : SSC U V ⟶ SC X where
 196  f n := sInc U V n
 197  comm' := by
 198    rintro i j (rfl : j + 1 = i)
 199    rw [SSC_d]
 200    exact (sBnd_comp_sInc U V j).symm
 201
 202@[simp] lemma smallι_f (n : ℕ) : (smallι U V).f n = sInc U V n := rfl
 203
 204/-- The inclusion of the small-chains subcomplex is a monomorphism of chain
 205complexes. -/
 206lemma smallι_mono : Mono (smallι U V) :=
 207  HomologicalComplex.mono_of_mono_f _ fun n => sInc_mono U V n
 208
 209/-! ## Stage 2 toolkit A: elements of free coproducts of copies of `ℤ` -/
 210
 211section Elements
 212
 213/-- Elementwise `ℤ`-linearity of a `ModuleCat` morphism (stated through the
 214underlying linear map, to avoid instance-resolution issues on carriers). -/
 215lemma mapSmul {M N : ModuleCat.{0} ℤ} (φ : M ⟶ N) (c : ℤ) (x : M) :
 216    φ (c • x) = c • φ x :=
 217  φ.hom.map_smul c x
 218
 219lemma zeroApp {M N : ModuleCat.{0} ℤ} (x : M) : (0 : M ⟶ N) x = 0 := by
 220  show (0 : M ⟶ N).hom x = 0
 221  rw [ModuleCat.hom_zero]
 222  rfl
 223
 224/-- Evaluation at `1 : ℤ` of morphisms out of `ℤ`, as a linear map. -/
 225noncomputable def ev1 {M : ModuleCat.{0} ℤ} : (ModuleCat.of ℤ ℤ ⟶ M) →ₗ[ℤ] M where
 226  toFun f := f (1 : ℤ)
 227  map_add' _ _ := rfl
 228  map_smul' _ _ := rfl
 229
 230@[simp] lemma ev1_apply {M : ModuleCat.{0} ℤ} (f : ModuleCat.of ℤ ℤ ⟶ M) :
 231    ev1 f = f (1 : ℤ) := rfl
 232
 233variable {κ : Type}
 234
 235/-- The generating element of the free `ℤ`-module `∐_κ ℤ` attached to an
 236index. -/
 237noncomputable def unitOf (i : κ) : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ) :=
 238  Sigma.ι (fun _ : κ => ModuleCat.of ℤ ℤ) i (1 : ℤ)
 239
 240lemma comp_unitOf {M : ModuleCat.{0} ℤ}
 241    (φ : (∐ fun _ : κ => ModuleCat.of ℤ ℤ) ⟶ M) (i : κ) :
 242    φ (unitOf i) = ev1 (Sigma.ι (fun _ : κ => ModuleCat.of ℤ ℤ) i ≫ φ) := by
 243  rw [ev1_apply, ModuleCat.comp_apply]
 244  rfl
 245
 246/-- The generating elements span the free module `∐_κ ℤ`. -/
 247lemma span_unitOf_eq_top :
 248    Submodule.span ℤ (Set.range (unitOf (κ := κ))) = ⊤ := by
 249  rw [Submodule.eq_top_iff']
 250  intro z
 251  set e := ModuleCat.coprodIsoDirectSum (fun _ : κ => ModuleCat.of ℤ ℤ) with he
 252  have h1 : e.inv (e.hom z) = z := by
 253    rw [← ModuleCat.comp_apply, e.hom_inv_id, ModuleCat.id_apply]
 254  have h2 : e.hom z =
 255      ∑ i ∈ (e.hom z).support, DirectSum.lof ℤ κ (fun _ => ℤ) i ((e.hom z) i) := by
 256    conv_lhs => rw [← DirectSum.sum_support_of (e.hom z)]
 257    refine Finset.sum_congr rfl fun i _ => ?_
 258    rw [DirectSum.lof_eq_of]
 259  have h3 : z = ∑ i ∈ (e.hom z).support, ((e.hom z) i) • unitOf i := by
 260    conv_lhs => rw [← h1]
 261    conv_lhs => rw [h2]
 262    rw [map_sum]
 263    refine Finset.sum_congr rfl fun i _ => ?_
 264    have h4 : DirectSum.lof ℤ κ (fun _ => ℤ) i ((e.hom z) i) =
 265        ((e.hom z) i) • DirectSum.lof ℤ κ (fun _ => ℤ) i (1 : ℤ) := by
 266      rw [← map_smul, smul_eq_mul, mul_one]
 267    rw [h4, mapSmul]
 268    congr 1
 269    rw [he]
 270    exact ModuleCat.lof_coprodIsoDirectSum_inv_apply
 271      (fun _ : κ => ModuleCat.of ℤ ℤ) i (1 : ℤ)
 272  rw [h3]
 273  exact Submodule.sum_mem _ fun i _ =>
 274    Submodule.smul_mem _ _ (Submodule.subset_span ⟨i, rfl⟩)
 275
 276/-- Induction principle: to prove a property of all elements of `∐_κ ℤ`
 277closed under `0`, `+`, `ℤ • ·`, it suffices to prove it for the generating
 278elements. -/
 279lemma freeInduction {p : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ) → Prop}
 280    (unit : ∀ i : κ, p (unitOf i)) (zero : p 0)
 281    (add : ∀ x y, p x → p y → p (x + y))
 282    (smulz : ∀ (c : ℤ) (x), p x → p (c • x))
 283    (z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) : p z := by
 284  have hz : z ∈ Submodule.span ℤ (Set.range (unitOf (κ := κ))) := by
 285    rw [span_unitOf_eq_top]; trivial
 286  refine Submodule.span_induction ?_ zero (fun x y _ _ hx hy => add x y hx hy)
 287    (fun c x _ hx => smulz c x hx) hz
 288  rintro _ ⟨i, rfl⟩
 289  exact unit i
 290
 291end Elements
 292
 293/-! ## Stage 2 toolkit B: the small span and support tracking -/
 294
 295section SmallSpan
 296
 297/-- The generating element of the singular chain group attached to a
 298singular simplex. -/
 299noncomputable def genUnit (X : TopCat.{0}) (n : ℕ) (s : Idx X n) : Cgrp X n :=
 300  unitOf (κ := Idx X n) s
 301
 302lemma genUnit_eq (X : TopCat.{0}) (n : ℕ) (s : Idx X n) :
 303    genUnit X n s = gen X n s (1 : ℤ) := rfl
 304
 305/-- The submodule of small chains inside the singular chain group. -/
 306noncomputable def smallSpan (U V : Set X) (n : ℕ) : Submodule ℤ (Cgrp X n) :=
 307  Submodule.span ℤ {z | ∃ s : Idx X n, Small U V s ∧ z = genUnit X n s}
 308
 309lemma genUnit_mem_smallSpan {U V : Set X} {n : ℕ} {s : Idx X n}
 310    (hs : Small U V s) : genUnit X n s ∈ smallSpan U V n :=
 311  Submodule.subset_span ⟨s, hs, rfl⟩
 312
 313/-- The generating element of the small chain group attached to a small
 314simplex. -/
 315noncomputable def sUnit (U V : Set X) (n : ℕ) (t : SIdx U V n) : ↥(sCgrp U V n) :=
 316  unitOf (κ := SIdx U V n) t
 317
 318lemma sInc_sUnit {U V : Set X} {n : ℕ} (t : SIdx U V n) :
 319    sInc U V n (sUnit U V n t) = genUnit X n t.1 := by
 320  show sInc U V n (unitOf t) = genUnit X n t.1
 321  rw [comp_unitOf]
 322  have h2 : Sigma.ι (fun _ : SIdx U V n => ModuleCat.of ℤ ℤ) t ≫ sInc U V n =
 323      gen X n t.1 := sgen_sInc U V t
 324  rw [h2]
 325  rfl
 326
 327/-- Elementwise injectivity of the degree-`n` inclusion. -/
 328lemma sInc_injective (U V : Set X) (n : ℕ) :
 329    Function.Injective (sInc U V n) := by
 330  intro a b hab
 331  have h := congrArg (sRet U V n) hab
 332  rw [← ModuleCat.comp_apply, ← ModuleCat.comp_apply, sInc_comp_sRet,
 333    ModuleCat.id_apply, ModuleCat.id_apply] at h
 334  exact h
 335
 336/-- The inclusion maps small chains into the small span. -/
 337lemma sInc_mem_smallSpan (U V : Set X) (n : ℕ) (z' : ↥(sCgrp U V n)) :
 338    sInc U V n z' ∈ smallSpan U V n := by
 339  induction z' using freeInduction with
 340  | unit t =>
 341      have h : sInc U V n (sUnit U V n t) = genUnit X n t.1 := sInc_sUnit t
 342      rw [show (unitOf t : ↥(sCgrp U V n)) = sUnit U V n t from rfl, h]
 343      exact genUnit_mem_smallSpan t.2
 344  | zero => rw [map_zero]; exact Submodule.zero_mem _
 345  | add x y hx hy => rw [map_add]; exact Submodule.add_mem _ hx hy
 346  | smulz c x hx => rw [mapSmul]; exact Submodule.smul_mem _ _ hx
 347
 348/-- Membership of small chains in the range of the inclusion. -/
 349lemma exists_sInc_eq {U V : Set X} {n : ℕ} {z : Cgrp X n}
 350    (hz : z ∈ smallSpan U V n) : ∃ z' : ↥(sCgrp U V n), sInc U V n z' = z := by
 351  refine Submodule.span_induction ?_ ?_ ?_ ?_ hz
 352  · rintro _ ⟨s, hs, rfl⟩
 353    exact ⟨sUnit U V n ⟨s, hs⟩, sInc_sUnit ⟨s, hs⟩⟩
 354  · exact ⟨0, map_zero _⟩
 355  · rintro x y _ _ ⟨a, ha⟩ ⟨b, hb⟩
 356    exact ⟨a + b, by rw [map_add, ha, hb]⟩
 357  · rintro c x _ ⟨a, ha⟩
 358    exact ⟨c • a, by rw [mapSmul, ha]⟩
 359
 360/-- Evaluation of an affine chain along `σ` lands in the small span as soon
 361as every support piece pushes to a small simplex. -/
 362lemma toChain_one_mem_smallSpan {U V : Set X} {n m : ℕ}
 363    (σ : C(stdSimplex ℝ (Fin (n + 1)), X)) (c : AC (stdSimplex ℝ (Fin (n + 1))) m)
 364    (h : ∀ w ∈ c.support, Small U V (pushSimplex σ w)) :
 365    ev1 (toChain σ m c) ∈ smallSpan U V m := by
 366  rw [toChain, Finsupp.linearCombination_apply, Finsupp.sum, map_sum]
 367  refine Submodule.sum_mem _ fun w hw => ?_
 368  rw [map_zsmul]
 369  exact zsmul_mem (genUnit_mem_smallSpan (h w hw)) _
 370
 371/-- Pushing a simplex along an affine piece keeps it inside a small
 372simplex's range: smallness is inherited. -/
 373lemma small_pushSimplex {U V : Set X} {n m : ℕ} {s : Idx X n}
 374    (hs : Small U V s) (w : Fin (m + 1) → stdSimplex ℝ (Fin (n + 1))) :
 375    Small U V (pushSimplex (simplexEquiv X n s) w) := by
 376  have hrange : Set.range ⇑(simplexEquiv X m (pushSimplex (simplexEquiv X n s) w)) ⊆
 377      Set.range ⇑(simplexEquiv X n s) := by
 378    rw [simplexEquiv_pushSimplex, ContinuousMap.coe_comp]
 379    exact Set.range_comp_subset_range _ _
 380  rcases hs with h | h
 381  · exact Or.inl (hrange.trans h)
 382  · exact Or.inr (hrange.trans h)
 383
 384/-- The singular subdivision operator preserves the small span. -/
 385lemma sdOp_mem_smallSpan {U V : Set X} {n : ℕ} {z : Cgrp X n}
 386    (hz : z ∈ smallSpan U V n) : sdOp X n z ∈ smallSpan U V n := by
 387  refine Submodule.span_induction ?_ ?_ ?_ ?_ hz
 388  · rintro _ ⟨s, hs, rfl⟩
 389    rw [genUnit_eq, ← ModuleCat.comp_apply, gen_sdOp]
 390    show ev1 (toChain (simplexEquiv X n s) n
 391      (asub (baryFn n) n (asimplex (idTuple n)))) ∈ smallSpan U V n
 392    exact toChain_one_mem_smallSpan _ _ fun w _ => small_pushSimplex hs w
 393  · rw [map_zero]; exact Submodule.zero_mem _
 394  · intro x y _ _ hx hy
 395    rw [map_add]; exact Submodule.add_mem _ hx hy
 396  · intro c x _ hx
 397    rw [mapSmul]; exact Submodule.smul_mem _ _ hx
 398
 399/-- The subdivision homotopy maps the small span into the small span one
 400degree up. -/
 401lemma tOp_mem_smallSpan {U V : Set X} {n : ℕ} {z : Cgrp X n}
 402    (hz : z ∈ smallSpan U V n) : tOp X n z ∈ smallSpan U V (n + 1) := by
 403  refine Submodule.span_induction ?_ ?_ ?_ ?_ hz
 404  · rintro _ ⟨s, hs, rfl⟩
 405    rw [genUnit_eq, ← ModuleCat.comp_apply, gen_tOp]
 406    show ev1 (toChain (simplexEquiv X n s) (n + 1)
 407      (atee (baryFn n) n (asimplex (idTuple n)))) ∈ smallSpan U V (n + 1)
 408    exact toChain_one_mem_smallSpan _ _ fun w _ => small_pushSimplex hs w
 409  · rw [map_zero]; exact Submodule.zero_mem _
 410  · intro x y _ _ hx hy
 411    rw [map_add]; exact Submodule.add_mem _ hx hy
 412  · intro c x _ hx
 413    rw [mapSmul]; exact Submodule.smul_mem _ _ hx
 414
 415/-- Iterated subdivision preserves the small span. -/
 416lemma sdOpIter_mem_smallSpan {U V : Set X} {n : ℕ} (k : ℕ) {z : Cgrp X n}
 417    (hz : z ∈ smallSpan U V n) : sdOpIter X n k z ∈ smallSpan U V n := by
 418  induction k with
 419  | zero => rw [sdOpIter_zero, ModuleCat.id_apply]; exact hz
 420  | succ k IH =>
 421      rw [sdOpIter_succ, ModuleCat.comp_apply]
 422      exact sdOp_mem_smallSpan IH
 423
 424/-- The telescoped homotopy maps the small span into the small span one
 425degree up. -/
 426lemma tOpIter_mem_smallSpan {U V : Set X} {n : ℕ} :
 427    ∀ (k : ℕ) {z : Cgrp X n}, z ∈ smallSpan U V n →
 428      tOpIter X n k z ∈ smallSpan U V (n + 1)
 429  | 0, z, _ => by
 430      rw [tOpIter_zero]
 431      show (0 : Cgrp X n ⟶ Cgrp X (n + 1)) z ∈ _
 432      rw [zeroApp]
 433      exact Submodule.zero_mem _
 434  | k + 1, z, hz => by
 435      rw [tOpIter_succ]
 436      show (tOp X n + sdOp X n ≫ tOpIter X n k) z ∈ _
 437      have hadd : (tOp X n + sdOp X n ≫ tOpIter X n k) z =
 438          tOp X n z + (sdOp X n ≫ tOpIter X n k) z := rfl
 439      rw [hadd, ModuleCat.comp_apply]
 440      exact Submodule.add_mem _ (tOp_mem_smallSpan hz)
 441        (tOpIter_mem_smallSpan k (sdOp_mem_smallSpan hz))
 442
 443/-- Additivity of the subdivision iterate. -/
 444lemma sdOpIter_add (X : TopCat.{0}) (n a b : ℕ) :
 445    sdOpIter X n (a + b) = sdOpIter X n a ≫ sdOpIter X n b := by
 446  induction b with
 447  | zero => rw [Nat.add_zero, sdOpIter_zero, Category.comp_id]
 448  | succ b IH =>
 449      rw [show a + (b + 1) = (a + b) + 1 from rfl, sdOpIter_succ, IH,
 450        sdOpIter_succ, Category.assoc]
 451
 452/-- **Uniform smallness.** For open `U, V` covering `X`, every singular
 453chain admits an iterate of the subdivision landing in the small span. -/
 454lemma exists_sdOpIter_mem_smallSpan {U V : Set X} (hU : IsOpen U) (hV : IsOpen V)
 455    (hUV : U ∪ V = Set.univ) {n : ℕ} (z : Cgrp X n) :
 456    ∃ k, sdOpIter X n k z ∈ smallSpan U V n := by
 457  induction z using freeInduction with
 458  | unit s =>
 459      obtain ⟨k, hk⟩ := exists_sdOpIter_small U V hU hV hUV s
 460      refine ⟨k, ?_⟩
 461      have h1 : sdOpIter X n k (unitOf s) = ev1 (gen X n s ≫ sdOpIter X n k) := by
 462        rw [show unitOf (κ := Idx X n) s = genUnit X n s from rfl, genUnit_eq,
 463          ← ModuleCat.comp_apply]
 464        rfl
 465      rw [h1, gen_comp_sdOpIter]
 466      exact toChain_one_mem_smallSpan _ _ fun w hw => hk w hw
 467  | zero => exact ⟨0, by rw [map_zero]; exact Submodule.zero_mem _⟩
 468  | add x y hx hy =>
 469      obtain ⟨k₁, h₁⟩ := hx
 470      obtain ⟨k₂, h₂⟩ := hy
 471      refine ⟨k₁ + k₂, ?_⟩
 472      rw [map_add]
 473      refine Submodule.add_mem _ ?_ ?_
 474      · rw [sdOpIter_add, ModuleCat.comp_apply]
 475        exact sdOpIter_mem_smallSpan k₂ h₁
 476      · rw [Nat.add_comm k₁ k₂, sdOpIter_add, ModuleCat.comp_apply]
 477        exact sdOpIter_mem_smallSpan k₁ h₂
 478  | smulz c x hx =>
 479      obtain ⟨k, hk⟩ := hx
 480      exact ⟨k, by rw [mapSmul]; exact Submodule.smul_mem _ _ hk⟩
 481
 482/-- Elementwise telescoped homotopy identity in positive degrees, on
 483cycles. -/
 484lemma sub_sdOpIter_eq_bnd_succ {n k : ℕ} (z : Cgrp X (n + 1))
 485    (hz : bnd X n z = 0) :
 486    z - sdOpIter X (n + 1) k z = bnd X (n + 1) (tOpIter X (n + 1) k z) := by
 487  have h := congrArg (fun f : Cgrp X (n + 1) ⟶ Cgrp X (n + 1) => f z)
 488    (tOpIter_chain_homotopy_succ X n k)
 489  have h1 : (bnd X n ≫ tOpIter X n k + tOpIter X (n + 1) k ≫ bnd X (n + 1)) z =
 490      tOpIter X n k (bnd X n z) + bnd X (n + 1) (tOpIter X (n + 1) k z) := by
 491    show (bnd X n ≫ tOpIter X n k) z + (tOpIter X (n + 1) k ≫ bnd X (n + 1)) z = _
 492    rw [ModuleCat.comp_apply, ModuleCat.comp_apply]
 493  have h2 : (𝟙 (Cgrp X (n + 1)) - sdOpIter X (n + 1) k) z =
 494      z - sdOpIter X (n + 1) k z := by
 495    show (𝟙 (Cgrp X (n + 1))) z - sdOpIter X (n + 1) k z = _
 496    rw [ModuleCat.id_apply]
 497  simp only [h1, h2] at h
 498  rw [hz, map_zero, zero_add] at h
 499  exact h.symm
 500
 501/-- Elementwise telescoped homotopy identity in degree `0`. -/
 502lemma sub_sdOpIter_eq_bnd_zero {k : ℕ} (z : Cgrp X 0) :
 503    z - sdOpIter X 0 k z = bnd X 0 (tOpIter X 0 k z) := by
 504  have h := congrArg (fun f : Cgrp X 0 ⟶ Cgrp X 0 => f z)
 505    (tOpIter_chain_homotopy_zero X k)
 506  have h1 : (tOpIter X 0 k ≫ bnd X 0) z = bnd X 0 (tOpIter X 0 k z) :=
 507    ModuleCat.comp_apply _ _ _
 508  have h2 : (𝟙 (Cgrp X 0) - sdOpIter X 0 k) z = z - sdOpIter X 0 k z := by
 509    show (𝟙 (Cgrp X 0)) z - sdOpIter X 0 k z = _
 510    rw [ModuleCat.id_apply]
 511  simp only [h1, h2] at h
 512  exact h.symm
 513
 514/-- Elementwise chain-map property of the subdivision iterate. -/
 515lemma sdOpIter_bnd_elem {n k : ℕ} (w : Cgrp X (n + 1)) :
 516    bnd X n (sdOpIter X (n + 1) k w) = sdOpIter X n k (bnd X n w) := by
 517  have h := congrArg (fun f : Cgrp X (n + 1) ⟶ Cgrp X n => f w)
 518    (sdOpIter_comp_bnd X n k)
 519  simpa only [ModuleCat.comp_apply] using h
 520
 521/-- Elementwise telescoped homotopy identity in every degree, on
 522boundaries. -/
 523lemma sub_sdOpIter_eq_bnd_of_boundary {n : ℕ} (k : ℕ) (z : Cgrp X n)
 524    (w : Cgrp X (n + 1)) (hw : z = bnd X n w) :
 525    z - sdOpIter X n k z = bnd X n (tOpIter X n k z) := by
 526  cases n with
 527  | zero => exact sub_sdOpIter_eq_bnd_zero z
 528  | succ m =>
 529      refine sub_sdOpIter_eq_bnd_succ z ?_
 530      rw [hw, ← ModuleCat.comp_apply]
 531      have hdd : bnd X (m + 1) ≫ bnd X m = 0 := by
 532        show (SC X).d (m + 2) (m + 1) ≫ (SC X).d (m + 1) m = 0
 533        exact HomologicalComplex.d_comp_d _ _ _ _
 534      rw [hdd]
 535      exact zeroApp w
 536
 537end SmallSpan
 538
 539/-! ## Stage 2 toolkit C: a concrete homology-isomorphism criterion for
 540short complexes of `ℤ`-modules -/
 541
 542section HomologyCriterion
 543
 544open ShortComplex
 545
 546variable {S T : ShortComplex (ModuleCat.{0} ℤ)}
 547
 548lemma τ₂_maps_ker (ψ : S ⟶ T) : ∀ x ∈ LinearMap.ker S.g.hom,
 549    ψ.τ₂ x ∈ LinearMap.ker T.g.hom := by
 550  intro x hx
 551  rw [LinearMap.mem_ker] at hx ⊢
 552  have h := congrArg (fun f : S.X₂ ⟶ T.X₃ => f x) ψ.comm₂₃
 553  simp only [ModuleCat.comp_apply] at h
 554  show T.g (ψ.τ₂ x) = 0
 555  rw [h, show S.g x = (0 : S.X₃) from hx, map_zero]
 556
 557/-- The induced map on concrete cycles. -/
 558noncomputable def kerMap (ψ : S ⟶ T) :
 559    ↥(LinearMap.ker S.g.hom) →ₗ[ℤ] ↥(LinearMap.ker T.g.hom) :=
 560  LinearMap.restrict ψ.τ₂.hom (τ₂_maps_ker ψ)
 561
 562@[simp] lemma kerMap_coe (ψ : S ⟶ T) (x : ↥(LinearMap.ker S.g.hom)) :
 563    (kerMap ψ x : T.X₂) = ψ.τ₂ (x : S.X₂) := rfl
 564
 565lemma kerMap_range_le (ψ : S ⟶ T) :
 566    LinearMap.range S.moduleCatToCycles ≤
 567      (LinearMap.range T.moduleCatToCycles).comap (kerMap ψ) := by
 568  rintro _ ⟨a, rfl⟩
 569  refine ⟨ψ.τ₁ a, ?_⟩
 570  apply Subtype.ext
 571  show T.f (ψ.τ₁ a) = ψ.τ₂ (S.f a)
 572  have h := congrArg (fun f : S.X₁ ⟶ T.X₂ => f a) ψ.comm₁₂
 573  simpa only [ModuleCat.comp_apply] using h
 574
 575/-- The induced map on concrete homology. -/
 576noncomputable def quotMap (ψ : S ⟶ T) :
 577    (↥(LinearMap.ker S.g.hom) ⧸ LinearMap.range S.moduleCatToCycles) →ₗ[ℤ]
 578      (↥(LinearMap.ker T.g.hom) ⧸ LinearMap.range T.moduleCatToCycles) :=
 579  Submodule.mapQ _ _ (kerMap ψ) (kerMap_range_le ψ)
 580
 581/-- The concrete left-homology map data for `ψ` relative to the
 582`moduleCat` left homology data on both sides. -/
 583noncomputable def lhMapData (ψ : S ⟶ T) :
 584    LeftHomologyMapData ψ S.moduleCatLeftHomologyData T.moduleCatLeftHomologyData where
 585  φK := ModuleCat.ofHom (kerMap ψ)
 586  φH := ModuleCat.ofHom (quotMap ψ)
 587  commi := by
 588    refine ModuleCat.hom_ext (LinearMap.ext fun x => ?_)
 589    rfl
 590  commf' := by
 591    refine ModuleCat.hom_ext (LinearMap.ext fun a => ?_)
 592    apply Subtype.ext
 593    show ψ.τ₂ (S.f a) = T.f (ψ.τ₁ a)
 594    have h := congrArg (fun f : S.X₁ ⟶ T.X₂ => f a) ψ.comm₁₂
 595    simpa only [ModuleCat.comp_apply] using h.symm
 596  commπ := by
 597    refine ModuleCat.hom_ext (LinearMap.ext fun x => ?_)
 598    show quotMap ψ (Submodule.Quotient.mk x) = Submodule.Quotient.mk (kerMap ψ x)
 599    rfl
 600
 601lemma quotMap_surjective (ψ : S ⟶ T)
 602    (hsurj : ∀ y : T.X₂, T.g y = 0 →
 603      ∃ (x : S.X₂) (w : T.X₁), S.g x = 0 ∧ ψ.τ₂ x = y + T.f w) :
 604    Function.Surjective (quotMap ψ) := by
 605  intro q
 606  obtain ⟨⟨y, hy⟩, rfl⟩ :=
 607    Submodule.mkQ_surjective (LinearMap.range T.moduleCatToCycles) q
 608  obtain ⟨x, w, hgx, hx⟩ := hsurj y (LinearMap.mem_ker.mp hy)
 609  refine ⟨Submodule.Quotient.mk ⟨x, LinearMap.mem_ker.mpr hgx⟩, ?_⟩
 610  show quotMap ψ (Submodule.Quotient.mk _) =
 611    Submodule.Quotient.mk (⟨y, hy⟩ : ↥(LinearMap.ker T.g.hom))
 612  rw [quotMap, Submodule.mapQ_apply]
 613  refine (Submodule.Quotient.eq _).mpr ⟨w, ?_⟩
 614  apply Subtype.ext
 615  show T.f w = ψ.τ₂ x - y
 616  rw [hx]
 617  abel
 618
 619lemma quotMap_injective (ψ : S ⟶ T)
 620    (hinj : ∀ x : S.X₂, S.g x = 0 → (∃ w : T.X₁, ψ.τ₂ x = T.f w) →
 621      ∃ v : S.X₁, x = S.f v) :
 622    Function.Injective (quotMap ψ) := by
 623  rw [injective_iff_map_eq_zero]
 624  intro q hq
 625  obtain ⟨⟨x, hx⟩, rfl⟩ :=
 626    Submodule.mkQ_surjective (LinearMap.range S.moduleCatToCycles) q
 627  have hq' : Submodule.Quotient.mk (p := LinearMap.range T.moduleCatToCycles)
 628      (kerMap ψ ⟨x, hx⟩) = 0 := by
 629    rw [← Submodule.mapQ_apply (LinearMap.range S.moduleCatToCycles)
 630      (h := kerMap_range_le ψ)]
 631    exact hq
 632  rw [Submodule.Quotient.mk_eq_zero] at hq'
 633  replace hq := hq'
 634  obtain ⟨w, hw⟩ := hq
 635  have hw' : ψ.τ₂ x = T.f w := by
 636    have := congrArg (Subtype.val) hw
 637    exact this.symm
 638  obtain ⟨v, hv⟩ := hinj x (LinearMap.mem_ker.mp hx) ⟨w, hw'⟩
 639  show Submodule.Quotient.mk (⟨x, hx⟩ : ↥(LinearMap.ker S.g.hom)) = 0
 640  rw [Submodule.Quotient.mk_eq_zero]
 641  exact ⟨v, Subtype.ext (by simpa using hv.symm)⟩
 642
 643/-- **The concrete criterion.** A morphism of short complexes of
 644`ℤ`-modules induces an isomorphism on homology as soon as the two
 645elementwise conditions hold. -/
 646lemma isIso_homologyMap_of_elementwise (ψ : S ⟶ T)
 647    (hsurj : ∀ y : T.X₂, T.g y = 0 →
 648      ∃ (x : S.X₂) (w : T.X₁), S.g x = 0 ∧ ψ.τ₂ x = y + T.f w)
 649    (hinj : ∀ x : S.X₂, S.g x = 0 → (∃ w : T.X₁, ψ.τ₂ x = T.f w) →
 650      ∃ v : S.X₁, x = S.f v) :
 651    IsIso (ShortComplex.homologyMap ψ) := by
 652  rw [(lhMapData ψ).homologyMap_eq]
 653  have hbij : Function.Bijective (quotMap ψ) :=
 654    ⟨quotMap_injective ψ hinj, quotMap_surjective ψ hsurj⟩
 655  have hiso : IsIso (lhMapData ψ).φH := by
 656    show IsIso (ModuleCat.ofHom (quotMap ψ))
 657    have hmono : Mono (ModuleCat.ofHom (quotMap ψ)) :=
 658      (ModuleCat.mono_iff_injective _).mpr hbij.1
 659    have hepi : Epi (ModuleCat.ofHom (quotMap ψ)) :=
 660      (ModuleCat.epi_iff_surjective _).mpr hbij.2
 661    exact isIso_of_mono_of_epi _
 662  infer_instance
 663
 664lemma epi_homologyMap_of_elementwise (ψ : S ⟶ T)
 665    (hsurj : ∀ y : T.X₂, T.g y = 0 →
 666      ∃ (x : S.X₂) (w : T.X₁), S.g x = 0 ∧ ψ.τ₂ x = y + T.f w) :
 667    Epi (ShortComplex.homologyMap ψ) := by
 668  rw [(lhMapData ψ).homologyMap_eq]
 669  have hepi : Epi (lhMapData ψ).φH := by
 670    show Epi (ModuleCat.ofHom (quotMap ψ))
 671    exact (ModuleCat.epi_iff_surjective _).mpr (quotMap_surjective ψ hsurj)
 672  apply epi_comp
 673end HomologyCriterion
 674
 675/-! ## Stage 2 toolkit D: chain-complex wrappers for the criterion -/
 676
 677section ChainCriterion
 678
 679variable {K L : ChainComplex (ModuleCat.{0} ℤ) ℕ}
 680
 681/-- Transport of `IsIso` on `homologyMap` through the honest-index short
 682complex functor `shortComplexFunctor'`. -/
 683lemma isIso_homologyMap_of_sc' (φ : K ⟶ L) (i j k : ℕ)
 684    (hi : (ComplexShape.down ℕ).prev j = i) (hk : (ComplexShape.down ℕ).next j = k)
 685    (h : IsIso (ShortComplex.homologyMap
 686      ((HomologicalComplex.shortComplexFunctor' (ModuleCat.{0} ℤ)
 687        (ComplexShape.down ℕ) i j k).map φ))) :
 688    IsIso (HomologicalComplex.homologyMap φ j) := by
 689  set e := HomologicalComplex.natIsoSc' (ModuleCat.{0} ℤ) (ComplexShape.down ℕ)
 690    i j k hi hk with he
 691  have hnat := e.hom.naturality φ
 692  have hcomm : (HomologicalComplex.shortComplexFunctor (ModuleCat.{0} ℤ)
 693      (ComplexShape.down ℕ) j).map φ =
 694      e.hom.app K ≫ (HomologicalComplex.shortComplexFunctor' (ModuleCat.{0} ℤ)
 695        (ComplexShape.down ℕ) i j k).map φ ≫ e.inv.app L := by
 696    rw [← Category.assoc, ← hnat, Category.assoc, Iso.hom_inv_id_app,
 697      Category.comp_id]
 698  have h1 : IsIso (ShortComplex.homologyMap (e.hom.app K)) :=
 699    (inferInstance : IsIso (ShortComplex.homologyMapIso (e.app K)).hom)
 700  have h2 : IsIso (ShortComplex.homologyMap (e.inv.app L)) :=
 701    (inferInstance : IsIso (ShortComplex.homologyMapIso (e.app L)).inv)
 702  show IsIso (ShortComplex.homologyMap
 703    ((HomologicalComplex.shortComplexFunctor (ModuleCat.{0} ℤ)
 704      (ComplexShape.down ℕ) j).map φ))
 705  rw [hcomm, ShortComplex.homologyMap_comp, ShortComplex.homologyMap_comp]
 706  infer_instance
 707
 708/-- Transport of `Epi` on `homologyMap` through the honest-index short
 709complex functor. -/
 710lemma epi_homologyMap_of_sc' (φ : K ⟶ L) (i j k : ℕ)
 711    (hi : (ComplexShape.down ℕ).prev j = i) (hk : (ComplexShape.down ℕ).next j = k)
 712    (h : Epi (ShortComplex.homologyMap
 713      ((HomologicalComplex.shortComplexFunctor' (ModuleCat.{0} ℤ)
 714        (ComplexShape.down ℕ) i j k).map φ))) :
 715    Epi (HomologicalComplex.homologyMap φ j) := by
 716  set e := HomologicalComplex.natIsoSc' (ModuleCat.{0} ℤ) (ComplexShape.down ℕ)
 717    i j k hi hk with he
 718  have hnat := e.hom.naturality φ
 719  have hcomm : (HomologicalComplex.shortComplexFunctor (ModuleCat.{0} ℤ)
 720      (ComplexShape.down ℕ) j).map φ =
 721      e.hom.app K ≫ (HomologicalComplex.shortComplexFunctor' (ModuleCat.{0} ℤ)
 722        (ComplexShape.down ℕ) i j k).map φ ≫ e.inv.app L := by
 723    rw [← Category.assoc, ← hnat, Category.assoc, Iso.hom_inv_id_app,
 724      Category.comp_id]
 725  have h1 : IsIso (ShortComplex.homologyMap (e.hom.app K)) :=
 726    (inferInstance : IsIso (ShortComplex.homologyMapIso (e.app K)).hom)
 727  have h2 : IsIso (ShortComplex.homologyMap (e.inv.app L)) :=
 728    (inferInstance : IsIso (ShortComplex.homologyMapIso (e.app L)).inv)
 729  show Epi (ShortComplex.homologyMap
 730    ((HomologicalComplex.shortComplexFunctor (ModuleCat.{0} ℤ)
 731      (ComplexShape.down ℕ) j).map φ))
 732  rw [hcomm, ShortComplex.homologyMap_comp, ShortComplex.homologyMap_comp]
 733  exact epi_comp _ _
 734
 735/-- Criterion for `homologyMap` in positive degree, with honest indices. -/
 736lemma isIso_homologyMap_chain_succ (φ : K ⟶ L) (n : ℕ)
 737    (hsurj : ∀ y : L.X (n + 1), L.d (n + 1) n y = 0 →
 738      ∃ (x : K.X (n + 1)) (w : L.X (n + 2)),
 739        K.d (n + 1) n x = 0 ∧ φ.f (n + 1) x = y + L.d (n + 2) (n + 1) w)
 740    (hinj : ∀ x : K.X (n + 1), K.d (n + 1) n x = 0 →
 741      (∃ w : L.X (n + 2), φ.f (n + 1) x = L.d (n + 2) (n + 1) w) →
 742      ∃ v : K.X (n + 2), x = K.d (n + 2) (n + 1) v) :
 743    IsIso (HomologicalComplex.homologyMap φ (n + 1)) := by
 744  refine isIso_homologyMap_of_sc' φ (n + 2) (n + 1) n
 745    (ChainComplex.prev ℕ (n + 1)) (ChainComplex.next_nat_succ n) ?_
 746  exact isIso_homologyMap_of_elementwise _ hsurj hinj
 747
 748/-- Criterion for `homologyMap` in degree `0`, with honest indices. -/
 749lemma isIso_homologyMap_chain_zero (φ : K ⟶ L)
 750    (hsurj : ∀ y : L.X 0,
 751      ∃ (x : K.X 0) (w : L.X 1), φ.f 0 x = y + L.d 1 0 w)
 752    (hinj : ∀ x : K.X 0, (∃ w : L.X 1, φ.f 0 x = L.d 1 0 w) →
 753      ∃ v : K.X 1, x = K.d 1 0 v) :
 754    IsIso (HomologicalComplex.homologyMap φ 0) := by
 755  have hdK : K.d 0 0 = 0 := K.shape 0 0 (by simp [ComplexShape.down_Rel])
 756  refine isIso_homologyMap_of_sc' φ 1 0 0
 757    (ChainComplex.prev ℕ 0) ChainComplex.next_nat_zero ?_
 758  refine isIso_homologyMap_of_elementwise _ ?_ ?_
 759  · intro y _
 760    obtain ⟨x, w, hx⟩ := hsurj y
 761    refine ⟨x, w, ?_, hx⟩
 762    show (K.d 0 0) x = 0
 763    rw [hdK]
 764    exact zeroApp x
 765  · intro x _ hx
 766    exact hinj x hx
 767
 768/-- Epi criterion for `homologyMap` in degree `0`. -/
 769lemma epi_homologyMap_chain_zero (φ : K ⟶ L)
 770    (hsurj : ∀ y : L.X 0,
 771      ∃ (x : K.X 0) (w : L.X 1), φ.f 0 x = y + L.d 1 0 w) :
 772    Epi (HomologicalComplex.homologyMap φ 0) := by
 773  have hdK : K.d 0 0 = 0 := K.shape 0 0 (by simp [ComplexShape.down_Rel])
 774  refine epi_homologyMap_of_sc' φ 1 0 0
 775    (ChainComplex.prev ℕ 0) ChainComplex.next_nat_zero ?_
 776  refine epi_homologyMap_of_elementwise _ ?_
 777  intro y _
 778  obtain ⟨x, w, hx⟩ := hsurj y
 779  refine ⟨x, w, ?_, hx⟩
 780  show (K.d 0 0) x = 0
 781  rw [hdK]
 782  exact zeroApp x
 783
 784end ChainCriterion
 785
 786/-! ## Stage 2: the small-chains theorem (Hatcher, Prop 2.21) -/
 787
 788section SmallChainsTheorem
 789
 790variable {U V : Set X}
 791
 792/-- Surjectivity input in positive degrees. -/
 793lemma small_surj_succ (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
 794    (n : ℕ) (y : Cgrp X (n + 1)) (hy : bnd X n y = 0) :
 795    ∃ (x : ↥(sCgrp U V (n + 1))) (w : Cgrp X (n + 2)),
 796      sBnd U V n x = 0 ∧ sInc U V (n + 1) x = y + bnd X (n + 1) w := by
 797  obtain ⟨k, hk⟩ := exists_sdOpIter_mem_smallSpan hU hV hUV y
 798  obtain ⟨x, hx⟩ := exists_sInc_eq hk
 799  refine ⟨x, -(tOpIter X (n + 1) k y), ?_, ?_⟩
 800  · -- x is a cycle in the small complex
 801    apply sInc_injective U V n
 802    have h1 : sInc U V n (sBnd U V n x) = bnd X n (sInc U V (n + 1) x) := by
 803      rw [← ModuleCat.comp_apply, ← ModuleCat.comp_apply, sBnd_comp_sInc]
 804    rw [h1, hx, sdOpIter_bnd_elem, hy, map_zero, map_zero]
 805  · rw [hx, map_neg]
 806    have h2 := sub_sdOpIter_eq_bnd_succ (k := k) y hy
 807    have : sdOpIter X (n + 1) k y = y - bnd X (n + 1) (tOpIter X (n + 1) k y) := by
 808      rw [← h2]; abel
 809    rw [this]; abel
 810
 811/-- Injectivity input in every degree `n` (with boundary from degree
 812`n + 1`). -/
 813lemma small_inj (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
 814    (n : ℕ) (x : ↥(sCgrp U V n)) (w : Cgrp X (n + 1))
 815    (hw : sInc U V n x = bnd X n w) :
 816    ∃ v : ↥(sCgrp U V (n + 1)), x = sBnd U V n v := by
 817  set z := sInc U V n x with hz
 818  have hzsmall : z ∈ smallSpan U V n := sInc_mem_smallSpan U V n x
 819  obtain ⟨k, hks⟩ := exists_sdOpIter_mem_smallSpan hU hV hUV w
 820  -- the corrected chain c := T_k z + sd^k w is small and has boundary z
 821  have hsd : sdOpIter X n k z = bnd X n (sdOpIter X (n + 1) k w) := by
 822    rw [sdOpIter_bnd_elem, hw]
 823  have hcorr : z - sdOpIter X n k z = bnd X n (tOpIter X n k z) :=
 824    sub_sdOpIter_eq_bnd_of_boundary k z w hw
 825  have hzbnd : z = bnd X n (tOpIter X n k z + sdOpIter X (n + 1) k w) := by
 826    rw [map_add, ← hcorr, ← hsd]
 827    abel
 828  have hcsmall : tOpIter X n k z + sdOpIter X (n + 1) k w ∈ smallSpan U V (n + 1) :=
 829    Submodule.add_mem _ (tOpIter_mem_smallSpan k hzsmall) hks
 830  obtain ⟨v, hv⟩ := exists_sInc_eq hcsmall
 831  refine ⟨v, ?_⟩
 832  apply sInc_injective U V n
 833  have h1 : sInc U V n (sBnd U V n v) = bnd X n (sInc U V (n + 1) v) := by
 834    rw [← ModuleCat.comp_apply, ← ModuleCat.comp_apply, sBnd_comp_sInc]
 835  rw [h1, hv, ← hzbnd, hz]
 836
 837/-- **Stage 2: the small-chains theorem.** For open `U, V` covering `X`,
 838the inclusion of the small-chains subcomplex induces an isomorphism on
 839homology in every degree. -/
 840theorem smallι_isIso_homologyMap (hU : IsOpen U) (hV : IsOpen V)
 841    (hUV : U ∪ V = Set.univ) (n : ℕ) :
 842    IsIso (HomologicalComplex.homologyMap (smallι U V) n) := by
 843  match n with
 844  | 0 =>
 845      refine isIso_homologyMap_chain_zero (smallι U V) ?_ ?_
 846      · intro y
 847        obtain ⟨k, hk⟩ := exists_sdOpIter_mem_smallSpan hU hV hUV y
 848        obtain ⟨x, hx⟩ := exists_sInc_eq hk
 849        refine ⟨x, -(tOpIter X 0 k y), ?_⟩
 850        let y' : ↥(Cgrp X 0) := y
 851        have hx' : sInc U V 0 x = sdOpIter X 0 k y' := hx
 852        have h2 := sub_sdOpIter_eq_bnd_zero (k := k) y'
 853        have h3 : sInc U V 0 x = y' + bnd X 0 (-(tOpIter X 0 k y')) := by
 854          rw [hx', map_neg]
 855          have h4 : sdOpIter X 0 k y' = y' - bnd X 0 (tOpIter X 0 k y') := by
 856            rw [← h2]; abel
 857          rw [h4]; abel
 858        exact h3
 859      · intro x hx
 860        obtain ⟨w, hw⟩ := hx
 861        have hw' : sInc U V 0 x = bnd X 0 w := hw
 862        obtain ⟨v, hv⟩ := small_inj hU hV hUV 0 x w hw'
 863        refine ⟨v, ?_⟩
 864        show x = (SSC U V).d 1 0 v
 865        rw [SSC_d]
 866        exact hv
 867  | n + 1 =>
 868      refine isIso_homologyMap_chain_succ (smallι U V) n ?_ ?_
 869      · intro y hy
 870        obtain ⟨x, w, h1, h2⟩ := small_surj_succ hU hV hUV n y hy
 871        refine ⟨x, w, ?_, h2⟩
 872        show (SSC U V).d (n + 1) n x = 0
 873        rw [SSC_d]
 874        exact h1
 875      · intro x hx hw
 876        obtain ⟨w, hw'⟩ := hw
 877        obtain ⟨v, hv⟩ := small_inj hU hV hUV (n + 1) x w hw'
 878        refine ⟨v, ?_⟩
 879        show x = (SSC U V).d (n + 2) (n + 1) v
 880        rw [SSC_d]
 881        exact hv
 882
 883/-- The small-chains homology isomorphism `H_n(C^{U,V}) ≅ H_n(X)`. -/
 884noncomputable def smallChainsHomologyIso (hU : IsOpen U) (hV : IsOpen V)
 885    (hUV : U ∪ V = Set.univ) (n : ℕ) :
 886    (SSC U V).homology n ≅ (SC X).homology n :=
 887  have := smallι_isIso_homologyMap hU hV hUV n
 888  asIso (HomologicalComplex.homologyMap (smallι U V) n)
 889
 890end SmallChainsTheorem
 891
 892/-! ## Stage 3 toolkit A: coordinates on free coproducts of copies of `ℤ` -/
 893
 894section Coordinates
 895
 896variable {κ κ' : Type}
 897
 898/-- The coordinate of an element of `∐_κ ℤ` at an index, through the
 899direct-sum presentation. -/
 900noncomputable def coordAt (i : κ) (z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) : ℤ :=
 901  (ModuleCat.coprodIsoDirectSum (fun _ : κ => ModuleCat.of ℤ ℤ)).hom z i
 902
 903lemma coordAt_unitOf (i j : κ) :
 904    coordAt j (unitOf i) = if i = j then 1 else 0 := by
 905  unfold coordAt unitOf
 906  rw [← ModuleCat.comp_apply, ModuleCat.ι_coprodIsoDirectSum_hom]
 907  show (DirectSum.lof ℤ κ (fun _ => ℤ) i (1 : ℤ)) j = _
 908  by_cases h : i = j
 909  · subst h
 910    rw [if_pos rfl, DirectSum.lof_eq_of, DirectSum.of_eq_same]
 911  · rw [if_neg h, DirectSum.lof_eq_of, DirectSum.of_eq_of_ne _ _ _ (Ne.symm h)]
 912
 913lemma coordAt_zero (i : κ) :
 914    coordAt i (0 : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) = 0 := by
 915  unfold coordAt
 916  rw [map_zero]
 917  exact DFinsupp.zero_apply i
 918
 919lemma coordAt_add (j : κ) (x y : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) :
 920    coordAt j (x + y) = coordAt j x + coordAt j y := by
 921  unfold coordAt
 922  rw [map_add]
 923  exact DFinsupp.add_apply _ _ _
 924
 925lemma coordAt_smul (j : κ) (c : ℤ) (x : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) :
 926    coordAt j (c • x) = c • coordAt j x := by
 927  unfold coordAt
 928  rw [mapSmul]
 929  exact DFinsupp.smul_apply _ _ _
 930
 931/-- The support of an element of `∐_κ ℤ`. -/
 932noncomputable def suppOf (z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) : Finset κ :=
 933  ((ModuleCat.coprodIsoDirectSum (fun _ : κ => ModuleCat.of ℤ ℤ)).hom z).support
 934
 935lemma mem_suppOf_iff {i : κ} {z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)} :
 936    i ∈ suppOf z ↔ coordAt i z ≠ 0 := by
 937  unfold suppOf coordAt
 938  exact DFinsupp.mem_support_iff
 939
 940/-- Every element of `∐_κ ℤ` is the (finite) sum of its coordinates times
 941the generating elements. -/
 942lemma sum_coordAt_smul_unitOf (z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) :
 943    z = ∑ i ∈ suppOf z, coordAt i z • unitOf i := by
 944  unfold suppOf coordAt
 945  set e := ModuleCat.coprodIsoDirectSum (fun _ : κ => ModuleCat.of ℤ ℤ) with he
 946  have h1 : e.inv (e.hom z) = z := by
 947    rw [← ModuleCat.comp_apply, e.hom_inv_id, ModuleCat.id_apply]
 948  have h2 : e.hom z =
 949      ∑ i ∈ (e.hom z).support, DirectSum.lof ℤ κ (fun _ => ℤ) i ((e.hom z) i) := by
 950    conv_lhs => rw [← DirectSum.sum_support_of (e.hom z)]
 951    refine Finset.sum_congr rfl fun i _ => ?_
 952    rw [DirectSum.lof_eq_of]
 953  have h3 : z = ∑ i ∈ (e.hom z).support, ((e.hom z) i) • unitOf i := by
 954    conv_lhs => rw [← h1]
 955    conv_lhs => rw [h2]
 956    rw [map_sum]
 957    refine Finset.sum_congr rfl fun i _ => ?_
 958    have h4 : DirectSum.lof ℤ κ (fun _ => ℤ) i ((e.hom z) i) =
 959        ((e.hom z) i) • DirectSum.lof ℤ κ (fun _ => ℤ) i (1 : ℤ) := by
 960      rw [← map_smul, smul_eq_mul, mul_one]
 961    rw [h4, mapSmul]
 962    congr 1
 963    rw [he]
 964    exact ModuleCat.lof_coprodIsoDirectSum_inv_apply
 965      (fun _ : κ => ModuleCat.of ℤ ℤ) i (1 : ℤ)
 966  exact h3
 967
 968/-- Coordinate tracking through a basis-index map: at an index in the image
 969of an injective index map, the coordinate of the image chain is the source
 970coordinate. -/
 971lemma coordAt_map_eq {ψ : κ → κ'} (hψ : Function.Injective ψ)
 972    {F : (∐ fun _ : κ => ModuleCat.of ℤ ℤ) ⟶ (∐ fun _ : κ' => ModuleCat.of ℤ ℤ)}
 973    (hF : ∀ i, F (unitOf i) = unitOf (ψ i)) (i : κ)
 974    (z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) :
 975    coordAt (ψ i) (F z) = coordAt i z := by
 976  induction z using freeInduction with
 977  | unit i' =>
 978      rw [hF, coordAt_unitOf, coordAt_unitOf]
 979      exact if_congr hψ.eq_iff rfl rfl
 980  | zero => rw [map_zero, coordAt_zero, coordAt_zero]
 981  | add x y hx hy => rw [map_add, coordAt_add, coordAt_add, hx, hy]
 982  | smulz c x hx => rw [mapSmul, coordAt_smul, coordAt_smul, hx]
 983
 984/-- Coordinate tracking through a basis-index map: at an index outside the
 985image of the index map, the coordinate of any image chain vanishes. -/
 986lemma coordAt_map_notMem {ψ : κ → κ'}
 987    {F : (∐ fun _ : κ => ModuleCat.of ℤ ℤ) ⟶ (∐ fun _ : κ' => ModuleCat.of ℤ ℤ)}
 988    (hF : ∀ i, F (unitOf i) = unitOf (ψ i)) {t : κ'} (ht : ∀ i, ψ i ≠ t)
 989    (z : ↥(∐ fun _ : κ => ModuleCat.of ℤ ℤ)) :
 990    coordAt t (F z) = 0 := by
 991  induction z using freeInduction with
 992  | unit i' =>
 993      rw [hF, coordAt_unitOf]
 994      exact if_neg (ht i')
 995  | zero => rw [map_zero, coordAt_zero]
 996  | add x y hx hy => rw [map_add, coordAt_add, hx, hy, add_zero]
 997  | smulz c x hx => rw [mapSmul, coordAt_smul, hx, smul_zero]
 998
 999end Coordinates
1000
1001/-! ## Stage 3 toolkit B: elements of binary biproducts of `ℤ`-modules -/
1002
1003section BiprodElements
1004
1005variable {A B : ModuleCat.{0} ℤ}
1006
1007lemma addApp {M N : ModuleCat.{0} ℤ} (f g : M ⟶ N) (x : M) :
1008    (f + g) x = f x + g x := by
1009  show (f + g).hom x = f.hom x + g.hom x
1010  rw [ModuleCat.hom_add]
1011  rfl
1012
1013lemma negApp {M N : ModuleCat.{0} ℤ} (f : M ⟶ N) (x : M) :
1014    (-f) x = -(f x) := by
1015  show (-f).hom x = -(f.hom x)
1016  rw [ModuleCat.hom_neg]
1017  rfl
1018
1019/-- Elementwise decomposition of an element of a binary biproduct into its
1020two components. -/
1021lemma biprod_decomp (z : ↥(A ⊞ B)) :
1022    z = (biprod.inl : A ⟶ A ⊞ B) ((biprod.fst : A ⊞ B ⟶ A) z) +
1023        (biprod.inr : B ⟶ A ⊞ B) ((biprod.snd : A ⊞ B ⟶ B) z) := by
1024  have h := congrArg
1025    (fun f : A ⊞ B ⟶ A ⊞ B => f z) (biprod.total (X := A) (Y := B))
1026  have h1 : (biprod.fst ≫ biprod.inl + biprod.snd ≫ biprod.inr :
1027      A ⊞ B ⟶ A ⊞ B) z =
1028      (biprod.inl : A ⟶ A ⊞ B) ((biprod.fst : A ⊞ B ⟶ A) z) +
1029        (biprod.inr : B ⟶ A ⊞ B) ((biprod.snd : A ⊞ B ⟶ B) z) := by
1030    rw [addApp, ModuleCat.comp_apply, ModuleCat.comp_apply]
1031  have h2 : (𝟙 (A ⊞ B) : A ⊞ B ⟶ A ⊞ B) z = z := ModuleCat.id_apply _ _
1032  simp only [h1, h2] at h
1033  exact h.symm
1034
1035/-- Elementwise extensionality in a binary biproduct. -/
1036lemma biprod_elem_ext {z w : ↥(A ⊞ B)}
1037    (h1 : (biprod.fst : A ⊞ B ⟶ A) z = (biprod.fst : A ⊞ B ⟶ A) w)
1038    (h2 : (biprod.snd : A ⊞ B ⟶ B) z = (biprod.snd : A ⊞ B ⟶ B) w) :
1039    z = w := by
1040  rw [biprod_decomp z, biprod_decomp w, h1, h2]
1041
1042/-- Elementwise formula for `biprod.desc`. -/
1043lemma descApp {M : ModuleCat.{0} ℤ} (u : A ⟶ M) (v : B ⟶ M) (z : ↥(A ⊞ B)) :
1044    biprod.desc u v z =
1045      u ((biprod.fst : A ⊞ B ⟶ A) z) + v ((biprod.snd : A ⊞ B ⟶ B) z) := by
1046  have h1 : biprod.desc u v
1047      ((biprod.inl : A ⟶ A ⊞ B) ((biprod.fst : A ⊞ B ⟶ A) z)) =
1048      u ((biprod.fst : A ⊞ B ⟶ A) z) := by
1049    rw [← ModuleCat.comp_apply, biprod.inl_desc]
1050  have h2 : biprod.desc u v
1051      ((biprod.inr : B ⟶ A ⊞ B) ((biprod.snd : A ⊞ B ⟶ B) z)) =
1052      v ((biprod.snd : A ⊞ B ⟶ B) z) := by
1053    rw [← ModuleCat.comp_apply, biprod.inr_desc]
1054  conv_lhs => rw [biprod_decomp z]
1055  rw [map_add, h1, h2]
1056
1057/-- Elementwise first component of `biprod.lift`. -/
1058lemma fst_liftApp {M : ModuleCat.{0} ℤ} (f : M ⟶ A) (g : M ⟶ B) (x : M) :
1059    (biprod.fst : A ⊞ B ⟶ A) (biprod.lift f g x) = f x := by
1060  rw [← ModuleCat.comp_apply, biprod.lift_fst]
1061
1062/-- Elementwise second component of `biprod.lift`. -/
1063lemma snd_liftApp {M : ModuleCat.{0} ℤ} (f : M ⟶ A) (g : M ⟶ B) (x : M) :
1064    (biprod.snd : A ⊞ B ⟶ B) (biprod.lift f g x) = g x := by
1065  rw [← ModuleCat.comp_apply, biprod.lift_snd]
1066
1067end BiprodElements
1068
1069/-! ## Stage 3 toolkit C: subspaces and simplex lifting -/
1070
1071section Subspaces
1072
1073/-- The `X`-simplex underlying a singular simplex of the subspace `W`. -/
1074noncomputable def pushIdx (W : Set X) {n : ℕ} (a : Idx (TopCat.of W) n) :
1075    Idx X n :=
1076  (TopCat.toSSet.map (SingularPair.subInc X W)).app (op ⦋n⦌) a
1077
1078lemma pushIdx_injective (W : Set X) (n : ℕ) :
1079    Function.Injective (pushIdx (X := X) W (n := n)) :=
1080  SingularPair.toSSet_map_app_injective (SingularPair.subInc X W)
1081    (SingularPair.subInc_injective X W) n
1082
1083lemma range_pushIdx (W : Set X) {n : ℕ} (a : Idx (TopCat.of W) n) :
1084    Set.range ⇑(simplexEquiv X n (pushIdx W a)) ⊆ W := by
1085  unfold pushIdx
1086  rw [simplexEquiv_map, ContinuousMap.coe_comp]
1087  rintro x ⟨t, rfl⟩
1088  exact ((simplexEquiv (TopCat.of W) n a) t).2
1089
1090/-- Lift a singular simplex of `X` whose range lies in `W` to a singular
1091simplex of the subspace `W`. -/
1092noncomputable def liftIdx (W : Set X) {n : ℕ} (s : Idx X n)
1093    (h : Set.range ⇑(simplexEquiv X n s) ⊆ W) : Idx (TopCat.of W) n :=
1094  (simplexEquiv (TopCat.of W) n).symm
1095    ⟨fun t => ⟨simplexEquiv X n s t, h ⟨t, rfl⟩⟩,
1096      (map_continuous (simplexEquiv X n s)).subtype_mk _⟩
1097
1098lemma pushIdx_liftIdx (W : Set X) {n : ℕ} (s : Idx X n)
1099    (h : Set.range ⇑(simplexEquiv X n s) ⊆ W) :
1100    pushIdx W (liftIdx W s h) = s := by
1101  apply (simplexEquiv X n).injective
1102  unfold pushIdx liftIdx
1103  rw [simplexEquiv_map, Equiv.apply_symm_apply]
1104  ext t
1105  rfl
1106
1107/-- The inclusion between nested subspaces of `X`, as a `TopCat`
1108morphism. -/
1109noncomputable def subIncl {W W' : Set X} (h : W ⊆ W') :
1110    TopCat.of W ⟶ TopCat.of W' :=
1111  TopCat.ofHom ⟨Set.inclusion h, continuous_inclusion h⟩
1112
1113lemma subIncl_comp_subInc {W W' : Set X} (h : W ⊆ W') :
1114    subIncl h ≫ SingularPair.subInc X W' = SingularPair.subInc X W := by
1115  ext x
1116  rfl
1117
1118lemma pushIdx_subIncl {W W' : Set X} (h : W ⊆ W') {n : ℕ}
1119    (a : Idx (TopCat.of W) n) :
1120    pushIdx W' ((TopCat.toSSet.map (subIncl h)).app (op ⦋n⦌) a) = pushIdx W a := by
1121  have h1 : (TopCat.toSSet.map (subIncl h ≫ SingularPair.subInc X W')).app
1122      (op ⦋n⦌) a =
1123      (TopCat.toSSet.map (SingularPair.subInc X W')).app (op ⦋n⦌)
1124        ((TopCat.toSSet.map (subIncl h)).app (op ⦋n⦌) a) := by
1125    rw [Functor.map_comp]
1126    rfl
1127  rw [pushIdx, ← h1, subIncl_comp_subInc, pushIdx]
1128
1129/-- Elementwise action of a chain map on generating elements. -/
1130lemma chainMap_unitOf {A B : TopCat.{0}} (f : A ⟶ B) {n : ℕ} (s : Idx A n) :
1131    chainMap f n (unitOf s) =
1132      unitOf ((TopCat.toSSet.map f).app (op ⦋n⦌) s) := by
1133  rw [comp_unitOf]
1134  have h : Sigma.ι (fun _ : Idx A n => ModuleCat.of ℤ ℤ) s ≫ chainMap f n =
1135      gen B n ((TopCat.toSSet.map f).app (op ⦋n⦌) s) := gen_map f n s
1136  rw [h, ev1_apply]
1137  rfl
1138
1139/-- Elementwise injectivity of the chain map of an injective continuous
1140map. -/
1141lemma chainMap_injective {A : TopCat.{0}} (f : A ⟶ X)
1142    (hf : Function.Injective f.hom) (n : ℕ) :
1143    Function.Injective (chainMap f n) := by
1144  intro a b hab
1145  have h := congrArg (SingularPair.genRetract f n) hab
1146  rw [← ModuleCat.comp_apply, ← ModuleCat.comp_apply,
1147    SingularPair.chainMap_comp_genRetract f hf n,
1148    ModuleCat.id_apply, ModuleCat.id_apply] at h
1149  exact h
1150
1151end Subspaces
1152
1153/-! ## Stage 3 toolkit D: the factor maps into the small subcomplex -/
1154
1155section MVMaps
1156
1157lemma small_pushIdx_left {n : ℕ} (a : Idx (TopCat.of U) n) :
1158    Small U V (pushIdx U a) := Or.inl (range_pushIdx U a)
1159
1160lemma small_pushIdx_right {n : ℕ} (a : Idx (TopCat.of V) n) :
1161    Small U V (pushIdx V a) := Or.inr (range_pushIdx V a)
1162
1163/-- The index map from `U`-simplices to small simplices. -/
1164noncomputable def uIdx {n : ℕ} (a : Idx (TopCat.of U) n) : SIdx U V n :=
1165  ⟨pushIdx U a, small_pushIdx_left U V a⟩
1166
1167/-- The index map from `V`-simplices to small simplices. -/
1168noncomputable def vIdx {n : ℕ} (a : Idx (TopCat.of V) n) : SIdx U V n :=
1169  ⟨pushIdx V a, small_pushIdx_right U V a⟩
1170
1171lemma uIdx_injective (n : ℕ) : Function.Injective (uIdx U V (n := n)) :=
1172  fun _ _ hab => pushIdx_injective U n (congrArg Subtype.val hab)
1173
1174lemma vIdx_injective (n : ℕ) : Function.Injective (vIdx U V (n := n)) :=
1175  fun _ _ hab => pushIdx_injective V n (congrArg Subtype.val hab)
1176
1177/-- The degree-`n` chain map `C_n(U) ⟶ C_n^{U,V}`. -/
1178noncomputable def uInc (n : ℕ) : Cgrp (TopCat.of U) n ⟶ sCgrp U V n :=
1179  Sigma.desc fun a => sgen U V n (uIdx U V a)
1180
1181/-- The degree-`n` chain map `C_n(V) ⟶ C_n^{U,V}`. -/
1182noncomputable def vInc (n : ℕ) : Cgrp (TopCat.of V) n ⟶ sCgrp U V n :=
1183  Sigma.desc fun a => sgen U V n (vIdx U V a)
1184
1185lemma gen_uInc {n : ℕ} (a : Idx (TopCat.of U) n) :
1186    gen (TopCat.of U) n a ≫ uInc U V n = sgen U V n (uIdx U V a) :=
1187  Sigma.ι_desc _ _
1188
1189lemma gen_vInc {n : ℕ} (a : Idx (TopCat.of V) n) :
1190    gen (TopCat.of V) n a ≫ vInc U V n = sgen U V n (vIdx U V a) :=
1191  Sigma.ι_desc _ _
1192
1193lemma uInc_unitOf {n : ℕ} (a : Idx (TopCat.of U) n) :
1194    uInc U V n (unitOf a) = unitOf (uIdx U V a) := by
1195  rw [comp_unitOf]
1196  have h : Sigma.ι (fun _ : Idx (TopCat.of U) n => ModuleCat.of ℤ ℤ) a ≫
1197      uInc U V n = sgen U V n (uIdx U V a) := gen_uInc U V a
1198  rw [h, ev1_apply]
1199  rfl
1200
1201lemma vInc_unitOf {n : ℕ} (a : Idx (TopCat.of V) n) :
1202    vInc U V n (unitOf a) = unitOf (vIdx U V a) := by
1203  rw [comp_unitOf]
1204  have h : Sigma.ι (fun _ : Idx (TopCat.of V) n => ModuleCat.of ℤ ℤ) a ≫
1205      vInc U V n = sgen U V n (vIdx U V a) := gen_vInc U V a
1206  rw [h, ev1_apply]
1207  rfl
1208
1209lemma uInc_comp_sInc (n : ℕ) :
1210    uInc U V n ≫ sInc U V n = chainMap (SingularPair.subInc X U) n := by
1211  apply Sigma.hom_ext
1212  intro a
1213  rw [← assoc]
1214  rw [show Sigma.ι (fun _ : Idx (TopCat.of U) n => ModuleCat.of ℤ ℤ) a ≫
1215    uInc U V n = sgen U V n (uIdx U V a) from gen_uInc U V a]
1216  rw [sgen_sInc, gen_map]
1217  rfl
1218
1219lemma vInc_comp_sInc (n : ℕ) :
1220    vInc U V n ≫ sInc U V n = chainMap (SingularPair.subInc X V) n := by
1221  apply Sigma.hom_ext
1222  intro a
1223  rw [← assoc]
1224  rw [show Sigma.ι (fun _ : Idx (TopCat.of V) n => ModuleCat.of ℤ ℤ) a ≫
1225    vInc U V n = sgen U V n (vIdx U V a) from gen_vInc U V a]
1226  rw [sgen_sInc, gen_map]
1227  rfl
1228
1229
1230lemma uInc_injective (n : ℕ) : Function.Injective (uInc U V n) := by
1231  intro a b hab
1232  have h := congrArg (sInc U V n) hab
1233  rw [← ModuleCat.comp_apply, ← ModuleCat.comp_apply, uInc_comp_sInc] at h
1234  exact chainMap_injective (SingularPair.subInc X U)
1235    (SingularPair.subInc_injective X U) n h
1236
1237lemma vInc_injective (n : ℕ) : Function.Injective (vInc U V n) := by
1238  intro a b hab
1239  have h := congrArg (sInc U V n) hab
1240  rw [← ModuleCat.comp_apply, ← ModuleCat.comp_apply, vInc_comp_sInc] at h
1241  exact chainMap_injective (SingularPair.subInc X V)
1242    (SingularPair.subInc_injective X V) n h
1243
1244lemma uInc_comm (n : ℕ) :
1245    uInc U V (n + 1) ≫ sBnd U V n = bnd (TopCat.of U) n ≫ uInc U V n := by
1246  have := sInc_mono U V n
1247  rw [← cancel_mono (sInc U V n), assoc, assoc, sBnd_comp_sInc, uInc_comp_sInc,
1248    ← assoc, uInc_comp_sInc]
1249  exact HomologicalComplex.Hom.comm (sChainMap (SingularPair.subInc X U)) (n + 1) n
1250
1251lemma vInc_comm (n : ℕ) :
1252    vInc U V (n + 1) ≫ sBnd U V n = bnd (TopCat.of V) n ≫ vInc U V n := by
1253  have := sInc_mono U V n
1254  rw [← cancel_mono (sInc U V n), assoc, assoc, sBnd_comp_sInc, vInc_comp_sInc,
1255    ← assoc, vInc_comp_sInc]
1256  exact HomologicalComplex.Hom.comm (sChainMap (SingularPair.subInc X V)) (n + 1) n
1257
1258/-- The chain map `C_*(U) ⟶ C^{U,V}_*(X)`: a simplex of `U` is small. -/
1259noncomputable def smallU : SC (TopCat.of U) ⟶ SSC U V where
1260  f n := uInc U V n
1261  comm' := by
1262    rintro i j (rfl : j + 1 = i)
1263    rw [SSC_d]
1264    exact uInc_comm U V j
1265
1266/-- The chain map `C_*(V) ⟶ C^{U,V}_*(X)`: a simplex of `V` is small. -/
1267noncomputable def smallV : SC (TopCat.of V) ⟶ SSC U V where
1268  f n := vInc U V n
1269  comm' := by
1270    rintro i j (rfl : j + 1 = i)
1271    rw [SSC_d]
1272    exact vInc_comm U V j
1273
1274@[simp] lemma smallU_f (n : ℕ) : (smallU U V).f n = uInc U V n := rfl
1275@[simp] lemma smallV_f (n : ℕ) : (smallV U V).f n = vInc U V n := rfl
1276
1277lemma smallU_comp_smallι :
1278    smallU U V ≫ smallι U V = sChainMap (SingularPair.subInc X U) := by
1279  apply HomologicalComplex.hom_ext
1280  intro n
1281  exact uInc_comp_sInc U V n
1282
1283lemma smallV_comp_smallι :
1284    smallV U V ≫ smallι U V = sChainMap (SingularPair.subInc X V) := by
1285  apply HomologicalComplex.hom_ext
1286  intro n
1287  exact vInc_comp_sInc U V n
1288
1289/-- The space-level inclusion `U ∩ V ↪ U`. -/
1290noncomputable def mvInclU : TopCat.of (U ∩ V : Set X) ⟶ TopCat.of U :=
1291  subIncl Set.inter_subset_left
1292
1293/-- The space-level inclusion `U ∩ V ↪ V`. -/
1294noncomputable def mvInclV : TopCat.of (U ∩ V : Set X) ⟶ TopCat.of V :=
1295  subIncl Set.inter_subset_right
1296
1297lemma pushIdx_mvInclU {n : ℕ} (a : Idx (TopCat.of (U ∩ V : Set X)) n) :
1298    pushIdx U ((TopCat.toSSet.map (mvInclU U V)).app (op ⦋n⦌) a) =
1299      pushIdx (U ∩ V : Set X) a :=
1300  pushIdx_subIncl Set.inter_subset_left a
1301
1302lemma pushIdx_mvInclV {n : ℕ} (a : Idx (TopCat.of (U ∩ V : Set X)) n) :
1303    pushIdx V ((TopCat.toSSet.map (mvInclV U V)).app (op ⦋n⦌) a) =
1304      pushIdx (U ∩ V : Set X) a :=
1305  pushIdx_subIncl Set.inter_subset_right a
1306
1307/-- Both routes `C_n(U ∩ V) ⟶ C_n^{U,V}` agree: through `U` and through
1308`V` a simplex of the intersection lands on the same small generator. -/
1309lemma inclU_uInc_eq_inclV_vInc (n : ℕ) :
1310    chainMap (mvInclU U V) n ≫ uInc U V n =
1311      chainMap (mvInclV U V) n ≫ vInc U V n := by
1312  apply Sigma.hom_ext
1313  intro a
1314  rw [← assoc]
1315  rw [show Sigma.ι (fun _ : Idx (TopCat.of (U ∩ V : Set X)) n =>
1316      ModuleCat.of ℤ ℤ) a ≫ chainMap (mvInclU U V) n =
1317      gen (TopCat.of U) n ((TopCat.toSSet.map (mvInclU U V)).app (op ⦋n⦌) a)
1318    from gen_map (mvInclU U V) n a]
1319  rw [gen_uInc, ← assoc]
1320  rw [show Sigma.ι (fun _ : Idx (TopCat.of (U ∩ V : Set X)) n =>
1321      ModuleCat.of ℤ ℤ) a ≫ chainMap (mvInclV U V) n =
1322      gen (TopCat.of V) n ((TopCat.toSSet.map (mvInclV U V)).app (op ⦋n⦌) a)
1323    from gen_map (mvInclV U V) n a]
1324  rw [gen_vInc]
1325  congr 1
1326
1327lemma sChainMap_inclU_smallU_eq :
1328    sChainMap (mvInclU U V) ≫ smallU U V =
1329      sChainMap (mvInclV U V) ≫ smallV U V := by
1330  apply HomologicalComplex.hom_ext
1331  intro n
1332  exact inclU_uInc_eq_inclV_vInc U V n
1333
1334end MVMaps
1335
1336/-! ## Stage 3: the Mayer-Vietoris short exact sequence -/
1337
1338section MVSES
1339
1340/-- The left map `x ↦ (i_* x, −j_* x)` of the Mayer-Vietoris sequence. -/
1341noncomputable def mvα :
1342    SC (TopCat.of (U ∩ V : Set X)) ⟶ SC (TopCat.of U) ⊞ SC (TopCat.of V) :=
1343  biprod.lift (sChainMap (mvInclU U V)) (-(sChainMap (mvInclV U V)))
1344
1345/-- The right map `(a, b) ↦ k_* a + l_* b` into the small subcomplex. -/
1346noncomputable def mvβ :
1347    SC (TopCat.of U) ⊞ SC (TopCat.of V) ⟶ SSC U V :=
1348  biprod.desc (smallU U V) (smallV U V)
1349
1350lemma mvα_comp_mvβ : mvα U V ≫ mvβ U V = 0 := by
1351  rw [mvα, mvβ, biprod.lift_desc, sChainMap_inclU_smallU_eq,
1352    Preadditive.neg_comp]
1353  exact add_neg_cancel _
1354
1355/-- **Stage 3.** The Mayer-Vietoris short complex of chain complexes
1356`0 ⟶ C_*(U ∩ V) ⟶ C_*(U) ⊞ C_*(V) ⟶ C^{U,V}_*(X) ⟶ 0`. -/
1357noncomputable def mvSES : ShortComplex (ChainComplex (ModuleCat.{0} ℤ) ℕ) :=
1358  ShortComplex.mk (mvα U V) (mvβ U V) (mvα_comp_mvβ U V)
1359
1360lemma mvαβ_degreewise_zero (n : ℕ) :
1361    biprod.lift (chainMap (mvInclU U V) n) (-(chainMap (mvInclV U V) n)) ≫
1362      biprod.desc (uInc U V n) (vInc U V n) = 0 := by
1363  rw [biprod.lift_desc, inclU_uInc_eq_inclV_vInc, Preadditive.neg_comp]
1364  exact add_neg_cancel _
1365
1366/-- The degree-`n` concrete Mayer-Vietoris short complex of `ℤ`-modules. -/
1367noncomputable def mvSESdeg (n : ℕ) : ShortComplex (ModuleCat.{0} ℤ) :=
1368  ShortComplex.mk
1369    (biprod.lift (chainMap (mvInclU U V) n) (-(chainMap (mvInclV U V) n)))
1370    (biprod.desc (uInc U V n) (vInc U V n))
1371    (mvαβ_degreewise_zero U V n)
1372
1373lemma mvSESdeg_mono (n : ℕ) : Mono (mvSESdeg U V n).f := by
1374  show Mono (biprod.lift (chainMap (mvInclU U V) n) (-(chainMap (mvInclV U V) n)))
1375  haveI h1 : Mono (chainMap (mvInclU U V) n) :=
1376    SingularPair.chainMap_mono _
1377      (fun a b hab => Set.inclusion_injective Set.inter_subset_left hab) n
1378  exact mono_of_mono_fac (biprod.lift_fst _ _)
1379
1380lemma mvSESdeg_epi (n : ℕ) : Epi (mvSESdeg U V n).g := by
1381  show Epi (biprod.desc (uInc U V n) (vInc U V n))
1382  rw [ModuleCat.epi_iff_surjective]
1383  intro y
1384  induction y using freeInduction with
1385  | unit t =>
1386      rcases t.2 with h | h
1387      · refine ⟨(biprod.inl : Cgrp (TopCat.of U) n ⟶ _)
1388          (unitOf (liftIdx U t.1 h)), ?_⟩
1389        rw [← ModuleCat.comp_apply, biprod.inl_desc, uInc_unitOf]
1390        congr 1
1391      · refine ⟨(biprod.inr : Cgrp (TopCat.of V) n ⟶ _)
1392          (unitOf (liftIdx V t.1 h)), ?_⟩
1393        rw [← ModuleCat.comp_apply, biprod.inr_desc, vInc_unitOf]
1394        congr 1
1395  | zero => exact ⟨0, map_zero _⟩
1396  | add x y hx hy =>
1397      obtain ⟨a, ha⟩ := hx
1398      obtain ⟨b, hb⟩ := hy
1399      exact ⟨a + b, by rw [map_add, ha, hb]⟩
1400  | smulz c x hx =>
1401      obtain ⟨a, ha⟩ := hx
1402      exact ⟨c • a, by rw [mapSmul, ha]⟩
1403
1404/-- The heart of the Mayer-Vietoris exactness: a pair of chains on `U` and
1405`V` whose images in the small complex cancel comes from a chain on
1406`U ∩ V`. -/
1407lemma mv_middle_exact (n : ℕ) {a : ↥(Cgrp (TopCat.of U) n)}
1408    {b : ↥(Cgrp (TopCat.of V) n)}
1409    (hab : uInc U V n a + vInc U V n b = 0) :
1410    ∃ x : ↥(Cgrp (TopCat.of (U ∩ V : Set X)) n),
1411      chainMap (mvInclU U V) n x = a ∧ chainMap (mvInclV U V) n x = -b := by
1412  classical
1413  have hsupp : ∀ i ∈ suppOf a,
1414      Set.range ⇑(simplexEquiv X n (pushIdx U i)) ⊆ U ∩ V := by
1415    intro i hi
1416    by_cases hmem : ∃ j : Idx (TopCat.of V) n, vIdx U V j = uIdx U V i
1417    · obtain ⟨j, hj⟩ := hmem
1418      have hUV : pushIdx V j = pushIdx U i := congrArg Subtype.val hj
1419      intro x hx
1420      refine ⟨range_pushIdx U i hx, ?_⟩
1421      rw [← hUV] at hx
1422      exact range_pushIdx V j hx
1423    · exfalso
1424      have hne : coordAt i a ≠ 0 := mem_suppOf_iff.mp hi
1425      have h1 : coordAt (uIdx U V i) (uInc U V n a) = coordAt i a :=
1426        coordAt_map_eq (uIdx_injective U V n) (uInc_unitOf U V) i a
1427      have h2 : coordAt (uIdx U V i) (vInc U V n b) = 0 :=
1428        coordAt_map_notMem (vInc_unitOf U V) (fun j hj => hmem ⟨j, hj⟩) b
1429      have h3 : coordAt (uIdx U V i) (uInc U V n a) +
1430          coordAt (uIdx U V i) (vInc U V n b) = 0 := by
1431        rw [← coordAt_add, hab, coordAt_zero]
1432      rw [h1, h2, add_zero] at h3
1433      exact hne h3
1434  set x : ↥(Cgrp (TopCat.of (U ∩ V : Set X)) n) :=
1435    ∑ i ∈ (suppOf a).attach,
1436      coordAt i.1 a • unitOf (liftIdx (U ∩ V : Set X) (pushIdx U i.1)
1437        (hsupp i.1 i.2)) with hxdef
1438  have hterm : ∀ i ∈ (suppOf a).attach,
1439      chainMap (mvInclU U V) n (coordAt i.1 a •
1440        unitOf (liftIdx (U ∩ V : Set X) (pushIdx U i.1) (hsupp i.1 i.2))) =
1441        coordAt i.1 a • unitOf i.1 := by
1442    intro i _
1443    have hidx : (TopCat.toSSet.map (mvInclU U V)).app (op ⦋n⦌)
1444        (liftIdx (U ∩ V : Set X) (pushIdx U i.1) (hsupp i.1 i.2)) = i.1 := by
1445      apply pushIdx_injective U n
1446      rw [pushIdx_mvInclU, pushIdx_liftIdx]
1447    rw [mapSmul, chainMap_unitOf, hidx]
1448  have hxU : chainMap (mvInclU U V) n x = a := by
1449    calc chainMap (mvInclU U V) n x
1450        = ∑ i ∈ (suppOf a).attach, coordAt i.1 a • unitOf i.1 := by
1451          rw [hxdef, map_sum]
1452          exact Finset.sum_congr rfl hterm
1453      _ = ∑ i ∈ suppOf a, coordAt i a • unitOf i :=
1454          Finset.sum_attach (suppOf a) (fun i => coordAt i a • unitOf i)
1455      _ = a := (sum_coordAt_smul_unitOf a).symm
1456  have hxV : vInc U V n (chainMap (mvInclV U V) n x) = uInc U V n a := by
1457    rw [← ModuleCat.comp_apply, ← inclU_uInc_eq_inclV_vInc,
1458      ModuleCat.comp_apply, hxU]
1459  refine ⟨x, hxU, ?_⟩
1460  apply vInc_injective U V n
1461  rw [map_neg, hxV]
1462  exact eq_neg_of_add_eq_zero_left hab
1463
1464lemma mvSESdeg_exact (n : ℕ) : (mvSESdeg U V n).Exact := by
1465  rw [ShortComplex.moduleCat_exact_iff]
1466  intro z hz
1467  have hz' : uInc U V n
1468      ((biprod.fst : Cgrp (TopCat.of U) n ⊞ Cgrp (TopCat.of V) n ⟶ _) z) +
1469      vInc U V n
1470      ((biprod.snd : Cgrp (TopCat.of U) n ⊞ Cgrp (TopCat.of V) n ⟶ _) z) = 0 := by
1471    rw [← descApp]
1472    exact hz
1473  obtain ⟨x, hxU, hxV⟩ := mv_middle_exact U V n hz'
1474  refine ⟨x, ?_⟩
1475  apply biprod_elem_ext
1476  · rw [show (mvSESdeg U V n).f x = biprod.lift (chainMap (mvInclU U V) n)
1477      (-(chainMap (mvInclV U V) n)) x from rfl, fst_liftApp]
1478    exact hxU
1479  · rw [show (mvSESdeg U V n).f x = biprod.lift (chainMap (mvInclU U V) n)
1480      (-(chainMap (mvInclV U V) n)) x from rfl, snd_liftApp, negApp, hxV,
1481      neg_neg]
1482
1483lemma mvSESdeg_shortExact (n : ℕ) : (mvSESdeg U V n).ShortExact where
1484  exact := mvSESdeg_exact U V n
1485  mono_f := mvSESdeg_mono U V n
1486  epi_g := mvSESdeg_epi U V n
1487
1488lemma mvα_f_compat (n : ℕ) :
1489    (mvα U V).f n ≫
1490      (HomologicalComplex.biprodXIso (SC (TopCat.of U)) (SC (TopCat.of V)) n).hom =
1491      biprod.lift (chainMap (mvInclU U V) n) (-(chainMap (mvInclV U V) n)) := by
1492  have hf : mvα U V ≫ biprod.fst = sChainMap (mvInclU U V) := biprod.lift_fst _ _
1493  have hs : mvα U V ≫ biprod.snd = -(sChainMap (mvInclV U V)) := biprod.lift_snd _ _
1494  apply biprod.hom_ext
1495  · rw [assoc, HomologicalComplex.biprodXIso_hom_fst,
1496      ← HomologicalComplex.comp_f, hf]
1497    exact (biprod.lift_fst _ _).symm
1498  · rw [assoc, HomologicalComplex.biprodXIso_hom_snd,
1499      ← HomologicalComplex.comp_f, hs, HomologicalComplex.neg_f_apply]
1500    exact (biprod.lift_snd _ _).symm
1501
1502lemma mvβ_f_compat (n : ℕ) :
1503    (HomologicalComplex.biprodXIso (SC (TopCat.of U)) (SC (TopCat.of V)) n).inv ≫
1504      (mvβ U V).f n = biprod.desc (uInc U V n) (vInc U V n) := by
1505  have hu : (biprod.inl : SC (TopCat.of U) ⟶ _) ≫ mvβ U V = smallU U V :=
1506    biprod.inl_desc _ _
1507  have hv : (biprod.inr : SC (TopCat.of V) ⟶ _) ≫ mvβ U V = smallV U V :=
1508    biprod.inr_desc _ _
1509  apply biprod.hom_ext'
1510  · rw [← assoc, HomologicalComplex.inl_biprodXIso_inv, biprod.inl_desc,
1511      ← HomologicalComplex.comp_f, hu, smallU_f]
1512  · rw [← assoc, HomologicalComplex.inr_biprodXIso_inv, biprod.inr_desc,
1513      ← HomologicalComplex.comp_f, hv, smallV_f]
1514
1515/-- Degreewise, the Mayer-Vietoris short complex is isomorphic to the
1516concrete short complex of `ℤ`-modules. -/
1517noncomputable def mvSESdegIso (n : ℕ) :
1518    mvSESdeg U V n ≅ (mvSES U V).map
1519      (HomologicalComplex.eval (ModuleCat.{0} ℤ) (ComplexShape.down ℕ) n) := by
1520  refine ShortComplex.isoMk (Iso.refl _)
1521    (HomologicalComplex.biprodXIso (SC (TopCat.of U)) (SC (TopCat.of V)) n).symm
1522    (Iso.refl _) ?_ ?_
1523  · show (Iso.refl _).hom ≫ (mvα U V).f n =
1524      biprod.lift (chainMap (mvInclU U V) n) (-(chainMap (mvInclV U V) n)) ≫
1525        (HomologicalComplex.biprodXIso (SC (TopCat.of U)) (SC (TopCat.of V)) n).inv
1526    rw [Iso.refl_hom, id_comp, ← mvα_f_compat, assoc, Iso.hom_inv_id, comp_id]
1527  · show (HomologicalComplex.biprodXIso (SC (TopCat.of U))
1528      (SC (TopCat.of V)) n).inv ≫ (mvβ U V).f n =
1529      biprod.desc (uInc U V n) (vInc U V n) ≫ (Iso.refl _).hom
1530    rw [Iso.refl_hom, comp_id, mvβ_f_compat]
1531
1532lemma mvSES_degreewise_shortExact (n : ℕ) :
1533    ((mvSES U V).map
1534      (HomologicalComplex.eval (ModuleCat.{0} ℤ) (ComplexShape.down ℕ) n)).ShortExact :=
1535  ShortComplex.shortExact_of_iso (mvSESdegIso U V n) (mvSESdeg_shortExact U V n)
1536
1537/-- **Stage 3.** The Mayer-Vietoris sequence
1538`0 ⟶ C_*(U ∩ V) ⟶ C_*(U) ⊞ C_*(V) ⟶ C^{U,V}_*(X) ⟶ 0` is a short exact
1539sequence of chain complexes (no openness or covering hypotheses needed). -/
1540theorem mvSES_shortExact : (mvSES U V).ShortExact :=
1541  HomologicalComplex.shortExact_of_degreewise_shortExact _
1542    (mvSES_degreewise_shortExact U V)
1543
1544end MVSES
1545
1546/-! ## Stage 4: the Mayer-Vietoris long exact sequence -/
1547
1548section MVLES
1549
1550attribute [local instance] Limits.preservesBinaryBiproducts_of_preservesBiproducts
1551
1552/-- The degree-`n` homology functor on chain complexes of `ℤ`-modules. -/
1553noncomputable abbrev HF (n : ℕ) :
1554    ChainComplex (ModuleCat.{0} ℤ) ℕ ⥤ ModuleCat.{0} ℤ :=
1555  HomologicalComplex.homologyFunctor (ModuleCat.{0} ℤ) (ComplexShape.down ℕ) n
1556
1557/-- Additivity of homology: `H_n(C_*(U) ⊞ C_*(V)) ≅ H_n(U) ⊞ H_n(V)`. -/
1558noncomputable def homologyBiprodIso (n : ℕ) :
1559    (SC (TopCat.of U) ⊞ SC (TopCat.of V)).homology n ≅
1560      (SC (TopCat.of U)).homology n ⊞ (SC (TopCat.of V)).homology n :=
1561  (HF n).mapBiprod (SC (TopCat.of U)) (SC (TopCat.of V))
1562
1563/-- The Mayer-Vietoris pair map
1564`H_n(U ∩ V) ⟶ H_n(U) ⊞ H_n(V)`, `[c] ↦ ([i_* c], −[j_* c])`, induced by the
1565space-level inclusions `U ∩ V ↪ U` and `U ∩ V ↪ V`. -/
1566noncomputable def mvPair (n : ℕ) :
1567    (SC (TopCat.of (U ∩ V : Set X))).homology n ⟶
1568      (SC (TopCat.of U)).homology n ⊞ (SC (TopCat.of V)).homology n :=
1569  biprod.lift (HomologicalComplex.homologyMap (sChainMap (mvInclU U V)) n)
1570    (-(HomologicalComplex.homologyMap (sChainMap (mvInclV U V)) n))
1571
1572/-- The Mayer-Vietoris sum map `H_n(U) ⊞ H_n(V) ⟶ H_n(X)`,
1573`([a], [b]) ↦ [k_* a] + [l_* b]`, induced by the space-level inclusions
1574`U ↪ X` and `V ↪ X`. -/
1575noncomputable def mvSum (n : ℕ) :
1576    (SC (TopCat.of U)).homology n ⊞ (SC (TopCat.of V)).homology n ⟶
1577      (SC X).homology n :=
1578  biprod.desc
1579    (HomologicalComplex.homologyMap (sChainMap (SingularPair.subInc X U)) n)
1580    (HomologicalComplex.homologyMap (sChainMap (SingularPair.subInc X V)) n)
1581
1582variable {U V}
1583
1584/-- **The Mayer-Vietoris connecting homomorphism**
1585`∂ : H_{n+1}(X) ⟶ H_n(U ∩ V)`, transported across the small-chains
1586isomorphism of Stage 2. -/
1587noncomputable def mvδ (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1588    (n : ℕ) :
1589    (SC X).homology (n + 1) ⟶ (SC (TopCat.of (U ∩ V : Set X))).homology n :=
1590  (smallChainsHomologyIso hU hV hUV (n + 1)).inv ≫
1591    (mvSES_shortExact U V).δ (n + 1) n (ComplexShape.down_mk _ _ rfl)
1592
1593lemma smallIso_hom (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1594    (n : ℕ) :
1595    (smallChainsHomologyIso hU hV hUV n).hom =
1596      HomologicalComplex.homologyMap (smallι U V) n := rfl
1597
1598variable (U V)
1599
1600lemma homologyMap_mvα_compat (n : ℕ) :
1601    HomologicalComplex.homologyMap (mvα U V) n ≫ (homologyBiprodIso U V n).hom =
1602      mvPair U V n := by
1603  have h := Limits.biprod.map_lift_mapBiprod (HF n)
1604    (SC (TopCat.of U)) (SC (TopCat.of V))
1605    (sChainMap (mvInclU U V)) (-(sChainMap (mvInclV U V)))
1606  rw [Functor.map_neg] at h
1607  exact h
1608
1609lemma mvPair_eq (n : ℕ) :
1610    mvPair U V n = HomologicalComplex.homologyMap (mvα U V) n ≫
1611      (homologyBiprodIso U V n).hom :=
1612  (homologyMap_mvα_compat U V n).symm
1613
1614lemma homologyMap_mvβ_compat (n : ℕ) :
1615    (homologyBiprodIso U V n).inv ≫
1616      HomologicalComplex.homologyMap (mvβ U V) n ≫
1617        HomologicalComplex.homologyMap (smallι U V) n = mvSum U V n := by
1618  have h := Limits.biprod.mapBiprod_inv_map_desc (HF n)
1619    (SC (TopCat.of U)) (SC (TopCat.of V)) (smallU U V) (smallV U V)
1620  have h2 : (homologyBiprodIso U V n).inv ≫
1621      HomologicalComplex.homologyMap (mvβ U V) n =
1622      biprod.desc ((HF n).map (smallU U V)) ((HF n).map (smallV U V)) := h
1623  rw [← assoc, h2]
1624  apply biprod.hom_ext'
1625  · rw [← assoc, biprod.inl_desc]
1626    have h3 : (biprod.inl :
1627        (SC (TopCat.of U)).homology n ⟶ _) ≫ mvSum U V n =
1628        HomologicalComplex.homologyMap
1629          (sChainMap (SingularPair.subInc X U)) n := biprod.inl_desc _ _
1630    rw [h3, ← smallU_comp_smallι]
1631    exact ((HF n).map_comp _ _).symm
1632  · rw [← assoc, biprod.inr_desc]
1633    have h3 : (biprod.inr :
1634        (SC (TopCat.of V)).homology n ⟶ _) ≫ mvSum U V n =
1635        HomologicalComplex.homologyMap
1636          (sChainMap (SingularPair.subInc X V)) n := biprod.inr_desc _ _
1637    rw [h3, ← smallV_comp_smallι]
1638    exact ((HF n).map_comp _ _).symm
1639
1640lemma mvSum_eq (n : ℕ) :
1641    mvSum U V n = (homologyBiprodIso U V n).inv ≫
1642      HomologicalComplex.homologyMap (mvβ U V) n ≫
1643        HomologicalComplex.homologyMap (smallι U V) n :=
1644  (homologyMap_mvβ_compat U V n).symm
1645
1646/-- `H_n(U ∩ V) → H_n(U) ⊞ H_n(V) → H_n(X)` composes to zero. -/
1647lemma mvPair_comp_mvSum (n : ℕ) : mvPair U V n ≫ mvSum U V n = 0 := by
1648  rw [mvPair_eq, mvSum_eq, assoc, Iso.hom_inv_id_assoc, ← assoc,
1649    ← HomologicalComplex.homologyMap_comp]
1650  have h : mvα U V ≫ mvβ U V = 0 := mvα_comp_mvβ U V
1651  rw [h, HomologicalComplex.homologyMap_zero, zero_comp]
1652
1653variable {U V}
1654
1655/-- `H_{n+1}(U) ⊞ H_{n+1}(V) → H_{n+1}(X) → H_n(U ∩ V)` composes to
1656zero. -/
1657lemma mvSum_comp_mvδ (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1658    (n : ℕ) :
1659    mvSum U V (n + 1) ≫ mvδ hU hV hUV n = 0 := by
1660  have h : HomologicalComplex.homologyMap (mvβ U V) (n + 1) ≫
1661      (mvSES_shortExact U V).δ (n + 1) n (ComplexShape.down_mk _ _ rfl) = 0 :=
1662    (mvSES_shortExact U V).comp_δ (n + 1) n (ComplexShape.down_mk _ _ rfl)
1663  rw [mvSum_eq, mvδ, ← smallIso_hom hU hV hUV (n + 1)]
1664  simp only [assoc]
1665  rw [Iso.hom_inv_id_assoc, h, comp_zero]
1666
1667/-- `H_{n+1}(X) → H_n(U ∩ V) → H_n(U) ⊞ H_n(V)` composes to zero. -/
1668lemma mvδ_comp_mvPair (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1669    (n : ℕ) :
1670    mvδ hU hV hUV n ≫ mvPair U V n = 0 := by
1671  have h : (mvSES_shortExact U V).δ (n + 1) n (ComplexShape.down_mk _ _ rfl) ≫
1672      HomologicalComplex.homologyMap (mvα U V) n = 0 :=
1673    (mvSES_shortExact U V).δ_comp (n + 1) n (ComplexShape.down_mk _ _ rfl)
1674  rw [mvδ, mvPair_eq]
1675  simp only [assoc]
1676  rw [reassoc_of% h, zero_comp, comp_zero]
1677
1678/-- **Mayer-Vietoris, exactness at `H_n(U ∩ V)`**:
1679`H_{n+1}(X) ⟶ H_n(U ∩ V) ⟶ H_n(U) ⊞ H_n(V)` is exact. -/
1680theorem mv_exact₁ (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1681    (n : ℕ) :
1682    (ShortComplex.mk (mvδ hU hV hUV n) (mvPair U V n)
1683      (mvδ_comp_mvPair hU hV hUV n)).Exact := by
1684  refine ShortComplex.exact_of_iso ?_
1685    ((mvSES_shortExact U V).homology_exact₁ (n + 1) n
1686      (ComplexShape.down_mk _ _ rfl))
1687  refine ShortComplex.isoMk (smallChainsHomologyIso hU hV hUV (n + 1))
1688    (Iso.refl _) (homologyBiprodIso U V n) ?_ ?_
1689  · show (smallChainsHomologyIso hU hV hUV (n + 1)).hom ≫ mvδ hU hV hUV n =
1690      (mvSES_shortExact U V).δ (n + 1) n (ComplexShape.down_mk _ _ rfl) ≫
1691        (Iso.refl _).hom
1692    rw [mvδ, Iso.hom_inv_id_assoc, Iso.refl_hom, comp_id]
1693  · show (Iso.refl _).hom ≫ mvPair U V n =
1694      HomologicalComplex.homologyMap (mvα U V) n ≫ (homologyBiprodIso U V n).hom
1695    rw [Iso.refl_hom, id_comp, mvPair_eq]
1696
1697/-- **Mayer-Vietoris, exactness at `H_n(U) ⊞ H_n(V)`**:
1698`H_n(U ∩ V) ⟶ H_n(U) ⊞ H_n(V) ⟶ H_n(X)` is exact (all degrees, including
1699`0`). -/
1700theorem mv_exact₂ (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1701    (n : ℕ) :
1702    (ShortComplex.mk (mvPair U V n) (mvSum U V n)
1703      (mvPair_comp_mvSum U V n)).Exact := by
1704  refine ShortComplex.exact_of_iso ?_
1705    ((mvSES_shortExact U V).homology_exact₂ n)
1706  refine ShortComplex.isoMk (Iso.refl _) (homologyBiprodIso U V n)
1707    (smallChainsHomologyIso hU hV hUV n) ?_ ?_
1708  · show (Iso.refl _).hom ≫ mvPair U V n =
1709      HomologicalComplex.homologyMap (mvα U V) n ≫ (homologyBiprodIso U V n).hom
1710    rw [Iso.refl_hom, id_comp, mvPair_eq]
1711  · show (homologyBiprodIso U V n).hom ≫ mvSum U V n =
1712      HomologicalComplex.homologyMap (mvβ U V) n ≫
1713        (smallChainsHomologyIso hU hV hUV n).hom
1714    rw [mvSum_eq, Iso.hom_inv_id_assoc, smallIso_hom]
1715
1716/-- **Mayer-Vietoris, exactness at `H_{n+1}(X)`**:
1717`H_{n+1}(U) ⊞ H_{n+1}(V) ⟶ H_{n+1}(X) ⟶ H_n(U ∩ V)` is exact. -/
1718theorem mv_exact₃ (hU : IsOpen U) (hV : IsOpen V) (hUV : U ∪ V = Set.univ)
1719    (n : ℕ) :
1720    (ShortComplex.mk (mvSum U V (n + 1)) (mvδ hU hV hUV n)
1721      (mvSum_comp_mvδ hU hV hUV n)).Exact := by
1722  refine ShortComplex.exact_of_iso ?_
1723    ((mvSES_shortExact U V).homology_exact₃ (n + 1) n
1724      (ComplexShape.down_mk _ _ rfl))
1725  refine ShortComplex.isoMk (homologyBiprodIso U V (n + 1))
1726    (smallChainsHomologyIso hU hV hUV (n + 1)) (Iso.refl _) ?_ ?_
1727  · show (homologyBiprodIso U V (n + 1)).hom ≫ mvSum U V (n + 1) =
1728      HomologicalComplex.homologyMap (mvβ U V) (n + 1) ≫
1729        (smallChainsHomologyIso hU hV hUV (n + 1)).hom
1730    rw [mvSum_eq, Iso.hom_inv_id_assoc, smallIso_hom]
1731  · show (smallChainsHomologyIso hU hV hUV (n + 1)).hom ≫ mvδ hU hV hUV n =
1732      (mvSES_shortExact U V).δ (n + 1) n (ComplexShape.down_mk _ _ rfl) ≫
1733        (Iso.refl _).hom
1734    rw [mvδ, Iso.hom_inv_id_assoc, Iso.refl_hom, comp_id]
1735
1736/-- **The degree-`0` tail**: `H_0(U) ⊞ H_0(V) ⟶ H_0(X)` is surjective; the
1737Mayer-Vietoris sequence ends `⋯ ⟶ H_0(U) ⊞ H_0(V) ⟶ H_0(X) ⟶ 0`. -/
1738theorem mvSum_epi_zero (hU : IsOpen U) (hV : IsOpen V)
1739    (hUV : U ∪ V = Set.univ) : Epi (mvSum U V 0) := by
1740  haveI h1 : Epi (HomologicalComplex.homologyMap (mvβ U V) 0) := by
1741    refine epi_homologyMap_chain_zero (mvβ U V) ?_
1742    intro y
1743    have hepi : Epi ((mvβ U V).f 0) := (mvSES_degreewise_shortExact U V 0).epi_g
1744    have hsurj : Function.Surjective ((mvβ U V).f 0) :=
1745      (ModuleCat.epi_iff_surjective _).mp hepi
1746    obtain ⟨x, hx⟩ := hsurj y
1747    refine ⟨x, 0, ?_⟩
1748    rw [map_zero, add_zero, hx]
1749  haveI h2 : IsIso (HomologicalComplex.homologyMap (smallι U V) 0) :=
1750    smallι_isIso_homologyMap hU hV hUV 0
1751  rw [mvSum_eq]
1752  infer_instance
1753
1754/-- **Sanity lock**: when `U = univ` (so `U` alone already covers `X`), the
1755Mayer-Vietoris sum map `H_n(U) ⊞ H_n(V) ⟶ H_n(X)` is an epimorphism in
1756every degree, because its first component is induced by the isomorphism
1757`univ ≃ X`. -/
1758theorem mvSum_epi_of_left_univ (V : Set X) (n : ℕ) :
1759    Epi (mvSum (Set.univ : Set X) V n) := by
1760  haveI hiso : IsIso (SingularPair.subInc X (Set.univ : Set X)) := by
1761    refine ⟨TopCat.ofHom ⟨fun x => ⟨x, trivial⟩,
1762      Continuous.subtype_mk continuous_id fun _ => trivial⟩, ?_, ?_⟩
1763    · ext x
1764      rfl
1765    · ext x
1766      rfl
1767  haveI h1 : IsIso (sChainMap (SingularPair.subInc X (Set.univ : Set X))) := by
1768    show IsIso (((AlgebraicTopology.singularChainComplexFunctor
1769      (ModuleCat.{0} ℤ)).obj (ModuleCat.of ℤ ℤ)).map
1770      (SingularPair.subInc X (Set.univ : Set X)))
1771    infer_instance
1772  haveI h2 : Epi (HomologicalComplex.homologyMap
1773      (sChainMap (SingularPair.subInc X (Set.univ : Set X))) n) := by
1774    haveI : IsIso (HomologicalComplex.homologyMap
1775        (sChainMap (SingularPair.subInc X (Set.univ : Set X))) n) := by
1776      show IsIso ((HF n).map (sChainMap (SingularPair.subInc X (Set.univ : Set X))))
1777      infer_instance
1778    infer_instance
1779  have hfac : (biprod.inl :
1780      (SC (TopCat.of (Set.univ : Set X))).homology n ⟶ _) ≫
1781      mvSum (Set.univ : Set X) V n =
1782      HomologicalComplex.homologyMap
1783        (sChainMap (SingularPair.subInc X (Set.univ : Set X))) n :=
1784    biprod.inl_desc _ _
1785  exact epi_of_epi_fac hfac
1786
1787end MVLES
1788
1789end SingularMayerVietoris
1790end Foundation
1791end IndisputableMonolith
1792

source mirrored from github.com/jonwashburn/shape-of-logic