Pith. sign in

IndisputableMonolith.Foundation.CircleWindingChain

IndisputableMonolith/Foundation/CircleWindingChain.lean · 7754 lines · 465 declarations

show as:
view math explainer →

open module explainer GitHub source

Explainer status: ready · generated 2026-08-10 16:47:38.797099+00:00

   1import IndisputableMonolith.Foundation.CircleWinding
   2import IndisputableMonolith.Foundation.CircleLifting
   3import IndisputableMonolith.Foundation.CircleFundamentalSimplex
   4import IndisputableMonolith.Foundation.CircleH1Computation
   5import Mathlib.AlgebraicTopology.SimplexCategory.Basic
   6import Mathlib.AlgebraicTopology.TopologicalSimplex
   7import Mathlib.Analysis.Convex.StdSimplex
   8import Mathlib.Topology.Homotopy.Path
   9import Mathlib.AlgebraicTopology.FundamentalGroupoid.SimplyConnected
  10import Mathlib.Algebra.Category.ModuleCat.Adjunctions
  11import Mathlib.Data.Finsupp.Order
  12import Mathlib.Data.Finsupp.SMulWithZero
  13import Mathlib.Dynamics.PeriodicPts.Defs
  14import Mathlib.Data.Fintype.Pigeonhole
  15import Mathlib.Logic.Equiv.Fin.Rotate
  16
  17/-!
  18# The winding invariant on singular 1-simplices, and the kills-boundaries identity
  19
  20This module lifts the path-level winding/displacement invariant of
  21`CircleWinding` to the level of *singular simplices* of `TopCat.sphere 1`, and
  22proves the single fact that makes it a homology invariant:
  23
  24* `simplexDisplacement` assigns a real number (the displacement, i.e. `2π ×`
  25  winding) to every singular `1`-simplex `f : C(Δ¹, S¹)`, by reparameterising the
  26  standard `1`-simplex `Δ¹` to the unit interval and taking `pathDisplacement`.
  27
  28* `simplexDisplacement_boundary`: for every singular `2`-simplex
  29  `F : C(Δ², S¹)`, the alternating face sum
  30  `disp(δ₀F) − disp(δ₁F) + disp(δ₂F)` is `0`.
  31
  32The second theorem is the chain-level "winding kills boundaries" statement.  Its
  33proof is the `2`-simplex telescoping: the boundary walk `v₀ → v₁ → v₂` along two
  34edges is homotopic rel endpoints (inside the convex, hence simply connected,
  35standard `2`-simplex) to the direct edge `v₀ → v₂`; pushing that homotopy through
  36`F` and combining `pathDisplacement_trans` (additivity) with
  37`pathDisplacement_homotopic` (homotopy invariance) gives
  38`disp(δ₁F) = disp(δ₂F) + disp(δ₀F)`, which is the vanishing of the alternating
  39sum.
  40
  41Together with `CircleWinding.pathWinding_fundamentalLoop` (the invariant sends the
  42once-around generator to `1`), this gives a winding homomorphism on `1`-cycles
  43that is a left inverse to the fundamental class: the "split-injective" half of
  44`H₁(S¹;ℤ) ≅ ℤ`.  The converse (every `1`-cycle is homologous to an integer
  45multiple of the fundamental cycle, i.e. surjectivity of the integer comparison
  46map) is the generation half and requires the simplicial prism / subdivision
  47operator, which Mathlib's singular homology does not yet provide.
  48
  49No axioms, `sorry`, or project-local `S¹` replacements are used.
  50-/
  51
  52namespace IndisputableMonolith
  53namespace Foundation
  54namespace CircleWindingChain
  55
  56open CategoryTheory Opposite
  57open CircleParam CircleWinding
  58open scoped BigOperators Real unitInterval Topology
  59
  60noncomputable section
  61
  62/-- A singular `1`-simplex of `TopCat.sphere 1`, presented as a continuous map
  63from the standard topological `1`-simplex `Δ¹ = stdSimplex ℝ (Fin 2)`. -/
  64abbrev OneSimplex : Type := C(stdSimplex ℝ (Fin 2), SphereOne)
  65
  66/-- A singular `2`-simplex of `TopCat.sphere 1`, presented as a continuous map
  67from the standard topological `2`-simplex `Δ² = stdSimplex ℝ (Fin 3)`. -/
  68abbrev TwoSimplex : Type := C(stdSimplex ℝ (Fin 3), SphereOne)
  69
  70/-- The reparameterisation of the unit interval onto the standard `1`-simplex,
  71`t ↦ (1 - t, t)`.  It is the inverse of Mathlib's
  72`stdSimplexHomeomorphUnitInterval`. -/
  73def intervalToSimplex : C(I, stdSimplex ℝ (Fin 2)) :=
  74  ⟨stdSimplexHomeomorphUnitInterval.symm, stdSimplexHomeomorphUnitInterval.symm.continuous⟩
  75
  76@[simp] theorem intervalToSimplex_apply (t : I) :
  77    intervalToSimplex t = stdSimplexHomeomorphUnitInterval.symm t := rfl
  78
  79theorem intervalToSimplex_zero :
  80    intervalToSimplex 0 = stdSimplex.vertex (0 : Fin 2) := by
  81  have h0 : stdSimplexHomeomorphUnitInterval (stdSimplex.vertex (0 : Fin 2)) = 0 :=
  82    stdSimplexHomeomorphUnitInterval_zero
  83  simp only [intervalToSimplex_apply]
  84  rw [← h0, Homeomorph.symm_apply_apply]
  85
  86theorem intervalToSimplex_one :
  87    intervalToSimplex 1 = stdSimplex.vertex (1 : Fin 2) := by
  88  have h1 : stdSimplexHomeomorphUnitInterval (stdSimplex.vertex (1 : Fin 2)) = 1 :=
  89    stdSimplexHomeomorphUnitInterval_one
  90  simp only [intervalToSimplex_apply]
  91  rw [← h1, Homeomorph.symm_apply_apply]
  92
  93/-- A singular `1`-simplex, read as a path in the unit-interval parameterisation. -/
  94def oneSimplexPath (f : OneSimplex) : C(I, SphereOne) := f.comp intervalToSimplex
  95
  96/-- A unit-interval path, read as a concrete singular `1`-simplex via the standard
  97homeomorphism `Δ¹ ≃ I`. -/
  98noncomputable def oneSimplexOfPath (γ : C(I, SphereOne)) : OneSimplex :=
  99  γ.comp ⟨stdSimplexHomeomorphUnitInterval, stdSimplexHomeomorphUnitInterval.continuous⟩
 100
 101/-- Converting a path to a concrete `1`-simplex and then reading it back as a path
 102returns the original path. -/
 103theorem oneSimplexPath_ofPath (γ : C(I, SphereOne)) :
 104    oneSimplexPath (oneSimplexOfPath γ) = γ := by
 105  ext t
 106  unfold oneSimplexPath oneSimplexOfPath intervalToSimplex
 107  simp
 108
 109/-- The unit-interval parameterisation and its inverse recover a concrete
 110singular `1`-simplex. -/
 111theorem oneSimplexOfPath_oneSimplexPath (f : OneSimplex) :
 112    oneSimplexOfPath (oneSimplexPath f) = f := by
 113  ext x
 114  unfold oneSimplexOfPath oneSimplexPath intervalToSimplex
 115  simp
 116
 117/-- **The displacement of a singular `1`-simplex**: the lift-independent angular
 118travel `2π × (winding number)`, obtained from the path-level displacement. -/
 119def simplexDisplacement (f : OneSimplex) : ℝ := pathDisplacement (oneSimplexPath f)
 120
 121/-- **The winding number of a singular `1`-simplex**, normalised by one full
 122turn. -/
 123def simplexWinding (f : OneSimplex) : ℝ := simplexDisplacement f / (2 * Real.pi)
 124
 125/-- The topological face map `Δ¹ → Δ²` induced by the `i`-th coface
 126`δ i : ⦋1⦌ ⟶ ⦋2⦌`, realised as an affine map of standard simplices. -/
 127def faceMap (i : Fin 3) : C(stdSimplex ℝ (Fin 2), stdSimplex ℝ (Fin 3)) :=
 128  ⟨stdSimplex.map (ConcreteCategory.hom (SimplexCategory.δ i)),
 129    stdSimplex.continuous_map _⟩
 130
 131@[simp] theorem faceMap_apply (i : Fin 3) (x : stdSimplex ℝ (Fin 2)) :
 132    faceMap i x = stdSimplex.map (ConcreteCategory.hom (SimplexCategory.δ i)) x := rfl
 133
 134open CategoryTheory in
 135/-- On the base face `δ₂ : Δ¹ → Δ²`, the second barycentric coordinate is
 136preserved.  This is the coordinate identity needed by the cone parameter
 137`x₁ / (1 - x₂)`. -/
 138theorem faceMap_two_coord_one (x : stdSimplex ℝ (Fin 2)) :
 139    ((faceMap (2 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 1 = x 1 := by
 140  rw [faceMap_apply]
 141  change FunOnFinite.linearMap ℝ ℝ
 142      ((ConcreteCategory.hom (SimplexCategory.δ (2 : Fin 3))) : Fin 2 → Fin 3) x 1 = x 1
 143  have hδ :
 144      ((ConcreteCategory.hom (SimplexCategory.δ (2 : Fin 3))) : Fin 2 → Fin 3) =
 145        (fun j : Fin 2 => (j.castSucc : Fin 3)) := by
 146    ext j
 147    fin_cases j <;> rfl
 148  rw [hδ, FunOnFinite.linearMap_apply_apply]
 149  exact Finset.sum_eq_single (1 : Fin 2)
 150    (by
 151      intro b hb hbne
 152      fin_cases b <;> simp at hb hbne)
 153    (by
 154      intro hnot
 155      simp at hnot)
 156
 157open CategoryTheory in
 158/-- On the base face `δ₂ : Δ¹ → Δ²`, the cone coordinate `x₂` is zero. -/
 159theorem faceMap_two_coord_two (x : stdSimplex ℝ (Fin 2)) :
 160    ((faceMap (2 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = 0 := by
 161  rw [faceMap_apply]
 162  change FunOnFinite.linearMap ℝ ℝ
 163      ((ConcreteCategory.hom (SimplexCategory.δ (2 : Fin 3))) : Fin 2 → Fin 3) x 2 = 0
 164  have hδ :
 165      ((ConcreteCategory.hom (SimplexCategory.δ (2 : Fin 3))) : Fin 2 → Fin 3) =
 166        (fun j : Fin 2 => (j.castSucc : Fin 3)) := by
 167    ext j
 168    fin_cases j <;> rfl
 169  rw [hδ, FunOnFinite.linearMap_apply_apply]
 170  exact Finset.sum_eq_zero (by
 171    intro b hb
 172    fin_cases b <;> simp at hb)
 173
 174open CategoryTheory in
 175/-- On the side face `δ₀ : Δ¹ → Δ²`, the coordinate `x₁` is the initial
 176`Δ¹` barycentric coordinate. -/
 177theorem faceMap_zero_coord_one (x : stdSimplex ℝ (Fin 2)) :
 178    ((faceMap (0 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 1 = x 0 := by
 179  rw [faceMap_apply]
 180  change FunOnFinite.linearMap ℝ ℝ
 181      ((ConcreteCategory.hom (SimplexCategory.δ (0 : Fin 3))) : Fin 2 → Fin 3) x 1 = x 0
 182  have hδ :
 183      ((ConcreteCategory.hom (SimplexCategory.δ (0 : Fin 3))) : Fin 2 → Fin 3) =
 184        (fun j : Fin 2 => j.succ) := by
 185    ext j
 186    fin_cases j <;> rfl
 187  rw [hδ, FunOnFinite.linearMap_apply_apply]
 188  exact Finset.sum_eq_single (0 : Fin 2)
 189    (by
 190      intro b hb hbne
 191      fin_cases b <;> simp at hb hbne)
 192    (by
 193      intro hnot
 194      simp at hnot)
 195
 196open CategoryTheory in
 197/-- On the side face `δ₀ : Δ¹ → Δ²`, the coordinate `x₂` is the terminal
 198`Δ¹` barycentric coordinate. -/
 199theorem faceMap_zero_coord_two (x : stdSimplex ℝ (Fin 2)) :
 200    ((faceMap (0 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = x 1 := by
 201  rw [faceMap_apply]
 202  change FunOnFinite.linearMap ℝ ℝ
 203      ((ConcreteCategory.hom (SimplexCategory.δ (0 : Fin 3))) : Fin 2 → Fin 3) x 2 = x 1
 204  have hδ :
 205      ((ConcreteCategory.hom (SimplexCategory.δ (0 : Fin 3))) : Fin 2 → Fin 3) =
 206        (fun j : Fin 2 => j.succ) := by
 207    ext j
 208    fin_cases j <;> rfl
 209  rw [hδ, FunOnFinite.linearMap_apply_apply]
 210  exact Finset.sum_eq_single (1 : Fin 2)
 211    (by
 212      intro b hb hbne
 213      fin_cases b <;> simp at hb hbne)
 214    (by
 215      intro hnot
 216      simp at hnot)
 217
 218open CategoryTheory in
 219/-- On the side face `δ₁ : Δ¹ → Δ²`, the coordinate `x₁` is zero. -/
 220theorem faceMap_one_coord_one (x : stdSimplex ℝ (Fin 2)) :
 221    ((faceMap (1 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 1 = 0 := by
 222  rw [faceMap_apply]
 223  change FunOnFinite.linearMap ℝ ℝ
 224      ((ConcreteCategory.hom (SimplexCategory.δ (1 : Fin 3))) : Fin 2 → Fin 3) x 1 = 0
 225  have hδ :
 226      ((ConcreteCategory.hom (SimplexCategory.δ (1 : Fin 3))) : Fin 2 → Fin 3) =
 227        (fun j : Fin 2 => if j = 0 then (0 : Fin 3) else 2) := by
 228    ext j
 229    fin_cases j <;> rfl
 230  rw [hδ, FunOnFinite.linearMap_apply_apply]
 231  exact Finset.sum_eq_zero (by
 232    intro b hb
 233    fin_cases b <;> simp at hb)
 234
 235open CategoryTheory in
 236/-- On the side face `δ₁ : Δ¹ → Δ²`, the coordinate `x₂` is the terminal
 237`Δ¹` barycentric coordinate. -/
 238theorem faceMap_one_coord_two (x : stdSimplex ℝ (Fin 2)) :
 239    ((faceMap (1 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = x 1 := by
 240  rw [faceMap_apply]
 241  change FunOnFinite.linearMap ℝ ℝ
 242      ((ConcreteCategory.hom (SimplexCategory.δ (1 : Fin 3))) : Fin 2 → Fin 3) x 2 = x 1
 243  have hδ :
 244      ((ConcreteCategory.hom (SimplexCategory.δ (1 : Fin 3))) : Fin 2 → Fin 3) =
 245        (fun j : Fin 2 => if j = 0 then (0 : Fin 3) else 2) := by
 246    ext j
 247    fin_cases j <;> rfl
 248  rw [hδ, FunOnFinite.linearMap_apply_apply]
 249  exact Finset.sum_eq_single (1 : Fin 2)
 250    (by
 251      intro b hb hbne
 252      fin_cases b <;> simp at hb hbne)
 253    (by
 254      intro hnot
 255      simp at hnot)
 256
 257/-- The `i`-th face of a singular `2`-simplex, as a singular `1`-simplex. -/
 258def face (F : TwoSimplex) (i : Fin 3) : OneSimplex := F.comp (faceMap i)
 259
 260/-- The geometric edge of `Δ²` selected by the `i`-th face map, as a continuous
 261map from the unit interval. -/
 262def simplexEdge (i : Fin 3) : C(I, stdSimplex ℝ (Fin 3)) := (faceMap i).comp intervalToSimplex
 263
 264@[simp] theorem simplexEdge_apply (i : Fin 3) (t : I) :
 265    simplexEdge i t = faceMap i (intervalToSimplex t) := rfl
 266
 267/-- Vertex `k` of the standard `2`-simplex. -/
 268abbrev V (k : Fin 3) : stdSimplex ℝ (Fin 3) := stdSimplex.vertex k
 269
 270theorem simplexEdge_zero (i : Fin 3) :
 271    simplexEdge i 0 = stdSimplex.vertex (ConcreteCategory.hom (SimplexCategory.δ i) 0) := by
 272  rw [simplexEdge_apply, intervalToSimplex_zero, faceMap_apply, stdSimplex.map_vertex]
 273
 274theorem simplexEdge_one (i : Fin 3) :
 275    simplexEdge i 1 = stdSimplex.vertex (ConcreteCategory.hom (SimplexCategory.δ i) 1) := by
 276  rw [simplexEdge_apply, intervalToSimplex_one, faceMap_apply, stdSimplex.map_vertex]
 277
 278/-- The edge `v₀ → v₁` of `Δ²`, realised by the face map `δ 2`. -/
 279def edge01 : Path (V 0) (V 1) where
 280  toContinuousMap := simplexEdge 2
 281  source' := by show simplexEdge 2 0 = V 0; rw [simplexEdge_zero]; congr 1
 282  target' := by show simplexEdge 2 1 = V 1; rw [simplexEdge_one]; congr 1
 283
 284/-- The edge `v₁ → v₂` of `Δ²`, realised by the face map `δ 0`. -/
 285def edge12 : Path (V 1) (V 2) where
 286  toContinuousMap := simplexEdge 0
 287  source' := by show simplexEdge 0 0 = V 1; rw [simplexEdge_zero]; congr 1
 288  target' := by show simplexEdge 0 1 = V 2; rw [simplexEdge_one]; congr 1
 289
 290/-- The edge `v₀ → v₂` of `Δ²`, realised by the face map `δ 1`. -/
 291def edge02 : Path (V 0) (V 2) where
 292  toContinuousMap := simplexEdge 1
 293  source' := by show simplexEdge 1 0 = V 0; rw [simplexEdge_zero]; congr 1
 294  target' := by show simplexEdge 1 1 = V 2; rw [simplexEdge_one]; congr 1
 295
 296/-- Reading the face `δᵢF` in the unit-interval parameterisation is the same as
 297composing `F` with the geometric edge `simplexEdge i`. -/
 298theorem oneSimplexPath_face (F : TwoSimplex) (i : Fin 3) :
 299    oneSimplexPath (face F i) = F.comp (simplexEdge i) := by
 300  ext t; rfl
 301
 302/-- The face displacement equals the displacement of the edge path pushed through
 303`F`.  This is the bridge between the singular-simplex face and the geometric
 304edge used in the telescoping. -/
 305theorem simplexDisplacement_face (F : TwoSimplex) (i : Fin 3)
 306    {a b : stdSimplex ℝ (Fin 3)} (e : Path a b) (he : e.toContinuousMap = simplexEdge i) :
 307    simplexDisplacement (face F i) = pathDisplacement ((e.map F.continuous) : C(I, SphereOne)) := by
 308  rw [simplexDisplacement, oneSimplexPath_face]
 309  congr 1
 310  ext t
 311  show F (simplexEdge i t) = F (e t)
 312  rw [← he]; rfl
 313
 314/-- **The winding invariant kills boundaries.**  For every singular `2`-simplex
 315`F`, the alternating sum of the displacements of its three faces vanishes.  This
 316is the `2`-simplex telescoping: the broken boundary walk is homotopic rel
 317endpoints, inside the simply connected standard `2`-simplex, to the direct edge. -/
 318theorem simplexDisplacement_boundary (F : TwoSimplex) :
 319    simplexDisplacement (face F 0) - simplexDisplacement (face F 1)
 320      + simplexDisplacement (face F 2) = 0 := by
 321  haveI : SimplyConnectedSpace (stdSimplex ℝ (Fin 3)) :=
 322    CircleLifting.stdSimplex_simplyConnectedSpace 3
 323  -- The broken walk `v₀ → v₁ → v₂` and the direct edge `v₀ → v₂` are homotopic
 324  -- rel endpoints in the simply connected standard `2`-simplex.
 325  have hhom : (edge01.trans edge12).Homotopic edge02 :=
 326    SimplyConnectedSpace.paths_homotopic _ _
 327  -- Push the homotopy through `F`.
 328  have hmap := hhom.map F
 329  rw [Path.map_trans] at hmap
 330  -- Convert to a `HomotopicRel` between the corresponding maps `I → S¹`.
 331  have hrel : ((edge01.map F.continuous).trans (edge12.map F.continuous) : C(I, SphereOne)).HomotopicRel
 332      ((edge02.map F.continuous) : C(I, SphereOne)) {0, 1} := by
 333    obtain ⟨H⟩ := hmap
 334    exact ⟨H⟩
 335  -- Homotopy invariance + additivity of the displacement give the telescoping.
 336  have htel : pathDisplacement ((edge02.map F.continuous) : C(I, SphereOne))
 337      = pathDisplacement ((edge01.map F.continuous) : C(I, SphereOne))
 338        + pathDisplacement ((edge12.map F.continuous) : C(I, SphereOne)) := by
 339    rw [← pathDisplacement_homotopic hrel,
 340      pathDisplacement_trans (edge01.map F.continuous) (edge12.map F.continuous)]
 341  -- Identify each face displacement with the corresponding edge displacement.
 342  have h2 : simplexDisplacement (face F 2)
 343      = pathDisplacement ((edge01.map F.continuous) : C(I, SphereOne)) :=
 344    simplexDisplacement_face F 2 edge01 rfl
 345  have h0 : simplexDisplacement (face F 0)
 346      = pathDisplacement ((edge12.map F.continuous) : C(I, SphereOne)) :=
 347    simplexDisplacement_face F 0 edge12 rfl
 348  have h1 : simplexDisplacement (face F 1)
 349      = pathDisplacement ((edge02.map F.continuous) : C(I, SphereOne)) :=
 350    simplexDisplacement_face F 1 edge02 rfl
 351  rw [h0, h1, h2, htel]; ring
 352
 353/-- The winding form of the kills-boundaries identity: the alternating face sum of
 354the winding numbers of a singular `2`-simplex vanishes. -/
 355theorem simplexWinding_boundary (F : TwoSimplex) :
 356    simplexWinding (face F 0) - simplexWinding (face F 1) + simplexWinding (face F 2) = 0 := by
 357  simp only [simplexWinding]
 358  have hb := simplexDisplacement_boundary F
 359  linear_combination hb / (2 * Real.pi)
 360
 361/-- The second barycentric coordinate of `intervalToSimplex t` is `t` itself.
 362This is the affine reparameterisation `t ↦ (1 - t, t)`. -/
 363theorem intervalToSimplex_coord_one (t : I) :
 364    ((intervalToSimplex t : stdSimplex ℝ (Fin 2)) : Fin 2 → ℝ) 1 = (t : ℝ) := rfl
 365
 366/-- Barycentric base parameter for coning a closed edge over the apex `v₂`.
 367Away from the apex it is `x₁ / (1 - x₂)`, i.e. the normalized coordinate along
 368the base edge `v₀ → v₁`; at the apex the value is set to `0`.  The eventual
 369zero-winding cone filler will feed this parameter into the lifted edge path and
 370multiply by `1 - x₂` to get continuity at the apex. -/
 371noncomputable def coneBaseParam (x : stdSimplex ℝ (Fin 3)) : I :=
 372  if h : x 2 = (1 : ℝ) then 0 else
 373    ⟨x 1 / (1 - x 2), by
 374      have hx1nonneg : 0 ≤ x 1 := (mem_Icc_of_mem_stdSimplex x.2 1).1
 375      have hx2le : x 2 ≤ (1 : ℝ) := (mem_Icc_of_mem_stdSimplex x.2 2).2
 376      have hx2lt : x 2 < (1 : ℝ) := lt_of_le_of_ne hx2le h
 377      have hdenpos : 0 < 1 - x 2 := sub_pos.mpr hx2lt
 378      constructor
 379      · exact div_nonneg hx1nonneg (le_of_lt hdenpos)
 380      · rw [div_le_one hdenpos]
 381        have hsum : x 0 + x 1 + x 2 = (1 : ℝ) := by
 382          have hsum := stdSimplex.sum_eq_one x
 383          rw [Fin.sum_univ_three] at hsum
 384          exact hsum
 385        have hx0nonneg : 0 ≤ x 0 := (mem_Icc_of_mem_stdSimplex x.2 0).1
 386        linarith
 387
 388
 389/-- If `x₂ ≠ 1`, the cone base parameter is the expected normalized barycentric
 390coordinate `x₁ / (1 - x₂)`. -/
 391theorem coneBaseParam_coe_of_coord_two_ne_one (x : stdSimplex ℝ (Fin 3))
 392    (h : x 2 ≠ (1 : ℝ)) :
 393    (coneBaseParam x : ℝ) = x 1 / (1 - x 2) := by
 394  simp [coneBaseParam, h]
 395
 396/-- Away from the apex `x₂ = 1`, the real-valued cone base parameter is
 397continuous.  The remaining non-apex continuity of `coneCirclePoint` is therefore
 398only the standard subtype-continuity wrapper for feeding this parameter into
 399`pathLift`. -/
 400theorem continuousAt_coneBaseParam_coe_of_coord_two_ne_one
 401    (x : stdSimplex ℝ (Fin 3)) (h : x 2 ≠ (1 : ℝ)) :
 402    ContinuousAt (fun y : stdSimplex ℝ (Fin 3) => (coneBaseParam y : ℝ)) x := by
 403  let raw : stdSimplex ℝ (Fin 3) → ℝ := fun y => y 1 / (1 - y 2)
 404  have hc1 : ContinuousAt (fun y : stdSimplex ℝ (Fin 3) => y 1) x :=
 405    ((continuous_apply 1).comp continuous_subtype_val).continuousAt
 406  have hc2 : ContinuousAt (fun y : stdSimplex ℝ (Fin 3) => y 2) x :=
 407    ((continuous_apply 2).comp continuous_subtype_val).continuousAt
 408  have hraw : ContinuousAt raw x := by
 409    apply ContinuousAt.div
 410    · exact hc1
 411    · exact continuousAt_const.sub hc2
 412    · exact sub_ne_zero.mpr h.symm
 413  apply hraw.congr_of_eventuallyEq
 414  have hcoord_cont : Continuous (fun y : stdSimplex ℝ (Fin 3) => y 2) :=
 415    (continuous_apply 2).comp continuous_subtype_val
 416  filter_upwards [hcoord_cont.continuousAt.eventually (isOpen_ne.mem_nhds h)] with y hy
 417  unfold raw
 418  exact coneBaseParam_coe_of_coord_two_ne_one y hy
 419
 420/-- Away from the apex, the cone base parameter is continuous as an
 421`I`-valued function, not merely after coercion to `ℝ`. -/
 422theorem continuousAt_coneBaseParam_of_coord_two_ne_one
 423    (x : stdSimplex ℝ (Fin 3)) (h : x 2 ≠ (1 : ℝ)) :
 424    ContinuousAt coneBaseParam x := by
 425  rw [ContinuousAt]
 426  rw [tendsto_subtype_rng]
 427  exact continuousAt_coneBaseParam_coe_of_coord_two_ne_one x h
 428
 429/-- On the base face `δ₂`, the cone base parameter is exactly the original
 430`Δ¹` coordinate. -/
 431theorem coneBaseParam_faceMap_two_coe (x : stdSimplex ℝ (Fin 2)) :
 432    (coneBaseParam (faceMap (2 : Fin 3) x) : ℝ) = x 1 := by
 433  rw [coneBaseParam_coe_of_coord_two_ne_one]
 434  · rw [faceMap_two_coord_one, faceMap_two_coord_two]
 435    ring
 436  · rw [faceMap_two_coord_two]
 437    norm_num
 438
 439/-- Along the actual geometric base edge `v₀ → v₁`, the cone base parameter is
 440the unit-interval parameter. -/
 441theorem coneBaseParam_simplexEdge_two_coe (t : I) :
 442    (coneBaseParam (simplexEdge (2 : Fin 3) t) : ℝ) = (t : ℝ) := by
 443  rw [simplexEdge_apply, coneBaseParam_faceMap_two_coe, intervalToSimplex_coord_one]
 444
 445/-- On the side face `δ₀`, away from the apex, the cone base parameter is `1`.
 446In the lifted cone formula this side therefore evaluates at the terminal endpoint
 447of the original closed edge. -/
 448theorem coneBaseParam_faceMap_zero_coe_of_not_apex (x : stdSimplex ℝ (Fin 2))
 449    (h : x 1 ≠ (1 : ℝ)) :
 450    (coneBaseParam (faceMap (0 : Fin 3) x) : ℝ) = 1 := by
 451  rw [coneBaseParam_coe_of_coord_two_ne_one]
 452  · rw [faceMap_zero_coord_one, faceMap_zero_coord_two]
 453    have hsum : x 0 + x 1 = (1 : ℝ) := by
 454      have hsum := stdSimplex.sum_eq_one x
 455      rw [Fin.sum_univ_two] at hsum
 456      exact hsum
 457    have hx0 : x 0 = 1 - x 1 := by linarith
 458    rw [hx0]
 459    exact div_self (sub_ne_zero.mpr h.symm)
 460  · rw [faceMap_zero_coord_two]
 461    exact h
 462
 463/-- On the side face `δ₁`, away from the apex, the cone base parameter is `0`.
 464This is the initial-endpoint side of the lifted cone formula. -/
 465theorem coneBaseParam_faceMap_one_coe_of_not_apex (x : stdSimplex ℝ (Fin 2))
 466    (h : x 1 ≠ (1 : ℝ)) :
 467    (coneBaseParam (faceMap (1 : Fin 3) x) : ℝ) = 0 := by
 468  rw [coneBaseParam_coe_of_coord_two_ne_one]
 469  · rw [faceMap_one_coord_one]
 470    simp
 471  · rw [faceMap_one_coord_two]
 472    exact h
 473
 474/-- The real lifted angle used by the cone filler for a closed zero-winding edge.
 475It contracts the lifted edge radially toward the apex value.  The only remaining
 476hard analysis is continuity at the apex, where `coneBaseParam` itself is not
 477continuous but the prefactor `1 - x₂` vanishes. -/
 478noncomputable def coneLiftAngle (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 3)) : ℝ :=
 479  (1 - x 2) * pathLift γ (coneBaseParam x) + x 2 * pathLift γ 0
 480
 481/-- Shifted form of the lifted cone angle.  This isolates the vanishing factor
 482`1 - x₂` at the apex. -/
 483theorem coneLiftAngle_sub_start
 484    (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 3)) :
 485    coneLiftAngle γ x - pathLift γ 0 =
 486      (1 - x 2) * (pathLift γ (coneBaseParam x) - pathLift γ 0) := by
 487  unfold coneLiftAngle
 488  ring
 489
 490/-- Uniform apex estimate for the lifted cone angle.  If the shifted lift is
 491bounded by `C`, then the distance from the cone angle to the apex angle is at
 492most `(1 - x₂) * C`.  Since `1 - x₂ → 0` at the apex, this is the squeeze
 493estimate that remains to be fed into the final continuity proof. -/
 494theorem norm_coneLiftAngle_sub_start_le
 495    (γ : C(I, SphereOne)) (C : ℝ)
 496    (hC : ∀ t : I, ‖pathLift γ t - pathLift γ 0‖ ≤ C)
 497    (x : stdSimplex ℝ (Fin 3)) :
 498    ‖coneLiftAngle γ x - pathLift γ 0‖ ≤ (1 - x 2) * C := by
 499  rw [coneLiftAngle_sub_start]
 500  have hnonneg : 0 ≤ 1 - x 2 := by
 501    have hx2le : x 2 ≤ (1 : ℝ) := (mem_Icc_of_mem_stdSimplex x.2 2).2
 502    linarith
 503  rw [norm_mul, Real.norm_eq_abs, abs_of_nonneg hnonneg]
 504  exact mul_le_mul_of_nonneg_left (hC (coneBaseParam x)) hnonneg
 505
 506/-- The lifted cone angle tends to the apex lift value at the cone apex.  This is
 507the analytic heart of the cone construction: compactness bounds the shifted lift,
 508and the barycentric factor `1 - x₂` squeezes the shifted term to zero. -/
 509theorem coneLiftAngle_tendsto_apex (γ : C(I, SphereOne)) :
 510    Filter.Tendsto (coneLiftAngle γ) (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 (pathLift γ 0)) := by
 511  obtain ⟨C, hC⟩ := pathLift_shifted_exists_norm_bound γ
 512  have hbound : ∀ x : stdSimplex ℝ (Fin 3),
 513      ‖coneLiftAngle γ x - pathLift γ 0‖ ≤ (1 - x 2) * C :=
 514    norm_coneLiftAngle_sub_start_le γ C hC
 515  have hscale : Filter.Tendsto (fun x : stdSimplex ℝ (Fin 3) => (1 - x 2) * C)
 516      (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 0) := by
 517    have hx2 : Filter.Tendsto (fun x : stdSimplex ℝ (Fin 3) => x 2)
 518        (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 (1 : ℝ)) := by
 519      have hc : Continuous (fun x : stdSimplex ℝ (Fin 3) => x 2) :=
 520        (continuous_apply 2).comp continuous_subtype_val
 521      exact hc.tendsto (stdSimplex.vertex (2 : Fin 3))
 522    have hsub : Filter.Tendsto (fun x : stdSimplex ℝ (Fin 3) => 1 - x 2)
 523        (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 (0 : ℝ)) := by
 524      have h := (tendsto_const_nhds (x := (1 : ℝ))).sub hx2
 525      simpa using h
 526    have hmul := hsub.mul (tendsto_const_nhds (x := C))
 527    simpa using hmul
 528  have hdiff : Filter.Tendsto (fun x : stdSimplex ℝ (Fin 3) => coneLiftAngle γ x - pathLift γ 0)
 529      (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 0) := by
 530    exact squeeze_zero_norm hbound hscale
 531  have hnorm : Filter.Tendsto (fun x : stdSimplex ℝ (Fin 3) => ‖coneLiftAngle γ x - pathLift γ 0‖)
 532      (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 0) := by
 533    simpa using hdiff.norm
 534  exact tendsto_iff_norm_sub_tendsto_zero.mpr hnorm
 535
 536/-- Away from the apex, the lifted cone angle is continuous by ordinary
 537coordinate arithmetic and continuity of the lifted path. -/
 538theorem continuousAt_coneLiftAngle_of_coord_two_ne_one
 539    (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 3)) (h : x 2 ≠ (1 : ℝ)) :
 540    ContinuousAt (coneLiftAngle γ) x := by
 541  unfold coneLiftAngle
 542  have hparam : ContinuousAt coneBaseParam x :=
 543    continuousAt_coneBaseParam_of_coord_two_ne_one x h
 544  have hpath :
 545      ContinuousAt (fun y : stdSimplex ℝ (Fin 3) => pathLift γ (coneBaseParam y)) x :=
 546    (pathLift γ).continuous.continuousAt.comp hparam
 547  have hc2 : ContinuousAt (fun y : stdSimplex ℝ (Fin 3) => y 2) x :=
 548    ((continuous_apply 2).comp continuous_subtype_val).continuousAt
 549  exact ((continuousAt_const.sub hc2).mul hpath).add (hc2.mul continuousAt_const)
 550
 551/-- On the base edge of the cone, the lifted cone angle is the original lifted
 552path. -/
 553theorem coneLiftAngle_simplexEdge_two (γ : C(I, SphereOne)) (t : I) :
 554    coneLiftAngle γ (simplexEdge (2 : Fin 3) t) = pathLift γ t := by
 555  unfold coneLiftAngle
 556  have h2 : ((simplexEdge (2 : Fin 3) t : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = 0 := by
 557    rw [simplexEdge_apply, faceMap_two_coord_two]
 558  have hp : coneBaseParam (simplexEdge (2 : Fin 3) t) = t := by
 559    ext
 560    exact coneBaseParam_simplexEdge_two_coe t
 561  rw [h2, hp]
 562  ring
 563
 564/-- On the `δ₁` side of the cone, the lifted cone angle is constantly the initial
 565lift value. -/
 566theorem coneLiftAngle_simplexEdge_one (γ : C(I, SphereOne)) (t : I) :
 567    coneLiftAngle γ (simplexEdge (1 : Fin 3) t) = pathLift γ 0 := by
 568  unfold coneLiftAngle
 569  have h2 : ((simplexEdge (1 : Fin 3) t : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = (t : ℝ) := by
 570    rw [simplexEdge_apply, faceMap_one_coord_two, intervalToSimplex_coord_one]
 571  rw [h2]
 572  by_cases ht : (t : ℝ) = 1
 573  · have htI : t = (1 : I) := by
 574      ext
 575      exact ht
 576    subst t
 577    simp [coneBaseParam]
 578  · have hparam : (coneBaseParam (simplexEdge (1 : Fin 3) t) : ℝ) = 0 := by
 579      rw [simplexEdge_apply]
 580      apply coneBaseParam_faceMap_one_coe_of_not_apex
 581      intro h1
 582      have : (t : ℝ) = 1 := by
 583        rw [← intervalToSimplex_coord_one t]
 584        exact h1
 585      exact ht this
 586    have hp : coneBaseParam (simplexEdge (1 : Fin 3) t) = (0 : I) := by
 587      ext
 588      exact hparam
 589    rw [hp]
 590    ring
 591
 592/-- On the `δ₀` side of a zero-winding closed cone, the lifted cone angle is also
 593constant.  The hypothesis is exactly the lifted endpoint equality forced by zero
 594winding. -/
 595theorem coneLiftAngle_simplexEdge_zero_of_lift_endpoint_eq
 596    (γ : C(I, SphereOne)) (hlift : pathLift γ 1 = pathLift γ 0) (t : I) :
 597    coneLiftAngle γ (simplexEdge (0 : Fin 3) t) = pathLift γ 0 := by
 598  unfold coneLiftAngle
 599  have h2 : ((simplexEdge (0 : Fin 3) t : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = (t : ℝ) := by
 600    rw [simplexEdge_apply, faceMap_zero_coord_two, intervalToSimplex_coord_one]
 601  rw [h2]
 602  by_cases ht : (t : ℝ) = 1
 603  · have htI : t = (1 : I) := by
 604      ext
 605      exact ht
 606    subst t
 607    simp [coneBaseParam]
 608  · have hparam : (coneBaseParam (simplexEdge (0 : Fin 3) t) : ℝ) = 1 := by
 609      rw [simplexEdge_apply]
 610      apply coneBaseParam_faceMap_zero_coe_of_not_apex
 611      intro h1
 612      have : (t : ℝ) = 1 := by
 613        rw [← intervalToSimplex_coord_one t]
 614        exact h1
 615      exact ht this
 616    have hp : coneBaseParam (simplexEdge (0 : Fin 3) t) = (1 : I) := by
 617      ext
 618      exact hparam
 619    rw [hp, hlift]
 620    ring
 621
 622/-- The pointwise `S¹` cone obtained by projecting the lifted cone angle through
 623the circle cover.  This is not yet packaged as a `ContinuousMap`; the next
 624frontier is proving continuity at the apex. -/
 625def coneCirclePoint (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 3)) : SphereOne :=
 626  trigCirclePoint (coneLiftAngle γ x)
 627
 628/-- The pointwise `S¹` cone tends to the basepoint at the apex. -/
 629theorem coneCirclePoint_tendsto_apex (γ : C(I, SphereOne)) :
 630    Filter.Tendsto (coneCirclePoint γ) (𝓝 (stdSimplex.vertex (2 : Fin 3))) (𝓝 (γ 0)) := by
 631  have htrig := continuous_trigCirclePoint.tendsto (pathLift γ 0)
 632  have ht := htrig.comp (coneLiftAngle_tendsto_apex γ)
 633  have h0 : trigCirclePoint (pathLift γ 0) = γ 0 := by
 634    exact congrFun (pathLift_lifts γ) 0
 635  rw [h0] at ht
 636  exact ht
 637
 638/-- The pointwise `S¹` cone is continuous at the apex.  Away from the apex the
 639remaining continuity is ordinary quotient-coordinate continuity; the apex was
 640the only singular analytic point. -/
 641theorem continuousAt_coneCirclePoint_apex (γ : C(I, SphereOne)) :
 642    ContinuousAt (coneCirclePoint γ) (stdSimplex.vertex (2 : Fin 3)) := by
 643  change Filter.Tendsto (coneCirclePoint γ) (𝓝 (stdSimplex.vertex (2 : Fin 3)))
 644    (𝓝 (coneCirclePoint γ (stdSimplex.vertex (2 : Fin 3))))
 645  have hapex : coneCirclePoint γ (stdSimplex.vertex (2 : Fin 3)) = γ 0 := by
 646    unfold coneCirclePoint coneLiftAngle
 647    change trigCirclePoint
 648        ((1 - (1 : ℝ)) * pathLift γ (coneBaseParam (stdSimplex.vertex (2 : Fin 3))) +
 649          (1 : ℝ) * pathLift γ 0) = γ 0
 650    simp
 651    exact congrFun (pathLift_lifts γ) 0
 652  rw [hapex]
 653  exact coneCirclePoint_tendsto_apex γ
 654
 655/-- Away from the apex, `coneCirclePoint` is continuous by composing the
 656non-apex continuity of `coneLiftAngle` with the circle covering map. -/
 657theorem continuousAt_coneCirclePoint_of_coord_two_ne_one
 658    (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 3)) (h : x 2 ≠ (1 : ℝ)) :
 659    ContinuousAt (coneCirclePoint γ) x := by
 660  unfold coneCirclePoint
 661  exact continuous_trigCirclePoint.continuousAt.comp
 662    (continuousAt_coneLiftAngle_of_coord_two_ne_one γ x h)
 663
 664/-- In `Δ²`, the condition `x₂ = 1` forces the point to be the apex vertex
 665`v₂`. -/
 666theorem stdSimplex_eq_vertex_two_of_coord_two_eq_one
 667    (x : stdSimplex ℝ (Fin 3)) (h : x 2 = (1 : ℝ)) :
 668    x = stdSimplex.vertex (2 : Fin 3) := by
 669  ext i
 670  fin_cases i
 671  · have hsum : x 0 + x 1 + x 2 = (1 : ℝ) := by
 672      have hsum := stdSimplex.sum_eq_one x
 673      rw [Fin.sum_univ_three] at hsum
 674      exact hsum
 675    have hx0nonneg : 0 ≤ x 0 := (mem_Icc_of_mem_stdSimplex x.2 0).1
 676    have hx1nonneg : 0 ≤ x 1 := (mem_Icc_of_mem_stdSimplex x.2 1).1
 677    have hx0 : x 0 = 0 := by linarith
 678    simpa using hx0
 679  · have hsum : x 0 + x 1 + x 2 = (1 : ℝ) := by
 680      have hsum := stdSimplex.sum_eq_one x
 681      rw [Fin.sum_univ_three] at hsum
 682      exact hsum
 683    have hx0nonneg : 0 ≤ x 0 := (mem_Icc_of_mem_stdSimplex x.2 0).1
 684    have hx1nonneg : 0 ≤ x 1 := (mem_Icc_of_mem_stdSimplex x.2 1).1
 685    have hx1 : x 1 = 0 := by linarith
 686    simpa using hx1
 687  · simpa using h
 688
 689/-- The pointwise cone is a continuous map `Δ² → S¹`.  This closes the analytic
 690packaging gap left after the pointwise cone identities: non-apex continuity is
 691ordinary coordinate continuity, and the apex is handled by the squeeze theorem
 692above. -/
 693theorem continuous_coneCirclePoint (γ : C(I, SphereOne)) :
 694    Continuous (coneCirclePoint γ) := by
 695  rw [continuous_iff_continuousAt]
 696  intro x
 697  by_cases h : x 2 = (1 : ℝ)
 698  · rw [stdSimplex_eq_vertex_two_of_coord_two_eq_one x h]
 699    exact continuousAt_coneCirclePoint_apex γ
 700  · exact continuousAt_coneCirclePoint_of_coord_two_ne_one γ x h
 701
 702/-- The pointwise cone restricts to the original path on the base edge. -/
 703theorem coneCirclePoint_simplexEdge_two (γ : C(I, SphereOne)) (t : I) :
 704    coneCirclePoint γ (simplexEdge (2 : Fin 3) t) = γ t := by
 705  unfold coneCirclePoint
 706  rw [coneLiftAngle_simplexEdge_two]
 707  exact congrFun (pathLift_lifts γ) t
 708
 709/-- The pointwise cone is constant on the `δ₁` side. -/
 710theorem coneCirclePoint_simplexEdge_one (γ : C(I, SphereOne)) (t : I) :
 711    coneCirclePoint γ (simplexEdge (1 : Fin 3) t) = γ 0 := by
 712  unfold coneCirclePoint
 713  rw [coneLiftAngle_simplexEdge_one]
 714  exact congrFun (pathLift_lifts γ) 0
 715
 716/-- The pointwise cone is constant on the `δ₀` side once the lifted endpoints
 717agree, which is the zero-winding condition in lifted form. -/
 718theorem coneCirclePoint_simplexEdge_zero_of_lift_endpoint_eq
 719    (γ : C(I, SphereOne)) (hlift : pathLift γ 1 = pathLift γ 0) (t : I) :
 720    coneCirclePoint γ (simplexEdge (0 : Fin 3) t) = γ 0 := by
 721  unfold coneCirclePoint
 722  rw [coneLiftAngle_simplexEdge_zero_of_lift_endpoint_eq γ hlift]
 723  exact congrFun (pathLift_lifts γ) 0
 724
 725/-- Arbitrary-base-face version of `coneLiftAngle_simplexEdge_two`: on the whole
 726base face `δ₂`, the lifted cone angle agrees with the lifted edge after the
 727standard `Δ¹ ≃ I` reparameterisation. -/
 728theorem coneLiftAngle_faceMap_two_of_oneSimplex (f : OneSimplex)
 729    (x : stdSimplex ℝ (Fin 2)) :
 730    coneLiftAngle (oneSimplexPath f) (faceMap (2 : Fin 3) x) =
 731      pathLift (oneSimplexPath f) (stdSimplexHomeomorphUnitInterval x) := by
 732  unfold coneLiftAngle
 733  have h2 : ((faceMap (2 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = 0 :=
 734    faceMap_two_coord_two x
 735  have hp : coneBaseParam (faceMap (2 : Fin 3) x) = stdSimplexHomeomorphUnitInterval x := by
 736    ext
 737    exact coneBaseParam_faceMap_two_coe x
 738  rw [h2, hp]
 739  ring
 740
 741/-- Path-parametric base-face version: on `δ₂`, the lifted cone angle agrees with
 742the lifted path. -/
 743theorem coneLiftAngle_faceMap_two (γ : C(I, SphereOne))
 744    (x : stdSimplex ℝ (Fin 2)) :
 745    coneLiftAngle γ (faceMap (2 : Fin 3) x) =
 746      pathLift γ (stdSimplexHomeomorphUnitInterval x) := by
 747  unfold coneLiftAngle
 748  have h2 : ((faceMap (2 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = 0 :=
 749    faceMap_two_coord_two x
 750  have hp : coneBaseParam (faceMap (2 : Fin 3) x) = stdSimplexHomeomorphUnitInterval x := by
 751    ext
 752    exact coneBaseParam_faceMap_two_coe x
 753  rw [h2, hp]
 754  ring
 755
 756/-- Pointwise base-face restriction for the cone: after projection to `S¹`, the
 757base face is exactly the original concrete singular edge. -/
 758theorem coneCirclePoint_faceMap_two_of_oneSimplex (f : OneSimplex)
 759    (x : stdSimplex ℝ (Fin 2)) :
 760    coneCirclePoint (oneSimplexPath f) (faceMap (2 : Fin 3) x) = f x := by
 761  unfold coneCirclePoint
 762  rw [coneLiftAngle_faceMap_two_of_oneSimplex]
 763  have htrig :
 764      trigCirclePoint (pathLift (oneSimplexPath f) (stdSimplexHomeomorphUnitInterval x)) =
 765        (oneSimplexPath f) (stdSimplexHomeomorphUnitInterval x) := by
 766    simpa [Function.comp_apply] using
 767      congrFun (pathLift_lifts (oneSimplexPath f)) (stdSimplexHomeomorphUnitInterval x)
 768  rw [htrig]
 769  unfold oneSimplexPath
 770  simp [intervalToSimplex]
 771
 772/-- Path-parametric base-face restriction for the cone. -/
 773theorem coneCirclePoint_faceMap_two (γ : C(I, SphereOne))
 774    (x : stdSimplex ℝ (Fin 2)) :
 775    coneCirclePoint γ (faceMap (2 : Fin 3) x) = oneSimplexOfPath γ x := by
 776  unfold coneCirclePoint oneSimplexOfPath
 777  rw [coneLiftAngle_faceMap_two]
 778  exact congrFun (pathLift_lifts γ) (stdSimplexHomeomorphUnitInterval x)
 779
 780/-- Arbitrary-side-face version for `δ₁`: the lifted cone angle is constant on
 781the whole side face. -/
 782theorem coneLiftAngle_faceMap_one (γ : C(I, SphereOne))
 783    (x : stdSimplex ℝ (Fin 2)) :
 784    coneLiftAngle γ (faceMap (1 : Fin 3) x) = pathLift γ 0 := by
 785  unfold coneLiftAngle
 786  have h2 : ((faceMap (1 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = x 1 :=
 787    faceMap_one_coord_two x
 788  rw [h2]
 789  by_cases hx : x 1 = (1 : ℝ)
 790  · rw [hx]
 791    simp
 792  · have hparam : (coneBaseParam (faceMap (1 : Fin 3) x) : ℝ) = 0 :=
 793      coneBaseParam_faceMap_one_coe_of_not_apex x hx
 794    have hp : coneBaseParam (faceMap (1 : Fin 3) x) = (0 : I) := by
 795      ext
 796      exact hparam
 797    rw [hp]
 798    ring
 799
 800/-- Arbitrary-side-face version for `δ₀`: the lifted cone angle is constant on
 801the whole side face once the lifted endpoints agree. -/
 802theorem coneLiftAngle_faceMap_zero_of_lift_endpoint_eq
 803    (γ : C(I, SphereOne)) (hlift : pathLift γ 1 = pathLift γ 0)
 804    (x : stdSimplex ℝ (Fin 2)) :
 805    coneLiftAngle γ (faceMap (0 : Fin 3) x) = pathLift γ 0 := by
 806  unfold coneLiftAngle
 807  have h2 : ((faceMap (0 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = x 1 :=
 808    faceMap_zero_coord_two x
 809  rw [h2]
 810  by_cases hx : x 1 = (1 : ℝ)
 811  · rw [hx]
 812    simp
 813  · have hparam : (coneBaseParam (faceMap (0 : Fin 3) x) : ℝ) = 1 :=
 814      coneBaseParam_faceMap_zero_coe_of_not_apex x hx
 815    have hp : coneBaseParam (faceMap (0 : Fin 3) x) = (1 : I) := by
 816      ext
 817      exact hparam
 818    rw [hp, hlift]
 819    ring
 820
 821/-- Arbitrary-side-face formula for `δ₀` without closing the edge.  This is the
 822terminal-return side of the cone: it linearly joins the terminal lift of the edge
 823back to its initial lift. -/
 824theorem coneLiftAngle_faceMap_zero
 825    (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 2)) :
 826    coneLiftAngle γ (faceMap (0 : Fin 3) x) =
 827      (1 - x 1) * pathLift γ 1 + x 1 * pathLift γ 0 := by
 828  unfold coneLiftAngle
 829  have h2 : ((faceMap (0 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 2 = x 1 :=
 830    faceMap_zero_coord_two x
 831  rw [h2]
 832  by_cases hx : x 1 = (1 : ℝ)
 833  · rw [hx]
 834    simp
 835  · have hparam : (coneBaseParam (faceMap (0 : Fin 3) x) : ℝ) = 1 :=
 836      coneBaseParam_faceMap_zero_coe_of_not_apex x hx
 837    have hp : coneBaseParam (faceMap (0 : Fin 3) x) = (1 : I) := by
 838      ext
 839      exact hparam
 840    rw [hp]
 841
 842/-- The concrete terminal-return side of the cone over a path. -/
 843noncomputable def coneTerminalSide (γ : C(I, SphereOne)) : OneSimplex where
 844  toFun x := trigCirclePoint ((1 - x 1) * pathLift γ 1 + x 1 * pathLift γ 0)
 845  continuous_toFun := by
 846    have hc1 : Continuous (fun x : stdSimplex ℝ (Fin 2) => x 1) :=
 847      (continuous_apply 1).comp continuous_subtype_val
 848    exact continuous_trigCirclePoint.comp
 849      (((continuous_const.sub hc1).mul continuous_const).add (hc1.mul continuous_const))
 850
 851/-- The concrete constant singular edge at a point of the circle. -/
 852def constantOneSimplex (p : SphereOne) : OneSimplex :=
 853  ContinuousMap.const (stdSimplex ℝ (Fin 2)) p
 854
 855/-- If the lifted endpoints of the base path agree, the terminal-return side of
 856the cone collapses to the constant apex edge. -/
 857theorem coneTerminalSide_eq_constantOneSimplex_of_lift_endpoint_eq
 858    (γ : C(I, SphereOne)) (hlift : pathLift γ 1 = pathLift γ 0) :
 859    coneTerminalSide γ = constantOneSimplex (γ 0) := by
 860  ext x
 861  change trigCirclePoint ((1 - x 1) * pathLift γ 1 + x 1 * pathLift γ 0) = γ 0
 862  rw [hlift]
 863  have h : (1 - x 1) * pathLift γ 0 + x 1 * pathLift γ 0 = pathLift γ 0 := by
 864    ring
 865  rw [h]
 866  exact congrFun (pathLift_lifts γ) 0
 867
 868/-- Zero winding collapses the terminal-return side of the cone over a singular
 869edge to the constant apex edge. -/
 870theorem coneTerminalSide_eq_constantOneSimplex_of_simplexWinding_zero
 871    (f : OneSimplex) (hzero : simplexWinding f = 0) :
 872    coneTerminalSide (oneSimplexPath f) =
 873      constantOneSimplex ((oneSimplexPath f) 0) := by
 874  have hlift : pathLift (oneSimplexPath f) 1 = pathLift (oneSimplexPath f) 0 := by
 875    apply pathLift_endpoint_eq_of_winding_zero
 876    simpa [simplexWinding, simplexDisplacement, pathWinding] using hzero
 877  exact coneTerminalSide_eq_constantOneSimplex_of_lift_endpoint_eq (oneSimplexPath f) hlift
 878
 879/-- Pointwise `S¹` side restriction for `δ₁`: the cone is constant on this side. -/
 880theorem coneCirclePoint_faceMap_one (γ : C(I, SphereOne))
 881    (x : stdSimplex ℝ (Fin 2)) :
 882    coneCirclePoint γ (faceMap (1 : Fin 3) x) = γ 0 := by
 883  unfold coneCirclePoint
 884  rw [coneLiftAngle_faceMap_one]
 885  exact congrFun (pathLift_lifts γ) 0
 886
 887/-- Pointwise `S¹` side restriction for `δ₀` under lifted endpoint equality. -/
 888theorem coneCirclePoint_faceMap_zero_of_lift_endpoint_eq
 889    (γ : C(I, SphereOne)) (hlift : pathLift γ 1 = pathLift γ 0)
 890    (x : stdSimplex ℝ (Fin 2)) :
 891    coneCirclePoint γ (faceMap (0 : Fin 3) x) = γ 0 := by
 892  unfold coneCirclePoint
 893  rw [coneLiftAngle_faceMap_zero_of_lift_endpoint_eq γ hlift]
 894  exact congrFun (pathLift_lifts γ) 0
 895
 896/-- Pointwise `S¹` side restriction for `δ₀` without the zero-winding endpoint
 897equality: the face is the terminal-return side of the cone. -/
 898theorem coneCirclePoint_faceMap_zero
 899    (γ : C(I, SphereOne)) (x : stdSimplex ℝ (Fin 2)) :
 900    coneCirclePoint γ (faceMap (0 : Fin 3) x) = coneTerminalSide γ x := by
 901  unfold coneCirclePoint coneTerminalSide
 902  rw [coneLiftAngle_faceMap_zero]
 903  rfl
 904
 905/-- The two side faces of the pointwise cone agree once the lifted endpoints of
 906the base path agree.  This is the pointwise form of the future face equation
 907`face F 0 = face F 1`. -/
 908theorem coneCirclePoint_side_faces_eq_of_lift_endpoint_eq
 909    (γ : C(I, SphereOne)) (hlift : pathLift γ 1 = pathLift γ 0)
 910    (x : stdSimplex ℝ (Fin 2)) :
 911    coneCirclePoint γ (faceMap (0 : Fin 3) x) =
 912      coneCirclePoint γ (faceMap (1 : Fin 3) x) := by
 913  rw [coneCirclePoint_faceMap_zero_of_lift_endpoint_eq γ hlift,
 914    coneCirclePoint_faceMap_one γ]
 915
 916/-- Zero-winding form of the pointwise side-face equality for the cone. -/
 917theorem coneCirclePoint_side_faces_eq_of_winding_zero
 918    (γ : C(I, SphereOne)) (hw : pathWinding γ = 0)
 919    (x : stdSimplex ℝ (Fin 2)) :
 920    coneCirclePoint γ (faceMap (0 : Fin 3) x) =
 921      coneCirclePoint γ (faceMap (1 : Fin 3) x) :=
 922  coneCirclePoint_side_faces_eq_of_lift_endpoint_eq γ
 923    (pathLift_endpoint_eq_of_winding_zero γ hw) x
 924
 925/-- Package the pointwise cone as a concrete singular `2`-simplex once its
 926continuity has been proved.  This definition deliberately isolates the only
 927remaining analytic obligation: continuity of `coneCirclePoint` at the apex. -/
 928def coneCircleMapOfContinuous (γ : C(I, SphereOne))
 929    (hcont : Continuous (coneCirclePoint γ)) : TwoSimplex where
 930  toFun := coneCirclePoint γ
 931  continuous_toFun := hcont
 932
 933/-- If the pointwise zero-winding cone is continuous, then its base face is the
 934original singular edge. -/
 935theorem coneCircleMapOfContinuous_face_two (f : OneSimplex)
 936    (hcont : Continuous (coneCirclePoint (oneSimplexPath f))) :
 937    face (coneCircleMapOfContinuous (oneSimplexPath f) hcont) (2 : Fin 3) = f := by
 938  ext x
 939  exact coneCirclePoint_faceMap_two_of_oneSimplex f x
 940
 941/-- Path-parametric base face of the cone. -/
 942theorem coneCircleMapOfContinuous_face_two_path (γ : C(I, SphereOne))
 943    (hcont : Continuous (coneCirclePoint γ)) :
 944    face (coneCircleMapOfContinuous γ hcont) (2 : Fin 3) = oneSimplexOfPath γ := by
 945  ext x
 946  change coneCirclePoint γ (faceMap (2 : Fin 3) x) = oneSimplexOfPath γ x
 947  exact coneCirclePoint_faceMap_two γ x
 948
 949/-- The `δ₀` face of the cone is the terminal-return side.  This is the open-edge
 950face formula needed before side terms are cancelled in a multi-edge prism. -/
 951theorem coneCircleMapOfContinuous_face_zero (γ : C(I, SphereOne))
 952    (hcont : Continuous (coneCirclePoint γ)) :
 953    face (coneCircleMapOfContinuous γ hcont) (0 : Fin 3) = coneTerminalSide γ := by
 954  ext x
 955  exact coneCirclePoint_faceMap_zero γ x
 956
 957/-- The `δ₁` face of the cone is the constant edge at the cone apex. -/
 958theorem coneCircleMapOfContinuous_face_one (γ : C(I, SphereOne))
 959    (hcont : Continuous (coneCirclePoint γ)) :
 960    face (coneCircleMapOfContinuous γ hcont) (1 : Fin 3) = constantOneSimplex (γ 0) := by
 961  ext x
 962  unfold constantOneSimplex
 963  exact coneCirclePoint_faceMap_one γ x
 964
 965/-- If the pointwise zero-winding cone is continuous, then its two side faces
 966agree. -/
 967theorem coneCircleMapOfContinuous_side_faces_eq_of_winding_zero (f : OneSimplex)
 968    (hzero : simplexWinding f = 0)
 969    (hcont : Continuous (coneCirclePoint (oneSimplexPath f))) :
 970    face (coneCircleMapOfContinuous (oneSimplexPath f) hcont) (0 : Fin 3) =
 971      face (coneCircleMapOfContinuous (oneSimplexPath f) hcont) (1 : Fin 3) := by
 972  ext x
 973  exact coneCirclePoint_side_faces_eq_of_winding_zero (oneSimplexPath f) hzero x
 974
 975/-- The fundamental singular `1`-simplex of `CircleFundamentalSimplex`, read in the
 976unit-interval parameterisation, is exactly the fundamental once-around loop. -/
 977theorem oneSimplexPath_fundamental :
 978    oneSimplexPath CircleFundamentalSimplex.fundamentalCirclePathMap = fundamentalLoop := by
 979  ext t
 980  show trigCirclePoint (2 * Real.pi * ((intervalToSimplex t : stdSimplex ℝ (Fin 2)) : Fin 2 → ℝ) 1)
 981      = trigCirclePoint (2 * Real.pi * (t : ℝ))
 982  rw [intervalToSimplex_coord_one]
 983
 984/-- **The displacement of the fundamental singular `1`-simplex is one full turn.** -/
 985theorem simplexDisplacement_fundamental :
 986    simplexDisplacement CircleFundamentalSimplex.fundamentalCirclePathMap = 2 * Real.pi := by
 987  rw [simplexDisplacement, oneSimplexPath_fundamental, pathDisplacement_fundamentalLoop]
 988
 989/-- **The winding invariant is a left inverse to the fundamental class.**  The
 990winding number of the once-around fundamental singular `1`-simplex is `1`. -/
 991theorem simplexWinding_fundamental :
 992    simplexWinding CircleFundamentalSimplex.fundamentalCirclePathMap = 1 := by
 993  rw [simplexWinding, simplexDisplacement_fundamental]
 994  have hpi : (2 : ℝ) * Real.pi ≠ 0 := by positivity
 995  field_simp
 996
 997/-- A singular `1`-simplex whose two endpoints agree has integer winding. -/
 998theorem simplexWinding_loop_integral (f : OneSimplex)
 999    (hloop : f (stdSimplex.vertex (1 : Fin 2)) = f (stdSimplex.vertex (0 : Fin 2))) :
1000    ∃ k : ℤ, simplexWinding f = (k : ℝ) := by
1001  unfold simplexWinding simplexDisplacement oneSimplexPath
1002  apply pathWinding_loop_integral
1003  rw [ContinuousMap.comp_apply, ContinuousMap.comp_apply, intervalToSimplex_one,
1004    intervalToSimplex_zero]
1005  exact hloop
1006
1007/-- **Closed-walk winding integrality (path form).**  Let `f : Fin k → C(I,S¹)`
1008be a cyclically connected family of paths: the terminal point of `f i` is the
1009initial point of `f (finRotate k i)` for every `i` (so the family closes up into
1010a single loop).  Then the total displacement around the walk is an integer
1011multiple of `2π`.
1012
1013This is the multi-edge generalization of `pathDisplacement_loop_intMul`: the
1014displacement is the endpoint difference of the canonical lift, and at each
1015junction the two lifts sit in the same fiber, so they differ by an element of the
1016deck group `2πℤ`.  Summing the junction differences cyclically (reindexing by
1017`finRotate`) telescopes the per-edge displacements to a single integer multiple of
1018`2π`.  It is exactly the integrality input needed for the `winding_integral`
1019field of a multi-edge cyclic edge-list piece, and it needs no prism/subdivision
1020operator. -/
1021theorem displacementSum_cyclic_intMul {k : ℕ} (f : Fin k → C(I, SphereOne))
1022    (hconn : ∀ i : Fin k, (f i) 1 = (f (finRotate k i)) 0) :
1023    ∃ m : ℤ, ∑ i, pathDisplacement (f i) = (m : ℝ) * (2 * Real.pi) := by
1024  have hjunc : ∀ i : Fin k, ∃ m : ℤ,
1025      pathLift (f i) 1 - pathLift (f (finRotate k i)) 0 = (m : ℝ) * (2 * Real.pi) := by
1026    intro i
1027    have h1 : trigCirclePoint (pathLift (f i) 1) = (f i) 1 :=
1028      congrFun (pathLift_lifts (f i)) 1
1029    have h0 : trigCirclePoint (pathLift (f (finRotate k i)) 0) = (f (finRotate k i)) 0 :=
1030      congrFun (pathLift_lifts (f (finRotate k i))) 0
1031    have hfib :
1032        trigCirclePoint (pathLift (f i) 1)
1033          = trigCirclePoint (pathLift (f (finRotate k i)) 0) := by
1034      rw [h1, h0]; exact hconn i
1035    obtain ⟨m, hm⟩ := (CircleLifting.trigCirclePoint_eq_iff _ _).1 hfib
1036    exact ⟨m, by rw [hm]; ring⟩
1037  choose m hm using hjunc
1038  refine ⟨∑ i, m i, ?_⟩
1039  calc
1040    ∑ i, pathDisplacement (f i)
1041        = ∑ i, (pathLift (f i) 1 - pathLift (f i) 0) := by
1042          refine Finset.sum_congr rfl (fun i _ => ?_)
1043          exact pathDisplacement_self (f i)
1044    _ = (∑ i, pathLift (f i) 1) - ∑ i, pathLift (f i) 0 := by
1045          rw [Finset.sum_sub_distrib]
1046    _ = (∑ i, pathLift (f i) 1) - ∑ i, pathLift (f (finRotate k i)) 0 := by
1047          congr 1
1048          exact (Equiv.sum_comp (finRotate k) (fun i => pathLift (f i) 0)).symm
1049    _ = ∑ i, (pathLift (f i) 1 - pathLift (f (finRotate k i)) 0) := by
1050          rw [Finset.sum_sub_distrib]
1051    _ = ∑ i, ((m i : ℝ) * (2 * Real.pi)) := by
1052          refine Finset.sum_congr rfl (fun i _ => ?_)
1053          exact hm i
1054    _ = (∑ i, m i : ℤ) * (2 * Real.pi) := by
1055          rw [← Finset.sum_mul]; push_cast; ring
1056
1057/-! ## Connection to the actual singular chain complex
1058
1059The development above works with singular simplices presented as continuous maps
1060`C(Δⁿ, S¹)` via `TopCat.toSSetObjEquiv`.  The following lemmas connect this to the
1061actual simplicial face maps `(TopCat.toSSet.obj (TopCat.sphere 1)).δ i`, so that the
1062kills-boundaries identity is a statement about the genuine boundary in
1063`CircleH1Computation.sphereOneSingularIntChainComplex`. -/
1064
1065/-- A singular `2`-simplex in the actual singular simplicial set of
1066`TopCat.sphere 1`. -/
1067abbrev SingularTwoSimplex : Type :=
1068  (TopCat.toSSet.obj (TopCat.sphere 1)).obj (op (SimplexCategory.mk 2))
1069
1070/-- A singular `1`-simplex in the actual singular simplicial set of
1071`TopCat.sphere 1`. -/
1072abbrev SingularOneSimplex : Type :=
1073  (TopCat.toSSet.obj (TopCat.sphere 1)).obj (op (SimplexCategory.mk 1))
1074
1075/-- A singular `0`-simplex in the actual singular simplicial set of
1076`TopCat.sphere 1`. -/
1077abbrev SingularZeroSimplex : Type :=
1078  (TopCat.toSSet.obj (TopCat.sphere 1)).obj (op (SimplexCategory.mk 0))
1079
1080open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1081/-- The free module on the actual singular `0`-simplices of `TopCat.sphere 1`. -/
1082abbrev singularZeroChainFree : ModuleCat ℤ :=
1083  (ModuleCat.free ℤ).obj SingularZeroSimplex
1084
1085open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1086/-- The raw singular chain group `C₀(S¹;ℤ)` maps to the explicit free module on
1087singular `0`-simplices by sending each coproduct summand to the corresponding
1088free generator. -/
1089noncomputable def singularZeroChainToFree :
1090    sphereOneSingularIntChainComplex.X 0 ⟶ singularZeroChainFree :=
1091  Sigma.desc (fun s : SingularZeroSimplex =>
1092    ModuleCat.ofHom
1093      (LinearMap.toSpanSingleton ℤ singularZeroChainFree (ModuleCat.freeMk s)))
1094
1095open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1096/-- The free module on the actual singular `1`-simplices of `TopCat.sphere 1`. -/
1097abbrev singularOneChainFree : ModuleCat ℤ :=
1098  (ModuleCat.free ℤ).obj SingularOneSimplex
1099
1100open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1101/-- The free module on the actual singular `2`-simplices of `TopCat.sphere 1`. -/
1102abbrev singularTwoChainFree : ModuleCat ℤ :=
1103  (ModuleCat.free ℤ).obj SingularTwoSimplex
1104
1105open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1106/-- The raw singular chain group `C₁(S¹;ℤ)` maps to the explicit free module on
1107singular `1`-simplices by sending each coproduct summand to the corresponding
1108free generator. -/
1109noncomputable def singularOneChainToFree :
1110    sphereOneSingularIntChainComplex.X 1 ⟶ singularOneChainFree :=
1111  Sigma.desc (fun s : SingularOneSimplex =>
1112    ModuleCat.ofHom
1113      (LinearMap.toSpanSingleton ℤ singularOneChainFree (ModuleCat.freeMk s)))
1114
1115open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1116/-- The explicit free module on singular `1`-simplices maps back to `C₁(S¹;ℤ)` by
1117sending each free generator to the matching coproduct summand generator. -/
1118noncomputable def singularOneChainFreeToChain :
1119    singularOneChainFree ⟶ sphereOneSingularIntChainComplex.X 1 :=
1120  ModuleCat.freeDesc (fun s : SingularOneSimplex =>
1121    ModuleCat.Hom.hom
1122      (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) 1)
1123
1124open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1125/-- The explicit free module on singular `2`-simplices maps back to `C₂(S¹;ℤ)` by
1126sending each free generator to the matching coproduct summand generator. -/
1127noncomputable def singularTwoChainFreeToChain :
1128    singularTwoChainFree ⟶ sphereOneSingularIntChainComplex.X 2 :=
1129  ModuleCat.freeDesc (fun s : SingularTwoSimplex =>
1130    ModuleCat.Hom.hom
1131      (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) 1)
1132
1133open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1134/-- Mathlib's raw `C₂(S¹;ℤ)` chain group maps to the explicit free module on
1135actual singular `2`-simplices by sending each coproduct summand generator to the
1136corresponding free singleton.  This is the `C₂` analog of
1137`singularOneChainToFree` and `singularZeroChainToFree`. -/
1138noncomputable def singularTwoChainToFree :
1139    sphereOneSingularIntChainComplex.X 2 ⟶ singularTwoChainFree :=
1140  Sigma.desc (fun s : SingularTwoSimplex =>
1141    ModuleCat.ofHom
1142      (LinearMap.toSpanSingleton ℤ singularTwoChainFree (ModuleCat.freeMk s)))
1143
1144open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1145/-- The explicit free-module boundary on singular `1`-simplices: each directed
1146edge maps to terminal `0`-face minus initial `0`-face. -/
1147noncomputable def singularOneBoundaryFree :
1148    singularOneChainFree ⟶ singularZeroChainFree :=
1149  ModuleCat.freeDesc (fun s : SingularOneSimplex =>
1150    ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s) -
1151      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s))
1152
1153open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1154/-- The explicit free-module boundary on singular `2`-simplices: the alternating
1155sum of its three singular `1`-faces. -/
1156noncomputable def singularTwoBoundaryFree :
1157    singularTwoChainFree ⟶ singularOneChainFree :=
1158  ModuleCat.freeDesc (fun s : SingularTwoSimplex =>
1159    ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) s) -
1160      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) s) +
1161      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) s))
1162
1163open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1164/-- On a singular generator summand, `singularOneChainToFree` is exactly the
1165corresponding free-module singleton map. -/
1166theorem singularOneChainToFree_ι (s : SingularOneSimplex) :
1167    Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫ singularOneChainToFree =
1168      ModuleCat.ofHom
1169        (LinearMap.toSpanSingleton ℤ singularOneChainFree (ModuleCat.freeMk s)) := by
1170  rw [singularOneChainToFree, Sigma.ι_desc]
1171
1172open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1173/-- On a free generator, `singularOneChainFreeToChain` is the matching singular
1174chain coproduct generator. -/
1175theorem singularOneChainFreeToChain_freeMk (s : SingularOneSimplex) :
1176    ModuleCat.Hom.hom singularOneChainFreeToChain (ModuleCat.freeMk s) =
1177      ModuleCat.Hom.hom
1178        (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) 1 := by
1179  rw [singularOneChainFreeToChain, ModuleCat.freeDesc_apply]
1180
1181open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1182/-- The explicit free boundary sends a free singular `1`-simplex generator to
1183terminal `0`-face minus initial `0`-face. -/
1184theorem singularOneBoundaryFree_freeMk (s : SingularOneSimplex) :
1185    ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk s) =
1186      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s) -
1187        ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s) := by
1188  rw [singularOneBoundaryFree, ModuleCat.freeDesc_apply]
1189
1190open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1191/-- The explicit free boundary sends a free singular `2`-simplex generator to the
1192alternating sum of its three singular `1`-faces. -/
1193theorem singularTwoBoundaryFree_freeMk (s : SingularTwoSimplex) :
1194    ModuleCat.Hom.hom singularTwoBoundaryFree (ModuleCat.freeMk s) =
1195      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) s) -
1196        ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) s) +
1197        ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) s) := by
1198  rw [singularTwoBoundaryFree, ModuleCat.freeDesc_apply]
1199
1200open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1201/-- Cone boundary shell for a singular edge.  If a singular `2`-simplex has base
1202face `δ₂` equal to a singular `1`-simplex `s` and its two side faces agree, then
1203its explicit free boundary is exactly the free generator of `s`.  Geometrically,
1204this is the algebraic content of filling a loop by coning it to a point. -/
1205theorem singularTwoBoundaryFree_freeMk_of_cone_faces
1206    (sigma : SingularTwoSimplex) (s : SingularOneSimplex)
1207    (hbase : (TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) sigma = s)
1208    (hsides :
1209      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) sigma =
1210        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) sigma) :
1211    ModuleCat.Hom.hom singularTwoBoundaryFree (ModuleCat.freeMk sigma) =
1212      ModuleCat.freeMk s := by
1213  rw [singularTwoBoundaryFree_freeMk, hbase, hsides]
1214  abel
1215
1216open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1217/-- The constant actual singular `1`-simplex at a point of `S¹`. -/
1218noncomputable def constantSingularOneSimplex (p : SphereOne) : SingularOneSimplex :=
1219  (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).symm
1220    (ContinuousMap.const (stdSimplex ℝ (Fin 2)) p)
1221
1222open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1223/-- The constant actual singular `2`-simplex at a point of `S¹`. -/
1224noncomputable def constantSingularTwoSimplex (p : SphereOne) : SingularTwoSimplex :=
1225  (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 2))).symm
1226    (ContinuousMap.const (stdSimplex ℝ (Fin 3)) p)
1227
1228open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1229/-- Every face of the constant singular `2`-simplex is the constant singular
1230`1`-simplex at the same point. -/
1231theorem constantSingularTwoSimplex_face (p : SphereOne) (i : Fin 3) :
1232    (TopCat.toSSet.obj (TopCat.sphere 1)).δ i (constantSingularTwoSimplex p) =
1233      constantSingularOneSimplex p := by
1234  apply (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).injective
1235  dsimp [constantSingularTwoSimplex, constantSingularOneSimplex,
1236    TopCat.toSSetObjEquiv, TopCat.toSSet,
1237    CategoryTheory.Presheaf.restrictedULiftYoneda,
1238    CategoryTheory.SimplicialObject.δ,
1239    CategoryTheory.ConcreteCategory.homEquiv,
1240    Homeomorph.continuousMapCongr, face, faceMap]
1241  ext x
1242  rfl
1243
1244open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1245/-- The constant singular `1`-simplex bounds the constant singular `2`-simplex in
1246the explicit free chain complex.  This is the degenerate base case of the
1247null-homotopy prism construction. -/
1248theorem constantSingularOneSimplex_free_boundary (p : SphereOne) :
1249    ModuleCat.Hom.hom singularTwoBoundaryFree
1250      (ModuleCat.freeMk (constantSingularTwoSimplex p)) =
1251        ModuleCat.freeMk (constantSingularOneSimplex p) := by
1252  rw [singularTwoBoundaryFree_freeMk]
1253  rw [constantSingularTwoSimplex_face p 0,
1254    constantSingularTwoSimplex_face p 1,
1255    constantSingularTwoSimplex_face p 2]
1256  abel
1257
1258/-- Terminal vertex of a directed singular edge, matching the positive boundary
1259term. -/
1260def edgeTerminal (e : SingularOneSimplex) : SingularZeroSimplex :=
1261  (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) e
1262
1263/-- Initial vertex of a directed singular edge, matching the negative boundary
1264term. -/
1265def edgeInitial (e : SingularOneSimplex) : SingularZeroSimplex :=
1266  (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) e
1267
1268/-- Incidence coefficient of a directed singular edge at a singular vertex:
1269`+1` at the terminal vertex, `-1` at the initial vertex, and the algebraic sum
1270when both endpoints coincide. -/
1271def incidenceCoeff [DecidableEq SingularZeroSimplex]
1272    (e : SingularOneSimplex) (v : SingularZeroSimplex) : ℤ :=
1273  (if edgeTerminal e = v then 1 else 0) - (if edgeInitial e = v then 1 else 0)
1274
1275/-- Orientation for an occurrence of a singular edge in a directed walk.  Backward
1276orientation represents the negative of the raw singular edge. -/
1277inductive EdgeOrientation where
1278  | forward
1279  | backward
1280  deriving DecidableEq
1281
1282/-- A singular edge together with a traversal orientation. -/
1283structure OrientedSingularEdge where
1284  edge : SingularOneSimplex
1285  orientation : EdgeOrientation
1286
1287/-- Initial vertex of an oriented singular edge occurrence. -/
1288def OrientedSingularEdge.initial (o : OrientedSingularEdge) : SingularZeroSimplex :=
1289  match o.orientation with
1290  | .forward => edgeInitial o.edge
1291  | .backward => edgeTerminal o.edge
1292
1293/-- Terminal vertex of an oriented singular edge occurrence. -/
1294def OrientedSingularEdge.terminal (o : OrientedSingularEdge) : SingularZeroSimplex :=
1295  match o.orientation with
1296  | .forward => edgeTerminal o.edge
1297  | .backward => edgeInitial o.edge
1298
1299/-- Free edge-chain contribution of one oriented singular edge occurrence. -/
1300noncomputable def OrientedSingularEdge.chain (o : OrientedSingularEdge) :
1301    singularOneChainFree :=
1302  match o.orientation with
1303  | .forward => ModuleCat.freeMk o.edge
1304  | .backward => - ModuleCat.freeMk o.edge
1305
1306/-- Coefficient of an edge in the explicit free `C₁` module. -/
1307def edgeCoeff (c : singularOneChainFree) (e : SingularOneSimplex) : ℤ :=
1308  c.toFun e
1309
1310/-- Coefficient of a vertex in the explicit free `C₀` module. -/
1311def vertexCoeff (z : singularZeroChainFree) (v : SingularZeroSimplex) : ℤ :=
1312  z.toFun v
1313
1314/-- Boundary coefficient at a vertex for a free edge-chain. -/
1315def vertexBoundaryCoeff (c : singularOneChainFree) (v : SingularZeroSimplex) : ℤ :=
1316  vertexCoeff (ModuleCat.Hom.hom singularOneBoundaryFree c) v
1317
1318/-- Support of a free edge-chain. -/
1319def edgeSupport (c : singularOneChainFree) : Finset SingularOneSimplex :=
1320  c.support
1321
1322/-- Cardinality of the support of a free edge-chain. -/
1323def edgeSupportCard (c : singularOneChainFree) : ℕ :=
1324  c.support.card
1325
1326/-- A free edge-chain has empty support exactly when it is zero. -/
1327theorem edgeSupport_eq_empty_iff (c : singularOneChainFree) :
1328    edgeSupport c = ∅ ↔ c = 0 := by
1329  unfold edgeSupport
1330  exact Finsupp.support_eq_empty
1331
1332/-- A free edge-chain has support-cardinality zero exactly when it is zero. -/
1333theorem edgeSupportCard_eq_zero_iff (c : singularOneChainFree) :
1334    edgeSupportCard c = 0 ↔ c = 0 := by
1335  unfold edgeSupportCard
1336  rw [Finset.card_eq_zero]
1337  exact Finsupp.support_eq_empty
1338
1339/-- Edge membership in support is nonzero coefficient. -/
1340theorem mem_edgeSupport_iff (c : singularOneChainFree) (e : SingularOneSimplex) :
1341    e ∈ edgeSupport c ↔ edgeCoeff c e ≠ 0 := by
1342  unfold edgeSupport edgeCoeff
1343  exact Finsupp.mem_support_iff
1344
1345/-- The free generator has coefficient `1` on itself. -/
1346theorem edgeCoeff_freeMk_self (e : SingularOneSimplex) :
1347    edgeCoeff (ModuleCat.freeMk e) e = 1 := by
1348  unfold edgeCoeff ModuleCat.freeMk
1349  exact Finsupp.single_eq_same
1350
1351open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1352/-- A free edge-chain with singleton support is its coefficient times that single
1353free generator. -/
1354theorem eq_zsmul_freeMk_of_edgeSupport_eq_single [DecidableEq SingularOneSimplex]
1355    (c : singularOneChainFree) (e : SingularOneSimplex)
1356    (hsupp : edgeSupport c = {e}) :
1357    c = edgeCoeff c e • ModuleCat.freeMk e := by
1358  apply Finsupp.ext
1359  intro x
1360  by_cases hx : x = e
1361  · subst x
1362    rw [ModuleCat.freeMk]
1363    change c.toFun e = c.toFun e * (Finsupp.single e (1 : ℤ) e)
1364    rw [Finsupp.single_eq_same]
1365    ring
1366  · have hx_not_mem : x ∉ edgeSupport c := by
1367      rw [hsupp]
1368      simp [hx]
1369    have hcx : edgeCoeff c x = 0 :=
1370      Classical.not_not.mp (mt (mem_edgeSupport_iff c x).mpr hx_not_mem)
1371    unfold edgeCoeff at hcx
1372    change c.toFun x = (edgeCoeff c e • ModuleCat.freeMk e).toFun x
1373    rw [hcx]
1374    rw [ModuleCat.freeMk]
1375    change 0 = edgeCoeff c e * (Finsupp.single e (1 : ℤ) x)
1376    have hsingle : (Finsupp.single e (1 : ℤ) : SingularOneSimplex →₀ ℤ) x = 0 :=
1377      Finsupp.single_eq_of_ne hx
1378    rw [hsingle]
1379    ring
1380
1381/-- If a finite integer sum is zero and one summand is positive, then some
1382summand is negative.  This is the finite algebra step behind the balanced-flow
1383"next edge" argument. -/
1384theorem exists_negative_of_sum_zero_of_positive
1385    {α : Type} [DecidableEq α] (s : Finset α) (f : α → ℤ)
1386    {a : α} (ha : a ∈ s) (hpos : 0 < f a)
1387    (hsum : ∑ x ∈ s, f x = 0) :
1388    ∃ b ∈ s, f b < 0 := by
1389  by_contra hnone
1390  push_neg at hnone
1391  have hnonneg : ∀ x ∈ s, 0 ≤ f x := by
1392    intro x hx
1393    exact hnone x hx
1394  have hle : f a ≤ ∑ x ∈ s, f x := by
1395    exact Finset.single_le_sum (fun x hx => hnonneg x hx) ha
1396  have hsum_pos : 0 < ∑ x ∈ s, f x := lt_of_lt_of_le hpos hle
1397  omega
1398
1399/-- Choose the traversal orientation suggested by an integer coefficient:
1400positive coefficients are followed forward, negative coefficients backward. -/
1401def orientationOfCoeff (n : ℤ) : EdgeOrientation :=
1402  if 0 < n then .forward else .backward
1403
1404/-- A supported edge of a flow, oriented according to the sign of its coefficient. -/
1405def orientedEdgeOfCoeff (c : singularOneChainFree) (e : SingularOneSimplex) :
1406    OrientedSingularEdge where
1407  edge := e
1408  orientation := orientationOfCoeff (edgeCoeff c e)
1409
1410/-- The signed coefficient of the edge in the chosen orientation. -/
1411def orientedCoeff (c : singularOneChainFree) (e : SingularOneSimplex) : ℤ :=
1412  match orientationOfCoeff (edgeCoeff c e) with
1413  | .forward => edgeCoeff c e
1414  | .backward => -edgeCoeff c e
1415
1416/-- A supported edge has positive coefficient when read in its sign-selected
1417orientation. -/
1418theorem orientedCoeff_pos_of_mem_edgeSupport
1419    (c : singularOneChainFree) {e : SingularOneSimplex} (he : e ∈ edgeSupport c) :
1420    0 < orientedCoeff c e := by
1421  have hne : edgeCoeff c e ≠ 0 := (mem_edgeSupport_iff c e).mp he
1422  unfold orientedCoeff orientationOfCoeff
1423  by_cases hp : 0 < edgeCoeff c e
1424  · simp [hp]
1425  · simp [hp]
1426    have hneg : edgeCoeff c e < 0 := by omega
1427    omega
1428
1429/-- Boundary coefficient of a single directed edge at a vertex.  It is `+1` at
1430the terminal endpoint, `-1` at the initial endpoint, and the algebraic sum if the
1431two endpoints coincide. -/
1432theorem vertexBoundaryCoeff_freeMk [DecidableEq SingularZeroSimplex]
1433    (e : SingularOneSimplex) (v : SingularZeroSimplex) :
1434    vertexBoundaryCoeff (ModuleCat.freeMk e) v =
1435      incidenceCoeff e v := by
1436  unfold vertexBoundaryCoeff vertexCoeff
1437  rw [singularOneBoundaryFree_freeMk]
1438  unfold incidenceCoeff edgeTerminal edgeInitial
1439  change ((ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) e) -
1440      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) e) :
1441        SingularZeroSimplex →₀ ℤ) v) = _
1442  rw [Finsupp.sub_apply]
1443  by_cases ht : (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) e = v
1444  · by_cases hi : (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) e = v
1445    · simp [ModuleCat.freeMk, ht, hi]
1446    · simp [ModuleCat.freeMk, ht, hi]
1447  · by_cases hi : (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) e = v
1448    · simp [ModuleCat.freeMk, ht, hi]
1449    · simp [ModuleCat.freeMk, ht, hi]
1450
1451/-- The incidence-sum expression for the boundary coefficient of a finite free
1452edge-chain.  Proving `vertexBoundaryCoeff_eq_incidenceSum` below is the local
1453finite-support algebra needed for the support-decreasing graph proof. -/
1454def boundaryIncidenceSum [DecidableEq SingularZeroSimplex]
1455    (c : singularOneChainFree) (v : SingularZeroSimplex) : ℤ :=
1456  c.sum (fun e n => n * incidenceCoeff e v)
1457
1458/-- Contribution of one raw edge coefficient to the boundary coefficient at a
1459vertex. -/
1460def edgeContribution [DecidableEq SingularZeroSimplex]
1461    (c : singularOneChainFree) (e : SingularOneSimplex) (v : SingularZeroSimplex) : ℤ :=
1462  edgeCoeff c e * incidenceCoeff e v
1463
1464/-- A supported non-loop edge, read in its sign-selected orientation, contributes
1465positively to the boundary coefficient at its terminal vertex.  This is the local
1466positivity fact used to force a compensating outgoing edge in a balanced flow. -/
1467theorem edgeContribution_pos_at_oriented_terminal
1468    [DecidableEq SingularZeroSimplex]
1469    (c : singularOneChainFree) {e : SingularOneSimplex}
1470    (he : e ∈ edgeSupport c)
1471    (hnotloop : (orientedEdgeOfCoeff c e).initial ≠ (orientedEdgeOfCoeff c e).terminal) :
1472    0 < edgeContribution c e (orientedEdgeOfCoeff c e).terminal := by
1473  have hne : edgeCoeff c e ≠ 0 := (mem_edgeSupport_iff c e).mp he
1474  by_cases hp : 0 < edgeCoeff c e
1475  · have hinit_ne : edgeInitial e ≠ edgeTerminal e := by
1476      simpa [orientedEdgeOfCoeff, OrientedSingularEdge.initial, OrientedSingularEdge.terminal,
1477        orientationOfCoeff, hp] using hnotloop
1478    simp [edgeContribution, incidenceCoeff, orientedEdgeOfCoeff,
1479      OrientedSingularEdge.terminal, orientationOfCoeff, hp, hinit_ne]
1480  · have hneg : edgeCoeff c e < 0 := by omega
1481    have hterm_ne : edgeTerminal e ≠ edgeInitial e := by
1482      simpa [orientedEdgeOfCoeff, OrientedSingularEdge.initial, OrientedSingularEdge.terminal,
1483        orientationOfCoeff, hp] using hnotloop
1484    simp [edgeContribution, incidenceCoeff, orientedEdgeOfCoeff,
1485      OrientedSingularEdge.terminal, orientationOfCoeff, hp, hterm_ne]
1486    omega
1487
1488/-- Incidence sum of a singleton edge coefficient. -/
1489theorem boundaryIncidenceSum_single [DecidableEq SingularZeroSimplex]
1490    (e : SingularOneSimplex) (n : ℤ) (v : SingularZeroSimplex) :
1491    boundaryIncidenceSum (Finsupp.single e n : singularOneChainFree) v =
1492      n * incidenceCoeff e v := by
1493  unfold boundaryIncidenceSum
1494  rw [Finsupp.sum_single_index]
1495  · ring_nf
1496
1497/-- Incidence sum is additive in the edge-flow. -/
1498theorem boundaryIncidenceSum_add [DecidableEq SingularZeroSimplex]
1499    (f g : singularOneChainFree) (v : SingularZeroSimplex) :
1500    boundaryIncidenceSum (f + g) v =
1501      boundaryIncidenceSum f v + boundaryIncidenceSum g v := by
1502  unfold boundaryIncidenceSum
1503  rw [Finsupp.sum_add_index']
1504  · intro e
1505    ring_nf
1506  · intro e a b
1507    ring
1508
1509/-- Incidence sum of the zero edge-flow. -/
1510theorem boundaryIncidenceSum_zero [DecidableEq SingularZeroSimplex]
1511    (v : SingularZeroSimplex) :
1512    boundaryIncidenceSum (0 : singularOneChainFree) v = 0 := by
1513  unfold boundaryIncidenceSum
1514  simp
1515
1516/-- The incidence sum is the explicit finite sum over the edge support. -/
1517theorem boundaryIncidenceSum_eq_support_sum
1518    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
1519    (c : singularOneChainFree) (v : SingularZeroSimplex) :
1520    boundaryIncidenceSum c v =
1521      ∑ e ∈ edgeSupport c, edgeContribution c e v := by
1522  unfold boundaryIncidenceSum edgeContribution edgeSupport edgeCoeff
1523  rw [Finsupp.sum]
1524  rfl
1525
1526/-- Target local balance formula: the boundary coefficient of any finite edge
1527flow is the finite sum of its edge coefficients times incidence signs. -/
1528def vertexBoundaryCoeff_eq_incidenceSum : Prop :=
1529  ∀ [DecidableEq SingularZeroSimplex] (c : singularOneChainFree) (v : SingularZeroSimplex),
1530    vertexBoundaryCoeff c v = boundaryIncidenceSum c v
1531
1532/-- Boundary coefficient of any finite free edge-flow is the finite incidence sum
1533over its support. -/
1534theorem vertexBoundaryCoeff_eq_incidenceSum_holds :
1535    vertexBoundaryCoeff_eq_incidenceSum := by
1536  intro _ c v
1537  induction c using Finsupp.induction_linear with
1538  | zero =>
1539      rw [boundaryIncidenceSum_zero]
1540      unfold vertexBoundaryCoeff vertexCoeff
1541      change (0 : singularZeroChainFree).toFun v = 0
1542      rfl
1543  | add f g hf hg =>
1544      rw [boundaryIncidenceSum_add]
1545      have hadd : vertexBoundaryCoeff (f + g) v =
1546          vertexBoundaryCoeff f v + vertexBoundaryCoeff g v := by
1547        unfold vertexBoundaryCoeff vertexCoeff
1548        rw [map_add]
1549        rfl
1550      rw [hadd, hf, hg]
1551  | single e n =>
1552      rw [boundaryIncidenceSum_single]
1553      have hsingle : (Finsupp.single e n : singularOneChainFree) =
1554          n • ModuleCat.freeMk e := by
1555        rw [ModuleCat.freeMk]
1556        rw [Finsupp.smul_single]
1557        simp
1558      rw [hsingle]
1559      unfold vertexBoundaryCoeff vertexCoeff
1560      rw [map_zsmul]
1561      change (n • (ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk e) :
1562          singularZeroChainFree)).toFun v =
1563        n * incidenceCoeff e v
1564      change n * ((ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk e) :
1565          singularZeroChainFree).toFun v) =
1566        n * incidenceCoeff e v
1567      rw [show (ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk e) :
1568            singularZeroChainFree).toFun v =
1569          vertexBoundaryCoeff (ModuleCat.freeMk e) v by rfl]
1570      rw [vertexBoundaryCoeff_freeMk]
1571
1572/-- If the incidence-sum formula is proved, every free-boundary-zero flow has zero
1573incidence sum at each vertex. -/
1574theorem boundaryIncidenceSum_eq_zero_of_boundary_zero
1575    (hformula : vertexBoundaryCoeff_eq_incidenceSum)
1576    [DecidableEq SingularZeroSimplex]
1577    {c : singularOneChainFree}
1578    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
1579    (v : SingularZeroSimplex) :
1580    boundaryIncidenceSum c v = 0 := by
1581  rw [← hformula c v]
1582  unfold vertexBoundaryCoeff vertexCoeff
1583  rw [hzero]
1584  rfl
1585
1586/-- Every free-boundary-zero flow has zero incidence sum at each vertex. -/
1587theorem boundaryIncidenceSum_eq_zero_of_boundary_zero'
1588    [DecidableEq SingularZeroSimplex]
1589    {c : singularOneChainFree}
1590    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
1591    (v : SingularZeroSimplex) :
1592    boundaryIncidenceSum c v = 0 :=
1593  boundaryIncidenceSum_eq_zero_of_boundary_zero
1594    vertexBoundaryCoeff_eq_incidenceSum_holds hzero v
1595
1596/-- In a balanced flow, a positive contribution at a vertex forces some negative
1597contribution at the same vertex.  Applied to a sign-selected supported edge, this
1598is the algebraic core of the next-edge existence step. -/
1599theorem exists_negative_edgeContribution_at_oriented_terminal
1600    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
1601    {c : singularOneChainFree}
1602    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
1603    {e : SingularOneSimplex}
1604    (he : e ∈ edgeSupport c)
1605    (hnotloop : (orientedEdgeOfCoeff c e).initial ≠ (orientedEdgeOfCoeff c e).terminal) :
1606    ∃ e' ∈ edgeSupport c,
1607      edgeContribution c e' (orientedEdgeOfCoeff c e).terminal < 0 := by
1608  let v := (orientedEdgeOfCoeff c e).terminal
1609  have hsum0 : boundaryIncidenceSum c v = 0 :=
1610    boundaryIncidenceSum_eq_zero_of_boundary_zero' hzero v
1611  have hsupport :
1612      boundaryIncidenceSum c v =
1613        ∑ x ∈ edgeSupport c, edgeContribution c x v :=
1614    boundaryIncidenceSum_eq_support_sum c v
1615  have hsum : ∑ x ∈ edgeSupport c, edgeContribution c x v = 0 := by
1616    rw [← hsupport, hsum0]
1617  have hpos : 0 < edgeContribution c e v :=
1618    edgeContribution_pos_at_oriented_terminal c he hnotloop
1619  exact exists_negative_of_sum_zero_of_positive
1620    (edgeSupport c) (fun x => edgeContribution c x v) he hpos hsum
1621
1622/-- If an edge contributes negatively to the boundary coefficient at a vertex,
1623then the sign-selected orientation of that edge starts at that vertex. -/
1624theorem initial_eq_of_negative_edgeContribution
1625    [DecidableEq SingularZeroSimplex]
1626    (c : singularOneChainFree) (e : SingularOneSimplex) (v : SingularZeroSimplex)
1627    (hneg : edgeContribution c e v < 0) :
1628    (orientedEdgeOfCoeff c e).initial = v := by
1629  unfold edgeContribution incidenceCoeff at hneg
1630  unfold orientedEdgeOfCoeff OrientedSingularEdge.initial orientationOfCoeff
1631  by_cases hp : 0 < edgeCoeff c e
1632  · simp [hp]
1633    by_cases hi : edgeInitial e = v
1634    · exact hi
1635    · by_cases ht : edgeTerminal e = v
1636      · simp [ht, hi] at hneg
1637        omega
1638      · simp [ht, hi] at hneg
1639  · simp [hp]
1640    by_cases hz : edgeCoeff c e = 0
1641    · simp [hz] at hneg
1642    · have hnegcoeff : edgeCoeff c e < 0 := by omega
1643      by_cases ht : edgeTerminal e = v
1644      · exact ht
1645      · by_cases hi : edgeInitial e = v
1646        · simp [ht, hi] at hneg
1647          omega
1648        · simp [ht, hi] at hneg
1649
1650/-- Local successor-edge theorem: in a balanced flow, a supported non-loop
1651oriented edge has a supported edge whose sign-selected orientation starts at its
1652terminal vertex. -/
1653theorem exists_next_orientedEdge_from_terminal
1654    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
1655    {c : singularOneChainFree}
1656    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
1657    {e : SingularOneSimplex}
1658    (he : e ∈ edgeSupport c)
1659    (hnotloop : (orientedEdgeOfCoeff c e).initial ≠ (orientedEdgeOfCoeff c e).terminal) :
1660    ∃ e' ∈ edgeSupport c,
1661      (orientedEdgeOfCoeff c e').initial = (orientedEdgeOfCoeff c e).terminal := by
1662  obtain ⟨e', he', hneg⟩ :=
1663    exists_negative_edgeContribution_at_oriented_terminal hzero he hnotloop
1664  exact ⟨e', he', initial_eq_of_negative_edgeContribution
1665    c e' (orientedEdgeOfCoeff c e).terminal hneg⟩
1666
1667/-- Boundary of one oriented singular edge occurrence: terminal vertex minus
1668initial vertex. -/
1669theorem OrientedSingularEdge.boundary_free (o : OrientedSingularEdge) :
1670    ModuleCat.Hom.hom singularOneBoundaryFree o.chain =
1671      ModuleCat.freeMk o.terminal - ModuleCat.freeMk o.initial := by
1672  cases o with
1673  | mk e ori =>
1674    cases ori
1675    · unfold OrientedSingularEdge.chain OrientedSingularEdge.terminal
1676        OrientedSingularEdge.initial
1677      rw [singularOneBoundaryFree_freeMk]
1678      rfl
1679    · unfold OrientedSingularEdge.chain OrientedSingularEdge.terminal
1680        OrientedSingularEdge.initial
1681      rw [map_neg, singularOneBoundaryFree_freeMk]
1682      unfold edgeInitial edgeTerminal
1683      abel_nf
1684
1685/-- Boundary coefficient of one oriented edge occurrence at a vertex. -/
1686theorem OrientedSingularEdge.vertexBoundaryCoeff_chain [DecidableEq SingularZeroSimplex]
1687    (o : OrientedSingularEdge) (v : SingularZeroSimplex) :
1688    vertexCoeff (ModuleCat.Hom.hom singularOneBoundaryFree o.chain) v =
1689      (if o.terminal = v then 1 else 0) - (if o.initial = v then 1 else 0) := by
1690  rw [o.boundary_free]
1691  unfold vertexCoeff
1692  change ((ModuleCat.freeMk o.terminal - ModuleCat.freeMk o.initial :
1693        SingularZeroSimplex →₀ ℤ) v) = _
1694  rw [Finsupp.sub_apply]
1695  by_cases ht : o.terminal = v
1696  · by_cases hi : o.initial = v <;> simp [ModuleCat.freeMk, ht, hi]
1697  · by_cases hi : o.initial = v <;> simp [ModuleCat.freeMk, ht, hi]
1698
1699open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1700/-- `C₁(S¹;ℤ)` is the explicit free ℤ-module on actual singular `1`-simplices.
1701This exposes the finite-support normal form needed for the remaining raw-chain
1702cancellation theorem. -/
1703noncomputable def singularOneChainFreeIso :
1704    sphereOneSingularIntChainComplex.X 1 ≅ singularOneChainFree where
1705  hom := singularOneChainToFree
1706  inv := singularOneChainFreeToChain
1707  hom_inv_id := by
1708    apply Sigma.hom_ext
1709    intro s
1710    apply ModuleCat.hom_ext
1711    apply DFunLike.ext
1712    intro n
1713    change ModuleCat.Hom.hom
1714        ((Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫ singularOneChainToFree) ≫
1715          singularOneChainFreeToChain) n =
1716      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) n
1717    rw [singularOneChainToFree, Sigma.ι_desc]
1718    change ModuleCat.Hom.hom
1719        (ModuleCat.ofHom
1720            (LinearMap.toSpanSingleton ℤ singularOneChainFree (ModuleCat.freeMk s)) ≫
1721          singularOneChainFreeToChain) n =
1722      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) n
1723    simp only [ModuleCat.hom_comp, ModuleCat.hom_ofHom, LinearMap.coe_comp,
1724      Function.comp_apply, LinearMap.toSpanSingleton_apply]
1725    rw [map_zsmul]
1726    rw [singularOneChainFreeToChain, ModuleCat.freeDesc_apply]
1727    change n •
1728        (ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) 1) =
1729      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) n
1730    rw [← map_zsmul]
1731    simp
1732  inv_hom_id := by
1733    apply ModuleCat.free_hom_ext
1734    intro s
1735    change ModuleCat.Hom.hom (singularOneChainFreeToChain ≫ singularOneChainToFree)
1736        (ModuleCat.freeMk s) =
1737      ModuleCat.Hom.hom (𝟙 singularOneChainFree) (ModuleCat.freeMk s)
1738    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp, Function.comp_apply]
1739    rw [singularOneChainFreeToChain, ModuleCat.freeDesc_apply]
1740    change ModuleCat.Hom.hom singularOneChainToFree
1741        (ModuleCat.Hom.hom
1742          (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) 1) =
1743      ModuleCat.freeMk s
1744    change ModuleCat.Hom.hom
1745        (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫ singularOneChainToFree) 1 =
1746      ModuleCat.freeMk s
1747    rw [singularOneChainToFree, Sigma.ι_desc]
1748    simp [LinearMap.toSpanSingleton_apply]
1749
1750open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1751/-- `C₂(S¹;ℤ)` is the explicit free ℤ-module on actual singular `2`-simplices.
1752This is the degree-`2` analog of `singularOneChainFreeIso`; it removes the
1753purely representational gap between raw singular `2`-chains and free-coordinate
1754`2`-chains. -/
1755noncomputable def singularTwoChainFreeIso :
1756    sphereOneSingularIntChainComplex.X 2 ≅ singularTwoChainFree where
1757  hom := singularTwoChainToFree
1758  inv := singularTwoChainFreeToChain
1759  hom_inv_id := by
1760    apply Sigma.hom_ext
1761    intro s
1762    apply ModuleCat.hom_ext
1763    apply DFunLike.ext
1764    intro n
1765    change ModuleCat.Hom.hom
1766        ((Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s ≫ singularTwoChainToFree) ≫
1767          singularTwoChainFreeToChain) n =
1768      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) n
1769    rw [singularTwoChainToFree, Sigma.ι_desc]
1770    change ModuleCat.Hom.hom
1771        (ModuleCat.ofHom
1772            (LinearMap.toSpanSingleton ℤ singularTwoChainFree (ModuleCat.freeMk s)) ≫
1773          singularTwoChainFreeToChain) n =
1774      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) n
1775    simp only [ModuleCat.hom_comp, ModuleCat.hom_ofHom, LinearMap.coe_comp,
1776      Function.comp_apply, LinearMap.toSpanSingleton_apply]
1777    rw [map_zsmul]
1778    rw [singularTwoChainFreeToChain, ModuleCat.freeDesc_apply]
1779    change n •
1780        (ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) 1) =
1781      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) n
1782    rw [← map_zsmul]
1783    simp
1784  inv_hom_id := by
1785    apply ModuleCat.free_hom_ext
1786    intro s
1787    change ModuleCat.Hom.hom (singularTwoChainFreeToChain ≫ singularTwoChainToFree)
1788        (ModuleCat.freeMk s) =
1789      ModuleCat.Hom.hom (𝟙 singularTwoChainFree) (ModuleCat.freeMk s)
1790    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp, Function.comp_apply]
1791    rw [singularTwoChainFreeToChain, ModuleCat.freeDesc_apply]
1792    change ModuleCat.Hom.hom singularTwoChainToFree
1793        (ModuleCat.Hom.hom
1794          (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) 1) =
1795      ModuleCat.freeMk s
1796    change ModuleCat.Hom.hom
1797        (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s ≫ singularTwoChainToFree) 1 =
1798      ModuleCat.freeMk s
1799    rw [singularTwoChainToFree, Sigma.ι_desc]
1800    simp [LinearMap.toSpanSingleton_apply]
1801
1802open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1803/-- The explicit free module on singular `0`-simplices maps back to `C₀(S¹;ℤ)` by
1804sending each free generator to the matching coproduct summand generator.  This is
1805the `C₀` analog of `singularOneChainFreeToChain`. -/
1806noncomputable def singularZeroChainFreeToChain :
1807    singularZeroChainFree ⟶ sphereOneSingularIntChainComplex.X 0 :=
1808  ModuleCat.freeDesc (fun s : SingularZeroSimplex =>
1809    ModuleCat.Hom.hom
1810      (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s) 1)
1811
1812open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1813/-- `C₀(S¹;ℤ)` is the explicit free ℤ-module on actual singular `0`-simplices.
1814This is the `C₀` analog of `singularOneChainFreeIso`; in particular
1815`singularZeroChainToFree` is an isomorphism, hence injective, which is what lets a
1816boundary computed in the explicit free `C₀` module be transported back to the raw
1817chain group. -/
1818noncomputable def singularZeroChainFreeIso :
1819    sphereOneSingularIntChainComplex.X 0 ≅ singularZeroChainFree where
1820  hom := singularZeroChainToFree
1821  inv := singularZeroChainFreeToChain
1822  hom_inv_id := by
1823    apply Sigma.hom_ext
1824    intro s
1825    apply ModuleCat.hom_ext
1826    apply DFunLike.ext
1827    intro n
1828    change ModuleCat.Hom.hom
1829        ((Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s ≫ singularZeroChainToFree) ≫
1830          singularZeroChainFreeToChain) n =
1831      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s) n
1832    rw [singularZeroChainToFree, Sigma.ι_desc]
1833    change ModuleCat.Hom.hom
1834        (ModuleCat.ofHom
1835            (LinearMap.toSpanSingleton ℤ singularZeroChainFree (ModuleCat.freeMk s)) ≫
1836          singularZeroChainFreeToChain) n =
1837      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s) n
1838    simp only [ModuleCat.hom_comp, ModuleCat.hom_ofHom, LinearMap.coe_comp,
1839      Function.comp_apply, LinearMap.toSpanSingleton_apply]
1840    rw [map_zsmul]
1841    rw [singularZeroChainFreeToChain, ModuleCat.freeDesc_apply]
1842    change n •
1843        (ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s) 1) =
1844      ModuleCat.Hom.hom (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s) n
1845    rw [← map_zsmul]
1846    simp
1847  inv_hom_id := by
1848    apply ModuleCat.free_hom_ext
1849    intro s
1850    change ModuleCat.Hom.hom (singularZeroChainFreeToChain ≫ singularZeroChainToFree)
1851        (ModuleCat.freeMk s) =
1852      ModuleCat.Hom.hom (𝟙 singularZeroChainFree) (ModuleCat.freeMk s)
1853    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp, Function.comp_apply]
1854    rw [singularZeroChainFreeToChain, ModuleCat.freeDesc_apply]
1855    change ModuleCat.Hom.hom singularZeroChainToFree
1856        (ModuleCat.Hom.hom
1857          (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s) 1) =
1858      ModuleCat.freeMk s
1859    change ModuleCat.Hom.hom
1860        (Sigma.ι (fun _ : SingularZeroSimplex => ModuleCat.of ℤ ℤ) s ≫ singularZeroChainToFree) 1 =
1861      ModuleCat.freeMk s
1862    rw [singularZeroChainToFree, Sigma.ι_desc]
1863    simp [LinearMap.toSpanSingleton_apply]
1864
1865open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1866/-- `singularZeroChainToFree` is injective: it is the forward map of an
1867isomorphism. -/
1868theorem singularZeroChainToFree_injective :
1869    Function.Injective (ModuleCat.Hom.hom singularZeroChainToFree) := by
1870  haveI : IsIso singularZeroChainToFree := by
1871    change IsIso singularZeroChainFreeIso.hom
1872    infer_instance
1873  exact (ModuleCat.mono_iff_injective singularZeroChainToFree).mp inferInstance
1874
1875/-- **The combinatorial face map agrees with the geometric one.**  The `i`-th
1876simplicial face of a singular `2`-simplex `σ`, transported through
1877`TopCat.toSSetObjEquiv`, is the geometric face `face` of the corresponding
1878continuous map.  This is the bridge identifying the chain-complex boundary with
1879the affine edge maps used in the telescoping. -/
1880theorem toSSetObjEquiv_delta (s : SingularTwoSimplex) (i : Fin 3) :
1881    TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))
1882        ((TopCat.toSSet.obj (TopCat.sphere 1)).δ i s)
1883      = face (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 2)) s) i := by
1884  ext x
1885  dsimp [TopCat.toSSetObjEquiv, TopCat.toSSet,
1886    CategoryTheory.Presheaf.restrictedULiftYoneda,
1887    CategoryTheory.SimplicialObject.δ,
1888    CategoryTheory.ConcreteCategory.homEquiv,
1889    Homeomorph.continuousMapCongr, face, faceMap]
1890  rfl
1891
1892open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1893/-- Turn a concrete continuous `1`-simplex `C(Δ¹,S¹)` into the corresponding
1894actual singular simplex in Mathlib's simplicial set. -/
1895noncomputable def singularOneSimplexOfMap (f : OneSimplex) : SingularOneSimplex :=
1896  (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).symm f
1897
1898open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1899/-- Turn a concrete continuous `2`-simplex `C(Δ²,S¹)` into the corresponding
1900actual singular simplex in Mathlib's simplicial set. -/
1901noncomputable def singularTwoSimplexOfMap (F : TwoSimplex) : SingularTwoSimplex :=
1902  (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 2))).symm F
1903
1904open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1905/-- Transport a concrete face equation through `TopCat.toSSetObjEquiv`: the
1906simplicial `δᵢ` face of the singular simplex associated to `F : C(Δ²,S¹)` is
1907the singular simplex associated to the concrete face map `face F i`. -/
1908theorem singularTwoSimplexOfMap_delta (F : TwoSimplex) (i : Fin 3) :
1909    (TopCat.toSSet.obj (TopCat.sphere 1)).δ i (singularTwoSimplexOfMap F) =
1910      singularOneSimplexOfMap (face F i) := by
1911  apply (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).injective
1912  rw [toSSetObjEquiv_delta]
1913  unfold singularOneSimplexOfMap singularTwoSimplexOfMap
1914  rw [Equiv.apply_symm_apply, Equiv.apply_symm_apply]
1915
1916theorem stdSimplexHomeomorphUnitInterval_coe (x : stdSimplex ℝ (Fin 2)) :
1917    ((stdSimplexHomeomorphUnitInterval x : I) : ℝ) = x 1 := by
1918  have h := intervalToSimplex_coord_one (stdSimplexHomeomorphUnitInterval x)
1919  unfold intervalToSimplex at h
1920  simp at h
1921  exact h.symm
1922
1923/-- The second barycentric coordinate of a `2`-simplex, read as a unit-interval
1924parameter. -/
1925noncomputable def twoSimplexCoordOneParam (x : stdSimplex ℝ (Fin 3)) : I :=
1926  ⟨x 1, mem_Icc_of_mem_stdSimplex x.2 1⟩
1927
1928theorem continuous_twoSimplexCoordOneParam :
1929    Continuous twoSimplexCoordOneParam := by
1930  rw [continuous_iff_continuousAt]
1931  intro x
1932  rw [ContinuousAt, tendsto_subtype_rng]
1933  exact ((continuous_apply 1).comp continuous_subtype_val).continuousAt
1934
1935theorem twoSimplexCoordOneParam_face_two (x : stdSimplex ℝ (Fin 2)) :
1936    twoSimplexCoordOneParam (faceMap (2 : Fin 3) x) =
1937      stdSimplexHomeomorphUnitInterval x := by
1938  ext
1939  change ((faceMap (2 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 1 =
1940    ((stdSimplexHomeomorphUnitInterval x : I) : ℝ)
1941  rw [faceMap_two_coord_one, stdSimplexHomeomorphUnitInterval_coe]
1942
1943theorem twoSimplexCoordOneParam_face_one (x : stdSimplex ℝ (Fin 2)) :
1944    twoSimplexCoordOneParam (faceMap (1 : Fin 3) x) = 0 := by
1945  ext
1946  change ((faceMap (1 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 1 = (0 : ℝ)
1947  exact faceMap_one_coord_one x
1948
1949theorem twoSimplexCoordOneParam_face_zero (x : stdSimplex ℝ (Fin 2)) :
1950    twoSimplexCoordOneParam (faceMap (0 : Fin 3) x) =
1951      unitInterval.symm (stdSimplexHomeomorphUnitInterval x) := by
1952  ext
1953  change ((faceMap (0 : Fin 3) x : stdSimplex ℝ (Fin 3)) : Fin 3 → ℝ) 1 =
1954    1 - ((stdSimplexHomeomorphUnitInterval x : I) : ℝ)
1955  rw [stdSimplexHomeomorphUnitInterval_coe, faceMap_zero_coord_one]
1956  have hsum : x 0 + x 1 = (1 : ℝ) := by
1957    have hs := stdSimplex.sum_eq_one x
1958    rw [Fin.sum_univ_two] at hs
1959    exact hs
1960  linarith
1961
1962/-- The triangular backtrack prism over a path `γ`.  It maps `x ∈ Δ²` to
1963`γ(x₁)`, so its three faces are the reversed path, the constant initial edge,
1964and the original path. -/
1965noncomputable def pathBacktrackMap (γ : C(I, SphereOne)) : TwoSimplex where
1966  toFun x := γ (twoSimplexCoordOneParam x)
1967  continuous_toFun := γ.continuous.comp continuous_twoSimplexCoordOneParam
1968
1969theorem pathBacktrackMap_face_zero (γ : C(I, SphereOne)) :
1970    face (pathBacktrackMap γ) (0 : Fin 3) =
1971      oneSimplexOfPath (CircleWinding.reversePath γ) := by
1972  ext x
1973  exact congrArg γ (twoSimplexCoordOneParam_face_zero x)
1974
1975theorem pathBacktrackMap_face_one (γ : C(I, SphereOne)) :
1976    face (pathBacktrackMap γ) (1 : Fin 3) = constantOneSimplex (γ 0) := by
1977  ext x
1978  exact congrArg γ (twoSimplexCoordOneParam_face_one x)
1979
1980theorem pathBacktrackMap_face_two (γ : C(I, SphereOne)) :
1981    face (pathBacktrackMap γ) (2 : Fin 3) = oneSimplexOfPath γ := by
1982  ext x
1983  exact congrArg γ (twoSimplexCoordOneParam_face_two x)
1984
1985open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1986/-- The singular `2`-simplex associated to the triangular backtrack prism over
1987a path. -/
1988noncomputable def pathBacktrackSingularTwoSimplex
1989    (γ : C(I, SphereOne)) : SingularTwoSimplex :=
1990  singularTwoSimplexOfMap (pathBacktrackMap γ)
1991
1992open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
1993theorem singularOneSimplexOfMap_constantOneSimplex (p : SphereOne) :
1994    singularOneSimplexOfMap (constantOneSimplex p) = constantSingularOneSimplex p := by
1995  apply (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).injective
1996  unfold singularOneSimplexOfMap constantOneSimplex constantSingularOneSimplex
1997  rw [Equiv.apply_symm_apply]
1998
1999open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2000/-- Boundary of the triangular backtrack prism: reverse path minus the constant
2001initial edge plus the original path. -/
2002theorem singularTwoBoundaryFree_freeMk_pathBacktrack
2003    (γ : C(I, SphereOne)) :
2004    ModuleCat.Hom.hom singularTwoBoundaryFree
2005      (ModuleCat.freeMk (pathBacktrackSingularTwoSimplex γ)) =
2006      ModuleCat.freeMk
2007        (singularOneSimplexOfMap (oneSimplexOfPath (CircleWinding.reversePath γ))) -
2008        ModuleCat.freeMk (constantSingularOneSimplex (γ 0)) +
2009          ModuleCat.freeMk (singularOneSimplexOfMap (oneSimplexOfPath γ)) := by
2010  unfold pathBacktrackSingularTwoSimplex
2011  rw [singularTwoBoundaryFree_freeMk]
2012  rw [singularTwoSimplexOfMap_delta, singularTwoSimplexOfMap_delta,
2013    singularTwoSimplexOfMap_delta]
2014  rw [pathBacktrackMap_face_zero, pathBacktrackMap_face_one,
2015    pathBacktrackMap_face_two]
2016  rw [singularOneSimplexOfMap_constantOneSimplex]
2017
2018/-! ### Geodesic (lift-linear) simplices in the universal cover
2019
2020The terminal-return side of every cone, the fundamental loop, and every chain
2021appearing in the terminal-side correction are *geodesics*: projections of
2022straight lines in the universal cover `ℝ → S¹`, of the form
2023`x ↦ trigCirclePoint((1 - x₁)·a + x₁·b)`.  Two structural facts reduce the
2024terminal-side correction to arithmetic of lift endpoints:
2025
2026* geodesics compose additively in homology, witnessed by an explicit lift-affine
2027  `2`-simplex `linearTwoSimplexMap` whose three faces are geodesics;
2028* a `2π·ℤ` shift of both lift endpoints leaves the geodesic unchanged, because
2029  `2π` is the deck period of the covering.
2030-/
2031
2032/-- A geodesic singular `1`-simplex: the projection of the straight line from the
2033lift value `a` to the lift value `b` in the universal cover `ℝ → S¹`. -/
2034noncomputable def geodesicOneSimplex (a b : ℝ) : OneSimplex where
2035  toFun x := trigCirclePoint ((1 - x 1) * a + x 1 * b)
2036  continuous_toFun := by
2037    have hc1 : Continuous (fun x : stdSimplex ℝ (Fin 2) => x 1) :=
2038      (continuous_apply 1).comp continuous_subtype_val
2039    exact continuous_trigCirclePoint.comp
2040      (((continuous_const.sub hc1).mul continuous_const).add (hc1.mul continuous_const))
2041
2042@[simp] theorem geodesicOneSimplex_apply (a b : ℝ) (x : stdSimplex ℝ (Fin 2)) :
2043    geodesicOneSimplex a b x = trigCirclePoint ((1 - x 1) * a + x 1 * b) := rfl
2044
2045/-- The terminal-return side of the cone is exactly the geodesic from the
2046terminal lift value to the initial lift value. -/
2047theorem coneTerminalSide_eq_geodesic (γ : C(I, SphereOne)) :
2048    coneTerminalSide γ = geodesicOneSimplex (pathLift γ 1) (pathLift γ 0) := rfl
2049
2050/-- A geodesic with equal endpoints is the constant edge at the projected point. -/
2051theorem geodesicOneSimplex_self (a : ℝ) :
2052    geodesicOneSimplex a a = constantOneSimplex (trigCirclePoint a) := by
2053  ext x
2054  simp only [geodesicOneSimplex_apply]
2055  rw [show (1 - x 1) * a + x 1 * a = a by ring]
2056  rfl
2057
2058/-- Shift invariance of geodesics: translating both lift endpoints by an integer
2059number of full turns `2π` leaves the geodesic unchanged. -/
2060theorem geodesicOneSimplex_shift (a b : ℝ) (m : ℤ) :
2061    geodesicOneSimplex (a + (m : ℝ) * (2 * Real.pi)) (b + (m : ℝ) * (2 * Real.pi)) =
2062      geodesicOneSimplex a b := by
2063  ext x
2064  simp only [geodesicOneSimplex_apply]
2065  rw [show (1 - x 1) * (a + (m : ℝ) * (2 * Real.pi)) + x 1 * (b + (m : ℝ) * (2 * Real.pi))
2066        = ((1 - x 1) * a + x 1 * b) + (m : ℝ) * (2 * Real.pi) by ring]
2067  exact (CircleLifting.trigCirclePoint_eq_iff _ _).mpr ⟨m, rfl⟩
2068
2069/-- A geodesic (lift-affine) singular `2`-simplex: `x ↦ trigCirclePoint` of the
2070affine combination of three lift values `p, q, r`.  Its three faces are the
2071geodesics on the three pairs of vertices. -/
2072noncomputable def linearTwoSimplexMap (p q r : ℝ) : TwoSimplex where
2073  toFun x := trigCirclePoint ((1 - x 1 - x 2) * p + x 1 * q + x 2 * r)
2074  continuous_toFun := by
2075    have hc1 : Continuous (fun x : stdSimplex ℝ (Fin 3) => x 1) :=
2076      (continuous_apply 1).comp continuous_subtype_val
2077    have hc2 : Continuous (fun x : stdSimplex ℝ (Fin 3) => x 2) :=
2078      (continuous_apply 2).comp continuous_subtype_val
2079    exact continuous_trigCirclePoint.comp
2080      (((((continuous_const.sub hc1).sub hc2).mul continuous_const).add
2081        (hc1.mul continuous_const)).add (hc2.mul continuous_const))
2082
2083@[simp] theorem linearTwoSimplexMap_apply (p q r : ℝ) (x : stdSimplex ℝ (Fin 3)) :
2084    linearTwoSimplexMap p q r x =
2085      trigCirclePoint ((1 - x 1 - x 2) * p + x 1 * q + x 2 * r) := rfl
2086
2087/-- The `δ₀` face of the lift-affine `2`-simplex is the geodesic from `q` to `r`. -/
2088theorem linearTwoSimplexMap_face_zero (p q r : ℝ) :
2089    face (linearTwoSimplexMap p q r) 0 = geodesicOneSimplex q r := by
2090  ext x
2091  simp only [face, ContinuousMap.comp_apply, linearTwoSimplexMap_apply,
2092    geodesicOneSimplex_apply]
2093  rw [faceMap_zero_coord_one, faceMap_zero_coord_two]
2094  have hsum : (x : Fin 2 → ℝ) 0 + (x : Fin 2 → ℝ) 1 = 1 := by
2095    have h := stdSimplex.sum_eq_one x
2096    rw [Fin.sum_univ_two] at h
2097    exact h
2098  congr 1
2099  have hx0 : (x : Fin 2 → ℝ) 0 = 1 - (x : Fin 2 → ℝ) 1 := by linarith
2100  rw [hx0]; ring
2101
2102/-- The `δ₁` face of the lift-affine `2`-simplex is the geodesic from `p` to `r`. -/
2103theorem linearTwoSimplexMap_face_one (p q r : ℝ) :
2104    face (linearTwoSimplexMap p q r) 1 = geodesicOneSimplex p r := by
2105  ext x
2106  simp only [face, ContinuousMap.comp_apply, linearTwoSimplexMap_apply,
2107    geodesicOneSimplex_apply]
2108  rw [faceMap_one_coord_one, faceMap_one_coord_two]
2109  congr 1
2110  ring
2111
2112/-- The `δ₂` face of the lift-affine `2`-simplex is the geodesic from `p` to `q`. -/
2113theorem linearTwoSimplexMap_face_two (p q r : ℝ) :
2114    face (linearTwoSimplexMap p q r) 2 = geodesicOneSimplex p q := by
2115  ext x
2116  simp only [face, ContinuousMap.comp_apply, linearTwoSimplexMap_apply,
2117    geodesicOneSimplex_apply]
2118  rw [faceMap_two_coord_one, faceMap_two_coord_two]
2119  congr 1
2120  ring
2121
2122open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2123/-- The singular `2`-simplex carried by the lift-affine `2`-simplex. -/
2124noncomputable def linearSingularTwoSimplex (p q r : ℝ) : SingularTwoSimplex :=
2125  singularTwoSimplexOfMap (linearTwoSimplexMap p q r)
2126
2127open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2128/-- **Geodesic composition law.**  The free boundary of the lift-affine
2129`2`-simplex on `(p, q, r)` is `geo(q,r) − geo(p,r) + geo(p,q)`.  In particular
2130`geo(p,q) + geo(q,r)` is homologous to `geo(p,r)`: geodesics compose additively
2131in `H₁`. -/
2132theorem singularTwoBoundaryFree_freeMk_linearSingularTwoSimplex (p q r : ℝ) :
2133    ModuleCat.Hom.hom singularTwoBoundaryFree
2134      (ModuleCat.freeMk (linearSingularTwoSimplex p q r)) =
2135      ModuleCat.freeMk (singularOneSimplexOfMap (geodesicOneSimplex q r)) -
2136        ModuleCat.freeMk (singularOneSimplexOfMap (geodesicOneSimplex p r)) +
2137        ModuleCat.freeMk (singularOneSimplexOfMap (geodesicOneSimplex p q)) := by
2138  unfold linearSingularTwoSimplex
2139  rw [singularTwoBoundaryFree_freeMk]
2140  rw [singularTwoSimplexOfMap_delta, singularTwoSimplexOfMap_delta,
2141    singularTwoSimplexOfMap_delta]
2142  rw [linearTwoSimplexMap_face_zero, linearTwoSimplexMap_face_one,
2143    linearTwoSimplexMap_face_two]
2144
2145/-- The geodesic from `0` to `2π` is the fundamental once-around simplex map. -/
2146theorem geodesicOneSimplex_zero_twoPi :
2147    geodesicOneSimplex 0 (2 * Real.pi) =
2148      CircleFundamentalSimplex.fundamentalCirclePathMap := by
2149  ext x
2150  simp only [geodesicOneSimplex_apply]
2151  rw [show (1 - x 1) * 0 + x 1 * (2 * Real.pi) = 2 * Real.pi * x 1 by ring]
2152  rfl
2153
2154open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2155/-- The singular simplex of the geodesic `0 → 2π` is the fundamental singular
2156`1`-simplex. -/
2157theorem singularOneSimplexOfMap_geodesic_zero_twoPi :
2158    singularOneSimplexOfMap (geodesicOneSimplex 0 (2 * Real.pi)) =
2159      CircleFundamentalSimplex.fundamentalSphereOneSingularOneSimplex := by
2160  rw [geodesicOneSimplex_zero_twoPi]
2161  rfl
2162
2163/-- The explicit real lift of the terminal-return side of the cone. -/
2164noncomputable def coneTerminalSideLift (γ : C(I, SphereOne)) : C(I, ℝ) where
2165  toFun t := (1 - (t : ℝ)) * pathLift γ 1 + (t : ℝ) * pathLift γ 0
2166  continuous_toFun := ((continuous_const.sub continuous_subtype_val).mul continuous_const).add
2167    (continuous_subtype_val.mul continuous_const)
2168
2169theorem coneTerminalSideLift_lifts (γ : C(I, SphereOne)) :
2170    trigCirclePoint ∘ ((coneTerminalSideLift γ) : I → ℝ) =
2171      oneSimplexPath (coneTerminalSide γ) := by
2172  funext t
2173  simp [coneTerminalSideLift, oneSimplexPath, coneTerminalSide, intervalToSimplex]
2174  rw [show ((stdSimplexHomeomorphUnitInterval.symm t : stdSimplex ℝ (Fin 2)) :
2175      Fin 2 → ℝ) 1 = (t : ℝ) by
2176    exact intervalToSimplex_coord_one t]
2177
2178/-- The terminal-return side of the cone has displacement opposite to the base
2179path. -/
2180theorem pathDisplacement_coneTerminalSide (γ : C(I, SphereOne)) :
2181    pathDisplacement (oneSimplexPath (coneTerminalSide γ)) =
2182      - pathDisplacement γ := by
2183  rw [pathDisplacement_eq (oneSimplexPath (coneTerminalSide γ))
2184    (coneTerminalSideLift γ) (coneTerminalSideLift_lifts γ)]
2185  dsimp [coneTerminalSideLift, pathDisplacement]
2186  ring
2187
2188/-- The terminal-return side has winding opposite to the base path displacement. -/
2189theorem simplexWinding_coneTerminalSide (γ : C(I, SphereOne)) :
2190    simplexWinding (coneTerminalSide γ) =
2191      - (pathDisplacement γ / (2 * Real.pi)) := by
2192  unfold simplexWinding simplexDisplacement
2193  rw [pathDisplacement_coneTerminalSide]
2194  ring
2195
2196open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2197/-- Free-boundary shell for the cone over an arbitrary singular edge.  The boundary
2198is the terminal-return side minus the constant apex side plus the original edge.
2199The zero-winding loop theorem is the special case where the terminal-return side
2200equals the constant side. -/
2201theorem singularTwoBoundaryFree_freeMk_coneCircleMap
2202    (f : OneSimplex) :
2203    ModuleCat.Hom.hom singularTwoBoundaryFree
2204      (ModuleCat.freeMk
2205        (singularTwoSimplexOfMap
2206          (coneCircleMapOfContinuous (oneSimplexPath f)
2207            (continuous_coneCirclePoint (oneSimplexPath f))))) =
2208      ModuleCat.freeMk (singularOneSimplexOfMap (coneTerminalSide (oneSimplexPath f))) -
2209        ModuleCat.freeMk
2210          (singularOneSimplexOfMap (constantOneSimplex ((oneSimplexPath f) 0))) +
2211          ModuleCat.freeMk (singularOneSimplexOfMap f) := by
2212  rw [singularTwoBoundaryFree_freeMk]
2213  rw [singularTwoSimplexOfMap_delta, singularTwoSimplexOfMap_delta,
2214    singularTwoSimplexOfMap_delta]
2215  rw [coneCircleMapOfContinuous_face_zero, coneCircleMapOfContinuous_face_one,
2216    coneCircleMapOfContinuous_face_two]
2217
2218open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2219/-- Zero-winding specialization of the arbitrary cone boundary shell: the
2220terminal-return side equals the constant apex side, so the cone's free boundary is
2221just the original edge generator. -/
2222theorem singularTwoBoundaryFree_freeMk_coneCircleMap_of_simplexWinding_zero
2223    (f : OneSimplex) (hzero : simplexWinding f = 0) :
2224    ModuleCat.Hom.hom singularTwoBoundaryFree
2225      (ModuleCat.freeMk
2226        (singularTwoSimplexOfMap
2227          (coneCircleMapOfContinuous (oneSimplexPath f)
2228            (continuous_coneCirclePoint (oneSimplexPath f))))) =
2229      ModuleCat.freeMk (singularOneSimplexOfMap f) := by
2230  rw [singularTwoBoundaryFree_freeMk_coneCircleMap]
2231  have hside :
2232      coneTerminalSide (oneSimplexPath f) =
2233        constantOneSimplex ((oneSimplexPath f) 0) :=
2234    coneTerminalSide_eq_constantOneSimplex_of_simplexWinding_zero f hzero
2235  rw [hside]
2236  abel
2237
2238open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2239/-- The singular `2`-simplex obtained by coning an arbitrary unit-interval path to
2240its initial point. -/
2241noncomputable def coneSingularTwoSimplexOfPath (γ : C(I, SphereOne)) : SingularTwoSimplex :=
2242  singularTwoSimplexOfMap
2243    (coneCircleMapOfContinuous γ (continuous_coneCirclePoint γ))
2244
2245open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2246/-- Path-parametric cone boundary shell.  This is the primitive finite-prism brick:
2247the boundary of the cone over a path is terminal-return side minus constant apex
2248side plus the path as a concrete singular edge. -/
2249theorem singularTwoBoundaryFree_freeMk_coneSingularTwoSimplexOfPath
2250    (γ : C(I, SphereOne)) :
2251    ModuleCat.Hom.hom singularTwoBoundaryFree
2252      (ModuleCat.freeMk (coneSingularTwoSimplexOfPath γ)) =
2253      ModuleCat.freeMk (singularOneSimplexOfMap (coneTerminalSide γ)) -
2254        ModuleCat.freeMk (singularOneSimplexOfMap (constantOneSimplex (γ 0))) +
2255          ModuleCat.freeMk (singularOneSimplexOfMap (oneSimplexOfPath γ)) := by
2256  unfold coneSingularTwoSimplexOfPath
2257  rw [singularTwoBoundaryFree_freeMk]
2258  rw [singularTwoSimplexOfMap_delta, singularTwoSimplexOfMap_delta,
2259    singularTwoSimplexOfMap_delta]
2260  rw [coneCircleMapOfContinuous_face_zero, coneCircleMapOfContinuous_face_one,
2261    coneCircleMapOfContinuous_face_two_path]
2262
2263open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2264/-- Sum of cone `2`-simplices over a finite family of paths. -/
2265noncomputable def coneSingularTwoChainOfPathFamily {k : ℕ}
2266    (γ : Fin k → C(I, SphereOne)) : singularTwoChainFree :=
2267  ∑ i, ModuleCat.freeMk (coneSingularTwoSimplexOfPath (γ i))
2268
2269open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2270/-- Finite-family cone boundary shell.  The summed cone boundary is the sum of
2271terminal-return sides, minus the sum of constant apex sides, plus the sum of the
2272base path edges.  This is the algebraic target whose side terms must telescope in
2273the multi-edge prism. -/
2274theorem singularTwoBoundaryFree_coneSingularTwoChainOfPathFamily {k : ℕ}
2275    (γ : Fin k → C(I, SphereOne)) :
2276    ModuleCat.Hom.hom singularTwoBoundaryFree (coneSingularTwoChainOfPathFamily γ) =
2277      (∑ i, ModuleCat.freeMk (singularOneSimplexOfMap (coneTerminalSide (γ i)))) -
2278        (∑ i, ModuleCat.freeMk (singularOneSimplexOfMap (constantOneSimplex ((γ i) 0)))) +
2279          (∑ i, ModuleCat.freeMk (singularOneSimplexOfMap (oneSimplexOfPath (γ i)))) := by
2280  unfold coneSingularTwoChainOfPathFamily
2281  rw [map_sum]
2282  rw [Finset.sum_congr rfl
2283    (fun i _ => singularTwoBoundaryFree_freeMk_coneSingularTwoSimplexOfPath (γ i))]
2284  rw [Finset.sum_add_distrib, Finset.sum_sub_distrib]
2285
2286/-- **The winding number of an actual singular `1`-simplex** of `TopCat.sphere 1`,
2287defined directly on the singular simplicial set. -/
2288def singularWinding (s : SingularOneSimplex) : ℝ :=
2289  simplexWinding (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s)
2290
2291open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2292/-- Transporting a concrete singular `1`-simplex into Mathlib's singular simplicial
2293set preserves the concrete winding number. -/
2294theorem singularWinding_singularOneSimplexOfMap (f : OneSimplex) :
2295    singularWinding (singularOneSimplexOfMap f) = simplexWinding f := by
2296  unfold singularWinding singularOneSimplexOfMap
2297  rw [Equiv.apply_symm_apply]
2298
2299open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2300/-- The actual singular terminal-return side has winding opposite to the base
2301path displacement. -/
2302theorem singularWinding_coneTerminalSide (γ : C(I, SphereOne)) :
2303    singularWinding (singularOneSimplexOfMap (coneTerminalSide γ)) =
2304      - (pathDisplacement γ / (2 * Real.pi)) := by
2305  rw [singularWinding_singularOneSimplexOfMap, simplexWinding_coneTerminalSide]
2306
2307/-- **The winding invariant kills the singular boundary.**  For every singular
2308`2`-simplex `s` in the actual singular simplicial set of `TopCat.sphere 1`, the
2309alternating sum of the winding numbers of its three simplicial faces vanishes.
2310This is the chain-level statement `W ∘ ∂₂ = 0` evaluated on a single generator:
2311the winding cochain annihilates boundaries. -/
2312theorem singularWinding_boundary (s : SingularTwoSimplex) :
2313    singularWinding ((TopCat.toSSet.obj (TopCat.sphere 1)).δ 0 s)
2314      - singularWinding ((TopCat.toSSet.obj (TopCat.sphere 1)).δ 1 s)
2315      + singularWinding ((TopCat.toSSet.obj (TopCat.sphere 1)).δ 2 s) = 0 := by
2316  simp only [singularWinding, toSSetObjEquiv_delta]
2317  exact simplexWinding_boundary _
2318
2319/-- The `δ₀` face of an actual singular `1`-simplex is its terminal endpoint,
2320after transport through `TopCat.toSSetObjEquiv`. -/
2321theorem singularOneSimplex_delta_zero_endpoint (s : SingularOneSimplex) :
2322    (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))
2323        ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s))
2324        (stdSimplex.vertex (0 : Fin 1))
2325      = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s)
2326          (stdSimplex.vertex (1 : Fin 2)) := by
2327  dsimp [TopCat.toSSetObjEquiv, TopCat.toSSet,
2328    CategoryTheory.Presheaf.restrictedULiftYoneda,
2329    CategoryTheory.SimplicialObject.δ,
2330    CategoryTheory.ConcreteCategory.homEquiv,
2331    Homeomorph.continuousMapCongr]
2332  congr 1
2333  change Homeomorph.ulift.symm
2334      (stdSimplex.map (ConcreteCategory.hom (SimplexCategory.δ (0 : Fin 2)))
2335        (stdSimplex.vertex (0 : Fin 1))) =
2336    Homeomorph.ulift.symm (stdSimplex.vertex (1 : Fin 2))
2337  rw [stdSimplex.map_vertex]
2338  rfl
2339
2340/-- The `δ₁` face of an actual singular `1`-simplex is its initial endpoint,
2341after transport through `TopCat.toSSetObjEquiv`. -/
2342theorem singularOneSimplex_delta_one_endpoint (s : SingularOneSimplex) :
2343    (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))
2344        ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s))
2345        (stdSimplex.vertex (0 : Fin 1))
2346      = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s)
2347          (stdSimplex.vertex (0 : Fin 2)) := by
2348  dsimp [TopCat.toSSetObjEquiv, TopCat.toSSet,
2349    CategoryTheory.Presheaf.restrictedULiftYoneda,
2350    CategoryTheory.SimplicialObject.δ,
2351    CategoryTheory.ConcreteCategory.homEquiv,
2352    Homeomorph.continuousMapCongr]
2353  congr 1
2354  change Homeomorph.ulift.symm
2355      (stdSimplex.map (ConcreteCategory.hom (SimplexCategory.δ (1 : Fin 2)))
2356        (stdSimplex.vertex (0 : Fin 1))) =
2357    Homeomorph.ulift.symm (stdSimplex.vertex (0 : Fin 2))
2358  rw [stdSimplex.map_vertex]
2359  rfl
2360
2361open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2362/-- A concrete singular edge with equal geometric endpoints becomes an actual
2363closed singular `1`-simplex after transport through `TopCat.toSSetObjEquiv`. -/
2364theorem singularOneSimplexOfMap_faces_eq_of_endpoints (f : OneSimplex)
2365    (h :
2366      f (stdSimplex.vertex (1 : Fin 2)) =
2367        f (stdSimplex.vertex (0 : Fin 2))) :
2368    (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2)
2369        (singularOneSimplexOfMap f) =
2370      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2)
2371        (singularOneSimplexOfMap f) := by
2372  apply (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))).injective
2373  ext x
2374  have hx : x = stdSimplex.vertex (0 : Fin 1) := by
2375    ext i
2376    fin_cases i
2377    have hsum := stdSimplex.sum_eq_one x
2378    simpa using hsum
2379  rw [hx]
2380  rw [singularOneSimplex_delta_zero_endpoint, singularOneSimplex_delta_one_endpoint]
2381  unfold singularOneSimplexOfMap
2382  rw [Equiv.apply_symm_apply]
2383  exact h
2384
2385/-- An actual singular `1`-simplex with equal simplicial faces has integer
2386winding.  This is the generator-level integrality input for proving
2387`cycleWinding_integral`. -/
2388theorem singularWinding_loop_integral (s : SingularOneSimplex)
2389    (hfaces :
2390      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2391        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s) :
2392    ∃ k : ℤ, singularWinding s = (k : ℝ) := by
2393  unfold singularWinding
2394  apply simplexWinding_loop_integral
2395  have hmap := congrArg
2396    (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))) hfaces
2397  have hpt := congrFun (congrArg ContinuousMap.toFun hmap) (stdSimplex.vertex (0 : Fin 1))
2398  calc
2399    (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s)
2400        (stdSimplex.vertex (1 : Fin 2))
2401        = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))
2402            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s))
2403            (stdSimplex.vertex (0 : Fin 1)) := (singularOneSimplex_delta_zero_endpoint s).symm
2404    _ = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))
2405            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s))
2406            (stdSimplex.vertex (0 : Fin 1)) := hpt
2407    _ = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s)
2408        (stdSimplex.vertex (0 : Fin 2)) := singularOneSimplex_delta_one_endpoint s
2409
2410/-- The actual `S¹`-point carried by a singular `0`-simplex, obtained by
2411transporting it through `TopCat.toSSetObjEquiv` and evaluating at the unique
2412vertex of `Δ⁰`. -/
2413def vertexPoint (v : SingularZeroSimplex) : SphereOne :=
2414  (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0)) v)
2415    (stdSimplex.vertex (0 : Fin 1))
2416
2417/-- A singular `1`-simplex of the chain complex, read as a path `I → S¹` in the
2418unit-interval parameterisation.  This is the bridge between the chain-level edge
2419and the path-level winding/displacement invariants. -/
2420def singularEdgePath (s : SingularOneSimplex) : C(I, SphereOne) :=
2421  oneSimplexPath (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s)
2422
2423open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2424/-- Reading a singular edge as a unit-interval path and then back as a concrete
2425singular `1`-simplex returns the original singular generator. -/
2426theorem singularOneSimplexOfMap_oneSimplexOfPath_singularEdgePath
2427    (s : SingularOneSimplex) :
2428    singularOneSimplexOfMap (oneSimplexOfPath (singularEdgePath s)) = s := by
2429  apply (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).injective
2430  unfold singularOneSimplexOfMap singularEdgePath
2431  rw [Equiv.apply_symm_apply, oneSimplexOfPath_oneSimplexPath]
2432
2433/-- The initial point of a singular edge's path is the `S¹`-point of its initial
2434`0`-face. -/
2435theorem singularEdgePath_zero (s : SingularOneSimplex) :
2436    singularEdgePath s 0 = vertexPoint (edgeInitial s) := by
2437  unfold singularEdgePath vertexPoint edgeInitial oneSimplexPath
2438  rw [ContinuousMap.comp_apply, intervalToSimplex_zero]
2439  exact (singularOneSimplex_delta_one_endpoint s).symm
2440
2441/-- The terminal point of a singular edge's path is the `S¹`-point of its terminal
2442`0`-face. -/
2443theorem singularEdgePath_one (s : SingularOneSimplex) :
2444    singularEdgePath s 1 = vertexPoint (edgeTerminal s) := by
2445  unfold singularEdgePath vertexPoint edgeTerminal oneSimplexPath
2446  rw [ContinuousMap.comp_apply, intervalToSimplex_one]
2447  exact (singularOneSimplex_delta_zero_endpoint s).symm
2448
2449/-- The winding of a singular edge is the displacement of its path, normalized by
2450one full turn. -/
2451theorem singularWinding_eq_pathDisplacement (s : SingularOneSimplex) :
2452    singularWinding s = pathDisplacement (singularEdgePath s) / (2 * Real.pi) := by
2453  unfold singularWinding simplexWinding simplexDisplacement singularEdgePath
2454  rfl
2455
2456open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2457/-- A closed singular edge with zero singular winding is homotopic rel endpoints
2458to the constant path at its basepoint.  This is the path-level null-homotopy
2459input needed by the remaining singular prism construction. -/
2460theorem singularEdgePath_homotopicRel_const_of_loop_winding_zero
2461    (s : SingularOneSimplex)
2462    (hfaces :
2463      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2464        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
2465    (hw : singularWinding s = 0) :
2466    (singularEdgePath s).HomotopicRel
2467      (ContinuousMap.const I (singularEdgePath s 0)) {0, 1} := by
2468  apply pathHomotopicRel_const_of_loop_winding_zero
2469  · rw [singularEdgePath_one, singularEdgePath_zero]
2470    exact congrArg vertexPoint hfaces
2471  · unfold pathWinding
2472    rw [← singularWinding_eq_pathDisplacement]
2473    exact hw
2474
2475/-- **Closed-walk winding integrality (singular-edge form).**  If a finite family
2476of singular `1`-simplices forms a cyclically connected walk (terminal `0`-face of
2477`e i` equals initial `0`-face of `e (finRotate k i)`), then the total winding
2478around the walk is an integer.
2479
2480This is the integrality engine for the `winding_integral` field of a multi-edge
2481cyclic edge-list piece: it reduces the integer winding of an extracted directed
2482cycle to the purely combinatorial fact that the cycle's `0`-faces chain up.  It
2483uses no prism/subdivision operator, only `displacementSum_cyclic_intMul` and the
2484endpoint identifications above. -/
2485theorem singularWindingSum_cyclic_integral {k : ℕ} (e : Fin k → SingularOneSimplex)
2486    (hconn : ∀ i : Fin k, edgeTerminal (e i) = edgeInitial (e (finRotate k i))) :
2487    ∃ n : ℤ, ∑ i, singularWinding (e i) = (n : ℝ) := by
2488  have hpathconn : ∀ i : Fin k,
2489      (singularEdgePath (e i)) 1 = (singularEdgePath (e (finRotate k i))) 0 := by
2490    intro i
2491    rw [singularEdgePath_one, singularEdgePath_zero]
2492    exact congrArg vertexPoint (hconn i)
2493  obtain ⟨m, hm⟩ :=
2494    displacementSum_cyclic_intMul (fun i => singularEdgePath (e i)) hpathconn
2495  refine ⟨m, ?_⟩
2496  have hsum :
2497      ∑ i, singularWinding (e i)
2498        = (∑ i, pathDisplacement (singularEdgePath (e i))) / (2 * Real.pi) := by
2499    rw [Finset.sum_div]
2500    refine Finset.sum_congr rfl (fun i _ => ?_)
2501    exact singularWinding_eq_pathDisplacement (e i)
2502  rw [hsum, hm]
2503  have hpi : (2 : ℝ) * Real.pi ≠ 0 := by positivity
2504  rw [mul_div_assoc, div_self hpi, mul_one]
2505
2506open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2507/-- **Cyclic free-boundary vanishing (C₀ telescoping).**  The free edge-chain of a
2508cyclically connected family of singular `1`-simplices is a cycle: its explicit
2509free boundary vanishes.  This is the `C₀` companion of
2510`singularWindingSum_cyclic_integral`; it is the same `finRotate` reindexing
2511telescoping, now applied to the boundary `terminal − initial` instead of the
2512winding displacement.  It supplies the boundary-zero proof needed to lift a closed
2513edge-walk to an element of the degree-`1` cycles. -/
2514theorem cyclicEdgeFamily_freeBoundary_zero {k : ℕ} (e : Fin k → SingularOneSimplex)
2515    (hconn : ∀ i : Fin k, edgeTerminal (e i) = edgeInitial (e (finRotate k i))) :
2516    ModuleCat.Hom.hom singularOneBoundaryFree (∑ i, ModuleCat.freeMk (e i)) = 0 := by
2517  rw [map_sum]
2518  have hterm : ∀ i : Fin k,
2519      ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk (e i))
2520        = ModuleCat.freeMk (edgeTerminal (e i)) - ModuleCat.freeMk (edgeInitial (e i)) := by
2521    intro i
2522    rw [singularOneBoundaryFree_freeMk]; rfl
2523  rw [Finset.sum_congr rfl (fun i _ => hterm i), Finset.sum_sub_distrib]
2524  have hreindex :
2525      (∑ i, ModuleCat.freeMk (edgeInitial (e i)) : singularZeroChainFree)
2526        = ∑ i, ModuleCat.freeMk (edgeTerminal (e i)) := by
2527    rw [← Equiv.sum_comp (finRotate k)
2528      (fun j => (ModuleCat.freeMk (edgeInitial (e j)) : singularZeroChainFree))]
2529    refine Finset.sum_congr rfl (fun i _ => ?_)
2530    exact congrArg ModuleCat.freeMk (hconn i).symm
2531  rw [hreindex, sub_self]
2532
2533open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2534/-- A singular `1`-simplex with equal endpoints is a cycle at the chain level.
2535This is the generator-level boundary-zero statement in the actual singular chain
2536complex. -/
2537theorem singularOneSimplexChain_boundary_zero_of_faces_eq (s : SingularOneSimplex)
2538    (hfaces :
2539      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2540        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s) :
2541    (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s)
2542      ≫ sphereOneSingularIntChainComplex.d 1 0 = 0 := by
2543  dsimp [sphereOneSingularIntChainComplex,
2544    AlgebraicTopology.singularChainComplexFunctor,
2545    AlgebraicTopology.SSet.singularChainComplexFunctor,
2546    AlgebraicTopology.alternatingFaceMapComplex,
2547    sigmaConst]
2548  rw [AlgebraicTopology.AlternatingFaceMapComplex.obj_d_eq]
2549  dsimp [AlgebraicTopology.AlternatingFaceMapComplex.objD]
2550  simp only [Fin.sum_univ_two, Fin.val_zero, pow_zero, one_zsmul, Fin.val_one, pow_one,
2551    neg_zsmul, one_zsmul, Preadditive.comp_add, Preadditive.comp_neg]
2552  simp only [CategoryTheory.SimplicialObject.δ]
2553  dsimp [sigmaConst]
2554  simp only [Sigma.ι_comp_map', Category.id_comp]
2555  change Sigma.ι (fun x => ModuleCat.of ℤ ℤ)
2556        ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s) +
2557      -Sigma.ι (fun x => ModuleCat.of ℤ ℤ)
2558          ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s) =
2559    0
2560  rw [hfaces]
2561  simp
2562
2563open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2564/-- Boundary of one singular `1`-simplex generator in explicit free-`C₀`
2565coordinates: terminal `0`-face minus initial `0`-face.  This is the raw
2566finite-support cancellation surface for the remaining cycle decomposition
2567theorem. -/
2568theorem singularOneSimplexChain_boundary_free (s : SingularOneSimplex) :
2569    Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫
2570        sphereOneSingularIntChainComplex.d 1 0 ≫ singularZeroChainToFree =
2571      ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ singularZeroChainFree
2572        (ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s) -
2573          ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s))) := by
2574  dsimp [sphereOneSingularIntChainComplex,
2575    AlgebraicTopology.singularChainComplexFunctor,
2576    AlgebraicTopology.SSet.singularChainComplexFunctor,
2577    AlgebraicTopology.alternatingFaceMapComplex,
2578    sigmaConst]
2579  rw [AlgebraicTopology.AlternatingFaceMapComplex.obj_d_eq]
2580  dsimp [AlgebraicTopology.AlternatingFaceMapComplex.objD]
2581  simp only [Fin.sum_univ_two, Fin.val_zero, pow_zero, one_zsmul, Fin.val_one, pow_one,
2582    neg_zsmul, one_zsmul, Preadditive.comp_add, Preadditive.comp_neg,
2583    Preadditive.add_comp, Preadditive.neg_comp]
2584  simp only [CategoryTheory.SimplicialObject.δ]
2585  dsimp [sigmaConst]
2586  simp only [Sigma.ι_comp_map'_assoc, Category.id_comp]
2587  rw [singularZeroChainToFree]
2588  rw [Sigma.ι_desc, Sigma.ι_desc]
2589  apply ModuleCat.hom_ext
2590  apply LinearMap.ext_ring
2591  simp only [ModuleCat.hom_add, ModuleCat.hom_neg, ModuleCat.hom_ofHom,
2592    LinearMap.add_apply, LinearMap.neg_apply, LinearMap.toSpanSingleton_apply]
2593  simp [sub_eq_add_neg]
2594
2595open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2596/-- The Mathlib singular boundary, transported from explicit free `C₁` to
2597explicit free `C₀`, is the free boundary `terminal - initial`. -/
2598theorem singularOneChainFreeToChain_boundary_free :
2599    singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 ≫
2600        singularZeroChainToFree =
2601      singularOneBoundaryFree := by
2602  apply ModuleCat.free_hom_ext
2603  intro s
2604  change ModuleCat.Hom.hom
2605      (singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 ≫
2606        singularZeroChainToFree) (ModuleCat.freeMk s) =
2607    ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk s)
2608  simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply]
2609  rw [singularOneChainFreeToChain_freeMk]
2610  change ModuleCat.Hom.hom
2611      (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫
2612        sphereOneSingularIntChainComplex.d 1 0 ≫ singularZeroChainToFree) 1 =
2613    ModuleCat.Hom.hom singularOneBoundaryFree (ModuleCat.freeMk s)
2614  rw [singularOneSimplexChain_boundary_free]
2615  rw [singularOneBoundaryFree_freeMk]
2616  simp [LinearMap.toSpanSingleton_apply]
2617
2618open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2619/-- Transporting Mathlib's raw boundary along the explicit free `C₁` isomorphism
2620gives the explicit free boundary. -/
2621theorem singularOneChainToFree_boundary_free :
2622    singularOneChainToFree ≫ singularOneBoundaryFree =
2623      sphereOneSingularIntChainComplex.d 1 0 ≫ singularZeroChainToFree := by
2624  haveI : IsIso singularOneChainFreeToChain := by
2625    change IsIso singularOneChainFreeIso.inv
2626    infer_instance
2627  rw [← cancel_epi singularOneChainFreeToChain]
2628  calc
2629    singularOneChainFreeToChain ≫ singularOneChainToFree ≫ singularOneBoundaryFree
2630        = singularOneBoundaryFree := by
2631          exact singularOneChainFreeIso.inv_hom_id_assoc singularOneBoundaryFree
2632    _ = singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 ≫
2633          singularZeroChainToFree := singularOneChainFreeToChain_boundary_free.symm
2634
2635open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2636/-- The actual cycle object element generated by a closed singular `1`-simplex. -/
2637noncomputable def closedSingularOneCycle (s : SingularOneSimplex)
2638    (hfaces :
2639      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2640        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s) :
2641    ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.cycles 1 :=
2642  sphereOneSingularIntChainComplex.liftCycles
2643    (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) 0 (by simp)
2644    (singularOneSimplexChain_boundary_zero_of_faces_eq s hfaces)
2645
2646open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2647/-- Including a closed singular generator cycle into `C₁` recovers the
2648corresponding coproduct generator. -/
2649theorem closedSingularOneCycle_iCycles (s : SingularOneSimplex)
2650    (hfaces :
2651      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2652        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s) :
2653    closedSingularOneCycle s hfaces ≫ sphereOneSingularIntChainComplex.iCycles 1 =
2654      Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s := by
2655  rw [closedSingularOneCycle, HomologicalComplex.liftCycles_i]
2656
2657open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2658/-- The constant singular `1`-simplex is closed. -/
2659theorem constantSingularOneSimplex_faces_eq (p : SphereOne) :
2660    (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2)
2661        (constantSingularOneSimplex p) =
2662      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2)
2663        (constantSingularOneSimplex p) := by
2664  apply (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))).injective
2665  dsimp [constantSingularOneSimplex,
2666    TopCat.toSSetObjEquiv, TopCat.toSSet,
2667    CategoryTheory.Presheaf.restrictedULiftYoneda,
2668    CategoryTheory.SimplicialObject.δ,
2669    CategoryTheory.ConcreteCategory.homEquiv,
2670    Homeomorph.continuousMapCongr]
2671  ext x
2672  rfl
2673
2674/-! ## The winding chain map and the split-injective half of `H₁(S¹;ℤ) ≅ ℤ`
2675
2676We assemble the singular winding numbers into an honest morphism of `ℤ`-modules
2677`W : C₁(S¹) → ℝ` out of the degree-`1` singular chain group, prove it annihilates
2678the singular boundary `∂₂` (so it descends to a homomorphism on `H₁`), and prove
2679it sends the fundamental cycle to `1`.
2680
2681This is the split-injective half of `H₁(S¹;ℤ) ≅ ℤ`: the comparison map
2682`ℤ → H₁`, `n ↦ n·[fundamental]`, has a left inverse, so it is injective and
2683`[fundamental]` has infinite order.  The converse (every `1`-cycle is homologous
2684to an integer multiple of the fundamental cycle) is the generation half; it needs
2685the simplicial prism / subdivision operator, which Mathlib's singular homology
2686does not yet provide. -/
2687
2688open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2689/-- **The winding chain map** `W : C₁(S¹;ℤ) → ℝ`.  On the free generator indexed
2690by a singular `1`-simplex `s` it is `n ↦ n · (winding number of s)`. -/
2691noncomputable def windingChainMap :
2692    sphereOneSingularIntChainComplex.X 1 ⟶ ModuleCat.of ℤ ℝ :=
2693  Limits.Sigma.desc (fun s : SingularOneSimplex =>
2694    ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ ℝ (singularWinding s)))
2695
2696open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2697/-- The winding chain map evaluates each generator to its winding number. -/
2698theorem windingChainMap_ι (s : SingularOneSimplex) :
2699    Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫ windingChainMap
2700      = ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ ℝ (singularWinding s)) :=
2701  Sigma.ι_desc _ s
2702
2703open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2704/-- Raw boundary of a singular `2`-simplex generator in `C₁(S¹;ℤ)`: the
2705alternating sum of its three singular `1`-faces.  The explicit prism construction
2706for zero-winding cycles will use this equality before applying any invariant. -/
2707theorem singularTwoSimplex_boundary_ι (s : SingularTwoSimplex) :
2708    (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s)
2709      ≫ sphereOneSingularIntChainComplex.d 2 1 =
2710        Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2711          ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) s) -
2712        Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2713          ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) s) +
2714        Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2715          ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) s) := by
2716  dsimp [sphereOneSingularIntChainComplex,
2717    AlgebraicTopology.singularChainComplexFunctor,
2718    AlgebraicTopology.SSet.singularChainComplexFunctor,
2719    AlgebraicTopology.alternatingFaceMapComplex, sigmaConst]
2720  rw [AlgebraicTopology.AlternatingFaceMapComplex.obj_d_eq]
2721  dsimp [AlgebraicTopology.AlternatingFaceMapComplex.objD]
2722  simp only [Fin.sum_univ_three, Fin.val_zero, pow_zero, one_zsmul, Fin.val_one, pow_one,
2723    Fin.val_two, neg_one_sq, neg_zsmul]
2724  simp only [CategoryTheory.SimplicialObject.δ]
2725  dsimp [sigmaConst]
2726  simp only [Preadditive.comp_add, Preadditive.comp_neg, Sigma.ι_comp_map', Category.id_comp]
2727  abel_nf
2728
2729open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2730/-- Element-level form of `singularTwoSimplex_boundary_ι`, applied to the unit
2731generator of the singular `2`-simplex summand. -/
2732theorem singularTwoSimplex_boundary_apply (s : SingularTwoSimplex) :
2733    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1)
2734      (ModuleCat.Hom.hom
2735        (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s) 1) =
2736        ModuleCat.Hom.hom
2737          (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2738            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) s)) 1 -
2739        ModuleCat.Hom.hom
2740          (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2741            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) s)) 1 +
2742        ModuleCat.Hom.hom
2743          (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2744            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) s)) 1 := by
2745  have h := congrArg (fun f =>
2746      ModuleCat.Hom.hom f (1 : ModuleCat.of ℤ ℤ))
2747    (singularTwoSimplex_boundary_ι s)
2748  simpa only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply,
2749    ModuleCat.hom_add, ModuleCat.hom_sub, ModuleCat.hom_neg,
2750    LinearMap.add_apply, LinearMap.sub_apply, LinearMap.neg_apply] using h
2751
2752open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2753/-- Mathlib's singular `C₂ → C₁` boundary, transported from explicit free `C₂`
2754to explicit free `C₁`, is exactly the free alternating-face boundary. -/
2755theorem singularTwoChainFreeToChain_boundary_free :
2756    singularTwoChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 2 1 ≫
2757        singularOneChainToFree =
2758      singularTwoBoundaryFree := by
2759  apply ModuleCat.free_hom_ext
2760  intro s
2761  change ModuleCat.Hom.hom
2762      (singularTwoChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 2 1 ≫
2763        singularOneChainToFree) (ModuleCat.freeMk s) =
2764      ModuleCat.Hom.hom singularTwoBoundaryFree (ModuleCat.freeMk s)
2765  simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply]
2766  rw [singularTwoChainFreeToChain, ModuleCat.freeDesc_apply]
2767  rw [singularTwoSimplex_boundary_apply]
2768  rw [singularTwoBoundaryFree_freeMk]
2769  rw [map_add, map_sub]
2770  change ModuleCat.Hom.hom
2771      (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2772        ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) s) ≫
2773          singularOneChainToFree) 1 -
2774      ModuleCat.Hom.hom
2775        (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2776          ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) s) ≫
2777            singularOneChainToFree) 1 +
2778      ModuleCat.Hom.hom
2779        (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2780          ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) s) ≫
2781            singularOneChainToFree) 1 =
2782    ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) s) -
2783      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) s) +
2784      ModuleCat.freeMk ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) s)
2785  rw [singularOneChainToFree_ι, singularOneChainToFree_ι, singularOneChainToFree_ι]
2786  simp [LinearMap.toSpanSingleton_apply]
2787
2788open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2789/-- If an explicit free `C₂` chain has a given free `C₁` boundary, then its raw
2790image in Mathlib's chain complex has the corresponding raw `C₁` boundary. -/
2791theorem rawBoundary_eq_of_singularTwoBoundaryFree_eq
2792    (B : singularTwoChainFree) (u : singularOneChainFree)
2793    (hB : ModuleCat.Hom.hom singularTwoBoundaryFree B = u) :
2794    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1)
2795      (ModuleCat.Hom.hom singularTwoChainFreeToChain B) =
2796        ModuleCat.Hom.hom singularOneChainFreeToChain u := by
2797  have hinj_toFree : Function.Injective (ModuleCat.Hom.hom singularOneChainToFree) := by
2798    haveI : IsIso singularOneChainToFree := by
2799      change IsIso singularOneChainFreeIso.hom
2800      infer_instance
2801    haveI : Mono singularOneChainToFree := inferInstance
2802    exact (ModuleCat.mono_iff_injective singularOneChainToFree).mp inferInstance
2803  apply hinj_toFree
2804  have hcomp := congrArg (fun f => ModuleCat.Hom.hom f B)
2805    singularTwoChainFreeToChain_boundary_free
2806  simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply] at hcomp
2807  rw [hB] at hcomp
2808  have hround :
2809      ModuleCat.Hom.hom singularOneChainToFree
2810        (ModuleCat.Hom.hom singularOneChainFreeToChain u) = u := by
2811    have hid := congrArg (fun f => ModuleCat.Hom.hom f u)
2812      singularOneChainFreeIso.inv_hom_id
2813    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
2814      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
2815    exact hid
2816  rw [hround]
2817  exact hcomp
2818
2819open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2820/-- Raw-chain form of `constantSingularOneSimplex_free_boundary`: the boundary of
2821the constant singular `2`-simplex is the raw generator corresponding to the
2822constant singular `1`-simplex. -/
2823theorem constantSingularOneSimplex_raw_boundary (p : SphereOne) :
2824    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1)
2825      (ModuleCat.Hom.hom singularTwoChainFreeToChain
2826        (ModuleCat.freeMk (constantSingularTwoSimplex p))) =
2827      ModuleCat.Hom.hom
2828        (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ)
2829          (constantSingularOneSimplex p)) 1 := by
2830  have hraw := rawBoundary_eq_of_singularTwoBoundaryFree_eq
2831    (ModuleCat.freeMk (constantSingularTwoSimplex p))
2832    (ModuleCat.freeMk (constantSingularOneSimplex p))
2833    (constantSingularOneSimplex_free_boundary p)
2834  rw [singularOneChainFreeToChain_freeMk] at hraw
2835  exact hraw
2836
2837open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2838/-- The constant closed singular `1`-cycle bounds the constant singular
2839`2`-simplex at the cycle-object level. -/
2840theorem constantSingularOneCycle_bounds (p : SphereOne) :
2841    ∃ b : sphereOneSingularIntChainComplex.X 2,
2842      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
2843        ModuleCat.Hom.hom
2844          (closedSingularOneCycle (constantSingularOneSimplex p)
2845            (constantSingularOneSimplex_faces_eq p)) 1 := by
2846  let b : sphereOneSingularIntChainComplex.X 2 :=
2847    ModuleCat.Hom.hom singularTwoChainFreeToChain
2848      (ModuleCat.freeMk (constantSingularTwoSimplex p))
2849  refine ⟨b, ?_⟩
2850  have hinj_iCycles :
2851      Function.Injective
2852        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
2853    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
2854  apply hinj_iCycles
2855  change ModuleCat.Hom.hom
2856      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
2857        sphereOneSingularIntChainComplex.iCycles 1) b =
2858    ModuleCat.Hom.hom
2859      ((closedSingularOneCycle (constantSingularOneSimplex p)
2860          (constantSingularOneSimplex_faces_eq p)) ≫
2861        sphereOneSingularIntChainComplex.iCycles 1) 1
2862  rw [HomologicalComplex.toCycles_i]
2863  rw [constantSingularOneSimplex_raw_boundary p]
2864  rw [closedSingularOneCycle_iCycles]
2865  rfl
2866
2867open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2868/-- Algebraic consumer for a hand-built free prism: if a closed singular
2869`1`-simplex generator is the explicit free boundary of a free `2`-chain, then
2870the corresponding cycle-object generator is a `toCycles` boundary.  The remaining
2871geometric task is therefore to construct such a free `2`-chain from a
2872rel-endpoint nullhomotopy. -/
2873theorem closedSingularOneCycle_bounds_of_free_boundary
2874    (s : SingularOneSimplex)
2875    (hfaces :
2876      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2877        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
2878    (B : singularTwoChainFree)
2879    (hB : ModuleCat.Hom.hom singularTwoBoundaryFree B = ModuleCat.freeMk s) :
2880    ∃ b : sphereOneSingularIntChainComplex.X 2,
2881      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
2882        ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 := by
2883  let b : sphereOneSingularIntChainComplex.X 2 :=
2884    ModuleCat.Hom.hom singularTwoChainFreeToChain B
2885  refine ⟨b, ?_⟩
2886  have hraw := rawBoundary_eq_of_singularTwoBoundaryFree_eq B (ModuleCat.freeMk s) hB
2887  rw [singularOneChainFreeToChain_freeMk] at hraw
2888  have hinj_iCycles :
2889      Function.Injective
2890        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
2891    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
2892  apply hinj_iCycles
2893  change ModuleCat.Hom.hom
2894      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
2895        sphereOneSingularIntChainComplex.iCycles 1) b =
2896    ModuleCat.Hom.hom
2897      ((closedSingularOneCycle s hfaces) ≫
2898        sphereOneSingularIntChainComplex.iCycles 1) 1
2899  rw [HomologicalComplex.toCycles_i]
2900  rw [hraw]
2901  rw [closedSingularOneCycle_iCycles]
2902  rfl
2903
2904open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2905/-- Raw-chain version of `closedSingularOneCycle_bounds_of_free_boundary`.  A raw
2906singular `2`-chain whose boundary is the raw generator of a closed singular edge
2907already proves that the closed generator cycle bounds. -/
2908theorem closedSingularOneCycle_bounds_of_raw_boundary
2909    (s : SingularOneSimplex)
2910    (hfaces :
2911      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2912        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
2913    (b : sphereOneSingularIntChainComplex.X 2)
2914    (hb : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1) b =
2915      ModuleCat.Hom.hom
2916        (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s) 1) :
2917    ∃ c : sphereOneSingularIntChainComplex.X 2,
2918      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) c =
2919        ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 := by
2920  refine ⟨b, ?_⟩
2921  have hinj_iCycles :
2922      Function.Injective
2923        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
2924    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
2925  apply hinj_iCycles
2926  change ModuleCat.Hom.hom
2927      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
2928        sphereOneSingularIntChainComplex.iCycles 1) b =
2929    ModuleCat.Hom.hom
2930      ((closedSingularOneCycle s hfaces) ≫
2931        sphereOneSingularIntChainComplex.iCycles 1) 1
2932  rw [HomologicalComplex.toCycles_i]
2933  rw [hb]
2934  rw [closedSingularOneCycle_iCycles]
2935  rfl
2936
2937open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2938/-- A cone singular `2`-simplex over a closed singular edge proves that the
2939corresponding closed singular `1`-cycle bounds.  This is the smallest geometric
2940handoff needed after `singularEdgePath_homotopicRel_const_of_loop_winding_zero`:
2941construct such a cone simplex from the rel-endpoint nullhomotopy. -/
2942theorem closedSingularOneCycle_bounds_of_cone_simplex
2943    (s : SingularOneSimplex)
2944    (hfaces :
2945      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
2946        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
2947    (sigma : SingularTwoSimplex)
2948    (hbase : (TopCat.toSSet.obj (TopCat.sphere 1)).δ (2 : Fin 3) sigma = s)
2949    (hsides :
2950      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 3) sigma =
2951        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 3) sigma) :
2952    ∃ b : sphereOneSingularIntChainComplex.X 2,
2953      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
2954        ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 :=
2955  closedSingularOneCycle_bounds_of_free_boundary s hfaces (ModuleCat.freeMk sigma)
2956    (singularTwoBoundaryFree_freeMk_of_cone_faces sigma s hbase hsides)
2957
2958open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2959/-- Continuous-map handoff for the cone filling.  It is enough to build a
2960continuous `F : C(Δ²,S¹)` whose base face is a given `f : C(Δ¹,S¹)` and whose two
2961side faces agree.  After transporting `F` through `TopCat.toSSetObjEquiv`, the
2962corresponding closed singular generator bounds in the actual chain complex. -/
2963theorem closedSingularOneCycle_bounds_of_cone_map
2964    (f : OneSimplex)
2965    (hfaces :
2966      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2)
2967          (singularOneSimplexOfMap f) =
2968        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2)
2969          (singularOneSimplexOfMap f))
2970    (F : TwoSimplex)
2971    (hbase : face F (2 : Fin 3) = f)
2972    (hsides : face F (0 : Fin 3) = face F (1 : Fin 3)) :
2973    ∃ b : sphereOneSingularIntChainComplex.X 2,
2974      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
2975        ModuleCat.Hom.hom
2976          (closedSingularOneCycle (singularOneSimplexOfMap f) hfaces) 1 := by
2977  refine closedSingularOneCycle_bounds_of_cone_simplex
2978    (singularOneSimplexOfMap f) hfaces (singularTwoSimplexOfMap F) ?_ ?_
2979  · rw [singularTwoSimplexOfMap_delta, hbase]
2980  · rw [singularTwoSimplexOfMap_delta, singularTwoSimplexOfMap_delta, hsides]
2981
2982open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
2983/-- Endpoint-form cone handoff.  To prove that a concrete closed edge bounds, it
2984is now enough to construct a continuous `2`-simplex whose base face is that edge
2985and whose two side faces agree.  This is the exact target left by the
2986zero-winding nullhomotopy: build the conical extension `F : C(Δ²,S¹)`. -/
2987theorem closedSingularOneCycle_bounds_of_closed_cone_map
2988    (f : OneSimplex)
2989    (hendpoints :
2990      f (stdSimplex.vertex (1 : Fin 2)) =
2991        f (stdSimplex.vertex (0 : Fin 2)))
2992    (F : TwoSimplex)
2993    (hbase : face F (2 : Fin 3) = f)
2994    (hsides : face F (0 : Fin 3) = face F (1 : Fin 3)) :
2995    ∃ b : sphereOneSingularIntChainComplex.X 2,
2996      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
2997        ModuleCat.Hom.hom
2998          (closedSingularOneCycle (singularOneSimplexOfMap f)
2999            (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints)) 1 :=
3000  closedSingularOneCycle_bounds_of_cone_map f
3001    (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints) F hbase hsides
3002
3003open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3004/-- Continuity-hypothesis form of the closed-edge cone filler.  After all
3005pointwise face identities above, the full singular `2`-chain boundary follows
3006from one remaining analytic theorem:
3007`Continuous (coneCirclePoint (oneSimplexPath f))`. -/
3008theorem closedSingularOneCycle_bounds_of_continuous_coneCirclePoint
3009    (f : OneSimplex)
3010    (hendpoints :
3011      f (stdSimplex.vertex (1 : Fin 2)) =
3012        f (stdSimplex.vertex (0 : Fin 2)))
3013    (hzero : simplexWinding f = 0)
3014    (hcont : Continuous (coneCirclePoint (oneSimplexPath f))) :
3015    ∃ b : sphereOneSingularIntChainComplex.X 2,
3016      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
3017        ModuleCat.Hom.hom
3018          (closedSingularOneCycle (singularOneSimplexOfMap f)
3019            (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints)) 1 :=
3020  closedSingularOneCycle_bounds_of_closed_cone_map f hendpoints
3021    (coneCircleMapOfContinuous (oneSimplexPath f) hcont)
3022    (coneCircleMapOfContinuous_face_two f hcont)
3023    (coneCircleMapOfContinuous_side_faces_eq_of_winding_zero f hzero hcont)
3024
3025open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3026/-- A closed singular edge with zero winding bounds by the explicit continuous
3027cone over its lifted path.  This removes the last analytic hypothesis from the
3028single-edge zero-winding cone construction. -/
3029theorem closedSingularOneCycle_bounds_of_zero_winding_coneCirclePoint
3030    (f : OneSimplex)
3031    (hendpoints :
3032      f (stdSimplex.vertex (1 : Fin 2)) =
3033        f (stdSimplex.vertex (0 : Fin 2)))
3034    (hzero : simplexWinding f = 0) :
3035    ∃ b : sphereOneSingularIntChainComplex.X 2,
3036      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
3037        ModuleCat.Hom.hom
3038          (closedSingularOneCycle (singularOneSimplexOfMap f)
3039            (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints)) 1 :=
3040  closedSingularOneCycle_bounds_of_continuous_coneCirclePoint f hendpoints hzero
3041    (continuous_coneCirclePoint (oneSimplexPath f))
3042
3043open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3044/-- Actual-singular-simplex form of the zero-winding cone theorem.  This removes
3045the `C(Δ¹,S¹)` presentation from the consumer side: any closed Mathlib singular
3046`1`-simplex with zero `singularWinding` bounds. -/
3047theorem closedSingularOneCycle_bounds_of_zero_singularWinding
3048    (s : SingularOneSimplex)
3049    (hfaces :
3050      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
3051        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
3052    (hzero : singularWinding s = 0) :
3053    ∃ b : sphereOneSingularIntChainComplex.X 2,
3054      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b =
3055        ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 := by
3056  let f : OneSimplex :=
3057    TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1)) s
3058  have hendpoints :
3059      f (stdSimplex.vertex (1 : Fin 2)) = f (stdSimplex.vertex (0 : Fin 2)) := by
3060    have hcong :=
3061      congrArg (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))) hfaces
3062    have happ := congrFun (congrArg ContinuousMap.toFun hcong) (stdSimplex.vertex (0 : Fin 1))
3063    calc
3064      f (stdSimplex.vertex (1 : Fin 2))
3065          = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))
3066            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s))
3067              (stdSimplex.vertex (0 : Fin 1)) := by
3068            exact (singularOneSimplex_delta_zero_endpoint s).symm
3069      _ = (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 0))
3070            ((TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s))
3071              (stdSimplex.vertex (0 : Fin 1)) := happ
3072      _ = f (stdSimplex.vertex (0 : Fin 2)) := by
3073            exact singularOneSimplex_delta_one_endpoint s
3074  have hzero_f : simplexWinding f = 0 := by
3075    simpa [f, singularWinding] using hzero
3076  obtain ⟨b, hb⟩ :=
3077    closedSingularOneCycle_bounds_of_zero_winding_coneCirclePoint f hendpoints hzero_f
3078  refine ⟨b, ?_⟩
3079  have hs : singularOneSimplexOfMap f = s := by
3080    unfold f singularOneSimplexOfMap
3081    rw [Equiv.symm_apply_apply]
3082  have hcycles :
3083      ModuleCat.Hom.hom
3084          (closedSingularOneCycle (singularOneSimplexOfMap f)
3085            (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints)) 1 =
3086        ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 := by
3087    have hinj_iCycles :
3088        Function.Injective
3089          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
3090      (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
3091    apply hinj_iCycles
3092    change ModuleCat.Hom.hom
3093        ((closedSingularOneCycle (singularOneSimplexOfMap f)
3094            (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints)) ≫
3095          sphereOneSingularIntChainComplex.iCycles 1) 1 =
3096      ModuleCat.Hom.hom ((closedSingularOneCycle s hfaces) ≫
3097          sphereOneSingularIntChainComplex.iCycles 1) 1
3098    rw [closedSingularOneCycle_iCycles, closedSingularOneCycle_iCycles]
3099    rw [hs]
3100  rw [← hcycles]
3101  exact hb
3102
3103open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3104/-- Scalar form of the zero-winding closed-generator cone theorem.  Any integer
3105multiple of a zero-winding closed singular generator bounds. -/
3106theorem closedSingularOneCycle_zsmul_bounds_of_zero_singularWinding
3107    (s : SingularOneSimplex)
3108    (hfaces :
3109      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
3110        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
3111    (hzero : singularWinding s = 0) (n : ModuleCat.of ℤ ℤ) :
3112    ∃ b : sphereOneSingularIntChainComplex.X 2,
3113      ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) n =
3114        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b := by
3115  obtain ⟨b, hb⟩ := closedSingularOneCycle_bounds_of_zero_singularWinding s hfaces hzero
3116  refine ⟨n • b, ?_⟩
3117  rw [map_zsmul]
3118  have hlin :
3119      ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) n =
3120        n • ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) (1 : ℤ) := by
3121    conv_lhs => rw [show n = n • (1 : ModuleCat.of ℤ ℤ) by simp]
3122    rw [map_zsmul]
3123  rw [hlin, ← hb]
3124
3125open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3126/-- Converse transport for `C₂`: if a raw singular `2`-chain has raw boundary
3127equal to the image of a free `C₁` chain, then its free-coordinate representative
3128has that free boundary.  This closes the representational gap between raw-prism
3129and free-prism witnesses; the remaining mathematical work is to build the raw
3130prism itself. -/
3131theorem singularTwoBoundaryFree_eq_of_rawBoundary_eq
3132    (b : sphereOneSingularIntChainComplex.X 2) (u : singularOneChainFree)
3133    (hb : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1) b =
3134      ModuleCat.Hom.hom singularOneChainFreeToChain u) :
3135    ModuleCat.Hom.hom singularTwoBoundaryFree
3136      (ModuleCat.Hom.hom singularTwoChainToFree b) = u := by
3137  have hcomp := congrArg (fun f =>
3138      ModuleCat.Hom.hom f (ModuleCat.Hom.hom singularTwoChainToFree b))
3139    singularTwoChainFreeToChain_boundary_free
3140  simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply] at hcomp
3141  have htwo :
3142      ModuleCat.Hom.hom singularTwoChainFreeToChain
3143        (ModuleCat.Hom.hom singularTwoChainToFree b) = b := by
3144    have hid := congrArg (fun f => ModuleCat.Hom.hom f b)
3145      singularTwoChainFreeIso.hom_inv_id
3146    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
3147      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
3148    exact hid
3149  rw [htwo, hb] at hcomp
3150  have hround :
3151      ModuleCat.Hom.hom singularOneChainToFree
3152        (ModuleCat.Hom.hom singularOneChainFreeToChain u) = u := by
3153    have hid := congrArg (fun f => ModuleCat.Hom.hom f u)
3154      singularOneChainFreeIso.inv_hom_id
3155    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
3156      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
3157    exact hid
3158  rw [hround] at hcomp
3159  exact hcomp.symm
3160
3161open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3162/-- Element-level exactness for a `ModuleCat` cokernel cofork: an element killed
3163by the cokernel projection lies in the range of the previous map. -/
3164theorem exists_preimage_of_isColimit_cokernel_eq_zero
3165    {R : Type} [Ring R] {M N Q : ModuleCat R} {f : M ⟶ N} {p : N ⟶ Q}
3166    {w : f ≫ p = 0} (hcol : IsColimit (CokernelCofork.ofπ p w))
3167    (x : N) (hx : ModuleCat.Hom.hom p x = 0) :
3168    ∃ m : M, ModuleCat.Hom.hom f m = x := by
3169  let desc : Q ⟶ ModuleCat.of R (N ⧸ LinearMap.range (ModuleCat.Hom.hom f)) :=
3170    hcol.desc (ModuleCat.cokernelCocone f)
3171  have hpdesc : p ≫ desc = (ModuleCat.cokernelCocone f).π := by
3172    simpa [desc, ModuleCat.cokernelCocone, CokernelCofork.ofπ] using
3173      hcol.fac (ModuleCat.cokernelCocone f) WalkingParallelPair.one
3174  have hq : Submodule.Quotient.mk x = (0 : N ⧸ LinearMap.range (ModuleCat.Hom.hom f)) := by
3175    have hxdesc : ModuleCat.Hom.hom (p ≫ desc) x = 0 := by
3176      simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply, hx, map_zero]
3177    rw [hpdesc] at hxdesc
3178    simpa [ModuleCat.cokernelCocone] using hxdesc
3179  have hxrange : x ∈ LinearMap.range (ModuleCat.Hom.hom f) := by
3180    exact (Submodule.Quotient.mk_eq_zero (LinearMap.range (ModuleCat.Hom.hom f))).mp hq
3181  rcases LinearMap.mem_range.mp hxrange with ⟨m, hm⟩
3182  exact ⟨m, hm⟩
3183
3184/-- In the downward natural-number chain-complex shape, the predecessor of degree
3185`1` is degree `2`. -/
3186theorem down_prev_one_eq_two : (ComplexShape.down ℕ).prev 1 = 2 := by
3187  unfold ComplexShape.prev
3188  split
3189  · rename_i h
3190    apply (ComplexShape.down ℕ).prev_eq
3191    · exact h.choose_spec
3192    · rw [ComplexShape.down_Rel]; norm_num
3193  · rename_i h
3194    exfalso
3195    apply h
3196    exact ⟨2, by rw [ComplexShape.down_Rel]; norm_num⟩
3197
3198open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3199/-- A degree-`1` cycle whose homology class is zero is explicitly a degree-`2`
3200boundary.  This is the element-level exactness of the homology cokernel
3201specialized to the circle singular chain complex. -/
3202theorem cycle_eq_boundary_of_homologyπ_eq_zero
3203    (z : sphereOneSingularIntChainComplex.cycles 1)
3204    (hz : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1) z = 0) :
3205    ∃ b : sphereOneSingularIntChainComplex.X 2,
3206      z = ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b := by
3207  let S := sphereOneSingularIntChainComplex.sc 1
3208  have hcol := ShortComplex.homologyIsCokernel S
3209  have hex := exists_preimage_of_isColimit_cokernel_eq_zero hcol z hz
3210  change ∃ b : sphereOneSingularIntChainComplex.X ((ComplexShape.down ℕ).prev 1),
3211      ModuleCat.Hom.hom
3212        (sphereOneSingularIntChainComplex.toCycles ((ComplexShape.down ℕ).prev 1) 1) b = z at hex
3213  rw [down_prev_one_eq_two] at hex
3214  rcases hex with ⟨b, hb⟩
3215  exact ⟨b, hb.symm⟩
3216
3217open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3218/-- The winding chain map annihilates the boundary of every singular `2`-simplex
3219generator.  This is the per-generator form of `∂₂ ≫ W = 0`. -/
3220theorem windingChainMap_boundary_generator (s : SingularTwoSimplex) :
3221    (Sigma.ι (fun _ : SingularTwoSimplex => ModuleCat.of ℤ ℤ) s)
3222      ≫ sphereOneSingularIntChainComplex.d 2 1 ≫ windingChainMap = 0 := by
3223  dsimp [sphereOneSingularIntChainComplex,
3224    AlgebraicTopology.singularChainComplexFunctor,
3225    AlgebraicTopology.SSet.singularChainComplexFunctor,
3226    AlgebraicTopology.alternatingFaceMapComplex, sigmaConst]
3227  rw [AlgebraicTopology.AlternatingFaceMapComplex.obj_d_eq]
3228  dsimp [AlgebraicTopology.AlternatingFaceMapComplex.objD]
3229  simp only [Fin.sum_univ_three, Fin.val_zero, pow_zero, one_zsmul, Fin.val_one, pow_one,
3230    Fin.val_two, neg_one_sq, neg_zsmul, Preadditive.comp_add, Preadditive.comp_neg,
3231    Preadditive.add_comp, Preadditive.neg_comp]
3232  simp only [CategoryTheory.SimplicialObject.δ]
3233  dsimp [sigmaConst]
3234  simp only [Sigma.ι_comp_map'_assoc, Category.id_comp]
3235  rw [windingChainMap_ι, windingChainMap_ι, windingChainMap_ι]
3236  have hb := singularWinding_boundary s
3237  simp only [CategoryTheory.SimplicialObject.δ] at hb
3238  apply ModuleCat.hom_ext
3239  apply LinearMap.ext_ring
3240  simp only [ModuleCat.hom_add, ModuleCat.hom_neg, ModuleCat.hom_ofHom, ModuleCat.hom_zero,
3241    LinearMap.add_apply, LinearMap.neg_apply, LinearMap.zero_apply,
3242    LinearMap.toSpanSingleton_apply, one_smul]
3243  linarith [hb]
3244
3245open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3246/-- **The winding chain map descends to homology.**  It annihilates the entire
3247degree-`2` boundary `∂₂`, hence factors through `H₁(S¹;ℤ)`. -/
3248theorem windingChainMap_boundary :
3249    sphereOneSingularIntChainComplex.d 2 1 ≫ windingChainMap = 0 := by
3250  apply Limits.Sigma.hom_ext
3251  intro s
3252  simp only [Limits.comp_zero]
3253  exact windingChainMap_boundary_generator s
3254
3255open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3256/-- The winding number of the fundamental singular `1`-simplex is `1`. -/
3257theorem singularWinding_fundamentalSimplex :
3258    singularWinding CircleFundamentalSimplex.fundamentalSphereOneSingularOneSimplex = 1 := by
3259  rw [singularWinding,
3260    show TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))
3261          CircleFundamentalSimplex.fundamentalSphereOneSingularOneSimplex
3262        = CircleFundamentalSimplex.fundamentalCirclePathMap from
3263      (TopCat.toSSetObjEquiv (TopCat.sphere 1) (op (SimplexCategory.mk 1))).apply_symm_apply _]
3264  exact simplexWinding_fundamental
3265
3266open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3267/-- **The winding chain map sends the fundamental cycle to `1`.**  Together with
3268`windingChainMap_boundary` this exhibits the integer comparison map
3269`ℤ → H₁(S¹;ℤ)` as split-injective: `[fundamental]` has infinite order. -/
3270theorem windingChainMap_fundamental :
3271    CircleH1Computation.fundamentalSphereOneSingularOneChain ≫ windingChainMap
3272      = ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ ℝ 1) := by
3273  rw [CircleH1Computation.fundamentalSphereOneSingularOneChain, windingChainMap_ι,
3274    singularWinding_fundamentalSimplex]
3275
3276/-! ### Descent to homology: the fundamental class has infinite order
3277
3278The chain-level data above is exactly what is needed to descend the winding
3279number to a homomorphism `H₁(S¹;ℤ) → ℝ` and to exhibit the integer comparison
3280map `ℤ → H₁(S¹;ℤ)`, `n ↦ n·[fundamental]`, as a (split) monomorphism.  This is
3281the *injective* half of `H₁(S¹;ℤ) ≅ ℤ`: distinct integer multiples of the
3282fundamental loop are never homologous, i.e. `[fundamental]` has infinite order.
3283The *surjective* (generation) half, that every singular `1`-cycle is homologous
3284to an integer multiple of the fundamental cycle, is **not** proved here; it
3285requires the simplicial prism / barycentric subdivision operator, which
3286Mathlib's singular homology does not provide. -/
3287
3288open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3289/-- **The winding number descends to homology** `H₁(S¹;ℤ) → ℝ`.  Because the
3290winding chain map annihilates `∂₂` (`windingChainMap_boundary`), it factors
3291through the degree-`1` opcycles and hence through `H₁`. -/
3292noncomputable def windingHomologyMap :
3293    sphereOneSingularIntChainComplex.homology 1 ⟶ ModuleCat.of ℤ ℝ :=
3294  sphereOneSingularIntChainComplex.homologyι 1
3295    ≫ sphereOneSingularIntChainComplex.descOpcycles windingChainMap 2 (by simp)
3296        windingChainMap_boundary
3297
3298open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3299/-- The fundamental singular `1`-chain, lifted to the cycle object using its
3300zero-boundary proof. -/
3301noncomputable def fundamentalCycle :
3302    ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.cycles 1 :=
3303  sphereOneSingularIntChainComplex.liftCycles
3304      CircleH1Computation.fundamentalSphereOneSingularOneChain 0 (by simp)
3305      CircleH1Computation.fundamentalSphereOneSingularOneChain_boundary_zero
3306
3307open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3308/-- Generation-shaped form of the zero-winding closed-edge cone theorem.  The
3309integer coefficient of the fundamental cycle is `0`; all of the edge is accounted
3310for by the explicit cone boundary. -/
3311theorem closedSingularOneCycle_boundary_generate_of_zero_winding_coneCirclePoint
3312    (f : OneSimplex)
3313    (hendpoints :
3314      f (stdSimplex.vertex (1 : Fin 2)) =
3315        f (stdSimplex.vertex (0 : Fin 2)))
3316    (hzero : simplexWinding f = 0) :
3317    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
3318      ModuleCat.Hom.hom
3319        (closedSingularOneCycle (singularOneSimplexOfMap f)
3320          (singularOneSimplexOfMap_faces_eq_of_endpoints f hendpoints)) 1 =
3321        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
3322          ModuleCat.Hom.hom fundamentalCycle n := by
3323  obtain ⟨b, hb⟩ :=
3324    closedSingularOneCycle_bounds_of_zero_winding_coneCirclePoint f hendpoints hzero
3325  refine ⟨0, b, ?_⟩
3326  rw [map_zero]
3327  simp
3328  exact hb.symm
3329
3330open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3331/-- Algebraic consumer for a closed-edge prism to an integer multiple of the
3332fundamental cycle.  If a free `2`-chain has boundary equal to the closed edge
3333generator minus the free-coordinate image of `n` times the fundamental cycle,
3334then the closed edge cycle is generated by the fundamental cycle modulo a
3335`2`-boundary. -/
3336theorem closedSingularOneCycle_boundary_generate_of_freePrismToFundamental
3337    (s : SingularOneSimplex)
3338    (hfaces :
3339      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
3340        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
3341    (n : ModuleCat.of ℤ ℤ) (B : singularTwoChainFree)
3342    (hB : ModuleCat.Hom.hom singularTwoBoundaryFree B =
3343      ModuleCat.freeMk s -
3344        ModuleCat.Hom.hom singularOneChainToFree
3345          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3346            (ModuleCat.Hom.hom fundamentalCycle n))) :
3347    ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 =
3348      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1)
3349        (ModuleCat.Hom.hom singularTwoChainFreeToChain B) +
3350        ModuleCat.Hom.hom fundamentalCycle n := by
3351  have hraw := rawBoundary_eq_of_singularTwoBoundaryFree_eq B
3352    (ModuleCat.freeMk s -
3353      ModuleCat.Hom.hom singularOneChainToFree
3354        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3355          (ModuleCat.Hom.hom fundamentalCycle n))) hB
3356  have hround :
3357      ModuleCat.Hom.hom singularOneChainFreeToChain
3358        (ModuleCat.Hom.hom singularOneChainToFree
3359          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3360            (ModuleCat.Hom.hom fundamentalCycle n))) =
3361        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3362          (ModuleCat.Hom.hom fundamentalCycle n) := by
3363    have hid := congrArg
3364      (fun f => ModuleCat.Hom.hom f
3365        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3366          (ModuleCat.Hom.hom fundamentalCycle n)))
3367      singularOneChainFreeIso.hom_inv_id
3368    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
3369      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
3370    exact hid
3371  rw [map_sub, singularOneChainFreeToChain_freeMk, hround] at hraw
3372  have hinj_iCycles :
3373      Function.Injective
3374        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
3375    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
3376  apply hinj_iCycles
3377  rw [map_add]
3378  change ModuleCat.Hom.hom
3379      ((closedSingularOneCycle s hfaces) ≫ sphereOneSingularIntChainComplex.iCycles 1) 1 =
3380    ModuleCat.Hom.hom
3381      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
3382        sphereOneSingularIntChainComplex.iCycles 1)
3383        (ModuleCat.Hom.hom singularTwoChainFreeToChain B) +
3384      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3385        (ModuleCat.Hom.hom fundamentalCycle n)
3386  rw [closedSingularOneCycle_iCycles, HomologicalComplex.toCycles_i, hraw]
3387  rw [sub_add_cancel]
3388  rfl
3389
3390open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3391/-- Raw-chain version of
3392`closedSingularOneCycle_boundary_generate_of_freePrismToFundamental`. -/
3393theorem closedSingularOneCycle_boundary_generate_of_rawPrismToFundamental
3394    (s : SingularOneSimplex)
3395    (hfaces :
3396      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
3397        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
3398    (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2)
3399    (hb : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1) b =
3400      ModuleCat.Hom.hom singularOneChainFreeToChain (ModuleCat.freeMk s) -
3401        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3402          (ModuleCat.Hom.hom fundamentalCycle n)) :
3403    ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) 1 =
3404      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
3405        ModuleCat.Hom.hom fundamentalCycle n := by
3406  have hinj_iCycles :
3407      Function.Injective
3408        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
3409    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
3410  apply hinj_iCycles
3411  rw [map_add]
3412  change ModuleCat.Hom.hom
3413      ((closedSingularOneCycle s hfaces) ≫ sphereOneSingularIntChainComplex.iCycles 1) 1 =
3414    ModuleCat.Hom.hom
3415      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
3416        sphereOneSingularIntChainComplex.iCycles 1) b +
3417      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3418        (ModuleCat.Hom.hom fundamentalCycle n)
3419  rw [closedSingularOneCycle_iCycles, HomologicalComplex.toCycles_i, hb,
3420    singularOneChainFreeToChain_freeMk]
3421  rw [sub_add_cancel]
3422  rfl
3423
3424open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3425/-- **The integer comparison map** `ℤ → H₁(S¹;ℤ)`, `n ↦ n·[fundamental]`.  The
3426fundamental singular `1`-chain is a cycle (`fundamentalSphereOneSingularOneChain_boundary_zero`),
3427so it lifts to the degree-`1` cycles and projects to a homology class. -/
3428noncomputable def fundamentalHomologyClass :
3429    ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.homology 1 :=
3430  fundamentalCycle ≫ sphereOneSingularIntChainComplex.homologyπ 1
3431
3432open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3433/-- **The winding homomorphism is a retraction of the comparison map.**  The
3434composite `ℤ → H₁(S¹;ℤ) → ℝ` is the standard inclusion `n ↦ n·1`.  This is the
3435homology-level form of "the winding number is inverse to the fundamental loop
3436class": it pins `[fundamental]` to the real number `1`. -/
3437theorem fundamentalHomologyClass_comp_windingHomologyMap :
3438    fundamentalHomologyClass ≫ windingHomologyMap
3439      = ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ ℝ 1) := by
3440  rw [fundamentalHomologyClass, fundamentalCycle, windingHomologyMap, Category.assoc,
3441    HomologicalComplex.homology_π_ι_assoc, HomologicalComplex.p_descOpcycles,
3442    HomologicalComplex.liftCycles_i_assoc]
3443  exact windingChainMap_fundamental
3444
3445open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3446/-- **`ℤ → H₁(S¹;ℤ)`, `n ↦ n·[fundamental]`, is a monomorphism.**  The fundamental
3447class has infinite order: distinct integer multiples of the once-around loop are
3448never homologous.  This is the injective half of `H₁(S¹;ℤ) ≅ ℤ`, proved by hand
3449from the covering-space winding invariant with no axioms and no `sorry`.
3450
3451It is *not* the full isomorphism: surjectivity (that the fundamental loop
3452*generates* `H₁`) is the separate generation theorem and is left open. -/
3453theorem fundamentalHomologyClass_mono : Mono fundamentalHomologyClass := by
3454  have hmono : Mono (fundamentalHomologyClass ≫ windingHomologyMap) := by
3455    rw [fundamentalHomologyClass_comp_windingHomologyMap, ModuleCat.mono_iff_injective]
3456    intro a b hab
3457    have hcast : (a : ℝ) = (b : ℝ) := by
3458      simpa [LinearMap.toSpanSingleton_apply, zsmul_eq_mul] using hab
3459    exact_mod_cast hcast
3460  exact mono_of_mono fundamentalHomologyClass windingHomologyMap
3461
3462open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3463/-- **`H₁(S¹;ℤ)` is nonzero, unconditionally.**  The fundamental loop is a nonzero
3464homology class: the winding retraction sends it to the real number `1`
3465(`fundamentalHomologyClass_comp_windingHomologyMap`).  Were the homology the zero
3466module, that comparison morphism would be the zero map, forcing `1 = 0` in `ℝ`.
3467
3468The decisive point: nonvanishing needs only the *existence* of one nonzero class,
3469which is exactly the injective half already in hand (`fundamentalHomologyClass_mono`).
3470It does **not** use the surjectivity/generation theorem, so it is axiom-free and
3471`sorry`-free, and independent of `zeroWindingCycles_bound`. -/
3472theorem homologyOne_nonzero :
3473    ¬ IsZero (sphereOneSingularIntChainComplex.homology 1) := by
3474  intro hzero
3475  have hfz : fundamentalHomologyClass = 0 := hzero.eq_zero_of_tgt _
3476  have h0 : fundamentalHomologyClass ≫ windingHomologyMap = 0 := by
3477    rw [hfz, zero_comp]
3478  rw [fundamentalHomologyClass_comp_windingHomologyMap] at h0
3479  have h1 := congrArg
3480    (fun g : ModuleCat.of ℤ ℤ ⟶ ModuleCat.of ℤ ℝ => ModuleCat.Hom.hom g (1 : ℤ)) h0
3481  simp [ModuleCat.hom_ofHom, LinearMap.toSpanSingleton_apply] at h1
3482
3483open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3484/-- **The strict-T8 Mathlib nonvanishing target, discharged unconditionally.**
3485`MathlibCohomologyBridge.circleH1Z` is `rfl`-equal to
3486`sphereOneSingularIntChainComplex.homology 1`
3487(`CircleH1Computation.singularHomologyFunctorSphereOneInt_eq_homologyOne`), so the
3488nonvanishing of the imported Mathlib singular `H₁(S¹;ℤ)` object is exactly
3489`homologyOne_nonzero`.  This is the concrete circle-H1 computation the strict
3490T-1-to-T8 frontier closure was waiting on. -/
3491theorem circleH1ZNonzero_unconditional :
3492    MathlibCohomologyBridge.circleH1ZNonzero := by
3493  intro hzero
3494  exact homologyOne_nonzero
3495    (hzero.of_iso CircleH1Computation.singularHomologyFunctorSphereOneIntIsoHomologyOne.symm)
3496
3497open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3498/-- The Mathlib circle-linking backend object now exists unconditionally, built
3499straight from `circleH1ZNonzero_unconditional`. -/
3500theorem mathlibCircleLinkingBackend_unconditional :
3501    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
3502  MathlibCohomologyBridge.mathlibCircleLinkingBackend_of_circleH1ZNonzero
3503    circleH1ZNonzero_unconditional
3504
3505open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3506/-- The exact remaining generation statement, in homology-level form.  It says
3507that every degree-`1` homology class is an integer multiple of the fundamental
3508circle class.  This is deliberately stated as surjectivity of the already-built
3509comparison morphism `fundamentalHomologyClass`; proving this is the remaining
3510surjective half of `H₁(S¹;ℤ) ≅ ℤ`.
3511
3512Note: this is **not** needed for the strict T-1-to-T8 frontier closure, which only
3513requires nonvanishing (`circleH1ZNonzero_unconditional`).  Surjectivity is the
3514stronger statement that upgrades nonvanishing to the full isomorphism. -/
3515def fundamentalHomologyClass_surjective : Prop :=
3516  Function.Surjective (ModuleCat.Hom.hom fundamentalHomologyClass)
3517
3518open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3519/-- If the fundamental circle class generates first homology, then the
3520homology-level winding map is injective.  The proof uses the already-proved
3521identity `fundamentalHomologyClass ≫ windingHomologyMap = (n ↦ n)`. -/
3522theorem windingHomologyMap_mono_of_fundamentalHomologyClass_surjective
3523    (hsurj : fundamentalHomologyClass_surjective) :
3524    Mono windingHomologyMap := by
3525  rw [ModuleCat.mono_iff_injective]
3526  intro x y hxy
3527  obtain ⟨a, rfl⟩ := hsurj x
3528  obtain ⟨b, rfl⟩ := hsurj y
3529  have hcomp :
3530      ModuleCat.Hom.hom (fundamentalHomologyClass ≫ windingHomologyMap) a =
3531        ModuleCat.Hom.hom (fundamentalHomologyClass ≫ windingHomologyMap) b := by
3532    simpa only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply] using hxy
3533  rw [fundamentalHomologyClass_comp_windingHomologyMap] at hcomp
3534  have hcast : (a : ℝ) = (b : ℝ) := by
3535    simpa [LinearMap.toSpanSingleton_apply, zsmul_eq_mul] using hcomp
3536  have hab : a = b := by
3537    exact_mod_cast hcast
3538  rw [hab]
3539
3540open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3541/-- Winding already proves injectivity, so the remaining generation statement
3542upgrades the fundamental-class comparison map to a bijection of underlying
3543modules. -/
3544theorem fundamentalHomologyClass_bijective_of_surjective
3545    (hsurj : fundamentalHomologyClass_surjective) :
3546    Function.Bijective (ModuleCat.Hom.hom fundamentalHomologyClass) := by
3547  constructor
3548  · haveI : Mono fundamentalHomologyClass := fundamentalHomologyClass_mono
3549    exact (ModuleCat.mono_iff_injective fundamentalHomologyClass).mp inferInstance
3550  · exact hsurj
3551
3552open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3553/-- If the fundamental class generates first homology, then the comparison
3554`ℤ → H₁(S¹;ℤ)` is an isomorphism in `ModuleCat`.  The proof is purely categorical:
3555generation gives `Epi`; winding gives `Mono`; modules are balanced, so mono+epi is
3556an isomorphism. -/
3557noncomputable def fundamentalHomologyClassIso_of_surjective
3558    (hsurj : fundamentalHomologyClass_surjective) :
3559    ModuleCat.of ℤ ℤ ≅ sphereOneSingularIntChainComplex.homology 1 := by
3560  haveI : Mono fundamentalHomologyClass := fundamentalHomologyClass_mono
3561  haveI : Epi fundamentalHomologyClass :=
3562    (ModuleCat.epi_iff_surjective fundamentalHomologyClass).mpr hsurj
3563  haveI : IsIso fundamentalHomologyClass := isIso_of_mono_of_epi fundamentalHomologyClass
3564  exact asIso fundamentalHomologyClass
3565
3566open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3567/-- **Final handoff criterion for the remaining Mathlib element.**  The exact
3568Mathlib target `H₁(TopCat.sphere 1;ℤ) ≅ ℤ` follows from the single still-open
3569generation theorem that the fundamental class is surjective on first homology. -/
3570theorem circleH1ZIsoInt_of_fundamentalHomologyClass_surjective
3571    (hsurj : fundamentalHomologyClass_surjective) :
3572    MathlibCohomologyBridge.circleH1ZIsoInt :=
3573  ⟨(fundamentalHomologyClassIso_of_surjective hsurj).symm⟩
3574
3575open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3576/-- The concrete cycle-representative generation statement.  Every cycle
3577representative of a degree-`1` homology class has the same homology class as some
3578integer multiple of the fundamental cycle.
3579
3580This is closer to the geometric missing theorem than bare surjectivity of
3581`fundamentalHomologyClass`: the remaining work is to prove this by showing that
3582the difference between a cycle and its matching winding multiple bounds. -/
3583def fundamentalCycleClass_generates : Prop :=
3584  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
3585    ∃ n : ModuleCat.of ℤ ℤ,
3586      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1) z =
3587        ModuleCat.Hom.hom fundamentalHomologyClass n
3588
3589open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3590/-- Cycle-representative generation implies surjectivity of the fundamental
3591homology class map.  Mathlib's `homologyπ` is an epimorphism, so every homology
3592class has a cycle representative; the generation statement then identifies that
3593representative's class with an integer multiple of the fundamental class. -/
3594theorem fundamentalHomologyClass_surjective_of_cycleClass_generates
3595    (hgen : fundamentalCycleClass_generates) :
3596    fundamentalHomologyClass_surjective := by
3597  intro y
3598  have hπsurj :
3599      Function.Surjective
3600        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1)) :=
3601    (ModuleCat.epi_iff_surjective (sphereOneSingularIntChainComplex.homologyπ 1)).mp inferInstance
3602  obtain ⟨z, hz⟩ := hπsurj y
3603  obtain ⟨n, hn⟩ := hgen z
3604  exact ⟨n, by rw [← hz, hn]⟩
3605
3606open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3607/-- Final Mathlib H₁ closure from the concrete cycle-representative generation
3608statement.  This is now the exact next theorem to prove geometrically. -/
3609theorem circleH1ZIsoInt_of_fundamentalCycleClass_generates
3610    (hgen : fundamentalCycleClass_generates) :
3611    MathlibCohomologyBridge.circleH1ZIsoInt :=
3612  circleH1ZIsoInt_of_fundamentalHomologyClass_surjective
3613    (fundamentalHomologyClass_surjective_of_cycleClass_generates hgen)
3614
3615open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3616/-- The fully concrete chain-level generation statement inside the cycle object:
3617every degree-`1` cycle is a lifted singular `2`-boundary plus an integer multiple
3618of the lifted fundamental cycle.
3619
3620This is now the geometric work left to prove.  A proof should construct the
3621`b : C₂(S¹;ℤ)` witness, usually by subdivision/prism machinery or an equivalent
3622singular filling of the zero-winding remainder. -/
3623def fundamentalCycle_boundary_generates : Prop :=
3624  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
3625    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
3626      z =
3627        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
3628          ModuleCat.Hom.hom fundamentalCycle n
3629
3630open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3631/-- A concrete boundary decomposition of every cycle implies cycle-class
3632generation.  The `toCycles 2 1` term dies under `homologyπ`, so the homology class
3633of the cycle is exactly the class of the corresponding integer multiple of the
3634fundamental cycle. -/
3635theorem fundamentalCycleClass_generates_of_boundary_generates
3636    (hgen : fundamentalCycle_boundary_generates) :
3637    fundamentalCycleClass_generates := by
3638  intro z
3639  obtain ⟨n, b, hz⟩ := hgen z
3640  refine ⟨n, ?_⟩
3641  rw [hz, map_add]
3642  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
3643      sphereOneSingularIntChainComplex.homologyπ 1) b +
3644    ModuleCat.Hom.hom (fundamentalCycle ≫ sphereOneSingularIntChainComplex.homologyπ 1) n =
3645      ModuleCat.Hom.hom fundamentalHomologyClass n
3646  rw [sphereOneSingularIntChainComplex.toCycles_comp_homologyπ]
3647  simp [fundamentalHomologyClass]
3648
3649open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3650/-- Final Mathlib H₁ closure from the concrete boundary-generation theorem. -/
3651theorem circleH1ZIsoInt_of_fundamentalCycle_boundary_generates
3652    (hgen : fundamentalCycle_boundary_generates) :
3653    MathlibCohomologyBridge.circleH1ZIsoInt :=
3654  circleH1ZIsoInt_of_fundamentalCycleClass_generates
3655    (fundamentalCycleClass_generates_of_boundary_generates hgen)
3656
3657open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3658/-- Winding of a degree-`1` cycle, computed by including it into `C₁(S¹;ℤ)` and
3659applying the winding chain map. -/
3660noncomputable def cycleWinding
3661    (z : sphereOneSingularIntChainComplex.cycles 1) : ℝ :=
3662  ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) z
3663
3664open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3665/-- Applying the descended homology-level winding map to the homology class of a
3666cycle recovers the chain-level winding of that cycle. -/
3667theorem homologyπ_windingHomologyMap_apply
3668    (z : sphereOneSingularIntChainComplex.cycles 1) :
3669    ModuleCat.Hom.hom windingHomologyMap
3670      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1) z) =
3671        cycleWinding z := by
3672  unfold cycleWinding windingHomologyMap
3673  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1 ≫
3674      sphereOneSingularIntChainComplex.homologyι 1 ≫
3675        sphereOneSingularIntChainComplex.descOpcycles windingChainMap 2 (by simp)
3676          windingChainMap_boundary) z =
3677    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) z
3678  rw [HomologicalComplex.homology_π_ι_assoc, HomologicalComplex.p_descOpcycles]
3679
3680open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3681/-- The lifted fundamental cycle has winding equal to its integer coefficient. -/
3682theorem cycleWinding_fundamentalCycle (n : ModuleCat.of ℤ ℤ) :
3683    cycleWinding (ModuleCat.Hom.hom fundamentalCycle n) = (n : ℝ) := by
3684  unfold cycleWinding
3685  change ModuleCat.Hom.hom
3686      (fundamentalCycle ≫ sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) n =
3687    (n : ℝ)
3688  rw [fundamentalCycle, HomologicalComplex.liftCycles_i_assoc]
3689  rw [windingChainMap_fundamental]
3690  simp [LinearMap.toSpanSingleton_apply]
3691
3692open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3693/-- Winding of a closed singular generator cycle is the integer coefficient times
3694the winding of the underlying singular simplex. -/
3695theorem cycleWinding_closedSingularOneCycle (s : SingularOneSimplex)
3696    (hfaces :
3697      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) s =
3698        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) s)
3699    (n : ModuleCat.of ℤ ℤ) :
3700    cycleWinding (ModuleCat.Hom.hom (closedSingularOneCycle s hfaces) n) =
3701      (n : ℝ) * singularWinding s := by
3702  unfold cycleWinding
3703  change ModuleCat.Hom.hom
3704      (closedSingularOneCycle s hfaces ≫
3705        sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) n =
3706    (n : ℝ) * singularWinding s
3707  rw [closedSingularOneCycle, HomologicalComplex.liftCycles_i_assoc]
3708  rw [windingChainMap_ι]
3709  simp [LinearMap.toSpanSingleton_apply]
3710
3711/-- A single finite-sum term in a closed-generator decomposition of a cycle. -/
3712structure ClosedSingularOneCycleTerm where
3713  simplex : SingularOneSimplex
3714  faces_eq :
3715    (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) simplex =
3716      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) simplex
3717  coeff : ModuleCat.of ℤ ℤ
3718
3719open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3720/-- The cycle represented by one closed-generator term. -/
3721noncomputable def ClosedSingularOneCycleTerm.cycle
3722    (t : ClosedSingularOneCycleTerm) :
3723    sphereOneSingularIntChainComplex.cycles 1 :=
3724  ModuleCat.Hom.hom (closedSingularOneCycle t.simplex t.faces_eq) t.coeff
3725
3726open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3727/-- The cycle represented by a finite list of closed-generator terms. -/
3728noncomputable def closedSingularOneCycleList :
3729    List ClosedSingularOneCycleTerm → sphereOneSingularIntChainComplex.cycles 1
3730  | [] => 0
3731  | t :: ts => t.cycle + closedSingularOneCycleList ts
3732
3733open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3734/-- The underlying `C₁` chain represented by one closed-generator term. -/
3735noncomputable def ClosedSingularOneCycleTerm.chain
3736    (t : ClosedSingularOneCycleTerm) :
3737    sphereOneSingularIntChainComplex.X 1 :=
3738  ModuleCat.Hom.hom
3739    (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) t.simplex) t.coeff
3740
3741open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3742/-- The underlying `C₁` chain represented by a finite list of closed-generator
3743terms. -/
3744noncomputable def closedSingularOneChainList :
3745    List ClosedSingularOneCycleTerm → sphereOneSingularIntChainComplex.X 1
3746  | [] => 0
3747  | t :: ts => t.chain + closedSingularOneChainList ts
3748
3749open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3750/-- Including a one-term closed-generator cycle into `C₁` gives the corresponding
3751raw singular-chain generator with its coefficient. -/
3752theorem ClosedSingularOneCycleTerm.cycle_iCycles
3753    (t : ClosedSingularOneCycleTerm) :
3754    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) t.cycle =
3755      t.chain := by
3756  rw [ClosedSingularOneCycleTerm.cycle, ClosedSingularOneCycleTerm.chain]
3757  change ModuleCat.Hom.hom
3758      (closedSingularOneCycle t.simplex t.faces_eq ≫
3759        sphereOneSingularIntChainComplex.iCycles 1) t.coeff =
3760    ModuleCat.Hom.hom
3761      (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) t.simplex) t.coeff
3762  rw [closedSingularOneCycle_iCycles]
3763  rfl
3764
3765open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3766/-- Including a finite closed-generator cycle list into `C₁` gives the matching
3767finite raw chain list. -/
3768theorem closedSingularOneCycleList_iCycles :
3769    ∀ ts : List ClosedSingularOneCycleTerm,
3770      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3771        (closedSingularOneCycleList ts) = closedSingularOneChainList ts
3772  | [] => by
3773      unfold closedSingularOneCycleList closedSingularOneChainList
3774      simp
3775  | t :: ts => by
3776      unfold closedSingularOneCycleList closedSingularOneChainList
3777      rw [map_add, t.cycle_iCycles, closedSingularOneCycleList_iCycles ts]
3778
3779open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3780/-- Raw-chain closed-generator spanning: every cycle, after inclusion into `C₁`,
3781is a finite raw sum of closed singular generators.  This is closer to the actual
3782finite-support cancellation theorem than `closedSingularOneCycleList_spans`. -/
3783def closedSingularOneChainList_spansCycles : Prop :=
3784  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
3785    ∃ ts : List ClosedSingularOneCycleTerm,
3786      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) z =
3787        closedSingularOneChainList ts
3788
3789open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3790/-- The remaining finite graph/cancellation theorem in explicit free-module
3791coordinates: every element of the free edge module whose free boundary is zero is
3792a finite sum of closed singular edge cycles. -/
3793def freeBoundaryKernel_decomposes : Prop :=
3794  ∀ c : singularOneChainFree,
3795    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
3796      ∃ ts : List ClosedSingularOneCycleTerm,
3797        c = ModuleCat.Hom.hom singularOneChainToFree (closedSingularOneChainList ts)
3798
3799open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3800/-- The free-boundary kernel decomposition theorem implies the raw-chain spanning
3801statement for actual cycle representatives. -/
3802theorem closedSingularOneChainList_spansCycles_of_freeBoundaryKernel_decomposes
3803    (hker : freeBoundaryKernel_decomposes) :
3804    closedSingularOneChainList_spansCycles := by
3805  intro z
3806  let c : singularOneChainFree :=
3807    ModuleCat.Hom.hom singularOneChainToFree
3808      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) z)
3809  have hc0 : ModuleCat.Hom.hom singularOneBoundaryFree c = 0 := by
3810    unfold c
3811    change ModuleCat.Hom.hom
3812        (sphereOneSingularIntChainComplex.iCycles 1 ≫ singularOneChainToFree ≫
3813          singularOneBoundaryFree) z = 0
3814    rw [singularOneChainToFree_boundary_free]
3815    rw [← Category.assoc, HomologicalComplex.iCycles_d]
3816    simp
3817  obtain ⟨ts, hts⟩ := hker c hc0
3818  refine ⟨ts, ?_⟩
3819  have hinj : Function.Injective (ModuleCat.Hom.hom singularOneChainToFree) := by
3820    haveI : IsIso singularOneChainToFree := by
3821      change IsIso singularOneChainFreeIso.hom
3822      infer_instance
3823    haveI : Mono singularOneChainToFree := inferInstance
3824    exact (ModuleCat.mono_iff_injective singularOneChainToFree).mp inferInstance
3825  apply hinj
3826  unfold c at hts
3827  rw [hts]
3828
3829open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3830/-- A single closed-generator term has integer winding. -/
3831theorem ClosedSingularOneCycleTerm.cycleWinding_integral
3832    (t : ClosedSingularOneCycleTerm) :
3833    ∃ n : ModuleCat.of ℤ ℤ, cycleWinding t.cycle = (n : ℝ) := by
3834  obtain ⟨k, hk⟩ := singularWinding_loop_integral t.simplex t.faces_eq
3835  refine ⟨t.coeff * k, ?_⟩
3836  rw [ClosedSingularOneCycleTerm.cycle, cycleWinding_closedSingularOneCycle, hk]
3837  simp
3838
3839open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3840/-- A closed-generator term whose underlying singular edge has zero winding
3841bounds, including its integer coefficient.  This is the list-ready scalar
3842consumer of the explicit cone construction. -/
3843theorem ClosedSingularOneCycleTerm.bounds_of_zero_singularWinding
3844    (t : ClosedSingularOneCycleTerm) (hzero : singularWinding t.simplex = 0) :
3845    ∃ b : sphereOneSingularIntChainComplex.X 2,
3846      t.cycle = ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b := by
3847  exact closedSingularOneCycle_zsmul_bounds_of_zero_singularWinding
3848    t.simplex t.faces_eq hzero t.coeff
3849
3850open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3851/-- A finite list of zero-winding closed-generator terms bounds by summing the
3852single-edge cone witnesses.  This is the first finite-sum consumer of the cone
3853construction. -/
3854theorem closedSingularOneCycleList_bounds_of_forall_zero_singularWinding :
3855    ∀ (ts : List ClosedSingularOneCycleTerm),
3856      (∀ t ∈ ts, singularWinding t.simplex = 0) →
3857        ∃ b : sphereOneSingularIntChainComplex.X 2,
3858          closedSingularOneCycleList ts =
3859            ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b
3860  | [] => by
3861      intro _
3862      refine ⟨0, ?_⟩
3863      unfold closedSingularOneCycleList
3864      simp
3865  | t :: ts => by
3866      intro hzero
3867      have htzero : singularWinding t.simplex = 0 := hzero t (by simp)
3868      have htszero : ∀ u ∈ ts, singularWinding u.simplex = 0 := by
3869        intro u hu
3870        exact hzero u (by simp [hu])
3871      obtain ⟨b₁, hb₁⟩ := t.bounds_of_zero_singularWinding htzero
3872      obtain ⟨b₂, hb₂⟩ :=
3873        closedSingularOneCycleList_bounds_of_forall_zero_singularWinding ts htszero
3874      refine ⟨b₁ + b₂, ?_⟩
3875      unfold closedSingularOneCycleList
3876      rw [hb₁, hb₂, map_add]
3877
3878open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3879/-- Any finite list of closed-generator terms has integer winding. -/
3880theorem closedSingularOneCycleList_winding_integral :
3881    ∀ ts : List ClosedSingularOneCycleTerm,
3882      ∃ n : ModuleCat.of ℤ ℤ, cycleWinding (closedSingularOneCycleList ts) = (n : ℝ)
3883  | [] => by
3884      refine ⟨0, ?_⟩
3885      unfold closedSingularOneCycleList cycleWinding
3886      simp
3887  | t :: ts => by
3888      obtain ⟨n₁, hn₁⟩ := t.cycleWinding_integral
3889      obtain ⟨n₂, hn₂⟩ := closedSingularOneCycleList_winding_integral ts
3890      refine ⟨n₁ + n₂, ?_⟩
3891      unfold closedSingularOneCycleList
3892      unfold cycleWinding at hn₁ hn₂ ⊢
3893      rw [map_add, hn₁, hn₂]
3894      simp
3895
3896open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3897/-- For a finite closed-generator list, subtracting the integer multiple of the
3898fundamental cycle matching its winding produces a zero-winding residual.  This is
3899the algebraic shell around the remaining geometric filling problem. -/
3900theorem closedSingularOneCycleList_zeroWinding_residual
3901    (ts : List ClosedSingularOneCycleTerm) :
3902    ∃ n : ModuleCat.of ℤ ℤ,
3903      cycleWinding (closedSingularOneCycleList ts) = (n : ℝ) ∧
3904        cycleWinding
3905          (closedSingularOneCycleList ts - ModuleCat.Hom.hom fundamentalCycle n) = 0 := by
3906  obtain ⟨n, hn⟩ := closedSingularOneCycleList_winding_integral ts
3907  refine ⟨n, hn, ?_⟩
3908  unfold cycleWinding at hn ⊢
3909  rw [map_sub]
3910  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap)
3911      (closedSingularOneCycleList ts) -
3912    cycleWinding (ModuleCat.Hom.hom fundamentalCycle n) = 0
3913  rw [hn, cycleWinding_fundamentalCycle]
3914  ring
3915
3916open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3917/-- If the zero-winding residual of a closed-generator list bounds, then the list
3918is generated by the fundamental cycle modulo a boundary. -/
3919theorem closedSingularOneCycleList_boundary_generate_of_residual_bound
3920    (ts : List ClosedSingularOneCycleTerm) (n : ModuleCat.of ℤ ℤ)
3921    (b : sphereOneSingularIntChainComplex.X 2)
3922    (hres :
3923      closedSingularOneCycleList ts - ModuleCat.Hom.hom fundamentalCycle n =
3924        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b) :
3925    closedSingularOneCycleList ts =
3926      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
3927        ModuleCat.Hom.hom fundamentalCycle n := by
3928  rw [← hres]
3929  abel
3930
3931open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3932/-- Finite closed-generator list spanning: every cycle is a finite sum of closed
3933singular generator cycles.  This is the finite-chain combinatorial statement
3934left for proving `cycleWinding_integral`. -/
3935def closedSingularOneCycleList_spans : Prop :=
3936  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
3937    ∃ ts : List ClosedSingularOneCycleTerm, z = closedSingularOneCycleList ts
3938
3939open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3940/-- Raw-chain closed-generator spanning implies cycle-object closed-generator
3941spanning, because `iCycles` is a monomorphism. -/
3942theorem closedSingularOneCycleList_spans_of_chainList_spansCycles
3943    (hspan : closedSingularOneChainList_spansCycles) :
3944    closedSingularOneCycleList_spans := by
3945  intro z
3946  obtain ⟨ts, hz⟩ := hspan z
3947  refine ⟨ts, ?_⟩
3948  have hinc : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) z =
3949      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
3950        (closedSingularOneCycleList ts) := by
3951    rw [hz, closedSingularOneCycleList_iCycles ts]
3952  have hinj :
3953      Function.Injective
3954        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
3955    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
3956  exact hinj hinc
3957
3958open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3959/-- First concrete geometric subtarget: every singular `1`-cycle has an integer
3960winding number.  This should follow from endpoint cancellation in a finite
3961integer chain. -/
3962def cycleWinding_integral : Prop :=
3963  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
3964    ∃ n : ModuleCat.of ℤ ℤ, cycleWinding z = (n : ℝ)
3965
3966open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3967/-- A general directed cycle piece in free-chain coordinates.  Unlike
3968`ClosedSingularOneCycleTerm`, this is not restricted to one closed edge: a piece
3969may represent a multi-edge directed cycle.  The fields record exactly what the
3970finite graph theorem must construct from a balanced finite edge flow. -/
3971structure DirectedCycleFreeTerm where
3972  cycle : sphereOneSingularIntChainComplex.cycles 1
3973  chain : singularOneChainFree
3974  chain_eq :
3975    ModuleCat.Hom.hom singularOneChainToFree
3976      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) cycle) = chain
3977  winding_integral : ∃ n : ModuleCat.of ℤ ℤ, cycleWinding cycle = (n : ℝ)
3978
3979open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3980/-- The raw `C₁ → C₀` boundary of the chain represented by a free edge-chain
3981vanishes whenever the explicit free boundary of that edge-chain vanishes.  This
3982transports a free-`C₀` boundary computation back to the raw chain group using the
3983injectivity of `singularZeroChainToFree`. -/
3984theorem d_singularOneChainFreeToChain_eq_zero_of_freeBoundary_zero
3985    (cFree : singularOneChainFree)
3986    (hb : ModuleCat.Hom.hom singularOneBoundaryFree cFree = 0) :
3987    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 1 0)
3988      (ModuleCat.Hom.hom singularOneChainFreeToChain cFree) = 0 := by
3989  apply singularZeroChainToFree_injective
3990  rw [map_zero]
3991  have hcomp := congrArg (fun f => ModuleCat.Hom.hom f cFree)
3992    singularOneChainFreeToChain_boundary_free
3993  simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply] at hcomp
3994  rw [hb] at hcomp
3995  exact hcomp
3996
3997open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
3998/-- Transporting a free edge-chain into the raw chain group and back recovers it:
3999`singularOneChainToFree ∘ singularOneChainFreeToChain = id`. -/
4000theorem singularOneChainToFree_freeToChain (c : singularOneChainFree) :
4001    ModuleCat.Hom.hom singularOneChainToFree
4002      (ModuleCat.Hom.hom singularOneChainFreeToChain c) = c := by
4003  have hid := congrArg (fun f => ModuleCat.Hom.hom f c) singularOneChainFreeIso.inv_hom_id
4004  simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp, Function.comp_apply,
4005    LinearMap.id_coe, id_eq] at hid
4006  exact hid
4007
4008open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4009/-- The winding chain map evaluated on the raw chain of one free generator is the
4010winding of that singular `1`-simplex. -/
4011theorem windingChainMap_singularOneChainFreeToChain_freeMk (s : SingularOneSimplex) :
4012    ModuleCat.Hom.hom windingChainMap
4013      (ModuleCat.Hom.hom singularOneChainFreeToChain (ModuleCat.freeMk s)) =
4014      singularWinding s := by
4015  rw [singularOneChainFreeToChain_freeMk]
4016  change ModuleCat.Hom.hom
4017      (Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) s ≫ windingChainMap) 1 =
4018    singularWinding s
4019  rw [windingChainMap_ι]
4020  simp [LinearMap.toSpanSingleton_apply]
4021
4022open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4023/-- Constant singular `1`-simplices have zero winding because each is the boundary
4024of a constant singular `2`-simplex. -/
4025theorem windingChainMap_constantSingularOneSimplex (p : SphereOne) :
4026    ModuleCat.Hom.hom windingChainMap
4027      (ModuleCat.Hom.hom singularOneChainFreeToChain
4028        (ModuleCat.freeMk (constantSingularOneSimplex p))) = 0 := by
4029  rw [singularOneChainFreeToChain_freeMk]
4030  rw [← constantSingularOneSimplex_raw_boundary p]
4031  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1 ≫ windingChainMap)
4032    (ModuleCat.Hom.hom singularTwoChainFreeToChain
4033      (ModuleCat.freeMk (constantSingularTwoSimplex p))) = 0
4034  rw [windingChainMap_boundary]
4035  simp
4036
4037open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4038/-- The winding chain map evaluated on the raw chain of a finite free edge-family
4039is the total winding of the family. -/
4040theorem windingChainMap_singularOneChainFreeToChain_sum {k : ℕ}
4041    (e : Fin k → SingularOneSimplex) :
4042    ModuleCat.Hom.hom windingChainMap
4043      (ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, ModuleCat.freeMk (e i))) =
4044      ∑ i, singularWinding (e i) := by
4045  rw [map_sum, map_sum]
4046  refine Finset.sum_congr rfl (fun i _ => ?_)
4047  exact windingChainMap_singularOneChainFreeToChain_freeMk (e i)
4048
4049open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4050/-- **The homological content of cyclic extraction, packaged.**  A cyclically
4051connected finite family of singular `1`-simplices assembles into a
4052`DirectedCycleFreeTerm`: its free edge-chain `∑ᵢ ⟨eᵢ⟩` lifts to a genuine
4053degree-`1` cycle (boundary vanishes by `cyclicEdgeFamily_freeBoundary_zero`), and
4054that cycle has integer winding (by `singularWindingSum_cyclic_integral`).  This
4055discharges the entire homological/winding obligation of cyclic extraction; the
4056only content left in the finite-flow decomposition is the *combinatorial* task of
4057exhibiting such a family inside a balanced flow. -/
4058noncomputable def directedCycleFreeTerm_of_cyclicFamily {k : ℕ}
4059    (e : Fin k → SingularOneSimplex)
4060    (hconn : ∀ i : Fin k, edgeTerminal (e i) = edgeInitial (e (finRotate k i))) :
4061    DirectedCycleFreeTerm := by
4062  have hb : ModuleCat.Hom.hom singularOneBoundaryFree (∑ i, ModuleCat.freeMk (e i)) = 0 :=
4063    cyclicEdgeFamily_freeBoundary_zero e hconn
4064  have hd : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 1 0)
4065      (ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, ModuleCat.freeMk (e i))) = 0 :=
4066    d_singularOneChainFreeToChain_eq_zero_of_freeBoundary_zero _ hb
4067  -- Route the lift `ℤ → X 1` through the free module (which carries a clean `ℤ`-module
4068  -- instance), avoiding the `ℤ`-module diamond on the raw chain group `X 1`.
4069  let φfree : ModuleCat.of ℤ ℤ ⟶ singularOneChainFree :=
4070    ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ singularOneChainFree (∑ i, ModuleCat.freeMk (e i)))
4071  let ψ : ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.X 1 :=
4072    φfree ≫ singularOneChainFreeToChain
4073  have hψ1 : ModuleCat.Hom.hom ψ 1 =
4074      ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, ModuleCat.freeMk (e i)) := by
4075    simp only [ψ, φfree, ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply,
4076      ModuleCat.hom_ofHom, LinearMap.toSpanSingleton_apply, one_smul]
4077  -- The raw boundary `freeToChain ≫ ∂` equals the explicit free boundary transported back
4078  -- through the (iso) `C₀` comparison; this is `singularOneChainFreeToChain_boundary_free`
4079  -- post-composed with the inverse of the `C₀` iso.
4080  have htofree : singularZeroChainToFree ≫ singularZeroChainFreeToChain
4081      = 𝟙 (sphereOneSingularIntChainComplex.X 0) := singularZeroChainFreeIso.hom_inv_id
4082  have hbridge : singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0
4083      = singularOneBoundaryFree ≫ singularZeroChainFreeToChain := by
4084    have h : (singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 ≫
4085        singularZeroChainToFree) ≫ singularZeroChainFreeToChain
4086        = singularOneBoundaryFree ≫ singularZeroChainFreeToChain := by
4087      rw [singularOneChainFreeToChain_boundary_free]
4088    rw [Category.assoc, Category.assoc, htofree, Category.comp_id] at h
4089    exact h
4090  -- `ψ ≫ ∂ = (φfree ≫ ∂_free) ≫ freeToChain₀ = 0` because the free boundary kills `∑ᵢ ⟨eᵢ⟩`.
4091  have hφb : φfree ≫ singularOneBoundaryFree = 0 := by
4092    apply ModuleCat.hom_ext
4093    apply LinearMap.ext_ring
4094    simp only [φfree, ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply,
4095      ModuleCat.hom_ofHom, LinearMap.toSpanSingleton_apply, one_smul, ModuleCat.hom_zero,
4096      LinearMap.zero_apply]
4097    exact hb
4098  have hψ : ψ ≫ sphereOneSingularIntChainComplex.d 1 0 = 0 := by
4099    calc ψ ≫ sphereOneSingularIntChainComplex.d 1 0
4100        = φfree ≫ singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 := by
4101          simp only [ψ, Category.assoc]
4102      _ = φfree ≫ singularOneBoundaryFree ≫ singularZeroChainFreeToChain := by rw [hbridge]
4103      _ = (φfree ≫ singularOneBoundaryFree) ≫ singularZeroChainFreeToChain := by
4104          rw [Category.assoc]
4105      _ = 0 := by rw [hφb, Limits.zero_comp]
4106  let cycMap : ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.cycles 1 :=
4107    sphereOneSingularIntChainComplex.liftCycles ψ 0 (by simp) hψ
4108  have hiC : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
4109      (ModuleCat.Hom.hom cycMap 1) =
4110      ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, ModuleCat.freeMk (e i)) := by
4111    change ModuleCat.Hom.hom (cycMap ≫ sphereOneSingularIntChainComplex.iCycles 1) 1 = _
4112    rw [HomologicalComplex.liftCycles_i]
4113    exact hψ1
4114  refine
4115    { cycle := ModuleCat.Hom.hom cycMap 1
4116      chain := ∑ i, ModuleCat.freeMk (e i)
4117      chain_eq := ?_
4118      winding_integral := ?_ }
4119  · rw [hiC, singularOneChainToFree_freeToChain]
4120  · obtain ⟨n, hn⟩ := singularWindingSum_cyclic_integral e hconn
4121    refine ⟨n, ?_⟩
4122    unfold cycleWinding
4123    change ModuleCat.Hom.hom windingChainMap
4124        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
4125          (ModuleCat.Hom.hom cycMap 1)) = (n : ℝ)
4126    rw [hiC, windingChainMap_singularOneChainFreeToChain_sum]
4127    exact hn
4128
4129/-! ### Oriented closed-walk engine
4130
4131The combinatorial extraction follows *sign-selected* orientations (a supported
4132edge is read forward when its coefficient is positive, backward when negative),
4133so the closed walks it produces are families of `OrientedSingularEdge`s, not bare
4134forward simplices.  The lemmas below generalise the forward engine
4135(`directedCycleFreeTerm_of_cyclicFamily`) to oriented families: a backward
4136occurrence contributes the reversed path (negating displacement and winding) and
4137the chain `-⟨e⟩`.  This is the keystone the walk extraction feeds. -/
4138
4139/-- Winding contribution of an oriented edge occurrence: the underlying singular
4140winding, negated for backward traversal. -/
4141noncomputable def orientedWinding (o : OrientedSingularEdge) : ℝ :=
4142  match o.orientation with
4143  | .forward => singularWinding o.edge
4144  | .backward => - singularWinding o.edge
4145
4146/-- The path traced by an oriented edge occurrence (reversed for backward). -/
4147noncomputable def orientedEdgePath (o : OrientedSingularEdge) : C(I, SphereOne) :=
4148  match o.orientation with
4149  | .forward => singularEdgePath o.edge
4150  | .backward => CircleWinding.reversePath (singularEdgePath o.edge)
4151
4152open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4153/-- Forward oriented edges need no path-base correction: the path-parametric base
4154edge is definitionally the original signed free generator after the standard
4155`Δ¹ ≃ I` round trip. -/
4156theorem OrientedSingularEdge.pathBase_eq_chain_of_forward
4157    (o : OrientedSingularEdge) (h : o.orientation = EdgeOrientation.forward) :
4158    ModuleCat.freeMk
4159      (singularOneSimplexOfMap (oneSimplexOfPath (orientedEdgePath o))) =
4160        o.chain := by
4161  rcases o with ⟨e, ori⟩
4162  cases ori
4163  · simp only [orientedEdgePath, OrientedSingularEdge.chain]
4164    rw [singularOneSimplexOfMap_oneSimplexOfPath_singularEdgePath]
4165  · simp at h
4166
4167open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4168/-- Local path-base residual of one oriented singular edge.  Forward edges have
4169zero residual; backward edges leave the standard reparameterisation prism target. -/
4170noncomputable def OrientedSingularEdge.pathBaseCorrectionBoundary
4171    (o : OrientedSingularEdge) : singularOneChainFree :=
4172  ModuleCat.freeMk (singularOneSimplexOfMap (oneSimplexOfPath (orientedEdgePath o))) -
4173    o.chain
4174
4175open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4176/-- Forward oriented edges have zero local path-base residual. -/
4177theorem OrientedSingularEdge.pathBaseCorrectionBoundary_eq_zero_of_forward
4178    (o : OrientedSingularEdge) (h : o.orientation = EdgeOrientation.forward) :
4179    o.pathBaseCorrectionBoundary = 0 := by
4180  unfold OrientedSingularEdge.pathBaseCorrectionBoundary
4181  rw [o.pathBase_eq_chain_of_forward h]
4182  abel
4183
4184open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4185/-- Backward oriented edges have a concrete path-base correction: the triangular
4186backtrack prism over the edge path, plus the constant `2`-simplex that cancels the
4187middle constant face. -/
4188theorem OrientedSingularEdge.pathBaseCorrectionBoundary_bounds_of_backward
4189    (o : OrientedSingularEdge) (h : o.orientation = EdgeOrientation.backward) :
4190    ∃ K : singularTwoChainFree,
4191      ModuleCat.Hom.hom singularTwoBoundaryFree K = o.pathBaseCorrectionBoundary := by
4192  rcases o with ⟨e, ori⟩
4193  cases ori
4194  · simp at h
4195  · refine ⟨ModuleCat.freeMk (pathBacktrackSingularTwoSimplex (singularEdgePath e)) +
4196        ModuleCat.freeMk (constantSingularTwoSimplex ((singularEdgePath e) 0)), ?_⟩
4197    rw [map_add, singularTwoBoundaryFree_freeMk_pathBacktrack,
4198      constantSingularOneSimplex_free_boundary]
4199    unfold OrientedSingularEdge.pathBaseCorrectionBoundary orientedEdgePath
4200      OrientedSingularEdge.chain
4201    rw [singularOneSimplexOfMap_oneSimplexOfPath_singularEdgePath]
4202    simp
4203    abel
4204
4205open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4206/-- Every oriented singular edge has a local path-base correction.  The forward
4207case is zero; the backward case is the backtrack prism. -/
4208theorem OrientedSingularEdge.pathBaseCorrectionBoundary_bounds
4209    (o : OrientedSingularEdge) :
4210    ∃ K : singularTwoChainFree,
4211      ModuleCat.Hom.hom singularTwoBoundaryFree K = o.pathBaseCorrectionBoundary := by
4212  cases h : o.orientation with
4213  | forward =>
4214      refine ⟨0, ?_⟩
4215      rw [map_zero, o.pathBaseCorrectionBoundary_eq_zero_of_forward h]
4216  | backward =>
4217      exact o.pathBaseCorrectionBoundary_bounds_of_backward h
4218
4219/-- Initial point of an oriented edge's path is the `S¹`-point of its oriented
4220initial vertex. -/
4221theorem orientedEdgePath_zero (o : OrientedSingularEdge) :
4222    orientedEdgePath o 0 = vertexPoint o.initial := by
4223  rcases o with ⟨e, ori⟩
4224  cases ori
4225  · simp only [orientedEdgePath, OrientedSingularEdge.initial]
4226    rw [singularEdgePath_zero]
4227  · simp only [orientedEdgePath, OrientedSingularEdge.initial,
4228      CircleWinding.reversePath_apply, unitInterval.symm_zero]
4229    rw [singularEdgePath_one]
4230
4231/-- Terminal point of an oriented edge's path is the `S¹`-point of its oriented
4232terminal vertex. -/
4233theorem orientedEdgePath_one (o : OrientedSingularEdge) :
4234    orientedEdgePath o 1 = vertexPoint o.terminal := by
4235  rcases o with ⟨e, ori⟩
4236  cases ori
4237  · simp only [orientedEdgePath, OrientedSingularEdge.terminal]
4238    rw [singularEdgePath_one]
4239  · simp only [orientedEdgePath, OrientedSingularEdge.terminal,
4240      CircleWinding.reversePath_apply, unitInterval.symm_one]
4241    rw [singularEdgePath_zero]
4242
4243/-- The oriented winding is the displacement of the oriented path, normalised by
4244one full turn. -/
4245theorem orientedWinding_eq_pathDisplacement (o : OrientedSingularEdge) :
4246    orientedWinding o = pathDisplacement (orientedEdgePath o) / (2 * Real.pi) := by
4247  rcases o with ⟨e, ori⟩
4248  cases ori
4249  · simp only [orientedWinding, orientedEdgePath]
4250    exact singularWinding_eq_pathDisplacement e
4251  · simp only [orientedWinding, orientedEdgePath]
4252    rw [CircleWinding.pathDisplacement_reverse, neg_div]
4253    rw [← singularWinding_eq_pathDisplacement]
4254
4255open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4256/-- The terminal-return side of an oriented edge has winding opposite to the
4257oriented edge winding. -/
4258theorem OrientedSingularEdge.singularWinding_terminalReturnSide
4259    (o : OrientedSingularEdge) :
4260    singularWinding
4261      (singularOneSimplexOfMap (coneTerminalSide (orientedEdgePath o))) =
4262        - orientedWinding o := by
4263  rw [singularWinding_coneTerminalSide, orientedWinding_eq_pathDisplacement]
4264
4265/-- **Closed-walk winding integrality (oriented form).**  A cyclically connected
4266family of oriented edge occurrences (oriented terminal of `o i` equals oriented
4267initial of `o (finRotate k i)`) has integer total oriented winding. -/
4268theorem orientedWindingSum_cyclic_integral {k : ℕ} (o : Fin k → OrientedSingularEdge)
4269    (hconn : ∀ i : Fin k, (o i).terminal = (o (finRotate k i)).initial) :
4270    ∃ n : ℤ, ∑ i, orientedWinding (o i) = (n : ℝ) := by
4271  have hpathconn : ∀ i : Fin k,
4272      (orientedEdgePath (o i)) 1 = (orientedEdgePath (o (finRotate k i))) 0 := by
4273    intro i
4274    rw [orientedEdgePath_one, orientedEdgePath_zero]
4275    exact congrArg vertexPoint (hconn i)
4276  obtain ⟨m, hm⟩ :=
4277    displacementSum_cyclic_intMul (fun i => orientedEdgePath (o i)) hpathconn
4278  refine ⟨m, ?_⟩
4279  have hsum :
4280      ∑ i, orientedWinding (o i)
4281        = (∑ i, pathDisplacement (orientedEdgePath (o i))) / (2 * Real.pi) := by
4282    rw [Finset.sum_div]
4283    refine Finset.sum_congr rfl (fun i _ => ?_)
4284    exact orientedWinding_eq_pathDisplacement (o i)
4285  rw [hsum, hm]
4286  have hpi : (2 : ℝ) * Real.pi ≠ 0 := by positivity
4287  rw [mul_div_assoc, div_self hpi, mul_one]
4288
4289open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4290/-- **Cyclic free-boundary vanishing (oriented form).**  The free edge-chain of a
4291cyclically connected oriented walk is a cycle: its explicit free boundary
4292vanishes (oriented telescoping of `terminal − initial`). -/
4293theorem cyclicOrientedFamily_freeBoundary_zero {k : ℕ} (o : Fin k → OrientedSingularEdge)
4294    (hconn : ∀ i : Fin k, (o i).terminal = (o (finRotate k i)).initial) :
4295    ModuleCat.Hom.hom singularOneBoundaryFree (∑ i, (o i).chain) = 0 := by
4296  rw [map_sum]
4297  rw [Finset.sum_congr rfl (fun i _ => (o i).boundary_free), Finset.sum_sub_distrib]
4298  have hreindex :
4299      (∑ i, ModuleCat.freeMk (o i).initial : singularZeroChainFree)
4300        = ∑ i, ModuleCat.freeMk (o i).terminal := by
4301    rw [← Equiv.sum_comp (finRotate k)
4302      (fun j => (ModuleCat.freeMk (o j).initial : singularZeroChainFree))]
4303    refine Finset.sum_congr rfl (fun i _ => ?_)
4304    exact congrArg ModuleCat.freeMk (hconn i).symm
4305  rw [hreindex, sub_self]
4306
4307open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4308/-- The winding chain map on the raw chain of one oriented edge occurrence is its
4309oriented winding. -/
4310theorem windingChainMap_freeToChain_orientedChain (o : OrientedSingularEdge) :
4311    ModuleCat.Hom.hom windingChainMap
4312      (ModuleCat.Hom.hom singularOneChainFreeToChain o.chain) = orientedWinding o := by
4313  rcases o with ⟨e, ori⟩
4314  cases ori
4315  · simp only [orientedWinding, OrientedSingularEdge.chain]
4316    exact windingChainMap_singularOneChainFreeToChain_freeMk e
4317  · simp only [orientedWinding, OrientedSingularEdge.chain]
4318    rw [map_neg, map_neg, windingChainMap_singularOneChainFreeToChain_freeMk]
4319
4320open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4321/-- The winding chain map on the raw chain of an oriented walk is its total
4322oriented winding. -/
4323theorem windingChainMap_freeToChain_orientedChain_sum {k : ℕ}
4324    (o : Fin k → OrientedSingularEdge) :
4325    ModuleCat.Hom.hom windingChainMap
4326      (ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (o i).chain)) =
4327      ∑ i, orientedWinding (o i) := by
4328  rw [map_sum, map_sum]
4329  refine Finset.sum_congr rfl (fun i _ => ?_)
4330  exact windingChainMap_freeToChain_orientedChain (o i)
4331
4332open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4333/-- **The homological content of oriented cyclic extraction, packaged.**  A
4334cyclically connected finite family of oriented edge occurrences assembles into a
4335`DirectedCycleFreeTerm`: its signed free edge-chain `∑ᵢ (oᵢ).chain` lifts to a
4336genuine degree-`1` cycle, with integer winding.  This generalises
4337`directedCycleFreeTerm_of_cyclicFamily` to the sign-selected orientations the
4338balanced-flow walk extraction produces. -/
4339noncomputable def directedCycleFreeTerm_of_orientedCyclicFamily {k : ℕ}
4340    (o : Fin k → OrientedSingularEdge)
4341    (hconn : ∀ i : Fin k, (o i).terminal = (o (finRotate k i)).initial) :
4342    DirectedCycleFreeTerm := by
4343  have hb : ModuleCat.Hom.hom singularOneBoundaryFree (∑ i, (o i).chain) = 0 :=
4344    cyclicOrientedFamily_freeBoundary_zero o hconn
4345  have hd : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 1 0)
4346      (ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (o i).chain)) = 0 :=
4347    d_singularOneChainFreeToChain_eq_zero_of_freeBoundary_zero _ hb
4348  let φfree : ModuleCat.of ℤ ℤ ⟶ singularOneChainFree :=
4349    ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ singularOneChainFree (∑ i, (o i).chain))
4350  let ψ : ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.X 1 :=
4351    φfree ≫ singularOneChainFreeToChain
4352  have hψ1 : ModuleCat.Hom.hom ψ 1 =
4353      ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (o i).chain) := by
4354    simp only [ψ, φfree, ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply,
4355      ModuleCat.hom_ofHom, LinearMap.toSpanSingleton_apply, one_smul]
4356  have htofree : singularZeroChainToFree ≫ singularZeroChainFreeToChain
4357      = 𝟙 (sphereOneSingularIntChainComplex.X 0) := singularZeroChainFreeIso.hom_inv_id
4358  have hbridge : singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0
4359      = singularOneBoundaryFree ≫ singularZeroChainFreeToChain := by
4360    have h : (singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 ≫
4361        singularZeroChainToFree) ≫ singularZeroChainFreeToChain
4362        = singularOneBoundaryFree ≫ singularZeroChainFreeToChain := by
4363      rw [singularOneChainFreeToChain_boundary_free]
4364    rw [Category.assoc, Category.assoc, htofree, Category.comp_id] at h
4365    exact h
4366  have hφb : φfree ≫ singularOneBoundaryFree = 0 := by
4367    apply ModuleCat.hom_ext
4368    apply LinearMap.ext_ring
4369    simp only [φfree, ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply,
4370      ModuleCat.hom_ofHom, LinearMap.toSpanSingleton_apply, one_smul, ModuleCat.hom_zero,
4371      LinearMap.zero_apply]
4372    exact hb
4373  have hψ : ψ ≫ sphereOneSingularIntChainComplex.d 1 0 = 0 := by
4374    calc ψ ≫ sphereOneSingularIntChainComplex.d 1 0
4375        = φfree ≫ singularOneChainFreeToChain ≫ sphereOneSingularIntChainComplex.d 1 0 := by
4376          simp only [ψ, Category.assoc]
4377      _ = φfree ≫ singularOneBoundaryFree ≫ singularZeroChainFreeToChain := by rw [hbridge]
4378      _ = (φfree ≫ singularOneBoundaryFree) ≫ singularZeroChainFreeToChain := by
4379          rw [Category.assoc]
4380      _ = 0 := by rw [hφb, Limits.zero_comp]
4381  let cycMap : ModuleCat.of ℤ ℤ ⟶ sphereOneSingularIntChainComplex.cycles 1 :=
4382    sphereOneSingularIntChainComplex.liftCycles ψ 0 (by simp) hψ
4383  have hiC : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
4384      (ModuleCat.Hom.hom cycMap 1) =
4385      ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (o i).chain) := by
4386    change ModuleCat.Hom.hom (cycMap ≫ sphereOneSingularIntChainComplex.iCycles 1) 1 = _
4387    rw [HomologicalComplex.liftCycles_i]
4388    exact hψ1
4389  refine
4390    { cycle := ModuleCat.Hom.hom cycMap 1
4391      chain := ∑ i, (o i).chain
4392      chain_eq := ?_
4393      winding_integral := ?_ }
4394  · rw [hiC, singularOneChainToFree_freeToChain]
4395  · obtain ⟨n, hn⟩ := orientedWindingSum_cyclic_integral o hconn
4396    refine ⟨n, ?_⟩
4397    unfold cycleWinding
4398    change ModuleCat.Hom.hom windingChainMap
4399        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
4400          (ModuleCat.Hom.hom cycMap 1)) = (n : ℝ)
4401    rw [hiC, windingChainMap_freeToChain_orientedChain_sum]
4402    exact hn
4403
4404open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4405/-- The cycle-object sum represented by a finite list of directed cycle pieces. -/
4406noncomputable def directedCycleFreeTermListCycle :
4407    List DirectedCycleFreeTerm → sphereOneSingularIntChainComplex.cycles 1
4408  | [] => 0
4409  | t :: ts => t.cycle + directedCycleFreeTermListCycle ts
4410
4411open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4412/-- The explicit free-chain sum represented by a finite list of directed cycle
4413pieces. -/
4414noncomputable def directedCycleFreeTermListChain :
4415    List DirectedCycleFreeTerm → singularOneChainFree
4416  | [] => 0
4417  | t :: ts => t.chain + directedCycleFreeTermListChain ts
4418
4419open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4420/-- The free-chain image of the cycle-object list is the corresponding explicit
4421free-chain list. -/
4422theorem directedCycleFreeTermList_chain_eq :
4423    ∀ ts : List DirectedCycleFreeTerm,
4424      ModuleCat.Hom.hom singularOneChainToFree
4425        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
4426          (directedCycleFreeTermListCycle ts)) =
4427        directedCycleFreeTermListChain ts
4428  | [] => by
4429      unfold directedCycleFreeTermListCycle directedCycleFreeTermListChain
4430      simp
4431  | t :: ts => by
4432      unfold directedCycleFreeTermListCycle directedCycleFreeTermListChain
4433      rw [map_add, map_add, t.chain_eq, directedCycleFreeTermList_chain_eq ts]
4434
4435open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4436/-- A finite list of directed cycle pieces has integer winding. -/
4437theorem directedCycleFreeTermList_winding_integral :
4438    ∀ ts : List DirectedCycleFreeTerm,
4439      ∃ n : ModuleCat.of ℤ ℤ, cycleWinding (directedCycleFreeTermListCycle ts) = (n : ℝ)
4440  | [] => by
4441      refine ⟨0, ?_⟩
4442      unfold directedCycleFreeTermListCycle cycleWinding
4443      simp
4444  | t :: ts => by
4445      obtain ⟨n₁, hn₁⟩ := t.winding_integral
4446      obtain ⟨n₂, hn₂⟩ := directedCycleFreeTermList_winding_integral ts
4447      refine ⟨n₁ + n₂, ?_⟩
4448      unfold directedCycleFreeTermListCycle
4449      unfold cycleWinding at hn₁ hn₂ ⊢
4450      rw [map_add, hn₁, hn₂]
4451      simp
4452
4453open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4454/-- Including a packaged directed-cycle term back into raw `C₁` recovers the raw
4455chain obtained from its explicit free-chain representative. -/
4456theorem DirectedCycleFreeTerm.iCycles_eq_freeToChain (t : DirectedCycleFreeTerm) :
4457    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) t.cycle =
4458      ModuleCat.Hom.hom singularOneChainFreeToChain t.chain := by
4459  have hinj_toFree : Function.Injective (ModuleCat.Hom.hom singularOneChainToFree) := by
4460    haveI : IsIso singularOneChainToFree := by
4461      change IsIso singularOneChainFreeIso.hom
4462      infer_instance
4463    haveI : Mono singularOneChainToFree := inferInstance
4464    exact (ModuleCat.mono_iff_injective singularOneChainToFree).mp inferInstance
4465  apply hinj_toFree
4466  rw [t.chain_eq, singularOneChainToFree_freeToChain]
4467
4468open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4469/-- The winding of a packaged directed-cycle term can be computed from its
4470explicit free-chain representative. -/
4471theorem DirectedCycleFreeTerm.cycleWinding_eq_freeChain (t : DirectedCycleFreeTerm) :
4472    cycleWinding t.cycle =
4473      ModuleCat.Hom.hom windingChainMap
4474        (ModuleCat.Hom.hom singularOneChainFreeToChain t.chain) := by
4475  unfold cycleWinding
4476  simp only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply]
4477  rw [t.iCycles_eq_freeToChain]
4478
4479open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4480/-- Correct general finite graph target: every free edge-chain in the kernel of
4481the explicit boundary decomposes into finitely many directed cycle pieces. -/
4482def freeBoundaryKernel_decomposesIntoDirectedCycles : Prop :=
4483  ∀ c : singularOneChainFree,
4484    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
4485      ∃ ts : List DirectedCycleFreeTerm, c = directedCycleFreeTermListChain ts
4486
4487open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4488/-- The general directed-cycle kernel decomposition theorem implies integer
4489winding for all singular `1`-cycles. -/
4490theorem cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoDirectedCycles
4491    (hker : freeBoundaryKernel_decomposesIntoDirectedCycles) :
4492    cycleWinding_integral := by
4493  intro z
4494  let c : singularOneChainFree :=
4495    ModuleCat.Hom.hom singularOneChainToFree
4496      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) z)
4497  have hc0 : ModuleCat.Hom.hom singularOneBoundaryFree c = 0 := by
4498    unfold c
4499    change ModuleCat.Hom.hom
4500        (sphereOneSingularIntChainComplex.iCycles 1 ≫ singularOneChainToFree ≫
4501          singularOneBoundaryFree) z = 0
4502    rw [singularOneChainToFree_boundary_free]
4503    rw [← Category.assoc, HomologicalComplex.iCycles_d]
4504    simp
4505  obtain ⟨ts, hts⟩ := hker c hc0
4506  have hcycle : z = directedCycleFreeTermListCycle ts := by
4507    have hinj_toFree : Function.Injective (ModuleCat.Hom.hom singularOneChainToFree) := by
4508      haveI : IsIso singularOneChainToFree := by
4509        change IsIso singularOneChainFreeIso.hom
4510        infer_instance
4511      haveI : Mono singularOneChainToFree := inferInstance
4512      exact (ModuleCat.mono_iff_injective singularOneChainToFree).mp inferInstance
4513    have hinj_iCycles :
4514        Function.Injective
4515          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
4516      (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
4517    apply hinj_iCycles
4518    apply hinj_toFree
4519    unfold c at hts
4520    rw [hts, directedCycleFreeTermList_chain_eq ts]
4521  obtain ⟨n, hn⟩ := directedCycleFreeTermList_winding_integral ts
4522  refine ⟨n, ?_⟩
4523  rw [hcycle, hn]
4524
4525/-! ### ℓ¹ size of a free edge-chain and its bookkeeping
4526
4527The unconditional directed-cycle decomposition is proved by induction on the
4528ℓ¹ size `∑ |coeff|` of the free edge-chain.  Each extraction step peels a
4529directed cycle (an oriented closed walk through the support) and subtracts it,
4530which lowers the magnitude of every edge on the walk by exactly one and leaves
4531all other coefficients unchanged.  The lemmas in this section make that ℓ¹
4532decrease precise. -/
4533
4534/-- ℓ¹ size of a free edge-chain: the sum of the absolute values of its
4535coefficients. -/
4536noncomputable def chainL1 (c : singularOneChainFree) : ℕ :=
4537  ∑ e ∈ edgeSupport c, (edgeCoeff c e).natAbs
4538
4539/-- The coefficient of a difference of free edge-chains is the difference of the
4540coefficients. -/
4541theorem edgeCoeff_sub (c d : singularOneChainFree) (e : SingularOneSimplex) :
4542    edgeCoeff (c - d) e = edgeCoeff c e - edgeCoeff d e := by
4543  show (c - d).toFun e = c.toFun e - d.toFun e
4544  exact Finsupp.sub_apply c d e
4545
4546open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4547/-- A supported peel that exactly cancels at least one supported edge strictly
4548shrinks support.  This is the generic support-cardinality bookkeeping needed by
4549any one-step cyclic extraction proof. -/
4550theorem edgeSupportCard_sub_lt_of_supported_exact_cancel
4551    [DecidableEq SingularOneSimplex]
4552    (c p : singularOneChainFree)
4553    (hpsupp : edgeSupport p ⊆ edgeSupport c)
4554    (hcancel : ∃ e, e ∈ edgeSupport p ∧ edgeCoeff p e = edgeCoeff c e) :
4555    edgeSupportCard (c - p) < edgeSupportCard c := by
4556  have hsubs : edgeSupport (c - p) ⊆ edgeSupport c := by
4557    intro e he
4558    by_contra hnotc
4559    have hc0 : edgeCoeff c e = 0 :=
4560      Classical.not_not.mp (mt (mem_edgeSupport_iff c e).mpr hnotc)
4561    have hp0 : edgeCoeff p e = 0 := by
4562      have hnotp : e ∉ edgeSupport p := fun hp => hnotc (hpsupp hp)
4563      exact Classical.not_not.mp (mt (mem_edgeSupport_iff p e).mpr hnotp)
4564    have hres0 : edgeCoeff (c - p) e = 0 := by
4565      rw [edgeCoeff_sub, hc0, hp0, sub_zero]
4566    exact (mem_edgeSupport_iff (c - p) e).mp he hres0
4567  obtain ⟨e, hep, hcoeff⟩ := hcancel
4568  have hec : e ∈ edgeSupport c := hpsupp hep
4569  have hnotres : e ∉ edgeSupport (c - p) := by
4570    intro heres
4571    have hne : edgeCoeff (c - p) e ≠ 0 :=
4572      (mem_edgeSupport_iff (c - p) e).mp heres
4573    have hzero : edgeCoeff (c - p) e = 0 := by
4574      rw [edgeCoeff_sub, hcoeff, sub_self]
4575    exact hne hzero
4576  unfold edgeSupportCard
4577  have hproper : edgeSupport (c - p) ⊂ edgeSupport c := by
4578    rw [Finset.ssubset_iff_subset_ne]
4579    refine ⟨hsubs, ?_⟩
4580    intro hsame
4581    exact hnotres (by rw [hsame]; exact hec)
4582  exact Finset.card_lt_card hproper
4583
4584/-- The coefficient of a sum of free edge-chains is the sum of the coefficients. -/
4585theorem edgeCoeff_add (c d : singularOneChainFree) (e : SingularOneSimplex) :
4586    edgeCoeff (c + d) e = edgeCoeff c e + edgeCoeff d e := by
4587  show (c + d).toFun e = c.toFun e + d.toFun e
4588  exact Finsupp.add_apply c d e
4589
4590/-- The coefficient of an integer multiple of a free edge-chain is the matching
4591integer multiple of the coefficient. -/
4592theorem edgeCoeff_zsmul (n : ℤ) (c : singularOneChainFree) (e : SingularOneSimplex) :
4593    edgeCoeff (n • c) e = n * edgeCoeff c e := by
4594  show (n • c).toFun e = n * c.toFun e
4595  rfl
4596
4597/-- The free-chain contribution of one sign-selected oriented edge is the single
4598generator with coefficient `+1` (forward) or `-1` (backward). -/
4599theorem orientedEdgeOfCoeff_chain_eq_single
4600    (c : singularOneChainFree) (e : SingularOneSimplex) :
4601    (orientedEdgeOfCoeff c e).chain =
4602      Finsupp.single e (if 0 < edgeCoeff c e then (1 : ℤ) else -1) := by
4603  by_cases hp : 0 < edgeCoeff c e
4604  · have horient : orientedEdgeOfCoeff c e = { edge := e, orientation := .forward } := by
4605      simp only [orientedEdgeOfCoeff, orientationOfCoeff, if_pos hp]
4606    rw [horient]
4607    show ModuleCat.freeMk e = _
4608    rw [if_pos hp, ModuleCat.freeMk]
4609  · have horient : orientedEdgeOfCoeff c e = { edge := e, orientation := .backward } := by
4610      simp only [orientedEdgeOfCoeff, orientationOfCoeff, if_neg hp]
4611    rw [horient]
4612    show -ModuleCat.freeMk e = _
4613    rw [if_neg hp, ModuleCat.freeMk, Finsupp.single_neg]
4614
4615/-- The unit coefficient chosen by an edge's sign has absolute value one. -/
4616theorem natAbs_sign_unit (a : ℤ) : (if 0 < a then (1 : ℤ) else -1).natAbs = 1 := by
4617  by_cases hp : 0 < a
4618  · rw [if_pos hp]; decide
4619  · rw [if_neg hp]; decide
4620
4621/-- An integer of absolute value one is exactly its sign-unit. -/
4622theorem eq_sign_unit_of_natAbs_eq_one (a : ℤ) (ha : a.natAbs = 1) :
4623    (if 0 < a then (1 : ℤ) else -1) = a := by
4624  by_cases hp : 0 < a
4625  · rw [if_pos hp]
4626    omega
4627  · rw [if_neg hp]
4628    omega
4629
4630/-- Multiplying the sign-unit by the absolute value recovers the integer. -/
4631theorem intNatAbs_mul_signUnit_eq_self (a : ℤ) :
4632    ((a.natAbs : ℤ) * (if 0 < a then (1 : ℤ) else -1)) = a := by
4633  by_cases hp : 0 < a
4634  · rw [if_pos hp]
4635    omega
4636  · rw [if_neg hp]
4637    omega
4638
4639/-- Subtracting the sign-unit from a nonzero integer drops its absolute value by
4640exactly one.  This is the per-edge ℓ¹ decrease of one directed-cycle peel. -/
4641theorem natAbs_sub_sign_unit (a : ℤ) (ha : a ≠ 0) :
4642    a.natAbs = (a - (if 0 < a then (1 : ℤ) else -1)).natAbs + 1 := by
4643  by_cases hp : 0 < a
4644  · rw [if_pos hp]; omega
4645  · rw [if_neg hp]
4646    have hneg : a < 0 := by omega
4647    omega
4648
4649/-- The sign-unit chosen by an edge's coefficient is never zero. -/
4650theorem sign_unit_ne_zero (a : ℤ) : (if 0 < a then (1 : ℤ) else -1) ≠ 0 := by
4651  by_cases hp : 0 < a <;> simp [hp]
4652
4653/-- Coefficient of a single generator: the value at the chosen point, zero
4654elsewhere. -/
4655theorem edgeCoeff_single [DecidableEq SingularOneSimplex]
4656    (a : SingularOneSimplex) (b : ℤ) (e : SingularOneSimplex) :
4657    edgeCoeff (Finsupp.single a b) e = if a = e then b else 0 := by
4658  show (Finsupp.single a b).toFun e = _
4659  rw [← Finsupp.single_apply]
4660  rfl
4661
4662/-- Coefficient of a finite sum of free edge-chains distributes over the sum. -/
4663theorem edgeCoeff_sum {k : ℕ} (f : Fin k → singularOneChainFree) (e : SingularOneSimplex) :
4664    edgeCoeff (∑ i, f i) e = ∑ i, edgeCoeff (f i) e := by
4665  show (Finsupp.applyAddHom e) (∑ i, f i) = ∑ i, (Finsupp.applyAddHom e) (f i)
4666  exact map_sum (Finsupp.applyAddHom e) f Finset.univ
4667
4668/-- A sum of `if`-selected values over an injective family collapses to the
4669selected value when the test point lies in the image, and to zero otherwise. -/
4670theorem sum_ite_image_of_injective [DecidableEq SingularOneSimplex] {k : ℕ}
4671    (g : Fin k → SingularOneSimplex) (hg : Function.Injective g)
4672    (F : SingularOneSimplex → ℤ) (e : SingularOneSimplex) :
4673    (∑ i : Fin k, (if g i = e then F (g i) else 0)) =
4674      if e ∈ Finset.image g Finset.univ then F e else 0 := by
4675  by_cases he : e ∈ Finset.image g Finset.univ
4676  · rw [if_pos he]
4677    obtain ⟨i₀, _, hi₀⟩ := Finset.mem_image.mp he
4678    rw [Finset.sum_eq_single_of_mem i₀ (Finset.mem_univ i₀)
4679      (fun j _ hj => by
4680        have hne : g j ≠ e := fun h => hj (hg (h.trans hi₀.symm))
4681        rw [if_neg hne])]
4682    rw [if_pos hi₀, hi₀]
4683  · rw [if_neg he]
4684    apply Finset.sum_eq_zero
4685    intro i _
4686    have hne : g i ≠ e := fun h => he (Finset.mem_image.mpr ⟨i, Finset.mem_univ i, h⟩)
4687    rw [if_neg hne]
4688
4689/-- The free edge-chain of an oriented closed walk through an injective family of
4690supported edges. -/
4691noncomputable def orientedCyclicChain {k : ℕ}
4692    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex) : singularOneChainFree :=
4693  ∑ i, (orientedEdgeOfCoeff c (g i)).chain
4694
4695/-- Pointwise coefficient of an oriented closed walk: on the walk it is the
4696sign-unit of the underlying flow, and off the walk it is zero. -/
4697theorem edgeCoeff_orientedCyclicChain [DecidableEq SingularOneSimplex] {k : ℕ}
4698    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex)
4699    (hg : Function.Injective g) (e : SingularOneSimplex) :
4700    edgeCoeff (orientedCyclicChain c g) e =
4701      if e ∈ Finset.image g Finset.univ then
4702        (if 0 < edgeCoeff c e then (1 : ℤ) else -1) else 0 := by
4703  unfold orientedCyclicChain
4704  rw [edgeCoeff_sum]
4705  have hterm : ∀ i : Fin k, edgeCoeff ((orientedEdgeOfCoeff c (g i)).chain) e
4706      = if g i = e then (if 0 < edgeCoeff c (g i) then (1 : ℤ) else -1) else 0 := by
4707    intro i
4708    rw [orientedEdgeOfCoeff_chain_eq_single, edgeCoeff_single]
4709  rw [Finset.sum_congr rfl (fun i _ => hterm i)]
4710  rw [sum_ite_image_of_injective g hg (fun x => if 0 < edgeCoeff c x then (1 : ℤ) else -1) e]
4711
4712/-- The support of an oriented closed walk is exactly the image of its edge
4713family. -/
4714theorem edgeSupport_orientedCyclicChain [DecidableEq SingularOneSimplex] {k : ℕ}
4715    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex)
4716    (hg : Function.Injective g) :
4717    edgeSupport (orientedCyclicChain c g) = Finset.image g Finset.univ := by
4718  ext e
4719  rw [mem_edgeSupport_iff, edgeCoeff_orientedCyclicChain c g hg e]
4720  by_cases he : e ∈ Finset.image g Finset.univ
4721  · rw [if_pos he]
4722    simp only [iff_true, he]
4723    exact sign_unit_ne_zero _
4724  · rw [if_neg he]
4725    simp [he]
4726
4727/-- If a sign-selected oriented closed walk hits a unit coefficient of the ambient
4728flow, then subtracting that walk strictly shrinks support.  This isolates the
4729support-cardinality part of large-support extraction from the separate problem of
4730encoding mixed-orientation walks in the old one-scalar cyclic-edge-list format. -/
4731theorem edgeSupportCard_sub_orientedCyclic_lt_of_unitCoeff
4732    [DecidableEq SingularOneSimplex] {k : ℕ}
4733    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex)
4734    (hg : Function.Injective g) (hmem : ∀ i, g i ∈ edgeSupport c)
4735    (hunit : ∃ i : Fin k, (edgeCoeff c (g i)).natAbs = 1) :
4736    edgeSupportCard (c - orientedCyclicChain c g) < edgeSupportCard c := by
4737  apply edgeSupportCard_sub_lt_of_supported_exact_cancel
4738  · rw [edgeSupport_orientedCyclicChain c g hg]
4739    exact Finset.image_subset_iff.mpr (fun i _ => hmem i)
4740  · obtain ⟨i, hi⟩ := hunit
4741    refine ⟨g i, ?_, ?_⟩
4742    · rw [edgeSupport_orientedCyclicChain c g hg]
4743      exact Finset.mem_image.mpr ⟨i, Finset.mem_univ i, rfl⟩
4744    · rw [edgeCoeff_orientedCyclicChain c g hg]
4745      have himg : g i ∈ Finset.image g Finset.univ :=
4746        Finset.mem_image.mpr ⟨i, Finset.mem_univ i, rfl⟩
4747      rw [if_pos himg]
4748      exact eq_sign_unit_of_natAbs_eq_one (edgeCoeff c (g i)) hi
4749
4750/-- Scaling a sign-selected oriented closed walk by the minimum absolute
4751coefficient on the walk strictly shrinks support.  This is the support-cardinality
4752bookkeeping needed for a true exact cyclic peel: the minimum-coefficient edge is
4753cancelled exactly, while no new edge outside the original support appears. -/
4754theorem edgeSupportCard_sub_scaled_orientedCyclic_lt
4755    [DecidableEq SingularOneSimplex] {k : ℕ}
4756    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex)
4757    (hk : 0 < k) (hg : Function.Injective g) (hmem : ∀ i, g i ∈ edgeSupport c) :
4758    ∃ m : ℤ, 0 < m ∧
4759      edgeSupportCard (c - m • orientedCyclicChain c g) < edgeSupportCard c := by
4760  let coeffAbs : Fin k → ℕ := fun i => (edgeCoeff c (g i)).natAbs
4761  haveI : Nonempty (Fin k) := ⟨⟨0, hk⟩⟩
4762  obtain ⟨i₀, _hi₀_mem, hi₀_min⟩ :=
4763    Finset.exists_min_image (Finset.univ : Finset (Fin k)) coeffAbs Finset.univ_nonempty
4764  let mN : ℕ := coeffAbs i₀
4765  let m : ℤ := (mN : ℤ)
4766  have hce_ne : edgeCoeff c (g i₀) ≠ 0 :=
4767    (mem_edgeSupport_iff c (g i₀)).mp (hmem i₀)
4768  have hmN_ne : mN ≠ 0 := by
4769    intro hzero
4770    apply hce_ne
4771    exact Int.natAbs_eq_zero.mp hzero
4772  have hm_pos_cast : (0 : ℤ) < (mN : ℤ) := by
4773    exact_mod_cast Nat.pos_of_ne_zero hmN_ne
4774  have hm_pos : 0 < m := hm_pos_cast
4775  refine ⟨m, hm_pos, ?_⟩
4776  apply edgeSupportCard_sub_lt_of_supported_exact_cancel
4777  · intro e he
4778    have hcoeff_ne : edgeCoeff (m • orientedCyclicChain c g) e ≠ 0 :=
4779      (mem_edgeSupport_iff (m • orientedCyclicChain c g) e).mp he
4780    have hP_ne : edgeCoeff (orientedCyclicChain c g) e ≠ 0 := by
4781      intro hP_zero
4782      apply hcoeff_ne
4783      rw [edgeCoeff_zsmul, hP_zero, mul_zero]
4784    have heP : e ∈ edgeSupport (orientedCyclicChain c g) :=
4785      (mem_edgeSupport_iff (orientedCyclicChain c g) e).mpr hP_ne
4786    rw [edgeSupport_orientedCyclicChain c g hg] at heP
4787    obtain ⟨i, _hi, rfl⟩ := Finset.mem_image.mp heP
4788    exact hmem i
4789  · refine ⟨g i₀, ?_, ?_⟩
4790    · have hcoeff_eq :
4791          edgeCoeff (m • orientedCyclicChain c g) (g i₀) = edgeCoeff c (g i₀) := by
4792        rw [edgeCoeff_zsmul, edgeCoeff_orientedCyclicChain c g hg]
4793        have himg : g i₀ ∈ Finset.image g Finset.univ :=
4794          Finset.mem_image.mpr ⟨i₀, Finset.mem_univ i₀, rfl⟩
4795        rw [if_pos himg]
4796        exact intNatAbs_mul_signUnit_eq_self (edgeCoeff c (g i₀))
4797      exact (mem_edgeSupport_iff (m • orientedCyclicChain c g) (g i₀)).mpr
4798        (by rw [hcoeff_eq]; exact hce_ne)
4799    · rw [edgeCoeff_zsmul, edgeCoeff_orientedCyclicChain c g hg]
4800      have himg : g i₀ ∈ Finset.image g Finset.univ :=
4801        Finset.mem_image.mpr ⟨i₀, Finset.mem_univ i₀, rfl⟩
4802      rw [if_pos himg]
4803      exact intNatAbs_mul_signUnit_eq_self (edgeCoeff c (g i₀))
4804
4805/-- The ℓ¹ size of an oriented closed walk through an injective family of `k`
4806edges is exactly `k`. -/
4807theorem chainL1_orientedCyclicChain [DecidableEq SingularOneSimplex] {k : ℕ}
4808    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex)
4809    (hg : Function.Injective g) :
4810    chainL1 (orientedCyclicChain c g) = k := by
4811  unfold chainL1
4812  rw [edgeSupport_orientedCyclicChain c g hg]
4813  have hone : ∀ e ∈ Finset.image g Finset.univ,
4814      (edgeCoeff (orientedCyclicChain c g) e).natAbs = 1 := by
4815    intro e he
4816    rw [edgeCoeff_orientedCyclicChain c g hg e, if_pos he]
4817    exact natAbs_sign_unit _
4818  rw [Finset.sum_congr rfl hone, Finset.sum_const, smul_eq_mul, mul_one,
4819    Finset.card_image_of_injective Finset.univ hg, Finset.card_univ, Fintype.card_fin]
4820
4821/-- **The ℓ¹ decrease of one directed-cycle peel.**  Subtracting an oriented
4822closed walk through `k` distinct supported edges from a balanced flow lowers the
4823ℓ¹ size by exactly `k`: every edge on the walk loses one unit of magnitude (its
4824sign is aligned with the flow, so the magnitudes subtract), and all other
4825coefficients are unchanged. -/
4826theorem chainL1_sub_orientedCyclic [DecidableEq SingularOneSimplex] {k : ℕ}
4827    (c : singularOneChainFree) (g : Fin k → SingularOneSimplex)
4828    (hg : Function.Injective g) (hmem : ∀ i, g i ∈ edgeSupport c) :
4829    chainL1 (c - orientedCyclicChain c g) + k = chainL1 c := by
4830  set P := orientedCyclicChain c g with hP
4831  have himg_sub : Finset.image g Finset.univ ⊆ edgeSupport c :=
4832    Finset.image_subset_iff.mpr (fun i _ => hmem i)
4833  -- pointwise additivity of natAbs on the support of `c`
4834  have hpt : ∀ e ∈ edgeSupport c,
4835      (edgeCoeff c e).natAbs
4836        = (edgeCoeff (c - P) e).natAbs + (edgeCoeff P e).natAbs := by
4837    intro e he
4838    have hce : edgeCoeff c e ≠ 0 := (mem_edgeSupport_iff c e).mp he
4839    rw [edgeCoeff_sub]
4840    rw [hP, edgeCoeff_orientedCyclicChain c g hg e]
4841    by_cases himg : e ∈ Finset.image g Finset.univ
4842    · rw [if_pos himg, natAbs_sign_unit]
4843      exact natAbs_sub_sign_unit (edgeCoeff c e) hce
4844    · rw [if_neg himg]
4845      simp
4846  -- supports of `c - P` and `P` are contained in the support of `c`
4847  have hPsupp : edgeSupport P ⊆ edgeSupport c := by
4848    rw [hP, edgeSupport_orientedCyclicChain c g hg]; exact himg_sub
4849  have hCPsupp : edgeSupport (c - P) ⊆ edgeSupport c := by
4850    intro e he
4851    by_contra hnotc
4852    have hc0 : edgeCoeff c e = 0 :=
4853      Classical.not_not.mp (mt (mem_edgeSupport_iff c e).mpr hnotc)
4854    have hP0 : edgeCoeff P e = 0 := by
4855      have : e ∉ edgeSupport P := fun hmem' => hnotc (hPsupp hmem')
4856      exact Classical.not_not.mp (mt (mem_edgeSupport_iff P e).mpr this)
4857    have : edgeCoeff (c - P) e = 0 := by rw [edgeCoeff_sub, hc0, hP0, sub_zero]
4858    exact (mem_edgeSupport_iff (c - P) e).mp he this
4859  -- extend the two residual/walk sums from their own supports to `edgeSupport c`
4860  have hsum_cP : ∑ e ∈ edgeSupport c, (edgeCoeff (c - P) e).natAbs = chainL1 (c - P) := by
4861    unfold chainL1
4862    refine (Finset.sum_subset hCPsupp (fun x _ hx => ?_)).symm
4863    have hx0 : edgeCoeff (c - P) x = 0 :=
4864      Classical.not_not.mp (mt (mem_edgeSupport_iff (c - P) x).mpr hx)
4865    rw [hx0]; rfl
4866  have hsum_P : ∑ e ∈ edgeSupport c, (edgeCoeff P e).natAbs = chainL1 P := by
4867    unfold chainL1
4868    refine (Finset.sum_subset hPsupp (fun x _ hx => ?_)).symm
4869    have hx0 : edgeCoeff P x = 0 :=
4870      Classical.not_not.mp (mt (mem_edgeSupport_iff P x).mpr hx)
4871    rw [hx0]; rfl
4872  have hP_k : chainL1 P = k := by rw [hP]; exact chainL1_orientedCyclicChain c g hg
4873  calc chainL1 (c - P) + k
4874      = chainL1 (c - P) + chainL1 P := by rw [hP_k]
4875    _ = (∑ e ∈ edgeSupport c, (edgeCoeff (c - P) e).natAbs)
4876          + (∑ e ∈ edgeSupport c, (edgeCoeff P e).natAbs) := by rw [hsum_cP, hsum_P]
4877    _ = ∑ e ∈ edgeSupport c,
4878          ((edgeCoeff (c - P) e).natAbs + (edgeCoeff P e).natAbs) := by
4879        rw [Finset.sum_add_distrib]
4880    _ = ∑ e ∈ edgeSupport c, (edgeCoeff c e).natAbs := (Finset.sum_congr rfl hpt).symm
4881    _ = chainL1 c := rfl
4882
4883/-! ### Existence of an oriented closed walk in a balanced nonzero flow
4884
4885A nonzero balanced free edge-flow always contains an oriented closed walk through
4886distinct supported edges.  If some supported edge is a loop (its two endpoints
4887coincide) the walk is that single edge.  Otherwise the balance condition lets us
4888take a successor edge from every supported edge (its initial vertex matches the
4889current edge's terminal vertex); iterating this successor on the finite support
4890must return to a periodic point, and the minimal period gives a simple closed
4891walk. -/
4892
4893open Function in
4894/-- **Oriented closed walk extraction.**  Every nonzero balanced free edge-flow
4895admits an oriented closed walk: a positive number `k` of distinct supported
4896edges `g : Fin k → SingularOneSimplex` whose sign-selected orientations connect
4897terminal-to-initial cyclically. -/
4898theorem exists_orientedCyclicFamily_of_balanced_nonzero
4899    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
4900    (c : singularOneChainFree)
4901    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
4902    (hne : c ≠ 0) :
4903    ∃ (k : ℕ) (g : Fin k → SingularOneSimplex),
4904      0 < k ∧ Function.Injective g ∧ (∀ i, g i ∈ edgeSupport c) ∧
4905        (∀ i, (orientedEdgeOfCoeff c (g i)).terminal
4906          = (orientedEdgeOfCoeff c (g (finRotate k i))).initial) := by
4907  by_cases hloopex : ∃ e ∈ edgeSupport c,
4908      (orientedEdgeOfCoeff c e).initial = (orientedEdgeOfCoeff c e).terminal
4909  · obtain ⟨e, he, hloop⟩ := hloopex
4910    refine ⟨1, fun _ => e, Nat.one_pos, ?_, ?_, ?_⟩
4911    · intro a b _; exact Subsingleton.elim a b
4912    · intro _; exact he
4913    · intro _; exact hloop.symm
4914  · push_neg at hloopex
4915    have hsupp_ne : (edgeSupport c).Nonempty := by
4916      rw [Finset.nonempty_iff_ne_empty]
4917      intro h; exact hne ((edgeSupport_eq_empty_iff c).mp h)
4918    obtain ⟨e₀, he₀⟩ := hsupp_ne
4919    haveI : Fintype {x // x ∈ edgeSupport c} := FinsetCoe.fintype _
4920    let y₀ : {x // x ∈ edgeSupport c} := ⟨e₀, he₀⟩
4921    let nextSupp : {x // x ∈ edgeSupport c} → {x // x ∈ edgeSupport c} := fun s =>
4922      ⟨(exists_next_orientedEdge_from_terminal hzero s.2 (hloopex s.1 s.2)).choose,
4923       (exists_next_orientedEdge_from_terminal hzero s.2 (hloopex s.1 s.2)).choose_spec.1⟩
4924    have nextSupp_spec : ∀ s : {x // x ∈ edgeSupport c},
4925        (orientedEdgeOfCoeff c (nextSupp s).val).initial
4926          = (orientedEdgeOfCoeff c s.val).terminal := fun s =>
4927      (exists_next_orientedEdge_from_terminal hzero s.2 (hloopex s.1 s.2)).choose_spec.2
4928    -- a periodic point exists by pigeonhole on the finite support
4929    have hper : (Function.periodicPts nextSupp).Nonempty := by
4930      obtain ⟨i, j, hij, hijeq⟩ :=
4931        Finite.exists_ne_map_eq_of_infinite (fun n : ℕ => nextSupp^[n] y₀)
4932      rcases Nat.lt_or_ge i j with hlt | hge
4933      · refine ⟨nextSupp^[i] y₀, Function.mk_mem_periodicPts (Nat.sub_pos_of_lt hlt) ?_⟩
4934        show nextSupp^[j - i] (nextSupp^[i] y₀) = nextSupp^[i] y₀
4935        rw [← Function.iterate_add_apply, Nat.sub_add_cancel hlt.le]
4936        exact hijeq.symm
4937      · have hlt : j < i := lt_of_le_of_ne hge hij.symm
4938        refine ⟨nextSupp^[j] y₀, Function.mk_mem_periodicPts (Nat.sub_pos_of_lt hlt) ?_⟩
4939        show nextSupp^[i - j] (nextSupp^[j] y₀) = nextSupp^[j] y₀
4940        rw [← Function.iterate_add_apply, Nat.sub_add_cancel hlt.le]
4941        exact hijeq
4942    obtain ⟨y, hy⟩ := hper
4943    have hp_pos : 0 < Function.minimalPeriod nextSupp y :=
4944      Function.minimalPeriod_pos_of_mem_periodicPts hy
4945    obtain ⟨m, hm⟩ := Nat.exists_eq_succ_of_ne_zero hp_pos.ne'
4946    have hp_iter : nextSupp^[m + 1] y = y := by
4947      have h := Function.iterate_minimalPeriod (f := nextSupp) (x := y)
4948      rwa [hm] at h
4949    have hinjOn : Set.InjOn (fun n => nextSupp^[n] y) (Set.Iio (m + 1)) := by
4950      have h := Function.iterate_injOn_Iio_minimalPeriod (f := nextSupp) (x := y)
4951      rwa [hm] at h
4952    refine ⟨m + 1, fun i => (nextSupp^[i.val] y).val, Nat.succ_pos m, ?_, ?_, ?_⟩
4953    · intro i j hgij
4954      apply Fin.ext
4955      exact hinjOn (Set.mem_Iio.mpr i.isLt) (Set.mem_Iio.mpr j.isLt) (Subtype.ext hgij)
4956    · intro i; exact (nextSupp^[i.val] y).property
4957    · intro i
4958      have hrot : nextSupp^[(finRotate (m + 1) i).val] y = nextSupp (nextSupp^[i.val] y) := by
4959        rw [finRotate_succ_apply, Fin.val_add_one]
4960        split
4961        · rename_i hlast
4962          have hival : i.val = m := by rw [hlast]; simp
4963          rw [hival, Function.iterate_zero_apply]
4964          have hsucc : nextSupp (nextSupp^[m] y) = nextSupp^[m + 1] y :=
4965            (Function.iterate_succ_apply' nextSupp m y).symm
4966          rw [hsucc, hp_iter]
4967        · rw [Function.iterate_succ_apply']
4968      show (orientedEdgeOfCoeff c (nextSupp^[i.val] y).val).terminal
4969        = (orientedEdgeOfCoeff c (nextSupp^[(finRotate (m + 1) i).val] y).val).initial
4970      rw [hrot]
4971      exact (nextSupp_spec (nextSupp^[i.val] y)).symm
4972
4973open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
4974/-- **One-step directed-cycle extraction (unconditional).**  Every nonzero
4975balanced free edge-flow splits as one directed-cycle piece plus a balanced
4976residual of strictly smaller ℓ¹ size.  The piece is the oriented closed walk of
4977`exists_orientedCyclicFamily_of_balanced_nonzero`, packaged through the oriented
4978homological engine; the ℓ¹ decrease is `chainL1_sub_orientedCyclic`. -/
4979theorem directedCycleExtraction
4980    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
4981    (c : singularOneChainFree)
4982    (hcbd : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
4983    (hne : c ≠ 0) :
4984    ∃ (t : DirectedCycleFreeTerm) (r : singularOneChainFree),
4985      c = t.chain + r ∧
4986        ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
4987          chainL1 r < chainL1 c := by
4988  obtain ⟨k, g, hk, hg_inj, hg_mem, hconn⟩ :=
4989    exists_orientedCyclicFamily_of_balanced_nonzero c hcbd hne
4990  let o : Fin k → OrientedSingularEdge := fun i => orientedEdgeOfCoeff c (g i)
4991  have hconn' : ∀ i, (o i).terminal = (o (finRotate k i)).initial := hconn
4992  let t := directedCycleFreeTerm_of_orientedCyclicFamily o hconn'
4993  have ht_chain : t.chain = orientedCyclicChain c g := rfl
4994  have hbd_t : ModuleCat.Hom.hom singularOneBoundaryFree t.chain = 0 := by
4995    rw [ht_chain]; unfold orientedCyclicChain
4996    exact cyclicOrientedFamily_freeBoundary_zero o hconn'
4997  refine ⟨t, c - t.chain, ?_, ?_, ?_⟩
4998  · abel
4999  · rw [map_sub, hcbd, hbd_t, sub_zero]
5000  · have hkey := chainL1_sub_orientedCyclic c g hg_inj hg_mem
5001    rw [ht_chain]
5002    omega
5003
5004open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5005/-- **The unconditional directed-cycle kernel decomposition.**  Every free
5006edge-chain in the kernel of the explicit boundary is a finite sum of
5007directed-cycle pieces.  Proved by strong induction on the ℓ¹ size, peeling one
5008oriented closed walk at a time with `directedCycleExtraction`.  This discharges
5009the hypothesis of `circleH1ZIsoInt_of_directedCycles_of_zeroWinding_bounds`
5010without any axiom or `sorry`. -/
5011theorem freeBoundaryKernel_decomposesIntoDirectedCycles_holds
5012    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex] :
5013    freeBoundaryKernel_decomposesIntoDirectedCycles := by
5014  intro c hc
5015  suffices H : ∀ n, ∀ c : singularOneChainFree, chainL1 c = n →
5016      ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
5017        ∃ ts : List DirectedCycleFreeTerm, c = directedCycleFreeTermListChain ts by
5018    exact H (chainL1 c) c rfl hc
5019  intro n
5020  induction n using Nat.strong_induction_on with
5021  | _ n ih =>
5022    intro c hcL1 hcbd
5023    by_cases hzero : c = 0
5024    · exact ⟨[], by rw [hzero]; rfl⟩
5025    · obtain ⟨t, r, hdecomp, hrbd, hrlt⟩ := directedCycleExtraction c hcbd hzero
5026      rw [hcL1] at hrlt
5027      obtain ⟨ts, hts⟩ := ih (chainL1 r) hrlt r rfl hrbd
5028      refine ⟨t :: ts, ?_⟩
5029      show c = t.chain + directedCycleFreeTermListChain ts
5030      rw [hdecomp, hts]
5031
5032/-! ### Directed-cycle generation reduction
5033
5034The finite-flow theorem reduces every cycle to a finite sum of
5035`DirectedCycleFreeTerm`s.  The remaining geometric filling problem can therefore
5036be localized: prove boundary-generation for one directed closed walk, then sum
5037the witnesses. -/
5038
5039open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5040/-- Local remaining geometric target: each directed-cycle term is homologous, at
5041the chain level, to an integer multiple of the fundamental cycle. -/
5042def directedCycleTerms_boundary_generate : Prop :=
5043  ∀ t : DirectedCycleFreeTerm,
5044    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
5045      t.cycle =
5046        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
5047          ModuleCat.Hom.hom fundamentalCycle n
5048
5049open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5050/-- If every directed-cycle term is generated by the fundamental cycle modulo a
5051boundary, then every finite directed-cycle list is. -/
5052theorem directedCycleFreeTermList_boundary_generates
5053    (hterm : directedCycleTerms_boundary_generate) :
5054    ∀ ts : List DirectedCycleFreeTerm,
5055      ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
5056        directedCycleFreeTermListCycle ts =
5057          ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
5058            ModuleCat.Hom.hom fundamentalCycle n
5059  | [] => by
5060      refine ⟨0, 0, ?_⟩
5061      unfold directedCycleFreeTermListCycle
5062      simp
5063  | t :: ts => by
5064      obtain ⟨n₁, b₁, ht⟩ := hterm t
5065      obtain ⟨n₂, b₂, hts⟩ := directedCycleFreeTermList_boundary_generates hterm ts
5066      refine ⟨n₁ + n₂, b₁ + b₂, ?_⟩
5067      unfold directedCycleFreeTermListCycle
5068      rw [ht, hts, map_add, map_add]
5069      abel
5070
5071open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5072/-- Boundary-generation for individual directed-cycle terms implies the global
5073circle chain-level generation theorem.  Combined with
5074`zeroWindingCycles_bound_iff_fundamentalCycle_boundary_generates`, this is the
5075next minimal geometric target: fill one directed closed walk. -/
5076theorem fundamentalCycle_boundary_generates_of_directedCycleTerms
5077    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
5078    (hterm : directedCycleTerms_boundary_generate) :
5079    fundamentalCycle_boundary_generates := by
5080  intro z
5081  let c : singularOneChainFree :=
5082    ModuleCat.Hom.hom singularOneChainToFree
5083      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) z)
5084  have hc0 : ModuleCat.Hom.hom singularOneBoundaryFree c = 0 := by
5085    unfold c
5086    change ModuleCat.Hom.hom
5087        (sphereOneSingularIntChainComplex.iCycles 1 ≫ singularOneChainToFree ≫
5088          singularOneBoundaryFree) z = 0
5089    rw [singularOneChainToFree_boundary_free]
5090    rw [← Category.assoc, HomologicalComplex.iCycles_d]
5091    simp
5092  obtain ⟨ts, hts⟩ := freeBoundaryKernel_decomposesIntoDirectedCycles_holds c hc0
5093  have hcycle : z = directedCycleFreeTermListCycle ts := by
5094    have hinj_toFree : Function.Injective (ModuleCat.Hom.hom singularOneChainToFree) := by
5095      haveI : IsIso singularOneChainToFree := by
5096        change IsIso singularOneChainFreeIso.hom
5097        infer_instance
5098      haveI : Mono singularOneChainToFree := inferInstance
5099      exact (ModuleCat.mono_iff_injective singularOneChainToFree).mp inferInstance
5100    have hinj_iCycles :
5101        Function.Injective
5102          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
5103      (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
5104    apply hinj_iCycles
5105    apply hinj_toFree
5106    unfold c at hts
5107    rw [hts, directedCycleFreeTermList_chain_eq ts]
5108  obtain ⟨n, b, hlist⟩ := directedCycleFreeTermList_boundary_generates hterm ts
5109  refine ⟨n, b, ?_⟩
5110  rw [hcycle, hlist]
5111
5112open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5113/-- The one-directed-cycle generation theorem is enough for the final Mathlib
5114circle H₁ computation. -/
5115theorem circleH1ZIsoInt_of_directedCycleTerms
5116    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
5117    (hterm : directedCycleTerms_boundary_generate) :
5118    MathlibCohomologyBridge.circleH1ZIsoInt :=
5119  circleH1ZIsoInt_of_fundamentalCycle_boundary_generates
5120    (fundamentalCycle_boundary_generates_of_directedCycleTerms hterm)
5121
5122/-! ### Oriented-family generation reduction
5123
5124The local prism construction needs the actual closed walk, not just a packaged
5125cycle object.  This structure retains that geometric data. -/
5126
5127/-- A concrete oriented cyclic family: a finite sign-oriented closed walk in the
5128singular `1`-simplices. -/
5129structure OrientedCyclicFamilyTerm where
5130  k : ℕ
5131  o : Fin k → OrientedSingularEdge
5132  hconn : ∀ i : Fin k, (o i).terminal = (o (finRotate k i)).initial
5133
5134open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5135/-- Package an oriented cyclic family as a directed-cycle term. -/
5136noncomputable def OrientedCyclicFamilyTerm.toDirectedCycleFreeTerm
5137    (T : OrientedCyclicFamilyTerm) : DirectedCycleFreeTerm :=
5138  directedCycleFreeTerm_of_orientedCyclicFamily T.o T.hconn
5139
5140open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5141/-- Including a concrete oriented cyclic family into raw `C₁` is exactly the raw
5142chain of its oriented edges. -/
5143theorem OrientedCyclicFamilyTerm.iCycles_eq_orientedChain
5144    (T : OrientedCyclicFamilyTerm) :
5145    ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5146      T.toDirectedCycleFreeTerm.cycle =
5147        ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (T.o i).chain) := by
5148  rw [DirectedCycleFreeTerm.iCycles_eq_freeToChain]
5149  rfl
5150
5151open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5152/-- The winding of a concrete oriented cyclic family is the sum of the oriented
5153winding contributions of its edges. -/
5154theorem OrientedCyclicFamilyTerm.cycleWinding_eq_sum
5155    (T : OrientedCyclicFamilyTerm) :
5156    cycleWinding T.toDirectedCycleFreeTerm.cycle =
5157      ∑ i, orientedWinding (T.o i) := by
5158  rw [DirectedCycleFreeTerm.cycleWinding_eq_freeChain]
5159  change ModuleCat.Hom.hom windingChainMap
5160      (ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (T.o i).chain)) =
5161    ∑ i, orientedWinding (T.o i)
5162  exact windingChainMap_freeToChain_orientedChain_sum T.o
5163
5164open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5165/-- Sum of path-cones over the oriented edge paths of a concrete cyclic family. -/
5166noncomputable def OrientedCyclicFamilyTerm.pathConeChain
5167    (T : OrientedCyclicFamilyTerm) : singularTwoChainFree :=
5168  coneSingularTwoChainOfPathFamily (fun i : Fin T.k => orientedEdgePath (T.o i))
5169
5170open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5171/-- The explicit free `C₁` boundary of the summed path-cones over an oriented
5172cyclic family.  The next geometric cancellation target is the difference between
5173the terminal-return side sum and the constant-apex side sum, together with the
5174fundamental-cycle correction. -/
5175theorem OrientedCyclicFamilyTerm.pathConeChain_boundary
5176    (T : OrientedCyclicFamilyTerm) :
5177    ModuleCat.Hom.hom singularTwoBoundaryFree T.pathConeChain =
5178      (∑ i, ModuleCat.freeMk
5179          (singularOneSimplexOfMap (coneTerminalSide (orientedEdgePath (T.o i))))) -
5180        (∑ i, ModuleCat.freeMk
5181          (singularOneSimplexOfMap (constantOneSimplex ((orientedEdgePath (T.o i)) 0)))) +
5182          (∑ i, ModuleCat.freeMk
5183            (singularOneSimplexOfMap (oneSimplexOfPath (orientedEdgePath (T.o i))))) := by
5184  unfold OrientedCyclicFamilyTerm.pathConeChain
5185  exact singularTwoBoundaryFree_coneSingularTwoChainOfPathFamily
5186    (fun i : Fin T.k => orientedEdgePath (T.o i))
5187
5188open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5189/-- In a cyclic oriented family, the sum of constant apex edges at each oriented
5190initial point is the same as the sum at each oriented terminal point.  This is the
5191index-shift skeleton for cancelling side chains in the multi-edge cone prism. -/
5192theorem OrientedCyclicFamilyTerm.constantApexSide_reindex_terminal
5193    (T : OrientedCyclicFamilyTerm) :
5194    (∑ i, ModuleCat.freeMk
5195        (singularOneSimplexOfMap (constantOneSimplex ((orientedEdgePath (T.o i)) 0))) :
5196        singularOneChainFree) =
5197      ∑ i, ModuleCat.freeMk
5198        (singularOneSimplexOfMap (constantOneSimplex ((orientedEdgePath (T.o i)) 1))) := by
5199  rw [← Equiv.sum_comp (finRotate T.k)
5200    (fun j => (ModuleCat.freeMk
5201      (singularOneSimplexOfMap (constantOneSimplex ((orientedEdgePath (T.o j)) 0))) :
5202        singularOneChainFree))]
5203  refine Finset.sum_congr rfl (fun i _ => ?_)
5204  apply congrArg ModuleCat.freeMk
5205  apply congrArg singularOneSimplexOfMap
5206  apply congrArg constantOneSimplex
5207  rw [orientedEdgePath_zero, orientedEdgePath_one]
5208  exact congrArg vertexPoint (T.hconn i).symm
5209
5210open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5211/-- A concrete oriented cyclic family has an integer total winding, and
5212subtracting that multiple of the fundamental cycle leaves a zero-winding residual.
5213This is the cycle-object version of the prism target. -/
5214theorem OrientedCyclicFamilyTerm.zeroWinding_residual
5215    (T : OrientedCyclicFamilyTerm) :
5216    ∃ n : ModuleCat.of ℤ ℤ,
5217      (∑ i, orientedWinding (T.o i)) = (n : ℝ) ∧
5218        cycleWinding
5219          (T.toDirectedCycleFreeTerm.cycle - ModuleCat.Hom.hom fundamentalCycle n) = 0 := by
5220  obtain ⟨n, hn⟩ := T.toDirectedCycleFreeTerm.winding_integral
5221  refine ⟨n, ?_, ?_⟩
5222  · rw [← T.cycleWinding_eq_sum, hn]
5223  · unfold cycleWinding at hn ⊢
5224    rw [map_sub]
5225    change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap)
5226        T.toDirectedCycleFreeTerm.cycle -
5227      cycleWinding (ModuleCat.Hom.hom fundamentalCycle n) = 0
5228    rw [hn, cycleWinding_fundamentalCycle]
5229    ring
5230
5231open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5232/-- In any boundary-generation witness for a concrete oriented cyclic family,
5233the integer coefficient is forced to be the total oriented winding. -/
5234theorem OrientedCyclicFamilyTerm.generation_coeff_eq_winding
5235    (T : OrientedCyclicFamilyTerm)
5236    (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2)
5237    (h :
5238      T.toDirectedCycleFreeTerm.cycle =
5239        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
5240          ModuleCat.Hom.hom fundamentalCycle n) :
5241    ∑ i, orientedWinding (T.o i) = (n : ℝ) := by
5242  have hboundary_winding :
5243      cycleWinding (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b) = 0 := by
5244    unfold cycleWinding
5245    change ModuleCat.Hom.hom
5246      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
5247        sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) b = 0
5248    rw [HomologicalComplex.toCycles_i_assoc, windingChainMap_boundary]
5249    simp
5250  calc ∑ i, orientedWinding (T.o i)
5251      = cycleWinding T.toDirectedCycleFreeTerm.cycle :=
5252        (T.cycleWinding_eq_sum).symm
5253    _ = cycleWinding
5254        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
5255          ModuleCat.Hom.hom fundamentalCycle n) := by rw [h]
5256    _ = (n : ℝ) := by
5257        unfold cycleWinding
5258        rw [map_add]
5259        change cycleWinding (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b) +
5260          cycleWinding (ModuleCat.Hom.hom fundamentalCycle n) = (n : ℝ)
5261        rw [hboundary_winding, cycleWinding_fundamentalCycle]
5262        simp
5263
5264open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5265/-- Chain represented by a list of concrete oriented cyclic families. -/
5266noncomputable def orientedCyclicFamilyTermListChain
5267    (ts : List OrientedCyclicFamilyTerm) : singularOneChainFree :=
5268  directedCycleFreeTermListChain (ts.map OrientedCyclicFamilyTerm.toDirectedCycleFreeTerm)
5269
5270open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5271/-- Cycle represented by a list of concrete oriented cyclic families. -/
5272noncomputable def orientedCyclicFamilyTermListCycle
5273    (ts : List OrientedCyclicFamilyTerm) :
5274    sphereOneSingularIntChainComplex.cycles 1 :=
5275  directedCycleFreeTermListCycle (ts.map OrientedCyclicFamilyTerm.toDirectedCycleFreeTerm)
5276
5277open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5278/-- One-step extraction retaining the actual oriented cyclic family data. -/
5279theorem orientedCyclicFamilyExtraction
5280    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
5281    (c : singularOneChainFree)
5282    (hcbd : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
5283    (hne : c ≠ 0) :
5284    ∃ (T : OrientedCyclicFamilyTerm) (r : singularOneChainFree),
5285      c = T.toDirectedCycleFreeTerm.chain + r ∧
5286        ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
5287          chainL1 r < chainL1 c := by
5288  obtain ⟨k, g, hk, hg_inj, hg_mem, hconn⟩ :=
5289    exists_orientedCyclicFamily_of_balanced_nonzero c hcbd hne
5290  let o : Fin k → OrientedSingularEdge := fun i => orientedEdgeOfCoeff c (g i)
5291  have hconn' : ∀ i, (o i).terminal = (o (finRotate k i)).initial := hconn
5292  let T : OrientedCyclicFamilyTerm := { k := k, o := o, hconn := hconn' }
5293  have hT_chain : T.toDirectedCycleFreeTerm.chain = orientedCyclicChain c g := rfl
5294  have hbd_T : ModuleCat.Hom.hom singularOneBoundaryFree T.toDirectedCycleFreeTerm.chain = 0 := by
5295    rw [hT_chain]; unfold orientedCyclicChain
5296    exact cyclicOrientedFamily_freeBoundary_zero o hconn'
5297  refine ⟨T, c - T.toDirectedCycleFreeTerm.chain, ?_, ?_, ?_⟩
5298  · abel
5299  · rw [map_sub, hcbd, hbd_T, sub_zero]
5300  · have hkey := chainL1_sub_orientedCyclic c g hg_inj hg_mem
5301    rw [hT_chain]
5302    omega
5303
5304open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5305/-- Support-cardinality version of oriented extraction.  The extracted oriented
5306closed walk is scaled by the minimum absolute coefficient on that walk, so the
5307residual is still balanced and has strictly smaller support.  This is the exact
5308finite-flow theorem needed before translating signed oriented cycles into the
5309older one-scalar `CyclicSingularEdgeListTerm` interface. -/
5310def largeSupportOrientedScaledExtractionStep : Prop :=
5311  ∀ c : singularOneChainFree,
5312    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
5313      c ≠ 0 →
5314        1 < edgeSupportCard c →
5315          ∃ (T : OrientedCyclicFamilyTerm) (m : ℤ) (r : singularOneChainFree),
5316            0 < m ∧
5317              c = m • T.toDirectedCycleFreeTerm.chain + r ∧
5318                ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
5319                  edgeSupportCard r < edgeSupportCard c
5320
5321open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5322/-- The support-cardinality oriented extraction step is unconditional.  The
5323`1 < support` hypothesis is retained to match the large-support interface, but
5324the proof only needs nonzero balanced flow. -/
5325theorem largeSupportOrientedScaledExtractionStep_holds
5326    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex] :
5327    largeSupportOrientedScaledExtractionStep := by
5328  intro c hcbd hne _hlarge
5329  obtain ⟨k, g, hk, hg_inj, hg_mem, hconn⟩ :=
5330    exists_orientedCyclicFamily_of_balanced_nonzero c hcbd hne
5331  let o : Fin k → OrientedSingularEdge := fun i => orientedEdgeOfCoeff c (g i)
5332  have hconn' : ∀ i, (o i).terminal = (o (finRotate k i)).initial := hconn
5333  let T : OrientedCyclicFamilyTerm := { k := k, o := o, hconn := hconn' }
5334  have hT_chain : T.toDirectedCycleFreeTerm.chain = orientedCyclicChain c g := rfl
5335  have hbd_T : ModuleCat.Hom.hom singularOneBoundaryFree T.toDirectedCycleFreeTerm.chain = 0 := by
5336    rw [hT_chain]; unfold orientedCyclicChain
5337    exact cyclicOrientedFamily_freeBoundary_zero o hconn'
5338  obtain ⟨m, hm_pos, hsupport⟩ :=
5339    edgeSupportCard_sub_scaled_orientedCyclic_lt c g hk hg_inj hg_mem
5340  refine ⟨T, m, c - m • T.toDirectedCycleFreeTerm.chain, hm_pos, ?_, ?_, ?_⟩
5341  · abel
5342  · rw [map_sub, map_zsmul, hbd_T, smul_zero, sub_zero]
5343    exact hcbd
5344  · rw [hT_chain]
5345    exact hsupport
5346
5347open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5348/-- Every balanced free edge-chain decomposes into concrete oriented cyclic
5349families. -/
5350theorem freeBoundaryKernel_decomposesIntoOrientedCyclicFamilies_holds
5351    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex] :
5352    ∀ c : singularOneChainFree,
5353      ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
5354        ∃ ts : List OrientedCyclicFamilyTerm, c = orientedCyclicFamilyTermListChain ts := by
5355  intro c hc
5356  suffices H : ∀ n, ∀ c : singularOneChainFree, chainL1 c = n →
5357      ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
5358        ∃ ts : List OrientedCyclicFamilyTerm, c = orientedCyclicFamilyTermListChain ts by
5359    exact H (chainL1 c) c rfl hc
5360  intro n
5361  induction n using Nat.strong_induction_on with
5362  | _ n ih =>
5363    intro c hcL1 hcbd
5364    by_cases hzero : c = 0
5365    · exact ⟨[], by rw [hzero]; rfl⟩
5366    · obtain ⟨T, r, hdecomp, hrbd, hrlt⟩ := orientedCyclicFamilyExtraction c hcbd hzero
5367      rw [hcL1] at hrlt
5368      obtain ⟨ts, hts⟩ := ih (chainL1 r) hrlt r rfl hrbd
5369      refine ⟨T :: ts, ?_⟩
5370      show c = T.toDirectedCycleFreeTerm.chain + orientedCyclicFamilyTermListChain ts
5371      rw [hdecomp, hts]
5372
5373open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5374/-- Local geometric target with the walk data retained: every concrete oriented
5375closed walk is homologous to an integer multiple of the fundamental cycle. -/
5376def orientedCyclicFamilies_boundary_generate : Prop :=
5377  ∀ T : OrientedCyclicFamilyTerm,
5378    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
5379      T.toDirectedCycleFreeTerm.cycle =
5380        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
5381          ModuleCat.Hom.hom fundamentalCycle n
5382
5383open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5384/-- Raw-chain form of the remaining prism target.  This is the form an explicit
5385singular prism construction should naturally prove: the `C₁` boundary of a
5386singular `2`-chain is the oriented closed walk minus the corresponding multiple
5387of the fundamental cycle. -/
5388def orientedCyclicFamilies_rawPrism_generate : Prop :=
5389  ∀ T : OrientedCyclicFamilyTerm,
5390    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
5391      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1) b =
5392        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5393          T.toDirectedCycleFreeTerm.cycle -
5394          ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5395            (ModuleCat.Hom.hom fundamentalCycle n)
5396
5397open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5398/-- Fully explicit raw-chain form of the remaining prism target: construct a
5399singular `2`-chain whose boundary is the raw oriented edge sum minus the matching
5400fundamental-cycle multiple. -/
5401def orientedCyclicFamilies_explicitRawPrism_generate : Prop :=
5402  ∀ T : OrientedCyclicFamilyTerm,
5403    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
5404      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1) b =
5405        ModuleCat.Hom.hom singularOneChainFreeToChain (∑ i, (T.o i).chain) -
5406          ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5407            (ModuleCat.Hom.hom fundamentalCycle n)
5408
5409open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5410/-- Free-coordinate prism target: construct an explicit free `C₂` chain whose
5411free boundary is the oriented edge sum minus the free-coordinate image of the
5412matching fundamental cycle.  This is the cleanest target for a hand-built finite
5413prism construction. -/
5414def orientedCyclicFamilies_freePrism_generate : Prop :=
5415  ∀ T : OrientedCyclicFamilyTerm,
5416    ∃ (n : ModuleCat.of ℤ ℤ) (B : singularTwoChainFree),
5417      ModuleCat.Hom.hom singularTwoBoundaryFree B =
5418        (∑ i, (T.o i).chain) -
5419          ModuleCat.Hom.hom singularOneChainToFree
5420            (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5421              (ModuleCat.Hom.hom fundamentalCycle n))
5422
5423open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5424/-- Free-coordinate image of an integer multiple of the fundamental cycle. -/
5425noncomputable def fundamentalCycleFreeChain (n : ModuleCat.of ℤ ℤ) : singularOneChainFree :=
5426  ModuleCat.Hom.hom singularOneChainToFree
5427    (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5428      (ModuleCat.Hom.hom fundamentalCycle n))
5429
5430open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5431/-- The free-coordinate image of the fundamental cycle has winding equal to its
5432integer coefficient. -/
5433theorem windingChainMap_fundamentalCycleFreeChain (n : ModuleCat.of ℤ ℤ) :
5434    ModuleCat.Hom.hom windingChainMap
5435      (ModuleCat.Hom.hom singularOneChainFreeToChain (fundamentalCycleFreeChain n)) =
5436        (n : ℝ) := by
5437  unfold fundamentalCycleFreeChain
5438  have hround :
5439      ModuleCat.Hom.hom singularOneChainFreeToChain
5440        (ModuleCat.Hom.hom singularOneChainToFree
5441          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5442            (ModuleCat.Hom.hom fundamentalCycle n))) =
5443        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5444          (ModuleCat.Hom.hom fundamentalCycle n) := by
5445    have hid := congrArg
5446      (fun f => ModuleCat.Hom.hom f
5447        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5448          (ModuleCat.Hom.hom fundamentalCycle n)))
5449      singularOneChainFreeIso.hom_inv_id
5450    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
5451      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
5452    exact hid
5453  rw [hround]
5454  exact cycleWinding_fundamentalCycle n
5455
5456open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5457/-- The desired free `C₁` boundary in the oriented-family free-prism target. -/
5458noncomputable def OrientedCyclicFamilyTerm.desiredFreePrismBoundary
5459    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ) : singularOneChainFree :=
5460  (∑ i, (T.o i).chain) - fundamentalCycleFreeChain n
5461
5462open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5463/-- Sum of the terminal-return sides in the path-cone boundary for an oriented
5464cyclic family. -/
5465noncomputable def OrientedCyclicFamilyTerm.terminalReturnSideChain
5466    (T : OrientedCyclicFamilyTerm) : singularOneChainFree :=
5467  ∑ i, ModuleCat.freeMk
5468    (singularOneSimplexOfMap (coneTerminalSide (orientedEdgePath (T.o i))))
5469
5470open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5471/-- The terminal-return side chain has winding equal to the negative total
5472oriented winding of the original cyclic family. -/
5473theorem OrientedCyclicFamilyTerm.winding_terminalReturnSideChain
5474    (T : OrientedCyclicFamilyTerm) :
5475    ModuleCat.Hom.hom windingChainMap
5476      (ModuleCat.Hom.hom singularOneChainFreeToChain T.terminalReturnSideChain) =
5477        - ∑ i, orientedWinding (T.o i) := by
5478  unfold OrientedCyclicFamilyTerm.terminalReturnSideChain
5479  rw [map_sum, map_sum]
5480  calc
5481    (∑ i, ModuleCat.Hom.hom windingChainMap
5482        (ModuleCat.Hom.hom singularOneChainFreeToChain
5483          (ModuleCat.freeMk
5484            (singularOneSimplexOfMap (coneTerminalSide (orientedEdgePath (T.o i)))))))
5485        = ∑ i, - orientedWinding (T.o i) := by
5486          refine Finset.sum_congr rfl (fun i _ => ?_)
5487          rw [windingChainMap_singularOneChainFreeToChain_freeMk]
5488          exact (T.o i).singularWinding_terminalReturnSide
5489    _ = - ∑ i, orientedWinding (T.o i) := by
5490          rw [Finset.sum_neg_distrib]
5491
5492open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5493/-- Sum of the initial constant-apex sides in the path-cone boundary for an
5494oriented cyclic family. -/
5495noncomputable def OrientedCyclicFamilyTerm.constantApexInitialSideChain
5496    (T : OrientedCyclicFamilyTerm) : singularOneChainFree :=
5497  ∑ i, ModuleCat.freeMk
5498    (singularOneSimplexOfMap (constantOneSimplex ((orientedEdgePath (T.o i)) 0)))
5499
5500open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5501/-- Sum of the terminal constant-apex sides in the path-cone boundary for an
5502oriented cyclic family. -/
5503noncomputable def OrientedCyclicFamilyTerm.constantApexTerminalSideChain
5504    (T : OrientedCyclicFamilyTerm) : singularOneChainFree :=
5505  ∑ i, ModuleCat.freeMk
5506    (singularOneSimplexOfMap (constantOneSimplex ((orientedEdgePath (T.o i)) 1)))
5507
5508open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5509/-- The terminal constant-apex side chain has zero winding. -/
5510theorem OrientedCyclicFamilyTerm.winding_constantApexTerminalSideChain
5511    (T : OrientedCyclicFamilyTerm) :
5512    ModuleCat.Hom.hom windingChainMap
5513      (ModuleCat.Hom.hom singularOneChainFreeToChain T.constantApexTerminalSideChain) =
5514        0 := by
5515  unfold OrientedCyclicFamilyTerm.constantApexTerminalSideChain
5516  rw [map_sum, map_sum]
5517  rw [Finset.sum_eq_zero]
5518  intro i _
5519  rw [singularOneSimplexOfMap_constantOneSimplex]
5520  exact windingChainMap_constantSingularOneSimplex ((orientedEdgePath (T.o i)) 1)
5521
5522open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5523/-- The cyclic connection reindexes the initial constant-apex side sum as the
5524terminal constant-apex side sum. -/
5525theorem OrientedCyclicFamilyTerm.constantApexInitialSideChain_eq_terminal
5526    (T : OrientedCyclicFamilyTerm) :
5527    T.constantApexInitialSideChain = T.constantApexTerminalSideChain := by
5528  unfold OrientedCyclicFamilyTerm.constantApexInitialSideChain
5529    OrientedCyclicFamilyTerm.constantApexTerminalSideChain
5530  exact T.constantApexSide_reindex_terminal
5531
5532open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5533/-- Sum of the path-parametric base edges appearing in the path-cone boundary. -/
5534noncomputable def OrientedCyclicFamilyTerm.pathBaseEdgeChain
5535    (T : OrientedCyclicFamilyTerm) : singularOneChainFree :=
5536  ∑ i, ModuleCat.freeMk
5537    (singularOneSimplexOfMap (oneSimplexOfPath (orientedEdgePath (T.o i))))
5538
5539open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5540/-- The signed free edge-chain of the oriented cyclic family. -/
5541noncomputable def OrientedCyclicFamilyTerm.orientedEdgeChain
5542    (T : OrientedCyclicFamilyTerm) : singularOneChainFree :=
5543  ∑ i, (T.o i).chain
5544
5545open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5546/-- The free `C₁` residual between the currently constructed path-cone boundary
5547and the desired free-prism boundary.  Filling this residual is exactly what turns
5548the finite path-cone skeleton into the final `freePrism` witness. -/
5549noncomputable def OrientedCyclicFamilyTerm.pathConeResidualBoundary
5550    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ) : singularOneChainFree :=
5551  ModuleCat.Hom.hom singularTwoBoundaryFree T.pathConeChain -
5552    T.desiredFreePrismBoundary n
5553
5554open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5555/-- Concrete expansion of the path-cone residual.  The remaining geometry is now
5556visible as a side-chain correction plus the difference between path-parametric
5557base edges and the signed oriented edge-chain, with the fundamental correction
5558carried explicitly. -/
5559theorem OrientedCyclicFamilyTerm.pathConeResidualBoundary_eq_explicit
5560    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ) :
5561    T.pathConeResidualBoundary n =
5562      T.terminalReturnSideChain - T.constantApexInitialSideChain +
5563        T.pathBaseEdgeChain - (T.orientedEdgeChain - fundamentalCycleFreeChain n) := by
5564  unfold OrientedCyclicFamilyTerm.pathConeResidualBoundary
5565    OrientedCyclicFamilyTerm.desiredFreePrismBoundary
5566    OrientedCyclicFamilyTerm.terminalReturnSideChain
5567    OrientedCyclicFamilyTerm.constantApexInitialSideChain
5568    OrientedCyclicFamilyTerm.pathBaseEdgeChain
5569    OrientedCyclicFamilyTerm.orientedEdgeChain
5570  rw [T.pathConeChain_boundary]
5571
5572open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5573/-- Terminal-side form of the residual.  After cyclic reindexing, the residual
5574splits into the terminal-return side correction and the path-edge-to-oriented-edge
5575correction. -/
5576theorem OrientedCyclicFamilyTerm.pathConeResidualBoundary_eq_terminalSide
5577    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ) :
5578    T.pathConeResidualBoundary n =
5579      T.terminalReturnSideChain - T.constantApexTerminalSideChain +
5580        T.pathBaseEdgeChain - (T.orientedEdgeChain - fundamentalCycleFreeChain n) := by
5581  rw [T.pathConeResidualBoundary_eq_explicit]
5582  rw [T.constantApexInitialSideChain_eq_terminal]
5583
5584open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5585/-- The terminal-side boundary expression left after the path-base correction has
5586been removed. -/
5587noncomputable def OrientedCyclicFamilyTerm.terminalSideCorrectionBoundary
5588    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ) : singularOneChainFree :=
5589  T.terminalReturnSideChain - T.constantApexTerminalSideChain +
5590    fundamentalCycleFreeChain n
5591
5592open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5593/-- Winding of the terminal-side correction boundary.  Choosing `n` to be the total
5594oriented winding makes this obstruction vanish. -/
5595theorem OrientedCyclicFamilyTerm.winding_terminalSideCorrectionBoundary
5596    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ) :
5597    ModuleCat.Hom.hom windingChainMap
5598      (ModuleCat.Hom.hom singularOneChainFreeToChain
5599        (T.terminalSideCorrectionBoundary n)) =
5600        - ∑ i, orientedWinding (T.o i) + (n : ℝ) := by
5601  unfold OrientedCyclicFamilyTerm.terminalSideCorrectionBoundary
5602  rw [map_add, map_sub]
5603  rw [map_add, map_sub]
5604  change ModuleCat.Hom.hom windingChainMap
5605      (ModuleCat.Hom.hom singularOneChainFreeToChain T.terminalReturnSideChain) -
5606    ModuleCat.Hom.hom windingChainMap
5607      (ModuleCat.Hom.hom singularOneChainFreeToChain T.constantApexTerminalSideChain) +
5608    ModuleCat.Hom.hom windingChainMap
5609      (ModuleCat.Hom.hom singularOneChainFreeToChain (fundamentalCycleFreeChain n)) =
5610      - ∑ i, orientedWinding (T.o i) + (n : ℝ)
5611  rw [T.winding_terminalReturnSideChain, T.winding_constantApexTerminalSideChain,
5612    windingChainMap_fundamentalCycleFreeChain]
5613  ring
5614
5615open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5616/-- The terminal-side correction boundary has zero winding when its fundamental
5617coefficient is the total oriented winding of the cyclic family. -/
5618theorem OrientedCyclicFamilyTerm.winding_terminalSideCorrectionBoundary_eq_zero
5619    (T : OrientedCyclicFamilyTerm) (n : ModuleCat.of ℤ ℤ)
5620    (hn : ∑ i, orientedWinding (T.o i) = (n : ℝ)) :
5621    ModuleCat.Hom.hom windingChainMap
5622      (ModuleCat.Hom.hom singularOneChainFreeToChain
5623        (T.terminalSideCorrectionBoundary n)) = 0 := by
5624  rw [T.winding_terminalSideCorrectionBoundary, hn]
5625  ring
5626
5627open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5628/-- Correction target left after summing the path-cones over an oriented cyclic
5629family.  A witness is a `2`-chain whose boundary is the residual between the
5630summed path-cone boundary and the desired free-prism boundary. -/
5631def orientedCyclicFamilies_pathConeCorrection_generate : Prop :=
5632  ∀ T : OrientedCyclicFamilyTerm,
5633    ∃ (n : ModuleCat.of ℤ ℤ) (K : singularTwoChainFree),
5634      ModuleCat.Hom.hom singularTwoBoundaryFree K =
5635        T.pathConeResidualBoundary n
5636
5637open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5638/-- Terminal-side correction target.  It asks for a `2`-chain whose boundary
5639turns the sum of terminal-return sides into the terminal constant sides, up to
5640the correct fundamental-cycle multiple. -/
5641def orientedCyclicFamilies_terminalSideCorrection_generate : Prop :=
5642  ∀ T : OrientedCyclicFamilyTerm,
5643    ∃ (n : ModuleCat.of ℤ ℤ) (Ks : singularTwoChainFree),
5644      ModuleCat.Hom.hom singularTwoBoundaryFree Ks =
5645        T.terminalSideCorrectionBoundary n
5646
5647open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5648/-- Path-base correction target.  It asks for a `2`-chain whose boundary replaces
5649the path-parametric base edges by the signed oriented singular-edge chain. -/
5650def orientedCyclicFamilies_pathBaseCorrection_generate : Prop :=
5651  ∀ T : OrientedCyclicFamilyTerm,
5652    ∃ Kp : singularTwoChainFree,
5653      ModuleCat.Hom.hom singularTwoBoundaryFree Kp =
5654        T.pathBaseEdgeChain - T.orientedEdgeChain
5655
5656open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5657/-- The family path-base residual is the sum of the local oriented-edge residuals. -/
5658theorem OrientedCyclicFamilyTerm.pathBaseCorrectionBoundary_sum
5659    (T : OrientedCyclicFamilyTerm) :
5660    T.pathBaseEdgeChain - T.orientedEdgeChain =
5661      ∑ i, (T.o i).pathBaseCorrectionBoundary := by
5662  unfold OrientedCyclicFamilyTerm.pathBaseEdgeChain
5663    OrientedCyclicFamilyTerm.orientedEdgeChain
5664    OrientedSingularEdge.pathBaseCorrectionBoundary
5665  rw [Finset.sum_sub_distrib]
5666
5667open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5668/-- Edge-local path-base corrections imply the family path-base correction target. -/
5669theorem orientedCyclicFamilies_pathBaseCorrection_generate_of_localEdges
5670    (hlocal : ∀ o : OrientedSingularEdge,
5671      ∃ K : singularTwoChainFree,
5672        ModuleCat.Hom.hom singularTwoBoundaryFree K =
5673          o.pathBaseCorrectionBoundary) :
5674    orientedCyclicFamilies_pathBaseCorrection_generate := by
5675  intro T
5676  choose K hK using hlocal
5677  refine ⟨∑ i, K (T.o i), ?_⟩
5678  rw [map_sum]
5679  rw [Finset.sum_congr rfl (fun i _ => hK (T.o i))]
5680  exact T.pathBaseCorrectionBoundary_sum.symm
5681
5682open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5683/-- The path-base correction target is closed: every reversed oriented edge is
5684filled by the triangular backtrack prism, and every forward edge has zero
5685residual. -/
5686theorem orientedCyclicFamilies_pathBaseCorrection_generate_holds :
5687    orientedCyclicFamilies_pathBaseCorrection_generate :=
5688  orientedCyclicFamilies_pathBaseCorrection_generate_of_localEdges
5689    OrientedSingularEdge.pathBaseCorrectionBoundary_bounds
5690
5691/-! ### Geodesic free-chain calculus for the terminal-side correction
5692
5693The terminal-return sides are geodesics, so the terminal-side correction lives
5694entirely in the geodesic free-chain calculus.  We need three facts, each an
5695explicit boundary identity: the composition law, the `2π`-shift winding step,
5696and the identification of the fundamental free chain with `n` copies of the
5697geodesic `0 → 2π`. -/
5698
5699open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5700/-- Free `C₁` generator of a geodesic (lift-linear) singular edge. -/
5701noncomputable def geodesicFreeChain (a b : ℝ) : singularOneChainFree :=
5702  ModuleCat.freeMk (singularOneSimplexOfMap (geodesicOneSimplex a b))
5703
5704open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5705/-- Composition law in free `C₁`: the boundary of the lift-affine `2`-simplex on
5706`(p, q, r)` is `geo(q,r) − geo(p,r) + geo(p,q)`. -/
5707theorem singularTwoBoundaryFree_geodesicFreeChain (p q r : ℝ) :
5708    ModuleCat.Hom.hom singularTwoBoundaryFree
5709      (ModuleCat.freeMk (linearSingularTwoSimplex p q r)) =
5710      geodesicFreeChain q r - geodesicFreeChain p r + geodesicFreeChain p q :=
5711  singularTwoBoundaryFree_freeMk_linearSingularTwoSimplex p q r
5712
5713open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5714/-- A `2π·ℤ` shift of both lift endpoints leaves the geodesic free chain
5715unchanged. -/
5716theorem geodesicFreeChain_shift (a b : ℝ) (m : ℤ) :
5717    geodesicFreeChain (a + (m : ℝ) * (2 * Real.pi)) (b + (m : ℝ) * (2 * Real.pi)) =
5718      geodesicFreeChain a b := by
5719  unfold geodesicFreeChain
5720  rw [geodesicOneSimplex_shift]
5721
5722open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5723/-- A degenerate geodesic (equal endpoints) bounds a constant `2`-simplex. -/
5724theorem geodesicFreeChain_self_bounds (a : ℝ) :
5725    ModuleCat.Hom.hom singularTwoBoundaryFree
5726        (ModuleCat.freeMk (constantSingularTwoSimplex (trigCirclePoint a))) =
5727      geodesicFreeChain a a := by
5728  unfold geodesicFreeChain
5729  rw [geodesicOneSimplex_self, singularOneSimplexOfMap_constantOneSimplex]
5730  exact constantSingularOneSimplex_free_boundary (trigCirclePoint a)
5731
5732open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5733/-- The geodesic `0 → 2π` free chain is the fundamental free generator. -/
5734theorem geodesicFreeChain_zero_twoPi_eq_fundamental :
5735    geodesicFreeChain 0 (2 * Real.pi) =
5736      ModuleCat.freeMk CircleFundamentalSimplex.fundamentalSphereOneSingularOneSimplex := by
5737  unfold geodesicFreeChain
5738  rw [singularOneSimplexOfMap_geodesic_zero_twoPi]
5739
5740open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5741/-- **Fundamental free chain identification.**  The free-coordinate image of `n`
5742times the fundamental cycle is `n` copies of the geodesic `0 → 2π`. -/
5743theorem fundamentalCycleFreeChain_eq_zsmul (n : ModuleCat.of ℤ ℤ) :
5744    fundamentalCycleFreeChain n = (n : ℤ) • geodesicFreeChain 0 (2 * Real.pi) := by
5745  rw [geodesicFreeChain_zero_twoPi_eq_fundamental]
5746  unfold fundamentalCycleFreeChain
5747  have hcomp : fundamentalCycle ≫ sphereOneSingularIntChainComplex.iCycles 1 =
5748      CircleH1Computation.fundamentalSphereOneSingularOneChain := by
5749    rw [fundamentalCycle, HomologicalComplex.liftCycles_i]
5750  have hiC : ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5751        (ModuleCat.Hom.hom fundamentalCycle n) =
5752      ModuleCat.Hom.hom CircleH1Computation.fundamentalSphereOneSingularOneChain n := by
5753    have h := congrArg (fun f => ModuleCat.Hom.hom f n) hcomp
5754    simpa only [ModuleCat.hom_comp, LinearMap.coe_comp, Function.comp_apply] using h
5755  have hcomp2 : CircleH1Computation.fundamentalSphereOneSingularOneChain ≫ singularOneChainToFree =
5756      ModuleCat.ofHom (LinearMap.toSpanSingleton ℤ singularOneChainFree
5757        (ModuleCat.freeMk CircleFundamentalSimplex.fundamentalSphereOneSingularOneSimplex)) :=
5758    singularOneChainToFree_ι CircleFundamentalSimplex.fundamentalSphereOneSingularOneSimplex
5759  have hfinal := congrArg (fun f => ModuleCat.Hom.hom f n) hcomp2
5760  simp only [ModuleCat.hom_comp, ModuleCat.hom_ofHom, LinearMap.coe_comp,
5761    Function.comp_apply, LinearMap.toSpanSingleton_apply] at hfinal
5762  rw [hiC]
5763  exact hfinal
5764
5765open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5766/-- One-turn geodesic boundary: `∂(linear 0 2π (z+2π)) = geo(0,z) − geo(0,z+2π)
5767+ geo(0,2π)`, using shift invariance to fold the `(2π, z+2π)` side onto
5768`(0, z)`. -/
5769theorem singularTwoBoundaryFree_linear_step (z : ℝ) :
5770    ModuleCat.Hom.hom singularTwoBoundaryFree
5771        (ModuleCat.freeMk (linearSingularTwoSimplex 0 (2 * Real.pi) (z + 2 * Real.pi))) =
5772      geodesicFreeChain 0 z - geodesicFreeChain 0 (z + 2 * Real.pi)
5773        + geodesicFreeChain 0 (2 * Real.pi) := by
5774  rw [singularTwoBoundaryFree_geodesicFreeChain]
5775  have hshift : geodesicFreeChain (2 * Real.pi) (z + 2 * Real.pi) = geodesicFreeChain 0 z := by
5776    have h := geodesicFreeChain_shift 0 z 1
5777    simpa using h
5778  rw [hshift]
5779
5780open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5781/-- **Geodesic winding step.**  Shifting the terminal lift endpoint by `m` full
5782turns adds `m` fundamental loops to the geodesic, modulo an explicit
5783`2`-boundary. -/
5784theorem geodesicFreeChain_step (y : ℝ) (m : ℤ) :
5785    ∃ K : singularTwoChainFree,
5786      ModuleCat.Hom.hom singularTwoBoundaryFree K =
5787        geodesicFreeChain 0 (y + (m : ℝ) * (2 * Real.pi)) - geodesicFreeChain 0 y
5788          - (m : ℤ) • geodesicFreeChain 0 (2 * Real.pi) := by
5789  induction m using Int.induction_on with
5790  | zero =>
5791    refine ⟨0, ?_⟩
5792    simp
5793  | succ i ih =>
5794    obtain ⟨K, hK⟩ := ih
5795    refine ⟨K - ModuleCat.freeMk
5796        (linearSingularTwoSimplex 0 (2 * Real.pi) (y + (i : ℝ) * (2 * Real.pi) + 2 * Real.pi)), ?_⟩
5797    rw [map_sub, hK, singularTwoBoundaryFree_linear_step (y + (i : ℝ) * (2 * Real.pi))]
5798    push_cast
5799    rw [show y + (i : ℝ) * (2 * Real.pi) + 2 * Real.pi = y + ((i : ℝ) + 1) * (2 * Real.pi) by ring,
5800      add_smul, one_smul]
5801    abel
5802  | pred i ih =>
5803    obtain ⟨K, hK⟩ := ih
5804    refine ⟨K + ModuleCat.freeMk
5805        (linearSingularTwoSimplex 0 (2 * Real.pi)
5806          (y + (-(i : ℝ) - 1) * (2 * Real.pi) + 2 * Real.pi)), ?_⟩
5807    rw [map_add, hK, singularTwoBoundaryFree_linear_step (y + (-(i : ℝ) - 1) * (2 * Real.pi))]
5808    push_cast
5809    rw [show y + (-(i : ℝ) - 1) * (2 * Real.pi) + 2 * Real.pi
5810          = y + (-(i : ℝ)) * (2 * Real.pi) by ring]
5811    rw [show (-(i : ℤ) - 1) = (-(i : ℤ)) + (-1) by ring, add_smul, neg_one_smul]
5812    push_cast
5813    abel
5814
5815open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5816/-- **The terminal-side correction target is closed unconditionally.**
5817
5818For a concrete oriented cyclic family `T`, the terminal-return sides are
5819geodesics, each from the terminal lift of one edge to the initial lift of the
5820next.  The cyclic connectivity `T.hconn` forces those lift endpoints to agree
5821modulo `2π·ℤ`; collecting the per-edge integer shifts gives the total winding
5822`n = ∑ m i`.  The bounding `2`-chain is assembled from three explicit families:
5823the lift-affine cones `linear 0 (bᵢ) (aᵢ)` (composition law), the winding-step
5824chains `Kstep i` (one per edge, from `geodesicFreeChain_step`), and the constant
5825apex `2`-simplices.  Telescoping with the index reindex `∑ geo(0,a(σ i)) =
5826∑ geo(0,a i)` and `∑ (m i)•g = n•g` leaves exactly
5827`terminalReturnSide − constantApexTerminalSide + n·(fundamental cycle)`. -/
5828theorem orientedCyclicFamilies_terminalSideCorrection_generate_holds :
5829    orientedCyclicFamilies_terminalSideCorrection_generate := by
5830  classical
5831  intro T
5832  -- Lift-level connectivity: terminal lift of edge `i` agrees with initial lift
5833  -- of edge `σ i` modulo a full turn.
5834  have hex : ∀ i : Fin T.k, ∃ m : ℤ,
5835      pathLift (orientedEdgePath (T.o i)) 1
5836        = pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0 + (m : ℝ) * (2 * Real.pi) := by
5837    intro i
5838    have h1 : trigCirclePoint (pathLift (orientedEdgePath (T.o i)) 1)
5839        = (orientedEdgePath (T.o i)) 1 :=
5840      congrFun (pathLift_lifts (orientedEdgePath (T.o i))) 1
5841    have h0 : trigCirclePoint (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0)
5842        = (orientedEdgePath (T.o (finRotate T.k i))) 0 :=
5843      congrFun (pathLift_lifts (orientedEdgePath (T.o (finRotate T.k i)))) 0
5844    have hfib : trigCirclePoint (pathLift (orientedEdgePath (T.o i)) 1)
5845        = trigCirclePoint (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0) := by
5846      rw [h1, h0, orientedEdgePath_one, orientedEdgePath_zero]
5847      exact congrArg vertexPoint (T.hconn i)
5848    exact (CircleLifting.trigCirclePoint_eq_iff _ _).1 hfib
5849  choose m hm using hex
5850  -- One winding-step chain per edge, from `geodesicFreeChain_step`.
5851  have hstep : ∀ i : Fin T.k, ∃ K : singularTwoChainFree,
5852      ModuleCat.Hom.hom singularTwoBoundaryFree K =
5853        geodesicFreeChain 0
5854            (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0 + (m i : ℝ) * (2 * Real.pi))
5855          - geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0)
5856          - (m i : ℤ) • geodesicFreeChain 0 (2 * Real.pi) := fun i =>
5857    geodesicFreeChain_step (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0) (m i)
5858  choose Kstep hKstep using hstep
5859  refine ⟨(∑ i, m i : ℤ),
5860      (∑ i, ModuleCat.freeMk (linearSingularTwoSimplex 0
5861          (pathLift (orientedEdgePath (T.o i)) 1) (pathLift (orientedEdgePath (T.o i)) 0)))
5862        - (∑ i, Kstep i)
5863        - (∑ i, ModuleCat.freeMk (constantSingularTwoSimplex
5864            (trigCirclePoint (pathLift (orientedEdgePath (T.o i)) 1)))), ?_⟩
5865  -- Rewrite the three target side-chains into geodesic free chains.
5866  have hret : T.terminalReturnSideChain
5867      = ∑ i, geodesicFreeChain (pathLift (orientedEdgePath (T.o i)) 1)
5868          (pathLift (orientedEdgePath (T.o i)) 0) := by
5869    unfold OrientedCyclicFamilyTerm.terminalReturnSideChain
5870    refine Finset.sum_congr rfl (fun i _ => ?_)
5871    unfold geodesicFreeChain
5872    rw [coneTerminalSide_eq_geodesic]
5873  have hcon : T.constantApexTerminalSideChain
5874      = ∑ i, geodesicFreeChain (pathLift (orientedEdgePath (T.o i)) 1)
5875          (pathLift (orientedEdgePath (T.o i)) 1) := by
5876    unfold OrientedCyclicFamilyTerm.constantApexTerminalSideChain
5877    refine Finset.sum_congr rfl (fun i _ => ?_)
5878    have hlift1 : trigCirclePoint (pathLift (orientedEdgePath (T.o i)) 1)
5879        = (orientedEdgePath (T.o i)) 1 :=
5880      congrFun (pathLift_lifts (orientedEdgePath (T.o i))) 1
5881    unfold geodesicFreeChain
5882    rw [geodesicOneSimplex_self, hlift1]
5883  -- Index reindex along the cyclic rotation and the scalar-sum identity.
5884  have hreindex :
5885      (∑ i, geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0))
5886        = ∑ i, geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o i)) 0) :=
5887    Equiv.sum_comp (finRotate T.k)
5888      (fun j => geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o j)) 0))
5889  -- Per-edge boundary evaluations.
5890  have hL1 : (∑ i, ModuleCat.Hom.hom singularTwoBoundaryFree
5891        (ModuleCat.freeMk (linearSingularTwoSimplex 0
5892          (pathLift (orientedEdgePath (T.o i)) 1) (pathLift (orientedEdgePath (T.o i)) 0))))
5893      = ∑ i, (geodesicFreeChain (pathLift (orientedEdgePath (T.o i)) 1)
5894            (pathLift (orientedEdgePath (T.o i)) 0)
5895          - geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o i)) 0)
5896          + geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o i)) 1)) :=
5897    Finset.sum_congr rfl (fun i _ =>
5898      singularTwoBoundaryFree_geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o i)) 1)
5899        (pathLift (orientedEdgePath (T.o i)) 0))
5900  have hL2 : (∑ i, ModuleCat.Hom.hom singularTwoBoundaryFree (Kstep i))
5901      = ∑ i, (geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o i)) 1)
5902          - geodesicFreeChain 0 (pathLift (orientedEdgePath (T.o (finRotate T.k i))) 0)
5903          - (m i : ℤ) • geodesicFreeChain 0 (2 * Real.pi)) := by
5904    refine Finset.sum_congr rfl (fun i _ => ?_)
5905    rw [hKstep i, ← hm i]
5906  have hL3 : (∑ i, ModuleCat.Hom.hom singularTwoBoundaryFree
5907        (ModuleCat.freeMk (constantSingularTwoSimplex
5908          (trigCirclePoint (pathLift (orientedEdgePath (T.o i)) 1)))))
5909      = ∑ i, geodesicFreeChain (pathLift (orientedEdgePath (T.o i)) 1)
5910          (pathLift (orientedEdgePath (T.o i)) 1) :=
5911    Finset.sum_congr rfl (fun i _ =>
5912      geodesicFreeChain_self_bounds (pathLift (orientedEdgePath (T.o i)) 1))
5913  -- Assemble.
5914  unfold OrientedCyclicFamilyTerm.terminalSideCorrectionBoundary
5915  rw [hret, hcon, fundamentalCycleFreeChain_eq_zsmul]
5916  rw [map_sub, map_sub, map_sum, map_sum, map_sum, hL1, hL2, hL3]
5917  simp only [Finset.sum_add_distrib, Finset.sum_sub_distrib]
5918  rw [hreindex, ← Finset.sum_smul]
5919  abel
5920
5921open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5922/-- The terminal-side and path-base correction targets together fill the full
5923path-cone residual. -/
5924theorem orientedCyclicFamilies_pathConeCorrection_generate_of_splitCorrections
5925    (hside : orientedCyclicFamilies_terminalSideCorrection_generate)
5926    (hpath : orientedCyclicFamilies_pathBaseCorrection_generate) :
5927    orientedCyclicFamilies_pathConeCorrection_generate := by
5928  intro T
5929  obtain ⟨n, Ks, hKs⟩ := hside T
5930  obtain ⟨Kp, hKp⟩ := hpath T
5931  refine ⟨n, Ks + Kp, ?_⟩
5932  rw [map_add, hKs, hKp, T.pathConeResidualBoundary_eq_terminalSide]
5933  unfold OrientedCyclicFamilyTerm.terminalSideCorrectionBoundary
5934  abel_nf
5935
5936/-- Filling the path-cone residual for every oriented cyclic family proves the
5937free-coordinate prism target named in the Phase 5 checklist. -/
5938theorem orientedCyclicFamilies_freePrism_generate_of_pathConeCorrection
5939    (hcorr : orientedCyclicFamilies_pathConeCorrection_generate) :
5940    orientedCyclicFamilies_freePrism_generate := by
5941  intro T
5942  obtain ⟨n, K, hK⟩ := hcorr T
5943  refine ⟨n, T.pathConeChain - K, ?_⟩
5944  rw [map_sub, hK]
5945  unfold OrientedCyclicFamilyTerm.pathConeResidualBoundary
5946    OrientedCyclicFamilyTerm.desiredFreePrismBoundary fundamentalCycleFreeChain
5947  abel
5948
5949open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5950/-- The two split correction targets are enough for the Phase 5 free-prism
5951generation target. -/
5952theorem orientedCyclicFamilies_freePrism_generate_of_splitCorrections
5953    (hside : orientedCyclicFamilies_terminalSideCorrection_generate)
5954    (hpath : orientedCyclicFamilies_pathBaseCorrection_generate) :
5955    orientedCyclicFamilies_freePrism_generate :=
5956  orientedCyclicFamilies_freePrism_generate_of_pathConeCorrection
5957    (orientedCyclicFamilies_pathConeCorrection_generate_of_splitCorrections hside hpath)
5958
5959open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5960/-- A free-coordinate prism construction gives the fully explicit raw prism
5961target after transporting the free `C₂` boundary through Mathlib's raw chain
5962complex. -/
5963theorem orientedCyclicFamilies_explicitRawPrism_generate_of_freePrism
5964    (hfree : orientedCyclicFamilies_freePrism_generate) :
5965    orientedCyclicFamilies_explicitRawPrism_generate := by
5966  intro T
5967  obtain ⟨n, B, hB⟩ := hfree T
5968  refine ⟨n, ModuleCat.Hom.hom singularTwoChainFreeToChain B, ?_⟩
5969  have hraw := rawBoundary_eq_of_singularTwoBoundaryFree_eq B
5970    ((∑ i, (T.o i).chain) -
5971      ModuleCat.Hom.hom singularOneChainToFree
5972        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5973          (ModuleCat.Hom.hom fundamentalCycle n))) hB
5974  have hround :
5975      ModuleCat.Hom.hom singularOneChainFreeToChain
5976        (ModuleCat.Hom.hom singularOneChainToFree
5977          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5978            (ModuleCat.Hom.hom fundamentalCycle n))) =
5979        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5980          (ModuleCat.Hom.hom fundamentalCycle n) := by
5981    have hid := congrArg
5982      (fun f => ModuleCat.Hom.hom f
5983        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
5984          (ModuleCat.Hom.hom fundamentalCycle n)))
5985      singularOneChainFreeIso.hom_inv_id
5986    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
5987      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
5988    exact hid
5989  rw [map_sub, hround] at hraw
5990  exact hraw
5991
5992open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
5993/-- Conversely, the fully explicit raw prism target gives the free-coordinate
5994prism target.  The proof uses the degree-`2` raw/free isomorphism and therefore
5995shows that `orientedCyclicFamilies_freePrism_generate` is not stronger in
5996substance than constructing the raw singular `2`-chain. -/
5997theorem orientedCyclicFamilies_freePrism_generate_of_explicitRawPrism
5998    (hexplicit : orientedCyclicFamilies_explicitRawPrism_generate) :
5999    orientedCyclicFamilies_freePrism_generate := by
6000  intro T
6001  obtain ⟨n, b, hb⟩ := hexplicit T
6002  let u : singularOneChainFree :=
6003    (∑ i, (T.o i).chain) -
6004      ModuleCat.Hom.hom singularOneChainToFree
6005        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6006          (ModuleCat.Hom.hom fundamentalCycle n))
6007  refine ⟨n, ModuleCat.Hom.hom singularTwoChainToFree b, ?_⟩
6008  apply singularTwoBoundaryFree_eq_of_rawBoundary_eq b u
6009  unfold u
6010  rw [hb, map_sub]
6011  have hround :
6012      ModuleCat.Hom.hom singularOneChainFreeToChain
6013        (ModuleCat.Hom.hom singularOneChainToFree
6014          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6015            (ModuleCat.Hom.hom fundamentalCycle n))) =
6016        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6017          (ModuleCat.Hom.hom fundamentalCycle n) := by
6018    have hid := congrArg
6019      (fun f => ModuleCat.Hom.hom f
6020        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6021          (ModuleCat.Hom.hom fundamentalCycle n)))
6022      singularOneChainFreeIso.hom_inv_id
6023    simp only [ModuleCat.hom_comp, ModuleCat.hom_id, LinearMap.coe_comp,
6024      Function.comp_apply, LinearMap.id_coe, id_eq] at hid
6025    exact hid
6026  rw [hround]
6027
6028open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6029/-- The fully explicit raw prism target implies the packaged raw prism target. -/
6030theorem orientedCyclicFamilies_rawPrism_generate_of_explicit
6031    (hexplicit : orientedCyclicFamilies_explicitRawPrism_generate) :
6032    orientedCyclicFamilies_rawPrism_generate := by
6033  intro T
6034  obtain ⟨n, b, hb⟩ := hexplicit T
6035  refine ⟨n, b, ?_⟩
6036  rw [T.iCycles_eq_orientedChain]
6037  exact hb
6038
6039open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6040/-- The packaged raw prism target is equivalent to the fully explicit raw-chain
6041target.  The equivalence is only the already-proved identification between an
6042oriented cyclic family's cycle object and its concrete signed edge sum. -/
6043theorem orientedCyclicFamilies_explicitRawPrism_generate_of_rawPrism
6044    (hraw : orientedCyclicFamilies_rawPrism_generate) :
6045    orientedCyclicFamilies_explicitRawPrism_generate := by
6046  intro T
6047  obtain ⟨n, b, hb⟩ := hraw T
6048  refine ⟨n, b, ?_⟩
6049  rw [← T.iCycles_eq_orientedChain]
6050  exact hb
6051
6052open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6053/-- The free-coordinate prism target and the fully explicit raw-prism target are
6054equivalent.  This packages the degree-`2` raw/free transport added above. -/
6055theorem orientedCyclicFamilies_freePrism_generate_iff_explicitRawPrism_generate :
6056    orientedCyclicFamilies_freePrism_generate ↔
6057      orientedCyclicFamilies_explicitRawPrism_generate := by
6058  constructor
6059  · exact orientedCyclicFamilies_explicitRawPrism_generate_of_freePrism
6060  · exact orientedCyclicFamilies_freePrism_generate_of_explicitRawPrism
6061
6062open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6063/-- The free-coordinate prism target and the packaged raw-prism target are
6064equivalent.  After this theorem, the only unsolved content is the actual
6065geometric prism construction, not the choice of raw/free coordinates. -/
6066theorem orientedCyclicFamilies_freePrism_generate_iff_rawPrism_generate :
6067    orientedCyclicFamilies_freePrism_generate ↔
6068      orientedCyclicFamilies_rawPrism_generate := by
6069  constructor
6070  · intro hfree
6071    exact orientedCyclicFamilies_rawPrism_generate_of_explicit
6072      (orientedCyclicFamilies_explicitRawPrism_generate_of_freePrism hfree)
6073  · intro hraw
6074    exact orientedCyclicFamilies_freePrism_generate_of_explicitRawPrism
6075      (orientedCyclicFamilies_explicitRawPrism_generate_of_rawPrism hraw)
6076
6077open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6078/-- Raw prism generation implies the cycle-object generation target.  This is a
6079pure categorical transport through `toCycles`; the remaining work is therefore
6080only to construct the raw prism `2`-chain. -/
6081theorem orientedCyclicFamilies_boundary_generate_of_rawPrism
6082    (hraw : orientedCyclicFamilies_rawPrism_generate) :
6083    orientedCyclicFamilies_boundary_generate := by
6084  intro T
6085  obtain ⟨n, b, hb⟩ := hraw T
6086  refine ⟨n, b, ?_⟩
6087  have hinj_iCycles :
6088      Function.Injective
6089        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
6090    (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
6091  apply hinj_iCycles
6092  rw [map_add]
6093  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6094      T.toDirectedCycleFreeTerm.cycle =
6095    ModuleCat.Hom.hom
6096      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
6097        sphereOneSingularIntChainComplex.iCycles 1) b +
6098      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6099        (ModuleCat.Hom.hom fundamentalCycle n)
6100  rw [HomologicalComplex.toCycles_i]
6101  rw [hb]
6102  abel
6103
6104open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6105/-- Cycle-object generation gives the packaged raw-chain prism equality by
6106including the cycle equality into `C₁`. -/
6107theorem orientedCyclicFamilies_rawPrism_generate_of_boundary_generate
6108    (hterm : orientedCyclicFamilies_boundary_generate) :
6109    orientedCyclicFamilies_rawPrism_generate := by
6110  intro T
6111  obtain ⟨n, b, hT⟩ := hterm T
6112  refine ⟨n, b, ?_⟩
6113  rw [hT, map_add]
6114  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.d 2 1) b =
6115    ModuleCat.Hom.hom
6116      (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
6117        sphereOneSingularIntChainComplex.iCycles 1) b +
6118      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6119        (ModuleCat.Hom.hom fundamentalCycle n) -
6120      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6121        (ModuleCat.Hom.hom fundamentalCycle n)
6122  rw [HomologicalComplex.toCycles_i]
6123  abel
6124
6125open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6126/-- Cycle-object generation gives the fully explicit raw-chain prism equality. -/
6127theorem orientedCyclicFamilies_explicitRawPrism_generate_of_boundary_generate
6128    (hterm : orientedCyclicFamilies_boundary_generate) :
6129    orientedCyclicFamilies_explicitRawPrism_generate := by
6130  intro T
6131  obtain ⟨n, b, hb⟩ :=
6132    orientedCyclicFamilies_rawPrism_generate_of_boundary_generate hterm T
6133  refine ⟨n, b, ?_⟩
6134  rw [← T.iCycles_eq_orientedChain]
6135  exact hb
6136
6137open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6138/-- If each concrete oriented cyclic family is generated by the fundamental
6139cycle modulo a boundary, then every finite list of such families is. -/
6140theorem orientedCyclicFamilyTermList_boundary_generates
6141    (hterm : orientedCyclicFamilies_boundary_generate) :
6142    ∀ ts : List OrientedCyclicFamilyTerm,
6143      ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
6144        orientedCyclicFamilyTermListCycle ts =
6145          ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
6146            ModuleCat.Hom.hom fundamentalCycle n
6147  | [] => by
6148      refine ⟨0, 0, ?_⟩
6149      unfold orientedCyclicFamilyTermListCycle directedCycleFreeTermListCycle
6150      simp
6151  | T :: ts => by
6152      obtain ⟨n₁, b₁, hT⟩ := hterm T
6153      obtain ⟨n₂, b₂, hts⟩ := orientedCyclicFamilyTermList_boundary_generates hterm ts
6154      refine ⟨n₁ + n₂, b₁ + b₂, ?_⟩
6155      change T.toDirectedCycleFreeTerm.cycle + orientedCyclicFamilyTermListCycle ts =
6156        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) (b₁ + b₂) +
6157          ModuleCat.Hom.hom fundamentalCycle (n₁ + n₂)
6158      rw [hT, hts, map_add, map_add]
6159      abel
6160
6161open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6162/-- Filling each concrete oriented cyclic family proves the global chain-level
6163generation theorem. -/
6164theorem fundamentalCycle_boundary_generates_of_orientedCyclicFamilies
6165    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
6166    (hterm : orientedCyclicFamilies_boundary_generate) :
6167    fundamentalCycle_boundary_generates := by
6168  intro z
6169  let c : singularOneChainFree :=
6170    ModuleCat.Hom.hom singularOneChainToFree
6171      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) z)
6172  have hc0 : ModuleCat.Hom.hom singularOneBoundaryFree c = 0 := by
6173    unfold c
6174    change ModuleCat.Hom.hom
6175        (sphereOneSingularIntChainComplex.iCycles 1 ≫ singularOneChainToFree ≫
6176          singularOneBoundaryFree) z = 0
6177    rw [singularOneChainToFree_boundary_free]
6178    rw [← Category.assoc, HomologicalComplex.iCycles_d]
6179    simp
6180  obtain ⟨ts, hts⟩ := freeBoundaryKernel_decomposesIntoOrientedCyclicFamilies_holds c hc0
6181  have hcycle : z = orientedCyclicFamilyTermListCycle ts := by
6182    have hinj_toFree : Function.Injective (ModuleCat.Hom.hom singularOneChainToFree) := by
6183      haveI : IsIso singularOneChainToFree := by
6184        change IsIso singularOneChainFreeIso.hom
6185        infer_instance
6186      haveI : Mono singularOneChainToFree := inferInstance
6187      exact (ModuleCat.mono_iff_injective singularOneChainToFree).mp inferInstance
6188    have hinj_iCycles :
6189        Function.Injective
6190          (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)) :=
6191      (ModuleCat.mono_iff_injective (sphereOneSingularIntChainComplex.iCycles 1)).mp inferInstance
6192    apply hinj_iCycles
6193    apply hinj_toFree
6194    unfold c at hts
6195    rw [hts]
6196    unfold orientedCyclicFamilyTermListChain orientedCyclicFamilyTermListCycle
6197    rw [directedCycleFreeTermList_chain_eq]
6198  obtain ⟨n, b, hlist⟩ := orientedCyclicFamilyTermList_boundary_generates hterm ts
6199  refine ⟨n, b, ?_⟩
6200  rw [hcycle, hlist]
6201
6202open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6203/-- The concrete oriented-family filling target is enough for the final Mathlib
6204circle H₁ computation. -/
6205theorem circleH1ZIsoInt_of_orientedCyclicFamilies
6206    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
6207    (hterm : orientedCyclicFamilies_boundary_generate) :
6208    MathlibCohomologyBridge.circleH1ZIsoInt :=
6209  circleH1ZIsoInt_of_fundamentalCycle_boundary_generates
6210    (fundamentalCycle_boundary_generates_of_orientedCyclicFamilies hterm)
6211
6212open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6213/-- The explicit free `C₁` chain represented by a finite list of singular
6214`1`-simplices, each with coefficient `1`. -/
6215noncomputable def singularEdgeListChain :
6216    List SingularOneSimplex → singularOneChainFree
6217  | [] => 0
6218  | e :: es => ModuleCat.freeMk e + singularEdgeListChain es
6219
6220open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6221/-- A forward edge-list has nonnegative coefficient at every singular edge before
6222the global scalar of a `CyclicSingularEdgeListTerm` is applied. -/
6223theorem edgeCoeff_singularEdgeListChain_nonneg [DecidableEq SingularOneSimplex]
6224    (es : List SingularOneSimplex) (e : SingularOneSimplex) :
6225    0 ≤ edgeCoeff (singularEdgeListChain es) e := by
6226  induction es with
6227  | nil =>
6228      unfold singularEdgeListChain edgeCoeff
6229      rfl
6230  | cons a as ih =>
6231      unfold singularEdgeListChain
6232      rw [edgeCoeff_add]
6233      by_cases ha : a = e
6234      · subst a
6235        rw [edgeCoeff_freeMk_self]
6236        omega
6237      · have hfree : edgeCoeff (ModuleCat.freeMk a) e = 0 := by
6238          rw [ModuleCat.freeMk, edgeCoeff_single a (1 : ℤ) e, if_neg ha]
6239        rw [hfree]
6240        omega
6241
6242open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6243/-- The free-chain represented by `List.ofFn e` is the finite sum of the
6244corresponding free generators. -/
6245theorem singularEdgeListChain_ofFn {k : ℕ} (e : Fin k → SingularOneSimplex) :
6246    singularEdgeListChain (List.ofFn e) = ∑ i, ModuleCat.freeMk (e i) := by
6247  induction k with
6248  | zero =>
6249      simp [singularEdgeListChain]
6250  | succ k ih =>
6251      rw [List.ofFn_succ]
6252      unfold singularEdgeListChain
6253      rw [ih (fun i : Fin k => e i.succ)]
6254      rw [Fin.sum_univ_succ]
6255
6256open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6257/-- A concrete cyclic edge-list piece.  It records an actual finite list of
6258singular `1`-simplices, a global integer coefficient for that listed cycle, and
6259the certified cycle object whose raw free-chain image is that coefficient times
6260the listed edge sum. -/
6261structure CyclicSingularEdgeListTerm where
6262  edges : List SingularOneSimplex
6263  coeff : ModuleCat.of ℤ ℤ
6264  cycle : sphereOneSingularIntChainComplex.cycles 1
6265  chain_eq :
6266    ModuleCat.Hom.hom singularOneChainToFree
6267      (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1) cycle) =
6268        coeff • singularEdgeListChain edges
6269  winding_integral : ∃ n : ModuleCat.of ℤ ℤ, cycleWinding cycle = (n : ℝ)
6270
6271open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6272/-- A genuinely forward cyclic family packages into the old concrete cyclic
6273edge-list interface.  This lemma marks the exact compatibility surface between
6274the older forward-only extraction target and the newer oriented-cycle engine. -/
6275noncomputable def cyclicSingularEdgeListTerm_of_cyclicFamily {k : ℕ}
6276    (e : Fin k → SingularOneSimplex)
6277    (hconn : ∀ i : Fin k, edgeTerminal (e i) = edgeInitial (e (finRotate k i))) :
6278    CyclicSingularEdgeListTerm where
6279  edges := List.ofFn e
6280  coeff := 1
6281  cycle := (directedCycleFreeTerm_of_cyclicFamily e hconn).cycle
6282  chain_eq := by
6283    have hchain := (directedCycleFreeTerm_of_cyclicFamily e hconn).chain_eq
6284    change ModuleCat.Hom.hom singularOneChainToFree
6285        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.iCycles 1)
6286          (directedCycleFreeTerm_of_cyclicFamily e hconn).cycle) =
6287          (directedCycleFreeTerm_of_cyclicFamily e hconn).chain at hchain
6288    rw [hchain]
6289    change (∑ i, ModuleCat.freeMk (e i)) = (1 : ModuleCat.of ℤ ℤ) •
6290      singularEdgeListChain (List.ofFn e)
6291    rw [singularEdgeListChain_ofFn]
6292    simp
6293  winding_integral := (directedCycleFreeTerm_of_cyclicFamily e hconn).winding_integral
6294
6295open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6296/-- If a concrete oriented cyclic family is everywhere forward, then it is a
6297concrete cyclic edge-list term in the older forward-only interface. -/
6298noncomputable def OrientedCyclicFamilyTerm.toCyclicSingularEdgeListTerm_of_all_forward
6299    (T : OrientedCyclicFamilyTerm)
6300    (hforward : ∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.forward) :
6301    CyclicSingularEdgeListTerm :=
6302  cyclicSingularEdgeListTerm_of_cyclicFamily
6303    (fun i : Fin T.k => (T.o i).edge)
6304    (by
6305      intro i
6306      have hconn := T.hconn i
6307      simpa [OrientedSingularEdge.terminal, OrientedSingularEdge.initial,
6308        hforward i, hforward (finRotate T.k i)] using hconn)
6309
6310open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6311/-- A concrete cyclic edge-list piece is, in particular, a directed-cycle piece
6312in the abstract free-boundary kernel decomposition interface. -/
6313noncomputable def CyclicSingularEdgeListTerm.toDirectedCycleFreeTerm
6314    (t : CyclicSingularEdgeListTerm) : DirectedCycleFreeTerm where
6315  cycle := t.cycle
6316  chain := t.coeff • singularEdgeListChain t.edges
6317  chain_eq := t.chain_eq
6318  winding_integral := t.winding_integral
6319
6320open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6321/-- The free-chain sum represented by a finite list of concrete cyclic edge-list
6322pieces. -/
6323noncomputable def cyclicSingularEdgeListTermListChain :
6324    List CyclicSingularEdgeListTerm → singularOneChainFree
6325  | [] => 0
6326  | t :: ts => t.coeff • singularEdgeListChain t.edges +
6327      cyclicSingularEdgeListTermListChain ts
6328
6329/-- The free-chain contribution of one concrete cyclic edge-list term. -/
6330noncomputable def CyclicSingularEdgeListTerm.chain
6331    (t : CyclicSingularEdgeListTerm) : singularOneChainFree :=
6332  t.coeff • singularEdgeListChain t.edges
6333
6334open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6335/-- Scale a concrete cyclic edge-list term by an integer without changing its
6336underlying edge list. -/
6337noncomputable def CyclicSingularEdgeListTerm.zsmul
6338    (n : ℤ) (t : CyclicSingularEdgeListTerm) : CyclicSingularEdgeListTerm where
6339  edges := t.edges
6340  coeff := n * t.coeff
6341  cycle := n • t.cycle
6342  chain_eq := by
6343    rw [map_zsmul, map_zsmul, t.chain_eq]
6344    change n • (t.coeff • singularEdgeListChain t.edges) =
6345      (n * t.coeff) • singularEdgeListChain t.edges
6346    rw [smul_smul]
6347  winding_integral := by
6348    obtain ⟨k, hk⟩ := t.winding_integral
6349    refine ⟨n * k, ?_⟩
6350    unfold cycleWinding at hk ⊢
6351    rw [map_zsmul, hk]
6352    simp [zsmul_eq_mul]
6353
6354open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6355/-- The free-chain contribution of a scaled cyclic edge-list term is the scaled
6356free-chain contribution. -/
6357theorem CyclicSingularEdgeListTerm.zsmul_chain
6358    (n : ℤ) (t : CyclicSingularEdgeListTerm) :
6359    (t.zsmul n).chain = n • t.chain := by
6360  unfold CyclicSingularEdgeListTerm.zsmul CyclicSingularEdgeListTerm.chain
6361  change (n * t.coeff) • singularEdgeListChain t.edges =
6362    n • (t.coeff • singularEdgeListChain t.edges)
6363  rw [smul_smul]
6364
6365open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6366/-- The free chain represented by a concrete cyclic edge-list term has zero
6367explicit boundary. -/
6368theorem CyclicSingularEdgeListTerm.boundary_chain_zero
6369    (t : CyclicSingularEdgeListTerm) :
6370    ModuleCat.Hom.hom singularOneBoundaryFree t.chain = 0 := by
6371  unfold CyclicSingularEdgeListTerm.chain
6372  rw [← t.chain_eq]
6373  change ModuleCat.Hom.hom
6374    (sphereOneSingularIntChainComplex.iCycles 1 ≫ singularOneChainToFree ≫
6375      singularOneBoundaryFree) t.cycle = 0
6376  rw [singularOneChainToFree_boundary_free]
6377  rw [← Category.assoc, HomologicalComplex.iCycles_d]
6378  simp
6379
6380open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6381/-- The all-forward conversion preserves the exact free-chain contribution of the
6382oriented cyclic family. -/
6383theorem OrientedCyclicFamilyTerm.toCyclicSingularEdgeListTerm_of_all_forward_chain
6384    (T : OrientedCyclicFamilyTerm)
6385    (hforward : ∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.forward) :
6386    (T.toCyclicSingularEdgeListTerm_of_all_forward hforward).chain =
6387      T.toDirectedCycleFreeTerm.chain := by
6388  unfold OrientedCyclicFamilyTerm.toCyclicSingularEdgeListTerm_of_all_forward
6389  unfold CyclicSingularEdgeListTerm.chain
6390  change (1 : ModuleCat.of ℤ ℤ) •
6391      singularEdgeListChain (List.ofFn (fun i : Fin T.k => (T.o i).edge)) =
6392    ∑ i, (T.o i).chain
6393  rw [singularEdgeListChain_ofFn]
6394  simp
6395  refine Finset.sum_congr rfl (fun i _ => ?_)
6396  simp [OrientedSingularEdge.chain, hforward i]
6397
6398open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6399/-- If a concrete oriented cyclic family is everywhere backward, then it is also
6400a concrete cyclic edge-list term in the older one-scalar interface, with global
6401coefficient `-1`. -/
6402noncomputable def OrientedCyclicFamilyTerm.toCyclicSingularEdgeListTerm_of_all_backward
6403    (T : OrientedCyclicFamilyTerm)
6404    (hbackward : ∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.backward) :
6405    CyclicSingularEdgeListTerm where
6406  edges := List.ofFn (fun i : Fin T.k => (T.o i).edge)
6407  coeff := -1
6408  cycle := T.toDirectedCycleFreeTerm.cycle
6409  chain_eq := by
6410    rw [DirectedCycleFreeTerm.iCycles_eq_freeToChain, singularOneChainToFree_freeToChain]
6411    rw [singularEdgeListChain_ofFn]
6412    rw [neg_one_zsmul]
6413    change (∑ i, (T.o i).chain) =
6414      - (∑ i, ModuleCat.freeMk (T.o i).edge : singularOneChainFree)
6415    rw [← Finset.sum_neg_distrib]
6416    refine Finset.sum_congr rfl (fun i _ => ?_)
6417    simp [OrientedSingularEdge.chain, hbackward i]
6418  winding_integral := T.toDirectedCycleFreeTerm.winding_integral
6419
6420open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6421/-- The all-backward conversion preserves the exact free-chain contribution of
6422the oriented cyclic family. -/
6423theorem OrientedCyclicFamilyTerm.toCyclicSingularEdgeListTerm_of_all_backward_chain
6424    (T : OrientedCyclicFamilyTerm)
6425    (hbackward : ∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.backward) :
6426    (T.toCyclicSingularEdgeListTerm_of_all_backward hbackward).chain =
6427      T.toDirectedCycleFreeTerm.chain := by
6428  unfold OrientedCyclicFamilyTerm.toCyclicSingularEdgeListTerm_of_all_backward
6429  unfold CyclicSingularEdgeListTerm.chain
6430  change (-1 : ModuleCat.of ℤ ℤ) •
6431      singularEdgeListChain (List.ofFn (fun i : Fin T.k => (T.o i).edge)) =
6432    ∑ i, (T.o i).chain
6433  rw [singularEdgeListChain_ofFn]
6434  rw [neg_one_zsmul]
6435  change - (∑ i, ModuleCat.freeMk (T.o i).edge : singularOneChainFree) =
6436    ∑ i, (T.o i).chain
6437  rw [← Finset.sum_neg_distrib]
6438  refine Finset.sum_congr rfl (fun i _ => ?_)
6439  simp [OrientedSingularEdge.chain, hbackward i]
6440
6441open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6442/-- If the global scalar of a concrete cyclic edge-list term is nonnegative, then
6443every raw edge coefficient in its represented free chain is nonnegative. -/
6444theorem CyclicSingularEdgeListTerm.edgeCoeff_chain_nonneg_of_coeff_nonneg
6445    [DecidableEq SingularOneSimplex]
6446    (t : CyclicSingularEdgeListTerm) (hcoeff : 0 ≤ t.coeff)
6447    (e : SingularOneSimplex) :
6448    0 ≤ edgeCoeff t.chain e := by
6449  unfold CyclicSingularEdgeListTerm.chain
6450  rw [edgeCoeff_zsmul]
6451  exact mul_nonneg hcoeff (edgeCoeff_singularEdgeListChain_nonneg t.edges e)
6452
6453open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6454/-- If the global scalar of a concrete cyclic edge-list term is nonpositive, then
6455every raw edge coefficient in its represented free chain is nonpositive. -/
6456theorem CyclicSingularEdgeListTerm.edgeCoeff_chain_nonpos_of_coeff_nonpos
6457    [DecidableEq SingularOneSimplex]
6458    (t : CyclicSingularEdgeListTerm) (hcoeff : t.coeff ≤ 0)
6459    (e : SingularOneSimplex) :
6460    edgeCoeff t.chain e ≤ 0 := by
6461  unfold CyclicSingularEdgeListTerm.chain
6462  rw [edgeCoeff_zsmul]
6463  exact mul_nonpos_of_nonpos_of_nonneg hcoeff
6464    (edgeCoeff_singularEdgeListChain_nonneg t.edges e)
6465
6466open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6467/-- A concrete cyclic edge-list term cannot represent a free edge-chain with both
6468a positive and a negative raw edge coefficient.  This is the formal obstruction
6469created by the old one-scalar edge-list interface: its represented chain is
6470globally sign-locked by `coeff`. -/
6471theorem CyclicSingularEdgeListTerm.chain_ne_of_mixed_sign
6472    [DecidableEq SingularOneSimplex]
6473    (t : CyclicSingularEdgeListTerm) (c : singularOneChainFree)
6474    {e f : SingularOneSimplex}
6475    (hepos : 0 < edgeCoeff c e) (hfneg : edgeCoeff c f < 0) :
6476    t.chain ≠ c := by
6477  intro ht
6478  by_cases hcoeff : 0 ≤ t.coeff
6479  · have hf_nonneg := t.edgeCoeff_chain_nonneg_of_coeff_nonneg hcoeff f
6480    rw [ht] at hf_nonneg
6481    omega
6482  · have hcoeff_neg : t.coeff < 0 := lt_of_not_ge hcoeff
6483    have hcoeff_nonpos : t.coeff ≤ 0 := le_of_lt hcoeff_neg
6484    have he_nonpos := t.edgeCoeff_chain_nonpos_of_coeff_nonpos hcoeff_nonpos e
6485    rw [ht] at he_nonpos
6486    omega
6487
6488open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6489/-- A single singular edge whose two endpoints agree is already a cyclic
6490edge-list term.  This closes the loop-edge subcase of the finite-flow extraction
6491argument: no successor search is needed when the selected supported edge is
6492itself closed. -/
6493noncomputable def cyclicSingularEdgeListTerm_of_loop
6494    (e : SingularOneSimplex)
6495    (hfaces :
6496      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) e =
6497        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) e)
6498    (n : ModuleCat.of ℤ ℤ) :
6499    CyclicSingularEdgeListTerm where
6500  edges := [e]
6501  coeff := n
6502  cycle := ModuleCat.Hom.hom (closedSingularOneCycle e hfaces) n
6503  chain_eq := by
6504    have hcomp :
6505        closedSingularOneCycle e hfaces ≫
6506          sphereOneSingularIntChainComplex.iCycles 1 ≫
6507          singularOneChainToFree =
6508        Sigma.ι (fun _ : SingularOneSimplex => ModuleCat.of ℤ ℤ) e ≫
6509          singularOneChainToFree := by
6510      simpa only [Category.assoc] using
6511        congrArg (fun f => f ≫ singularOneChainToFree)
6512          (closedSingularOneCycle_iCycles e hfaces)
6513    change ModuleCat.Hom.hom
6514        (closedSingularOneCycle e hfaces ≫
6515          sphereOneSingularIntChainComplex.iCycles 1 ≫
6516          singularOneChainToFree) n =
6517        n • singularEdgeListChain [e]
6518    rw [hcomp]
6519    rw [singularOneChainToFree_ι]
6520    simp [singularEdgeListChain, LinearMap.toSpanSingleton_apply]
6521  winding_integral := by
6522    obtain ⟨k, hk⟩ := singularWinding_loop_integral e hfaces
6523    refine ⟨n * k, ?_⟩
6524    rw [cycleWinding_closedSingularOneCycle, hk]
6525    simp
6526
6527open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6528/-- A nonzero single-edge free flow with zero boundary has equal endpoints. -/
6529theorem singleEdgeFlow_zero_boundary_faces_eq
6530    (e : SingularOneSimplex) (n : ModuleCat.of ℤ ℤ)
6531    (hn : n ≠ 0)
6532    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree (n • ModuleCat.freeMk e) = 0) :
6533    edgeTerminal e = edgeInitial e := by
6534  by_contra hne
6535  have hboundary :
6536      n • (ModuleCat.freeMk (edgeTerminal e) - ModuleCat.freeMk (edgeInitial e)) =
6537        (0 : singularZeroChainFree) := by
6538    rw [← hzero]
6539    rw [map_zsmul, singularOneBoundaryFree_freeMk]
6540    rfl
6541  have hcoeff := congrArg (fun z : singularZeroChainFree => z.toFun (edgeTerminal e)) hboundary
6542  change (n • (ModuleCat.freeMk (edgeTerminal e) - ModuleCat.freeMk (edgeInitial e)) :
6543      SingularZeroSimplex →₀ ℤ) (edgeTerminal e) = 0 at hcoeff
6544  have hn0 : n = 0 := by
6545    have hne' : edgeInitial e ≠ edgeTerminal e := fun h => hne h.symm
6546    rw [Finsupp.smul_apply, Finsupp.sub_apply] at hcoeff
6547    simpa [ModuleCat.freeMk, hne'] using hcoeff
6548  exact hn hn0
6549
6550open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6551/-- If a balanced free edge-chain has singleton support, that single supported
6552edge is a loop.  This is the residual obstruction needed in the parallel-edge
6553case: a one-edge balanced residual cannot sit on a non-loop edge. -/
6554theorem singletonSupport_zero_boundary_faces_eq
6555    [DecidableEq SingularOneSimplex]
6556    (c : singularOneChainFree) (e : SingularOneSimplex)
6557    (hsupp : edgeSupport c = {e})
6558    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0) :
6559    edgeTerminal e = edgeInitial e := by
6560  have he_mem : e ∈ edgeSupport c := by
6561    rw [hsupp]
6562    simp
6563  have hcoeff_ne : edgeCoeff c e ≠ 0 :=
6564    (mem_edgeSupport_iff c e).mp he_mem
6565  have hc : c = edgeCoeff c e • ModuleCat.freeMk e :=
6566    eq_zsmul_freeMk_of_edgeSupport_eq_single c e hsupp
6567  rw [hc] at hzero
6568  exact singleEdgeFlow_zero_boundary_faces_eq e (edgeCoeff c e) hcoeff_ne hzero
6569
6570open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6571/-- The two-edge parallel-flow obstruction shape: one singular edge with
6572coefficient `+1` and a second with coefficient `-1`. -/
6573noncomputable def parallelTwoEdgeFlow
6574    (e f : SingularOneSimplex) : singularOneChainFree :=
6575  ModuleCat.freeMk e - ModuleCat.freeMk f
6576
6577open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6578/-- The positive edge in a two-edge parallel flow has coefficient `+1`. -/
6579theorem parallelTwoEdgeFlow_coeff_left
6580    [DecidableEq SingularOneSimplex]
6581    {e f : SingularOneSimplex} (hne : e ≠ f) :
6582    edgeCoeff (parallelTwoEdgeFlow e f) e = 1 := by
6583  unfold parallelTwoEdgeFlow
6584  rw [edgeCoeff_sub, edgeCoeff_freeMk_self]
6585  have hf : edgeCoeff (ModuleCat.freeMk f) e = 0 := by
6586    rw [ModuleCat.freeMk, edgeCoeff_single f (1 : ℤ) e,
6587      if_neg (fun h : f = e => hne h.symm)]
6588  rw [hf]
6589  norm_num
6590
6591open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6592/-- The negative edge in a two-edge parallel flow has coefficient `-1`. -/
6593theorem parallelTwoEdgeFlow_coeff_right
6594    [DecidableEq SingularOneSimplex]
6595    {e f : SingularOneSimplex} (hne : e ≠ f) :
6596    edgeCoeff (parallelTwoEdgeFlow e f) f = -1 := by
6597  unfold parallelTwoEdgeFlow
6598  rw [edgeCoeff_sub, edgeCoeff_freeMk_self]
6599  have he : edgeCoeff (ModuleCat.freeMk e) f = 0 := by
6600    rw [ModuleCat.freeMk, edgeCoeff_single e (1 : ℤ) f]
6601    simp [hne]
6602  rw [he]
6603  norm_num
6604
6605open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6606/-- If two distinct singular edges have the same endpoints, their signed
6607two-edge flow is balanced. -/
6608theorem parallelTwoEdgeFlow_boundary_zero
6609    {e f : SingularOneSimplex}
6610    (hterm : edgeTerminal e = edgeTerminal f)
6611    (hinit : edgeInitial e = edgeInitial f) :
6612    ModuleCat.Hom.hom singularOneBoundaryFree (parallelTwoEdgeFlow e f) = 0 := by
6613  unfold parallelTwoEdgeFlow
6614  rw [map_sub, singularOneBoundaryFree_freeMk, singularOneBoundaryFree_freeMk]
6615  change ModuleCat.freeMk (edgeTerminal e) - ModuleCat.freeMk (edgeInitial e) -
6616      (ModuleCat.freeMk (edgeTerminal f) - ModuleCat.freeMk (edgeInitial f)) = 0
6617  rw [hterm, hinit]
6618  abel
6619
6620open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6621/-- The support of a distinct two-edge parallel flow is exactly the two listed
6622edges. -/
6623theorem parallelTwoEdgeFlow_support
6624    [DecidableEq SingularOneSimplex]
6625    {e f : SingularOneSimplex} (hne : e ≠ f) :
6626    edgeSupport (parallelTwoEdgeFlow e f) = {e, f} := by
6627  ext x
6628  rw [mem_edgeSupport_iff]
6629  unfold parallelTwoEdgeFlow
6630  rw [edgeCoeff_sub]
6631  rw [ModuleCat.freeMk, edgeCoeff_single e (1 : ℤ) x]
6632  rw [ModuleCat.freeMk, edgeCoeff_single f (1 : ℤ) x]
6633  by_cases he : e = x
6634  · by_cases hf : f = x
6635    · subst x
6636      exact False.elim (hne hf.symm)
6637    · subst x
6638      simp [hf]
6639  · by_cases hf : f = x
6640    · subst x
6641      simp [hne]
6642    · have hxe : x ≠ e := fun h => he h.symm
6643      have hxf : x ≠ f := fun h => hf h.symm
6644      simp [he, hf, hxe, hxf]
6645
6646open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6647/-- A distinct two-edge parallel flow has support-cardinality two. -/
6648theorem parallelTwoEdgeFlow_supportCard
6649    [DecidableEq SingularOneSimplex]
6650    {e f : SingularOneSimplex} (hne : e ≠ f) :
6651    edgeSupportCard (parallelTwoEdgeFlow e f) = 2 := by
6652  change (edgeSupport (parallelTwoEdgeFlow e f)).card = 2
6653  rw [parallelTwoEdgeFlow_support hne]
6654  simp [hne]
6655
6656open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6657/-- A distinct two-edge parallel flow is nonzero. -/
6658theorem parallelTwoEdgeFlow_ne_zero
6659    [DecidableEq SingularOneSimplex]
6660    {e f : SingularOneSimplex} (hne : e ≠ f) :
6661    parallelTwoEdgeFlow e f ≠ 0 := by
6662  intro hzero
6663  have hcoeff := parallelTwoEdgeFlow_coeff_left (e := e) (f := f) hne
6664  rw [hzero] at hcoeff
6665  change edgeCoeff (0 : singularOneChainFree) e = 1 at hcoeff
6666  change (0 : ℤ) = 1 at hcoeff
6667  norm_num at hcoeff
6668
6669open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6670/-- A distinct two-edge parallel flow lies in the large-support branch. -/
6671theorem parallelTwoEdgeFlow_largeSupport
6672    [DecidableEq SingularOneSimplex]
6673    {e f : SingularOneSimplex} (hne : e ≠ f) :
6674    1 < edgeSupportCard (parallelTwoEdgeFlow e f) := by
6675  rw [parallelTwoEdgeFlow_supportCard hne]
6676  norm_num
6677
6678open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6679/-- A nonzero single-edge free flow with zero boundary is already a cyclic
6680edge-list decomposition.  This is the support-cardinality-one subcase of the
6681finite-flow extraction theorem. -/
6682theorem singleEdgeFlow_decomposesIntoCyclicEdgeLists
6683    (e : SingularOneSimplex) (n : ModuleCat.of ℤ ℤ)
6684    (hn : n ≠ 0)
6685    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree (n • ModuleCat.freeMk e) = 0) :
6686    ∃ ts : List CyclicSingularEdgeListTerm,
6687      n • ModuleCat.freeMk e = cyclicSingularEdgeListTermListChain ts := by
6688  have hfaces : edgeTerminal e = edgeInitial e :=
6689    singleEdgeFlow_zero_boundary_faces_eq e n hn hzero
6690  let t := cyclicSingularEdgeListTerm_of_loop e hfaces n
6691  refine ⟨[t], ?_⟩
6692  change n • ModuleCat.freeMk e =
6693    t.coeff • singularEdgeListChain t.edges + cyclicSingularEdgeListTermListChain []
6694  simp [t, cyclicSingularEdgeListTerm_of_loop, singularEdgeListChain,
6695    cyclicSingularEdgeListTermListChain]
6696
6697open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6698/-- Any balanced free edge-flow with singleton support is a one-term cyclic
6699edge-list.  This packages the support-cardinality-one case in the native
6700`edgeSupport` language used by the support-decreasing induction. -/
6701theorem singletonSupportFlow_decomposesIntoCyclicEdgeLists
6702    (c : singularOneChainFree) (e : SingularOneSimplex)
6703    (hsupp : edgeSupport c = {e})
6704    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0) :
6705    ∃ ts : List CyclicSingularEdgeListTerm,
6706      c = cyclicSingularEdgeListTermListChain ts := by
6707  have he_mem : e ∈ edgeSupport c := by
6708    rw [hsupp]
6709    simp
6710  have hn : edgeCoeff c e ≠ 0 := (mem_edgeSupport_iff c e).mp he_mem
6711  have hc_single : c = (Finsupp.single e (edgeCoeff c e) : singularOneChainFree) := by
6712    apply Finsupp.ext
6713    intro x
6714    by_cases hx : x = e
6715    · subst x
6716      change c.toFun e = (Finsupp.single e (c.toFun e) : singularOneChainFree) e
6717      rw [Finsupp.single_eq_same]
6718    · have hx_not_mem : x ∉ edgeSupport c := by
6719        rw [hsupp]
6720        simp [hx]
6721      have hcx : edgeCoeff c x = 0 := by
6722        exact Classical.not_not.mp (mt (mem_edgeSupport_iff c x).mpr hx_not_mem)
6723      unfold edgeCoeff at hcx
6724      change c.toFun x = (Finsupp.single e (edgeCoeff c e) : singularOneChainFree) x
6725      rw [hcx]
6726      rw [Finsupp.single_eq_of_ne hx]
6727  have hsmul : (Finsupp.single e (edgeCoeff c e) : singularOneChainFree) =
6728      edgeCoeff c e • ModuleCat.freeMk e := by
6729    rw [ModuleCat.freeMk]
6730    rw [Finsupp.smul_single]
6731    simp
6732  rw [hc_single, hsmul] at hzero ⊢
6733  exact singleEdgeFlow_decomposesIntoCyclicEdgeLists e (edgeCoeff c e) hn hzero
6734
6735/-- A singleton cyclic-edge-list chain is its term's chain. -/
6736theorem cyclicSingularEdgeListTermListChain_single
6737    (t : CyclicSingularEdgeListTerm) :
6738    cyclicSingularEdgeListTermListChain [t] = t.chain := by
6739  simp [cyclicSingularEdgeListTermListChain, CyclicSingularEdgeListTerm.chain]
6740
6741open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6742/-- Mapping concrete cyclic edge-list terms to abstract directed-cycle terms
6743preserves the represented free-chain sum. -/
6744theorem directedCycleListChain_of_cyclicEdgeList :
6745    ∀ ts : List CyclicSingularEdgeListTerm,
6746      directedCycleFreeTermListChain (ts.map CyclicSingularEdgeListTerm.toDirectedCycleFreeTerm) =
6747        cyclicSingularEdgeListTermListChain ts
6748  | [] => by
6749      unfold directedCycleFreeTermListChain cyclicSingularEdgeListTermListChain
6750      rfl
6751  | t :: ts => by
6752      unfold directedCycleFreeTermListChain cyclicSingularEdgeListTermListChain
6753      change t.coeff • singularEdgeListChain t.edges +
6754          directedCycleFreeTermListChain (ts.map CyclicSingularEdgeListTerm.toDirectedCycleFreeTerm) =
6755        t.coeff • singularEdgeListChain t.edges + cyclicSingularEdgeListTermListChain ts
6756      rw [directedCycleListChain_of_cyclicEdgeList ts]
6757
6758open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6759/-- More concrete remaining finite graph target: every balanced free edge-flow
6760decomposes into finitely many cyclic edge-list pieces. -/
6761def freeBoundaryKernel_decomposesIntoCyclicEdgeLists : Prop :=
6762  ∀ c : singularOneChainFree,
6763    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6764      ∃ ts : List CyclicSingularEdgeListTerm, c = cyclicSingularEdgeListTermListChain ts
6765
6766/-- One-step extraction target for the support-decreasing proof: every nonzero
6767balanced free edge-flow splits into one cyclic edge-list piece plus a balanced
6768residual whose edge support is strictly smaller. -/
6769def cyclicEdgeListExtractionStep : Prop :=
6770  ∀ c : singularOneChainFree,
6771    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6772      c ≠ 0 →
6773        ∃ (t : CyclicSingularEdgeListTerm) (r : singularOneChainFree),
6774          c = t.chain + r ∧
6775            ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
6776              edgeSupportCard r < edgeSupportCard c
6777
6778/-- A support-decreasing one-step cyclic extraction proves the full finite cyclic
6779edge-list decomposition by strong induction on support cardinality. -/
6780theorem freeBoundaryKernel_decomposesIntoCyclicEdgeLists_of_extractionStep
6781    (hstep : cyclicEdgeListExtractionStep) :
6782    freeBoundaryKernel_decomposesIntoCyclicEdgeLists := by
6783  intro c hc
6784  let P : ℕ → Prop := fun n =>
6785    ∀ c : singularOneChainFree,
6786      edgeSupportCard c = n →
6787        ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6788          ∃ ts : List CyclicSingularEdgeListTerm, c = cyclicSingularEdgeListTermListChain ts
6789  have hP : ∀ n, P n := by
6790    intro n
6791    induction n using Nat.strong_induction_on with
6792    | h n ih =>
6793      intro c hcCard hcBoundary
6794      by_cases hzero : c = 0
6795      · refine ⟨[], ?_⟩
6796        rw [hzero]
6797        rfl
6798      · obtain ⟨t, r, hdecomp, hrBoundary, hrLt⟩ := hstep c hcBoundary hzero
6799        have hrLtN : edgeSupportCard r < n := by
6800          simpa [hcCard] using hrLt
6801        obtain ⟨ts, hts⟩ := ih (edgeSupportCard r) hrLtN r rfl hrBoundary
6802        refine ⟨t :: ts, ?_⟩
6803        unfold cyclicSingularEdgeListTermListChain
6804        rw [← hts]
6805        exact hdecomp
6806  exact hP (edgeSupportCard c) c rfl hc
6807
6808open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6809/-- The zero free edge-flow decomposes as the empty cyclic edge-list.  This is the
6810base case for the support-decreasing finite-flow induction. -/
6811theorem zeroFlow_decomposesIntoCyclicEdgeLists :
6812    ∃ ts : List CyclicSingularEdgeListTerm,
6813      (0 : singularOneChainFree) = cyclicSingularEdgeListTermListChain ts := by
6814  exact ⟨[], rfl⟩
6815
6816open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6817/-- A free edge-flow with support-cardinality zero has the empty cyclic
6818edge-list decomposition. -/
6819theorem supportCard_zero_decomposesIntoCyclicEdgeLists
6820    (c : singularOneChainFree) (hcard : edgeSupportCard c = 0) :
6821    ∃ ts : List CyclicSingularEdgeListTerm, c = cyclicSingularEdgeListTermListChain ts := by
6822  have hzero : c = 0 := (edgeSupportCard_eq_zero_iff c).mp hcard
6823  rw [hzero]
6824  exact zeroFlow_decomposesIntoCyclicEdgeLists
6825
6826open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6827/-- Any balanced free edge-flow with support-cardinality at most one decomposes
6828into cyclic edge-list pieces.  This packages the zero and singleton support base
6829cases for the support-decreasing induction. -/
6830theorem supportCard_le_one_decomposesIntoCyclicEdgeLists
6831    (c : singularOneChainFree)
6832    (hcard : edgeSupportCard c ≤ 1)
6833    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0) :
6834    ∃ ts : List CyclicSingularEdgeListTerm, c = cyclicSingularEdgeListTermListChain ts := by
6835  have hcases : edgeSupportCard c = 0 ∨ edgeSupportCard c = 1 := by
6836    omega
6837  rcases hcases with h0 | h1
6838  · exact supportCard_zero_decomposesIntoCyclicEdgeLists c h0
6839  · have hsupp_card : (edgeSupport c).card = 1 := h1
6840    obtain ⟨e, he⟩ := Finset.card_eq_one.mp hsupp_card
6841    exact singletonSupportFlow_decomposesIntoCyclicEdgeLists c e he hzero
6842
6843open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6844/-- Any nonzero balanced free edge-flow with support-cardinality at most one
6845admits the one-step extraction required by `cyclicEdgeListExtractionStep`. -/
6846theorem supportCard_le_one_extractionStep
6847    (c : singularOneChainFree)
6848    (hcard : edgeSupportCard c ≤ 1)
6849    (hzero : ModuleCat.Hom.hom singularOneBoundaryFree c = 0)
6850    (hne : c ≠ 0) :
6851    ∃ (t : CyclicSingularEdgeListTerm) (r : singularOneChainFree),
6852      c = t.chain + r ∧
6853        ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
6854          edgeSupportCard r < edgeSupportCard c := by
6855  have hnot0 : edgeSupportCard c ≠ 0 := by
6856    intro h0
6857    exact hne ((edgeSupportCard_eq_zero_iff c).mp h0)
6858  have h1 : edgeSupportCard c = 1 := by omega
6859  have hsupp_card : (edgeSupport c).card = 1 := h1
6860  obtain ⟨e, hsupp⟩ := Finset.card_eq_one.mp hsupp_card
6861  have he_mem : e ∈ edgeSupport c := by
6862    rw [hsupp]
6863    simp
6864  have hn : edgeCoeff c e ≠ 0 := (mem_edgeSupport_iff c e).mp he_mem
6865  have hc_single : c = (Finsupp.single e (edgeCoeff c e) : singularOneChainFree) := by
6866    apply Finsupp.ext
6867    intro x
6868    by_cases hx : x = e
6869    · subst x
6870      change c.toFun e = (Finsupp.single e (c.toFun e) : singularOneChainFree) e
6871      rw [Finsupp.single_eq_same]
6872    · have hx_not_mem : x ∉ edgeSupport c := by
6873        rw [hsupp]
6874        simp [hx]
6875      have hcx : edgeCoeff c x = 0 := by
6876        exact Classical.not_not.mp (mt (mem_edgeSupport_iff c x).mpr hx_not_mem)
6877      unfold edgeCoeff at hcx
6878      change c.toFun x = (Finsupp.single e (edgeCoeff c e) : singularOneChainFree) x
6879      rw [hcx]
6880      rw [Finsupp.single_eq_of_ne hx]
6881  have hsmul : (Finsupp.single e (edgeCoeff c e) : singularOneChainFree) =
6882      edgeCoeff c e • ModuleCat.freeMk e := by
6883    rw [ModuleCat.freeMk]
6884    rw [Finsupp.smul_single]
6885    simp
6886  have hzero_single :
6887      ModuleCat.Hom.hom singularOneBoundaryFree (edgeCoeff c e • ModuleCat.freeMk e) = 0 := by
6888    rw [← hsmul, ← hc_single]
6889    exact hzero
6890  have hfaces : edgeTerminal e = edgeInitial e :=
6891    singleEdgeFlow_zero_boundary_faces_eq e (edgeCoeff c e) hn hzero_single
6892  let t := cyclicSingularEdgeListTerm_of_loop e hfaces (edgeCoeff c e)
6893  refine ⟨t, 0, ?_, ?_, ?_⟩
6894  · rw [hc_single, hsmul]
6895    simp [CyclicSingularEdgeListTerm.chain, t, cyclicSingularEdgeListTerm_of_loop,
6896      singularEdgeListChain]
6897  · simp
6898  · have hzero_card : edgeSupportCard (0 : singularOneChainFree) = 0 :=
6899      (edgeSupportCard_eq_zero_iff (0 : singularOneChainFree)).mpr rfl
6900    rw [hzero_card, h1]
6901    norm_num
6902
6903open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6904/-- If a loop edge is peeled off and the residual is already decomposed, then the
6905whole flow is decomposed.  This is the loop-edge branch needed by the future
6906support-decreasing extraction proof. -/
6907theorem loopEdge_plus_residual_decomposesIntoCyclicEdgeLists
6908    (e : SingularOneSimplex)
6909    (hfaces :
6910      (TopCat.toSSet.obj (TopCat.sphere 1)).δ (0 : Fin 2) e =
6911        (TopCat.toSSet.obj (TopCat.sphere 1)).δ (1 : Fin 2) e)
6912    (n : ModuleCat.of ℤ ℤ)
6913    (r : singularOneChainFree)
6914    (hres : ∃ ts : List CyclicSingularEdgeListTerm,
6915      r = cyclicSingularEdgeListTermListChain ts) :
6916    ∃ ts : List CyclicSingularEdgeListTerm,
6917      n • ModuleCat.freeMk e + r = cyclicSingularEdgeListTermListChain ts := by
6918  obtain ⟨ts, hts⟩ := hres
6919  let t := cyclicSingularEdgeListTerm_of_loop e hfaces n
6920  refine ⟨t :: ts, ?_⟩
6921  unfold cyclicSingularEdgeListTermListChain
6922  rw [← hts]
6923  simp [t, cyclicSingularEdgeListTerm_of_loop, singularEdgeListChain]
6924
6925/-- Remaining finite-flow extraction target after the zero/singleton/loop-edge
6926branches are closed: a balanced nonzero flow with support-cardinality greater
6927than one can be split into one cyclic edge-list piece plus a balanced residual
6928with strictly smaller support. -/
6929def largeSupportCyclicEdgeListExtractionStep : Prop :=
6930  ∀ c : singularOneChainFree,
6931    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6932      c ≠ 0 →
6933        1 < edgeSupportCard c →
6934          ∃ (t : CyclicSingularEdgeListTerm) (r : singularOneChainFree),
6935            c = t.chain + r ∧
6936              ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
6937                edgeSupportCard r < edgeSupportCard c
6938
6939open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6940/-- Stronger but cleaner large-support peel target: find a concrete cyclic
6941edge-list term whose chain is supported inside the current flow and exactly
6942cancels at least one supported edge.  The generic support lemma then supplies the
6943strict support-cardinality drop. -/
6944def largeSupportSupportedExactCyclicPeelStep : Prop :=
6945  ∀ c : singularOneChainFree,
6946    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6947      c ≠ 0 →
6948        1 < edgeSupportCard c →
6949          ∃ t : CyclicSingularEdgeListTerm,
6950            edgeSupport t.chain ⊆ edgeSupport c ∧
6951              ∃ e, e ∈ edgeSupport t.chain ∧ edgeCoeff t.chain e = edgeCoeff c e
6952
6953open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6954/-- A supported exact cyclic peel proves the literal large-support extraction
6955target.  This packages the residual as `c - t.chain`, gets boundary-zero from the
6956cyclic term, and gets the strict support drop from
6957`edgeSupportCard_sub_lt_of_supported_exact_cancel`. -/
6958theorem largeSupportCyclicEdgeListExtractionStep_of_supportedExactPeel
6959    [DecidableEq SingularOneSimplex]
6960    (hpeel : largeSupportSupportedExactCyclicPeelStep) :
6961    largeSupportCyclicEdgeListExtractionStep := by
6962  intro c hbd hne hlarge
6963  obtain ⟨t, htsupp, hcancel⟩ := hpeel c hbd hne hlarge
6964  refine ⟨t, c - t.chain, ?_, ?_, ?_⟩
6965  · abel
6966  · rw [map_sub, hbd, t.boundary_chain_zero, sub_zero]
6967  · exact edgeSupportCard_sub_lt_of_supported_exact_cancel c t.chain htsupp hcancel
6968
6969open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6970/-- Uniform-orientation variant of the large-support extraction step.  This is the
6971exact extra condition needed to feed the older one-scalar cyclic-edge-list
6972interface from the newer oriented closed-walk extraction machinery. -/
6973def largeSupportUniformOrientedExtractionStep : Prop :=
6974  ∀ c : singularOneChainFree,
6975    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6976      c ≠ 0 →
6977        1 < edgeSupportCard c →
6978          ∃ (T : OrientedCyclicFamilyTerm) (r : singularOneChainFree),
6979            c = T.toDirectedCycleFreeTerm.chain + r ∧
6980              ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
6981                edgeSupportCard r < edgeSupportCard c ∧
6982                  ((∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.forward) ∨
6983                    (∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.backward))
6984
6985open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
6986/-- Scaled uniform-orientation variant of the large-support extraction step.  This
6987matches the support-decreasing oriented theorem: the cyclic piece may need to be
6988multiplied by the minimum coefficient on the closed walk before support strictly
6989drops. -/
6990def largeSupportUniformOrientedScaledExtractionStep : Prop :=
6991  ∀ c : singularOneChainFree,
6992    ModuleCat.Hom.hom singularOneBoundaryFree c = 0 →
6993      c ≠ 0 →
6994        1 < edgeSupportCard c →
6995          ∃ (T : OrientedCyclicFamilyTerm) (m : ℤ) (r : singularOneChainFree),
6996            0 < m ∧
6997              c = m • T.toDirectedCycleFreeTerm.chain + r ∧
6998                ModuleCat.Hom.hom singularOneBoundaryFree r = 0 ∧
6999                  edgeSupportCard r < edgeSupportCard c ∧
7000                    ((∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.forward) ∨
7001                      (∀ i : Fin T.k, (T.o i).orientation = EdgeOrientation.backward))
7002
7003open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7004/-- A scaled large-support extraction whose oriented cycle is uniformly forward
7005or uniformly backward proves the older concrete cyclic-edge-list extraction
7006target. -/
7007theorem largeSupportCyclicEdgeListExtractionStep_of_uniformOrientedScaled
7008    (huniform : largeSupportUniformOrientedScaledExtractionStep) :
7009    largeSupportCyclicEdgeListExtractionStep := by
7010  intro c hbd hne hlarge
7011  obtain ⟨T, m, r, _hm, hdecomp, hrbd, hrlt, hunif⟩ := huniform c hbd hne hlarge
7012  rcases hunif with hforward | hbackward
7013  · let base := T.toCyclicSingularEdgeListTerm_of_all_forward hforward
7014    let t := base.zsmul m
7015    refine ⟨t, r, ?_, hrbd, hrlt⟩
7016    rw [hdecomp]
7017    change m • T.toDirectedCycleFreeTerm.chain + r = (base.zsmul m).chain + r
7018    rw [CyclicSingularEdgeListTerm.zsmul_chain, T.toCyclicSingularEdgeListTerm_of_all_forward_chain hforward]
7019  · let base := T.toCyclicSingularEdgeListTerm_of_all_backward hbackward
7020    let t := base.zsmul m
7021    refine ⟨t, r, ?_, hrbd, hrlt⟩
7022    rw [hdecomp]
7023    change m • T.toDirectedCycleFreeTerm.chain + r = (base.zsmul m).chain + r
7024    rw [CyclicSingularEdgeListTerm.zsmul_chain, T.toCyclicSingularEdgeListTerm_of_all_backward_chain hbackward]
7025
7026open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7027/-- A large-support extraction whose oriented cycle is uniformly forward or
7028uniformly backward proves the older concrete cyclic-edge-list extraction target.
7029This theorem isolates the remaining finite-flow obstruction to the uniformity of
7030the extracted sign-selected cycle. -/
7031theorem largeSupportCyclicEdgeListExtractionStep_of_uniformOriented
7032    (huniform : largeSupportUniformOrientedExtractionStep) :
7033    largeSupportCyclicEdgeListExtractionStep := by
7034  intro c hbd hne hlarge
7035  obtain ⟨T, r, hdecomp, hrbd, hrlt, hunif⟩ := huniform c hbd hne hlarge
7036  rcases hunif with hforward | hbackward
7037  · let t := T.toCyclicSingularEdgeListTerm_of_all_forward hforward
7038    refine ⟨t, r, ?_, hrbd, hrlt⟩
7039    rw [hdecomp]
7040    rw [T.toCyclicSingularEdgeListTerm_of_all_forward_chain hforward]
7041  · let t := T.toCyclicSingularEdgeListTerm_of_all_backward hbackward
7042    refine ⟨t, r, ?_, hrbd, hrlt⟩
7043    rw [hdecomp]
7044    rw [T.toCyclicSingularEdgeListTerm_of_all_backward_chain hbackward]
7045
7046open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7047/-- The full support-decreasing extraction theorem is reduced to the genuine
7048remaining case: support-cardinality greater than one.  The support-cardinality
7049`≤ 1` cases are already closed by
7050`supportCard_le_one_decomposesIntoCyclicEdgeLists`; this theorem packages the
7051logical handoff so later work only has to prove the repeated-vertex extraction
7052for large support. -/
7053theorem cyclicEdgeListExtractionStep_of_largeSupport
7054    (hlarge : largeSupportCyclicEdgeListExtractionStep) :
7055    cyclicEdgeListExtractionStep := by
7056  intro c hzero hne
7057  by_cases hsmall : edgeSupportCard c ≤ 1
7058  · exact supportCard_le_one_extractionStep c hsmall hzero hne
7059  · have hlarge_card : 1 < edgeSupportCard c := by omega
7060    exact hlarge c hzero hne hlarge_card
7061
7062open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7063/-- The full finite cyclic edge-list decomposition follows from the single
7064remaining large-support repeated-vertex extraction theorem. -/
7065theorem freeBoundaryKernel_decomposesIntoCyclicEdgeLists_of_largeSupport
7066    (hlarge : largeSupportCyclicEdgeListExtractionStep) :
7067    freeBoundaryKernel_decomposesIntoCyclicEdgeLists :=
7068  freeBoundaryKernel_decomposesIntoCyclicEdgeLists_of_extractionStep
7069    (cyclicEdgeListExtractionStep_of_largeSupport hlarge)
7070
7071open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7072/-- Concrete cyclic edge-list decomposition implies the abstract directed-cycle
7073decomposition target. -/
7074theorem freeBoundaryKernel_decomposesIntoDirectedCycles_of_cyclicEdgeLists
7075    (hker : freeBoundaryKernel_decomposesIntoCyclicEdgeLists) :
7076    freeBoundaryKernel_decomposesIntoDirectedCycles := by
7077  intro c hc
7078  obtain ⟨ts, hts⟩ := hker c hc
7079  refine ⟨ts.map CyclicSingularEdgeListTerm.toDirectedCycleFreeTerm, ?_⟩
7080  rw [directedCycleListChain_of_cyclicEdgeList ts]
7081  exact hts
7082
7083open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7084/-- The concrete cyclic edge-list decomposition theorem gives integer winding for
7085all singular `1`-cycles. -/
7086theorem cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoCyclicEdgeLists
7087    (hker : freeBoundaryKernel_decomposesIntoCyclicEdgeLists) :
7088    cycleWinding_integral :=
7089  cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoDirectedCycles
7090    (freeBoundaryKernel_decomposesIntoDirectedCycles_of_cyclicEdgeLists hker)
7091
7092open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7093/-- If every cycle is a finite sum of closed singular generator cycles, then every
7094cycle has integer winding. -/
7095theorem cycleWinding_integral_of_closedSingularOneCycleList_spans
7096    (hspan : closedSingularOneCycleList_spans) :
7097    cycleWinding_integral := by
7098  intro z
7099  obtain ⟨ts, hz⟩ := hspan z
7100  obtain ⟨n, hn⟩ := closedSingularOneCycleList_winding_integral ts
7101  refine ⟨n, ?_⟩
7102  rw [hz, hn]
7103
7104open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7105/-- Second concrete geometric subtarget: every zero-winding singular `1`-cycle is
7106a singular `2`-boundary.  This is the filling theorem that should be supplied by
7107subdivision/prism machinery or an equivalent singular-chain construction. -/
7108def zeroWindingCycles_bound : Prop :=
7109  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
7110    cycleWinding z = 0 →
7111      ∃ b : sphereOneSingularIntChainComplex.X 2,
7112        z = ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b
7113
7114open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7115/-- If zero-winding cycles bound, every finite closed-generator list is generated
7116by the fundamental cycle modulo a boundary: choose the list's integer winding,
7117subtract that multiple of the fundamental cycle, and fill the zero-winding
7118residual. -/
7119theorem closedSingularOneCycleList_boundary_generates_of_zeroWindingCycles_bound
7120    (hzero : zeroWindingCycles_bound) (ts : List ClosedSingularOneCycleTerm) :
7121    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
7122      closedSingularOneCycleList ts =
7123        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
7124          ModuleCat.Hom.hom fundamentalCycle n := by
7125  obtain ⟨n, _hn, hreszero⟩ := closedSingularOneCycleList_zeroWinding_residual ts
7126  obtain ⟨b, hb⟩ :=
7127    hzero (closedSingularOneCycleList ts - ModuleCat.Hom.hom fundamentalCycle n) hreszero
7128  exact ⟨n, b, closedSingularOneCycleList_boundary_generate_of_residual_bound ts n b hb⟩
7129
7130open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7131/-- Closed-generator list spanning plus zero-winding filling gives the full
7132fundamental-cycle boundary-generation theorem.  This separates the remaining
7133work into a finite-support spanning theorem and the zero-winding filling theorem. -/
7134theorem fundamentalCycle_boundary_generates_of_closedSingularOneCycleList_spans
7135    (hspan : closedSingularOneCycleList_spans) (hzero : zeroWindingCycles_bound) :
7136    fundamentalCycle_boundary_generates := by
7137  intro z
7138  obtain ⟨ts, hz⟩ := hspan z
7139  obtain ⟨n, b, hts⟩ := closedSingularOneCycleList_boundary_generates_of_zeroWindingCycles_bound hzero ts
7140  refine ⟨n, b, ?_⟩
7141  rw [hz, hts]
7142
7143open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7144/-- Local oriented-family consumer for zero-winding filling: subtract the integer
7145total winding multiple of the fundamental cycle, fill the zero-winding residual,
7146and recover the requested boundary-plus-fundamental decomposition. -/
7147theorem OrientedCyclicFamilyTerm.boundary_generate_of_zeroWindingCycles_bound
7148    (T : OrientedCyclicFamilyTerm) (hzero : zeroWindingCycles_bound) :
7149    ∃ (n : ModuleCat.of ℤ ℤ) (b : sphereOneSingularIntChainComplex.X 2),
7150      T.toDirectedCycleFreeTerm.cycle =
7151        ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1) b +
7152          ModuleCat.Hom.hom fundamentalCycle n := by
7153  obtain ⟨n, _hn, hreszero⟩ := T.zeroWinding_residual
7154  obtain ⟨b, hb⟩ :=
7155    hzero (T.toDirectedCycleFreeTerm.cycle - ModuleCat.Hom.hom fundamentalCycle n) hreszero
7156  refine ⟨n, b, ?_⟩
7157  rw [← hb]
7158  abel
7159
7160open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7161/-- Homology-level zero-winding target: every cycle with zero winding represents
7162the zero first-homology class.  By `cycle_eq_boundary_of_homologyπ_eq_zero`, this
7163is enough to produce the explicit singular `2`-boundary required by
7164`zeroWindingCycles_bound`. -/
7165def zeroWindingCycles_homologyClass_zero : Prop :=
7166  ∀ z : sphereOneSingularIntChainComplex.cycles 1,
7167    cycleWinding z = 0 →
7168      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1) z = 0
7169
7170open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7171/-- If zero winding kills the homology class, then zero-winding cycles bound
7172explicit singular `2`-chains. -/
7173theorem zeroWindingCycles_bound_of_homologyClass_zero
7174    (hzeroClass : zeroWindingCycles_homologyClass_zero) :
7175    zeroWindingCycles_bound := by
7176  intro z hz
7177  exact cycle_eq_boundary_of_homologyπ_eq_zero z (hzeroClass z hz)
7178
7179open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7180/-- If the homology-level winding map is monic, then every zero-winding cycle has
7181zero homology class. -/
7182theorem zeroWindingCycles_homologyClass_zero_of_windingHomologyMap_mono
7183    (hmono : Mono windingHomologyMap) :
7184    zeroWindingCycles_homologyClass_zero := by
7185  intro z hz
7186  have hinj : Function.Injective (ModuleCat.Hom.hom windingHomologyMap) :=
7187    (ModuleCat.mono_iff_injective windingHomologyMap).mp hmono
7188  apply hinj
7189  rw [homologyπ_windingHomologyMap_apply, hz]
7190  simp
7191
7192open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7193/-- The explicit zero-winding filling theorem implies the homology-class version:
7194boundaries die under the homology projection. -/
7195theorem zeroWindingCycles_homologyClass_zero_of_zeroWindingCycles_bound
7196    (hzero : zeroWindingCycles_bound) :
7197    zeroWindingCycles_homologyClass_zero := by
7198  intro z hz
7199  obtain ⟨b, hb⟩ := hzero z hz
7200  rw [hb]
7201  change ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
7202      sphereOneSingularIntChainComplex.homologyπ 1) b = 0
7203  rw [sphereOneSingularIntChainComplex.toCycles_comp_homologyπ]
7204  simp
7205
7206open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7207/-- The homology-class zero-winding theorem is equivalent to injectivity of the
7208homology-level winding map. -/
7209theorem windingHomologyMap_mono_of_zeroWindingCycles_homologyClass_zero
7210    (hzeroClass : zeroWindingCycles_homologyClass_zero) :
7211    Mono windingHomologyMap := by
7212  rw [ModuleCat.mono_iff_injective]
7213  intro x y hxy
7214  have hπsurj :
7215      Function.Surjective
7216        (ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1)) :=
7217    (ModuleCat.epi_iff_surjective (sphereOneSingularIntChainComplex.homologyπ 1)).mp inferInstance
7218  obtain ⟨zx, hzx⟩ := hπsurj x
7219  obtain ⟨zy, hzy⟩ := hπsurj y
7220  have hπdiff :
7221      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1) (zx - zy) =
7222        x - y := by
7223    rw [map_sub, hzx, hzy]
7224  have hWdiff :
7225      ModuleCat.Hom.hom windingHomologyMap (x - y) = 0 := by
7226    rw [map_sub, hxy, sub_self]
7227  have hcycleZero : cycleWinding (zx - zy) = 0 := by
7228    rw [← homologyπ_windingHomologyMap_apply (zx - zy), hπdiff, hWdiff]
7229  have hhomZero :
7230      ModuleCat.Hom.hom (sphereOneSingularIntChainComplex.homologyπ 1) (zx - zy) = 0 :=
7231    hzeroClass (zx - zy) hcycleZero
7232  have hsub : x - y = 0 := by
7233    rw [← hπdiff]
7234    exact hhomZero
7235  exact sub_eq_zero.mp hsub
7236
7237open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7238/-- The chain-level zero-winding filling theorem is equivalent to injectivity of
7239the homology-level winding map. -/
7240theorem zeroWindingCycles_bound_iff_windingHomologyMap_mono :
7241    zeroWindingCycles_bound ↔ Mono windingHomologyMap := by
7242  constructor
7243  · intro hzero
7244    exact windingHomologyMap_mono_of_zeroWindingCycles_homologyClass_zero
7245      (zeroWindingCycles_homologyClass_zero_of_zeroWindingCycles_bound hzero)
7246  · intro hmono
7247    exact zeroWindingCycles_bound_of_homologyClass_zero
7248      (zeroWindingCycles_homologyClass_zero_of_windingHomologyMap_mono hmono)
7249
7250open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7251/-- A monic homology-level winding map closes the zero-winding filling target. -/
7252theorem zeroWindingCycles_bound_of_windingHomologyMap_mono
7253    (hmono : Mono windingHomologyMap) :
7254    zeroWindingCycles_bound :=
7255  zeroWindingCycles_bound_of_homologyClass_zero
7256    (zeroWindingCycles_homologyClass_zero_of_windingHomologyMap_mono hmono)
7257
7258open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7259/-- Surjectivity of the fundamental class map closes the zero-winding filling
7260target, via injectivity of the homology-level winding map. -/
7261theorem zeroWindingCycles_bound_of_fundamentalHomologyClass_surjective
7262    (hsurj : fundamentalHomologyClass_surjective) :
7263    zeroWindingCycles_bound :=
7264  zeroWindingCycles_bound_of_windingHomologyMap_mono
7265    (windingHomologyMap_mono_of_fundamentalHomologyClass_surjective hsurj)
7266
7267open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7268/-- Homology-level generation by the fundamental circle class closes the
7269zero-winding filling target. -/
7270theorem zeroWindingCycles_bound_of_fundamentalCycleClass_generates
7271    (hgen : fundamentalCycleClass_generates) :
7272    zeroWindingCycles_bound :=
7273  zeroWindingCycles_bound_of_fundamentalHomologyClass_surjective
7274    (fundamentalHomologyClass_surjective_of_cycleClass_generates hgen)
7275
7276open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7277/-- If the concrete boundary-generation theorem is supplied directly, then the
7278zero-winding filling theorem follows.  Indeed, write `z = ∂b + n·γ`; winding
7279kills `∂b` and sends the fundamental cycle `γ` to `1`, so `W(z)=0` forces
7280`n = 0`.  Thus `z = ∂b`.
7281
7282This isolates the remaining geometric work: it is enough to prove the
7283circle-only chain-level generation theorem `fundamentalCycle_boundary_generates`.
7284-/
7285theorem zeroWindingCycles_bound_of_fundamentalCycle_boundary_generates
7286    (hgen : fundamentalCycle_boundary_generates) :
7287    zeroWindingCycles_bound := by
7288  intro z hz0
7289  obtain ⟨n, b, hz⟩ := hgen z
7290  have hboundary_winding :
7291      ModuleCat.Hom.hom
7292        (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
7293          sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) b = 0 := by
7294    rw [HomologicalComplex.toCycles_i_assoc, windingChainMap_boundary]
7295    simp
7296  have hwind_n : cycleWinding z = (n : ℝ) := by
7297    rw [hz]
7298    unfold cycleWinding
7299    rw [map_add]
7300    change ModuleCat.Hom.hom
7301        (sphereOneSingularIntChainComplex.toCycles 2 1 ≫
7302          sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) b +
7303        cycleWinding (ModuleCat.Hom.hom fundamentalCycle n) = (n : ℝ)
7304    rw [hboundary_winding, cycleWinding_fundamentalCycle]
7305    simp
7306  have hn_real : (n : ℝ) = 0 := by
7307    rw [← hwind_n]
7308    exact hz0
7309  have hn : n = 0 := by
7310    exact_mod_cast hn_real
7311  refine ⟨b, ?_⟩
7312  rw [hz, hn]
7313  simp
7314
7315open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7316/-- The one-directed-cycle generation theorem closes the zero-winding filling
7317target. -/
7318theorem zeroWindingCycles_bound_of_directedCycleTerms
7319    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7320    (hterm : directedCycleTerms_boundary_generate) :
7321    zeroWindingCycles_bound :=
7322  zeroWindingCycles_bound_of_fundamentalCycle_boundary_generates
7323    (fundamentalCycle_boundary_generates_of_directedCycleTerms hterm)
7324
7325open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7326/-- Filling each concrete oriented cyclic family closes the zero-winding filling
7327target. -/
7328theorem zeroWindingCycles_bound_of_orientedCyclicFamilies
7329    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7330    (hterm : orientedCyclicFamilies_boundary_generate) :
7331    zeroWindingCycles_bound :=
7332  zeroWindingCycles_bound_of_fundamentalCycle_boundary_generates
7333    (fundamentalCycle_boundary_generates_of_orientedCyclicFamilies hterm)
7334
7335open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7336/-- A raw prism filling for each concrete oriented cyclic family closes the
7337zero-winding filling target. -/
7338theorem zeroWindingCycles_bound_of_rawPrism
7339    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7340    (hraw : orientedCyclicFamilies_rawPrism_generate) :
7341    zeroWindingCycles_bound :=
7342  zeroWindingCycles_bound_of_orientedCyclicFamilies
7343    (orientedCyclicFamilies_boundary_generate_of_rawPrism hraw)
7344
7345open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7346/-- A fully explicit raw prism filling for each concrete oriented cyclic family
7347closes the zero-winding filling target. -/
7348theorem zeroWindingCycles_bound_of_explicitRawPrism
7349    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7350    (hexplicit : orientedCyclicFamilies_explicitRawPrism_generate) :
7351    zeroWindingCycles_bound :=
7352  zeroWindingCycles_bound_of_rawPrism
7353    (orientedCyclicFamilies_rawPrism_generate_of_explicit hexplicit)
7354
7355open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7356/-- A free-coordinate prism construction closes the zero-winding filling target. -/
7357theorem zeroWindingCycles_bound_of_freePrism
7358    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7359    (hfree : orientedCyclicFamilies_freePrism_generate) :
7360    zeroWindingCycles_bound :=
7361  zeroWindingCycles_bound_of_explicitRawPrism
7362    (orientedCyclicFamilies_explicitRawPrism_generate_of_freePrism hfree)
7363
7364open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7365/-- A raw prism filling for each concrete oriented cyclic family is enough for
7366the final Mathlib circle H₁ computation. -/
7367theorem circleH1ZIsoInt_of_rawPrism
7368    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7369    (hraw : orientedCyclicFamilies_rawPrism_generate) :
7370    MathlibCohomologyBridge.circleH1ZIsoInt :=
7371  circleH1ZIsoInt_of_orientedCyclicFamilies
7372    (orientedCyclicFamilies_boundary_generate_of_rawPrism hraw)
7373
7374open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7375/-- A fully explicit raw prism filling for each concrete oriented cyclic family
7376is enough for the final Mathlib circle H₁ computation. -/
7377theorem circleH1ZIsoInt_of_explicitRawPrism
7378    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7379    (hexplicit : orientedCyclicFamilies_explicitRawPrism_generate) :
7380    MathlibCohomologyBridge.circleH1ZIsoInt :=
7381  circleH1ZIsoInt_of_rawPrism
7382    (orientedCyclicFamilies_rawPrism_generate_of_explicit hexplicit)
7383
7384open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7385/-- A free-coordinate prism construction is enough for the final Mathlib circle
7386H₁ computation. -/
7387theorem circleH1ZIsoInt_of_freePrism
7388    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7389    (hfree : orientedCyclicFamilies_freePrism_generate) :
7390    MathlibCohomologyBridge.circleH1ZIsoInt :=
7391  circleH1ZIsoInt_of_explicitRawPrism
7392    (orientedCyclicFamilies_explicitRawPrism_generate_of_freePrism hfree)
7393
7394open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7395/-- The path-cone residual correction target closes the zero-winding filling
7396theorem. -/
7397theorem zeroWindingCycles_bound_of_pathConeCorrection
7398    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7399    (hcorr : orientedCyclicFamilies_pathConeCorrection_generate) :
7400    zeroWindingCycles_bound :=
7401  zeroWindingCycles_bound_of_freePrism
7402    (orientedCyclicFamilies_freePrism_generate_of_pathConeCorrection hcorr)
7403
7404open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7405/-- The path-cone residual correction target is enough for the full Mathlib circle
7406`H₁(S¹;ℤ) ≅ ℤ` computation. -/
7407theorem circleH1ZIsoInt_of_pathConeCorrection
7408    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex]
7409    (hcorr : orientedCyclicFamilies_pathConeCorrection_generate) :
7410    MathlibCohomologyBridge.circleH1ZIsoInt :=
7411  circleH1ZIsoInt_of_freePrism
7412    (orientedCyclicFamilies_freePrism_generate_of_pathConeCorrection hcorr)
7413
7414open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7415/-- Integer-valued winding together with filling of zero-winding cycles gives the
7416fully concrete boundary-generation statement.  For a cycle `z`, choose the
7417integer `n` equal to its winding, subtract `n` times the fundamental cycle, and
7418fill the resulting zero-winding cycle. -/
7419theorem fundamentalCycle_boundary_generates_of_integral_winding_of_zeroWinding_bounds
7420    (hint : cycleWinding_integral) (hzero : zeroWindingCycles_bound) :
7421    fundamentalCycle_boundary_generates := by
7422  intro z
7423  obtain ⟨n, hn⟩ := hint z
7424  let r : sphereOneSingularIntChainComplex.cycles 1 :=
7425    z - ModuleCat.Hom.hom fundamentalCycle n
7426  have hrw : cycleWinding r = 0 := by
7427    unfold r
7428    unfold cycleWinding at hn ⊢
7429    rw [map_sub]
7430    have hfund : ModuleCat.Hom.hom
7431        (sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap)
7432        (ModuleCat.Hom.hom fundamentalCycle n) = (n : ℝ) := by
7433      change ModuleCat.Hom.hom
7434          (fundamentalCycle ≫ sphereOneSingularIntChainComplex.iCycles 1 ≫ windingChainMap) n =
7435        (n : ℝ)
7436      rw [fundamentalCycle, HomologicalComplex.liftCycles_i_assoc]
7437      rw [windingChainMap_fundamental]
7438      simp [LinearMap.toSpanSingleton_apply]
7439    rw [hfund, hn]
7440    abel
7441  obtain ⟨b, hb⟩ := hzero r hrw
7442  refine ⟨n, b, ?_⟩
7443  unfold r at hb
7444  rw [← hb]
7445  abel
7446
7447open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7448/-- With integer-valued winding already proved, the two remaining geometric
7449formulations are equivalent: zero-winding cycles bound iff every cycle is a
7450boundary plus an integer multiple of the fundamental cycle. -/
7451theorem zeroWindingCycles_bound_iff_fundamentalCycle_boundary_generates :
7452    zeroWindingCycles_bound ↔ fundamentalCycle_boundary_generates := by
7453  constructor
7454  · intro hzero
7455    exact fundamentalCycle_boundary_generates_of_integral_winding_of_zeroWinding_bounds
7456      (by
7457        classical
7458        exact cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoDirectedCycles
7459          freeBoundaryKernel_decomposesIntoDirectedCycles_holds)
7460      hzero
7461  · exact zeroWindingCycles_bound_of_fundamentalCycle_boundary_generates
7462
7463open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7464/-- Zero-winding filling implies the local oriented-family generation target:
7465apply the equivalent global fundamental-cycle generation theorem to the packaged
7466cycle of the oriented family. -/
7467theorem orientedCyclicFamilies_boundary_generate_of_zeroWindingCycles_bound
7468    (hzero : zeroWindingCycles_bound) :
7469    orientedCyclicFamilies_boundary_generate := by
7470  intro T
7471  exact T.boundary_generate_of_zeroWindingCycles_bound hzero
7472
7473open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7474/-- The explicit oriented-family local target is equivalent to zero-winding
7475filling.  This pins the remaining geometric work to one concrete closed-walk
7476filling theorem without changing the final H₁ statement. -/
7477theorem orientedCyclicFamilies_boundary_generate_iff_zeroWindingCycles_bound :
7478    orientedCyclicFamilies_boundary_generate ↔ zeroWindingCycles_bound := by
7479  classical
7480  constructor
7481  · intro hterm
7482    exact zeroWindingCycles_bound_of_orientedCyclicFamilies hterm
7483  · exact orientedCyclicFamilies_boundary_generate_of_zeroWindingCycles_bound
7484
7485open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7486/-- Zero-winding filling gives the fully explicit raw-prism target. -/
7487theorem orientedCyclicFamilies_explicitRawPrism_generate_of_zeroWindingCycles_bound
7488    (hzero : zeroWindingCycles_bound) :
7489    orientedCyclicFamilies_explicitRawPrism_generate :=
7490  orientedCyclicFamilies_explicitRawPrism_generate_of_boundary_generate
7491    (orientedCyclicFamilies_boundary_generate_of_zeroWindingCycles_bound hzero)
7492
7493open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7494/-- The fully explicit raw-prism target is equivalent to zero-winding filling. -/
7495theorem orientedCyclicFamilies_explicitRawPrism_generate_iff_zeroWindingCycles_bound
7496    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex] :
7497    orientedCyclicFamilies_explicitRawPrism_generate ↔ zeroWindingCycles_bound := by
7498  constructor
7499  · intro hexplicit
7500    exact zeroWindingCycles_bound_of_explicitRawPrism hexplicit
7501  · exact orientedCyclicFamilies_explicitRawPrism_generate_of_zeroWindingCycles_bound
7502
7503open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7504/-- The free-coordinate prism target named in the Phase 5 checklist is equivalent
7505to the actual zero-winding filling theorem.  This uses the raw/free `C₂`
7506transport, so the only remaining gap is the geometric filling construction
7507itself. -/
7508theorem orientedCyclicFamilies_freePrism_generate_iff_zeroWindingCycles_bound
7509    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex] :
7510    orientedCyclicFamilies_freePrism_generate ↔ zeroWindingCycles_bound := by
7511  constructor
7512  · intro hfree
7513    exact
7514      (orientedCyclicFamilies_explicitRawPrism_generate_iff_zeroWindingCycles_bound).mp
7515        (orientedCyclicFamilies_explicitRawPrism_generate_of_freePrism hfree)
7516  · intro hzero
7517    exact orientedCyclicFamilies_freePrism_generate_of_explicitRawPrism
7518      (orientedCyclicFamilies_explicitRawPrism_generate_of_zeroWindingCycles_bound hzero)
7519
7520open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7521/-- The packaged raw-prism target is also equivalent to zero-winding filling. -/
7522theorem orientedCyclicFamilies_rawPrism_generate_iff_zeroWindingCycles_bound
7523    [DecidableEq SingularZeroSimplex] [DecidableEq SingularOneSimplex] :
7524    orientedCyclicFamilies_rawPrism_generate ↔ zeroWindingCycles_bound := by
7525  constructor
7526  · intro hraw
7527    exact
7528      (orientedCyclicFamilies_explicitRawPrism_generate_iff_zeroWindingCycles_bound).mp
7529        (orientedCyclicFamilies_explicitRawPrism_generate_of_rawPrism hraw)
7530  · intro hzero
7531    exact orientedCyclicFamilies_rawPrism_generate_of_explicit
7532      (orientedCyclicFamilies_explicitRawPrism_generate_of_zeroWindingCycles_bound hzero)
7533
7534open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7535/-- Final Mathlib H₁ closure from the two concrete geometric subtargets: integer
7536winding on cycles and filling of zero-winding cycles. -/
7537theorem circleH1ZIsoInt_of_integral_winding_of_zeroWinding_bounds
7538    (hint : cycleWinding_integral) (hzero : zeroWindingCycles_bound) :
7539    MathlibCohomologyBridge.circleH1ZIsoInt :=
7540  circleH1ZIsoInt_of_fundamentalCycle_boundary_generates
7541    (fundamentalCycle_boundary_generates_of_integral_winding_of_zeroWinding_bounds
7542      hint hzero)
7543
7544open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7545/-- Final Mathlib H₁ closure from the abstract directed-cycle decomposition of
7546balanced free edge-flows plus filling of zero-winding cycles. -/
7547theorem circleH1ZIsoInt_of_directedCycles_of_zeroWinding_bounds
7548    (hcycles : freeBoundaryKernel_decomposesIntoDirectedCycles)
7549    (hzero : zeroWindingCycles_bound) :
7550    MathlibCohomologyBridge.circleH1ZIsoInt :=
7551  circleH1ZIsoInt_of_integral_winding_of_zeroWinding_bounds
7552    (cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoDirectedCycles hcycles)
7553    hzero
7554
7555open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7556/-- Integer-valued winding on all singular `1`-cycles, with no finite-flow
7557hypothesis left.  The proof is the unconditional directed-cycle decomposition
7558above, supplied with classical decidable equality for the actual singular
7559simplices. -/
7560theorem cycleWinding_integral_unconditional : cycleWinding_integral := by
7561  classical
7562  exact cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoDirectedCycles
7563    freeBoundaryKernel_decomposesIntoDirectedCycles_holds
7564
7565open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7566/-- Final Mathlib H₁ closure after discharging the finite-flow half
7567unconditionally.  The only remaining geometric input is the zero-winding filling
7568theorem `zeroWindingCycles_bound`. -/
7569theorem circleH1ZIsoInt_of_zeroWinding_bounds
7570    (hzero : zeroWindingCycles_bound) :
7571    MathlibCohomologyBridge.circleH1ZIsoInt :=
7572  circleH1ZIsoInt_of_integral_winding_of_zeroWinding_bounds
7573    cycleWinding_integral_unconditional hzero
7574
7575open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7576/-- The real finite-flow theorem plus injectivity of the homology-level winding
7577map computes the circle's first singular homology as `ℤ`.  This bypasses the old
7578one-scalar cyclic-edge-list interface: the finite-flow half is already closed by
7579the directed-cycle decomposition. -/
7580theorem circleH1ZIsoInt_of_windingHomologyMap_mono
7581    (hmono : Mono windingHomologyMap) :
7582    MathlibCohomologyBridge.circleH1ZIsoInt :=
7583  circleH1ZIsoInt_of_zeroWinding_bounds
7584    (zeroWindingCycles_bound_of_windingHomologyMap_mono hmono)
7585
7586open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7587/-- Injectivity of the homology-level winding map is enough to build the Mathlib
7588circle-linking backend required by the strict T8 replacement. -/
7589theorem mathlibCircleLinkingBackend_of_windingHomologyMap_mono
7590    (hmono : Mono windingHomologyMap) :
7591    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
7592  MathlibCohomologyBridge.mathlibCircleLinkingBackend_of_circleH1ZIsoInt
7593    (circleH1ZIsoInt_of_windingHomologyMap_mono hmono)
7594
7595open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7596/-- Final Mathlib H₁ closure from the two remaining concrete theorem obligations:
7597finite cyclic edge-list decomposition of balanced free edge-flows, and filling of
7598zero-winding cycles. -/
7599theorem circleH1ZIsoInt_of_cyclicEdgeLists_of_zeroWinding_bounds
7600    (hcycles : freeBoundaryKernel_decomposesIntoCyclicEdgeLists)
7601    (hzero : zeroWindingCycles_bound) :
7602    MathlibCohomologyBridge.circleH1ZIsoInt :=
7603  circleH1ZIsoInt_of_integral_winding_of_zeroWinding_bounds
7604    (cycleWinding_integral_of_freeBoundaryKernel_decomposesIntoCyclicEdgeLists hcycles)
7605    hzero
7606
7607open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7608/-- Final Mathlib H₁ closure from the support-decreasing cyclic extraction step
7609and filling of zero-winding cycles. -/
7610theorem circleH1ZIsoInt_of_extractionStep_of_zeroWinding_bounds
7611    (hstep : cyclicEdgeListExtractionStep)
7612    (hzero : zeroWindingCycles_bound) :
7613    MathlibCohomologyBridge.circleH1ZIsoInt :=
7614  circleH1ZIsoInt_of_cyclicEdgeLists_of_zeroWinding_bounds
7615    (freeBoundaryKernel_decomposesIntoCyclicEdgeLists_of_extractionStep hstep)
7616    hzero
7617
7618open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7619/-- Final Mathlib H₁ closure from the exact remaining finite-flow target and
7620zero-winding filling.  All zero/singleton/loop-edge extraction branches are
7621already closed; the only finite-flow input here is the support-cardinality `> 1`
7622repeated-vertex extraction theorem. -/
7623theorem circleH1ZIsoInt_of_largeSupport_of_zeroWinding_bounds
7624    (hlarge : largeSupportCyclicEdgeListExtractionStep)
7625    (hzero : zeroWindingCycles_bound) :
7626    MathlibCohomologyBridge.circleH1ZIsoInt :=
7627  circleH1ZIsoInt_of_cyclicEdgeLists_of_zeroWinding_bounds
7628    (freeBoundaryKernel_decomposesIntoCyclicEdgeLists_of_largeSupport hlarge)
7629    hzero
7630
7631open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7632/-- The same concrete cyclic-edge-list and zero-winding filling obligations also
7633produce the nonzero H₁ target used by the Mathlib linking backend. -/
7634theorem circleH1ZNonzero_of_cyclicEdgeLists_of_zeroWinding_bounds
7635    (hcycles : freeBoundaryKernel_decomposesIntoCyclicEdgeLists)
7636    (hzero : zeroWindingCycles_bound) :
7637    MathlibCohomologyBridge.circleH1ZNonzero :=
7638  MathlibCohomologyBridge.circleH1ZNonzero_of_iso_int
7639    (circleH1ZIsoInt_of_cyclicEdgeLists_of_zeroWinding_bounds hcycles hzero)
7640
7641open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7642/-- Nonzero H₁ after the finite-flow half has been discharged unconditionally.
7643Only `zeroWindingCycles_bound` remains. -/
7644theorem circleH1ZNonzero_of_zeroWinding_bounds
7645    (hzero : zeroWindingCycles_bound) :
7646    MathlibCohomologyBridge.circleH1ZNonzero :=
7647  MathlibCohomologyBridge.circleH1ZNonzero_of_iso_int
7648    (circleH1ZIsoInt_of_zeroWinding_bounds hzero)
7649
7650open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7651/-- The support-decreasing cyclic extraction step and zero-winding filling also
7652produce the nonzero H₁ target used by the Mathlib linking backend. -/
7653theorem circleH1ZNonzero_of_extractionStep_of_zeroWinding_bounds
7654    (hstep : cyclicEdgeListExtractionStep)
7655    (hzero : zeroWindingCycles_bound) :
7656    MathlibCohomologyBridge.circleH1ZNonzero :=
7657  MathlibCohomologyBridge.circleH1ZNonzero_of_iso_int
7658    (circleH1ZIsoInt_of_extractionStep_of_zeroWinding_bounds hstep hzero)
7659
7660open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7661/-- The exact two remaining targets also produce the nonzero H₁ backend target. -/
7662theorem circleH1ZNonzero_of_largeSupport_of_zeroWinding_bounds
7663    (hlarge : largeSupportCyclicEdgeListExtractionStep)
7664    (hzero : zeroWindingCycles_bound) :
7665    MathlibCohomologyBridge.circleH1ZNonzero :=
7666  MathlibCohomologyBridge.circleH1ZNonzero_of_iso_int
7667    (circleH1ZIsoInt_of_largeSupport_of_zeroWinding_bounds hlarge hzero)
7668
7669open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7670/-- The concrete cyclic-edge-list and zero-winding filling obligations build the
7671Mathlib circle-linking backend required by the strict T8 replacement. -/
7672theorem mathlibCircleLinkingBackend_of_cyclicEdgeLists_of_zeroWinding_bounds
7673    (hcycles : freeBoundaryKernel_decomposesIntoCyclicEdgeLists)
7674    (hzero : zeroWindingCycles_bound) :
7675    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
7676  MathlibCohomologyBridge.mathlibCircleLinkingBackend_of_circleH1ZIsoInt
7677    (circleH1ZIsoInt_of_cyclicEdgeLists_of_zeroWinding_bounds hcycles hzero)
7678
7679open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7680/-- Mathlib circle-linking backend after the finite-flow half has been discharged
7681unconditionally.  Only `zeroWindingCycles_bound` remains. -/
7682theorem mathlibCircleLinkingBackend_of_zeroWinding_bounds
7683    (hzero : zeroWindingCycles_bound) :
7684    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
7685  MathlibCohomologyBridge.mathlibCircleLinkingBackend_of_circleH1ZIsoInt
7686    (circleH1ZIsoInt_of_zeroWinding_bounds hzero)
7687
7688open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7689/-- The support-decreasing cyclic extraction step and zero-winding filling build
7690the Mathlib circle-linking backend required by the strict T8 replacement. -/
7691theorem mathlibCircleLinkingBackend_of_extractionStep_of_zeroWinding_bounds
7692    (hstep : cyclicEdgeListExtractionStep)
7693    (hzero : zeroWindingCycles_bound) :
7694    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
7695  MathlibCohomologyBridge.mathlibCircleLinkingBackend_of_circleH1ZIsoInt
7696    (circleH1ZIsoInt_of_extractionStep_of_zeroWinding_bounds hstep hzero)
7697
7698open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7699/-- The exact two remaining targets build the Mathlib circle-linking backend
7700required by the strict T8 replacement. -/
7701theorem mathlibCircleLinkingBackend_of_largeSupport_of_zeroWinding_bounds
7702    (hlarge : largeSupportCyclicEdgeListExtractionStep)
7703    (hzero : zeroWindingCycles_bound) :
7704    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
7705  MathlibCohomologyBridge.mathlibCircleLinkingBackend_of_circleH1ZIsoInt
7706    (circleH1ZIsoInt_of_largeSupport_of_zeroWinding_bounds hlarge hzero)
7707
7708/-! ### Unconditional Phase-5 closure
7709
7710The terminal-side correction (`orientedCyclicFamilies_terminalSideCorrection_generate_holds`)
7711and the path-base correction (`orientedCyclicFamilies_pathBaseCorrection_generate_holds`)
7712are both proved with no remaining hypotheses, so the free-coordinate prism target,
7713the zero-winding filling theorem, and the full Mathlib computation
7714`H₁(S¹;ℤ) ≅ ℤ` all hold unconditionally. -/
7715
7716open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7717/-- **The free-coordinate prism generation target holds unconditionally.**  Both
7718correction halves are closed, so every concrete oriented cyclic family bounds the
7719desired free-prism residual. -/
7720theorem orientedCyclicFamilies_freePrism_generate_holds :
7721    orientedCyclicFamilies_freePrism_generate :=
7722  orientedCyclicFamilies_freePrism_generate_of_splitCorrections
7723    orientedCyclicFamilies_terminalSideCorrection_generate_holds
7724    orientedCyclicFamilies_pathBaseCorrection_generate_holds
7725
7726open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7727/-- **Zero-winding cycles bound, unconditionally.**  Every zero-winding singular
7728`1`-cycle on `S¹` is a boundary, via the unconditional free-prism construction. -/
7729theorem zeroWindingCycles_bound_holds : zeroWindingCycles_bound := by
7730  classical
7731  exact (orientedCyclicFamilies_freePrism_generate_iff_zeroWindingCycles_bound).mp
7732    orientedCyclicFamilies_freePrism_generate_holds
7733
7734open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7735/-- **`H₁(S¹;ℤ) ≅ ℤ`, unconditionally.**  Integer-valued winding on cycles is
7736already closed; zero-winding filling is now closed too, so the full Mathlib
7737first-homology computation holds with no remaining hypotheses, axioms, or
7738`sorry`. -/
7739theorem circleH1ZIsoInt_holds : MathlibCohomologyBridge.circleH1ZIsoInt :=
7740  circleH1ZIsoInt_of_zeroWinding_bounds zeroWindingCycles_bound_holds
7741
7742open CategoryTheory.Limits AlgebraicTopology CircleH1Computation in
7743/-- **The Mathlib circle-linking backend exists unconditionally**, as required by
7744the strict T8 dimension replacement. -/
7745theorem mathlibCircleLinkingBackend_holds :
7746    Nonempty MathlibCohomologyBridge.MathlibCircleLinkingBackend :=
7747  mathlibCircleLinkingBackend_of_zeroWinding_bounds zeroWindingCycles_bound_holds
7748
7749end
7750
7751end CircleWindingChain
7752end Foundation
7753end IndisputableMonolith
7754

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