Skip to content
The Lumenary

Formal mathematics laboratory

Lumenary.HomotopyTheory

Homotopy theory

Formal library

  • eckmann_hiltontheoremProved here from basic factsNo axioms
    eckmann_hiltonLean 4Proved here from basic factsFormally verified
    /-- **Eckmann–Hilton.** If a set carries two binary operations `m₁`, `m₂` with units `e₁`, `e₂`
    that satisfy the interchange law `(a ·₂ b) ·₁ (c ·₂ d) = (a ·₁ c) ·₂ (b ·₁ d)`, then the units
    agree, the operations agree, and the operation is commutative. For `πₙ` with `n ≥ 2`,
    concatenation of cubes in two different coordinate directions gives two such operations. -/
    theorem eckmann_hilton {M : Type*} (m₁ m₂ : M → M → M) (e₁ e₂ : M)
        (h₁l : ∀ a, m₁ e₁ a = a) (h₁r : ∀ a, m₁ a e₁ = a)
        (h₂l : ∀ a, m₂ e₂ a = a) (h₂r : ∀ a, m₂ a e₂ = a)
        (interchange : ∀ a b c d, m₁ (m₂ a b) (m₂ c d) = m₂ (m₁ a c) (m₁ b d)) :
        e₁ = e₂ ∧ (∀ a b, m₁ a b = m₂ a b) ∧ (∀ a b, m₁ a b = m₁ b a) := by
      -- the units agree
      have he : e₁ = e₂ :=
        calc e₁ = m₁ e₁ e₁ := (h₁l e₁).symm
          _ = m₁ (m₂ e₂ e₁) (m₂ e₁ e₂) := by rw [h₂l, h₂r]
          _ = m₂ (m₁ e₂ e₁) (m₁ e₁ e₂) := interchange _ _ _ _
          _ = m₂ e₂ e₂ := by rw [h₁r, h₁l]
          _ = e₂ := h₂l e₂
      -- the operations agree
      have hm : ∀ a b, m₁ a b = m₂ a b := fun a b =>
        calc m₁ a b = m₁ (m₂ a e₂) (m₂ e₂ b) := by rw [h₂r, h₂l]
          _ = m₂ (m₁ a e₂) (m₁ e₂ b) := interchange _ _ _ _
          _ = m₂ a b := by rw [← he, h₁r, h₁l]
      refine ⟨he, hm, fun a b => ?_⟩
      -- and the operation is commutative
      calc m₁ a b = m₁ (m₂ e₂ a) (m₂ b e₂) := by rw [h₂l, h₂r]
        _ = m₂ (m₁ e₂ b) (m₁ a e₂) := interchange _ _ _ _
        _ = m₂ b a := by rw [← he, h₁l, h₁r]
        _ = m₁ b a := (hm b a).symm
    Axioms used: No axiomsformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • pi_commtheoremApplies a library theorempropext, Classical.choice, Quot.sound
    pi_commLean 4Applies a library theoremFormally verified
    /-- **Higher homotopy groups are abelian:** `πₙ₊₂(X, x)` is commutative. This uses Mathlib's
    instance `HomotopyGroup.commGroup`, which is built with `EckmannHilton.commGroup` from the
    interchange law for concatenation in two different cube directions. -/
    theorem pi_comm (n : ℕ) (X : Type*) [TopologicalSpace X] (x : X)
        (a b : π_ (n + 2) X x) : a * b = b * a :=
      mul_comm a b
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • pi_onetheoremApplies a library theorempropext, Classical.choice, Quot.sound
    pi_oneLean 4Applies a library theoremFormally verified
    /-- `π₁(X, x)`, defined with cubes, is isomorphic as a group to the fundamental group of loops
    up to homotopy. This applies Mathlib's `HomotopyGroup.pi1MulEquivFundamentalGroup`. -/
    theorem pi_one (X : Type*) [TopologicalSpace X] (x : X) :
        Nonempty (π_ 1 X x ≃* FundamentalGroup X x) :=
      ⟨HomotopyGroup.pi1MulEquivFundamentalGroup⟩
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • loops_of_loopstheoremApplies a library theorempropext, Classical.choice, Quot.sound
    loops_of_loopsLean 4Applies a library theoremFormally verified
    /-- **Loops of loops are higher loops:** the space of `M`-cubes in the space of `N`-cubes of `X`
    is homeomorphic to the space of `(M ⊕ N)`-cubes of `X`. Taking `M` with one element this is the
    statement `Ω(Ωⁿ X) ≅ Ωⁿ⁺¹ X` behind `πₖ(ΩX) ≅ πₖ₊₁(X)`. This applies Mathlib's
    `GenLoop.genLoopGenLoopEquiv`. -/
    theorem loops_of_loops (M N : Type*) (X : Type*) [TopologicalSpace X] (x : X) :
        Nonempty (Ω^ M (Ω^ N X x) GenLoop.const ≃ₜ Ω^ (M ⊕ N) X x) :=
      ⟨GenLoop.genLoopGenLoopEquiv x⟩
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • hopfdefDefinitionpropext, Classical.choice, Quot.sound
    hopfLean 4Formally verified
    /-- The **Hopf map** `ℂ² → ℂ × ℝ ≅ ℝ³`, `(z, w) ↦ (2 z w̄, |z|² - |w|²)`. Restricted to the unit
    sphere `S³ ⊂ ℂ²` it is the Hopf fibration `S³ → S²`. -/
    noncomputable def hopf (p : ℂ × ℂ) : ℂ × ℝ :=
      (2 * p.1 * conj p.2, Complex.normSq p.1 - Complex.normSq p.2)
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • hopf_mem_spheretheoremProved here from basic factspropext, Classical.choice, Quot.sound
    hopf_mem_sphereLean 4Proved here from basic factsFormally verified
    /-- The Hopf map sends `S³` to `S²`: if `|z|² + |w|² = 1` then
    `|2 z w̄|² + (|z|² - |w|²)² = 4|z|²|w|² + (|z|² - |w|²)² = (|z|² + |w|²)² = 1`. -/
    theorem hopf_mem_sphere (z w : ℂ) (h : Complex.normSq z + Complex.normSq w = 1) :
        Complex.normSq (hopf (z, w)).1 + (hopf (z, w)).2 ^ 2 = 1 := by
      simp only [hopf, Complex.normSq_mul, Complex.normSq_conj]
      have h2 : Complex.normSq 2 = 4 := by norm_num [Complex.normSq_apply]
      rw [h2]
      linear_combination (Complex.normSq z + Complex.normSq w + 1) * h
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • hopf_circle_invarianttheoremProved here from basic factspropext, Classical.choice, Quot.sound
    hopf_circle_invariantLean 4Proved here from basic factsFormally verified
    /-- The Hopf map is constant on circles: multiplying `(z, w)` by a unit complex number `λ`
    does not change `hopf (z, w)`, because `λ λ̄ = |λ|² = 1`. -/
    theorem hopf_circle_invariant (l z w : ℂ) (hl : Complex.normSq l = 1) :
        hopf (l * z, l * w) = hopf (z, w) := by
      have hc : l * conj l = 1 := by rw [Complex.mul_conj, hl, Complex.ofReal_one]
      unfold hopf
      ext
      · -- first component: `2 (λz) conj(λw) = 2 z w̄ · λλ̄`
        simp only [map_mul]
        linear_combination (2 * z * conj w) * hc
      · -- second component: `|λz|² - |λw|² = |λ|² (|z|² - |w|²)`
        simp only [Complex.normSq_mul, hl, one_mul]
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • hopf_fibretheoremProved here from basic factspropext, Classical.choice, Quot.sound
    hopf_fibreLean 4Proved here from basic factsFormally verified
    /-- **The fibres of the Hopf map are exactly circles.** If two points `(z, w)` and `(z', w')` of
    `S³` have the same image, then `(z', w') = λ · (z, w)` for a unit complex number `λ`; one can
    take the Hermitian inner product `λ = z' z̄ + w' w̄`. Together with `hopf_circle_invariant`, the
    fibre over each point of `S²` is a great circle of `S³`. -/
    theorem hopf_fibre (z w z' w' : ℂ) (hs : Complex.normSq z + Complex.normSq w = 1)
        (hs' : Complex.normSq z' + Complex.normSq w' = 1) (heq : hopf (z, w) = hopf (z', w')) :
        ∃ l : ℂ, Complex.normSq l = 1 ∧ z' = l * z ∧ w' = l * w := by
      simp only [hopf, Prod.mk.injEq] at heq
      obtain ⟨h1, h2⟩ := heq
      -- the moduli agree
      have hz : Complex.normSq z = Complex.normSq z' := by linarith
      have hw : Complex.normSq w = Complex.normSq w' := by linarith
      -- the same facts as identities of complex numbers
      have e1 : z * conj w = z' * conj w' := by linear_combination h1 / 2
      have e1c : conj z * w = conj z' * w' := by
        have := congrArg conj e1
        simpa [map_mul, mul_comm] using this
      have mz : z * conj z = (Complex.normSq z : ℂ) := Complex.mul_conj z
      have mw : w * conj w = (Complex.normSq w : ℂ) := Complex.mul_conj w
      have mz' : z' * conj z' = (Complex.normSq z' : ℂ) := Complex.mul_conj z'
      have mw' : w' * conj w' = (Complex.normSq w' : ℂ) := Complex.mul_conj w'
      have cz : (Complex.normSq z : ℂ) = Complex.normSq z' := by rw [hz]
      have cw : (Complex.normSq w : ℂ) = Complex.normSq w' := by rw [hw]
      have cs : (Complex.normSq z : ℂ) + Complex.normSq w = 1 := by
        rw [← Complex.ofReal_add, hs, Complex.ofReal_one]
      -- the circle parameter is the Hermitian inner product of the two points
      set l := z' * conj z + w' * conj w with hl
      have hz' : z' = l * z := by
        rw [hl]
        linear_combination (-z') * mz + (-w') * e1 + (-z') * mw' + z' * cw + (-z') * cs
      have hw' : w' = l * w := by
        rw [hl]
        linear_combination (-z') * e1c + (-w') * mz' + (-w') * mw + w' * cz + (-w') * cs
      refine ⟨l, ?_, hz', hw'⟩
      -- `1 = |z'|² + |w'|² = |λ|² (|z|² + |w|²) = |λ|²`
      have k1 : Complex.normSq z' = Complex.normSq l * Complex.normSq z := by
        rw [← Complex.normSq_mul, ← hz']
      have k2 : Complex.normSq w' = Complex.normSq l * Complex.normSq w := by
        rw [← Complex.normSq_mul, ← hw']
      linear_combination (-Complex.normSq l) * hs - k1 - k2 + hs'
    Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
  • bijective_of_exacttheoremProved here from basic factspropext
    bijective_of_exactLean 4Proved here from basic factsFormally verified
    /-- **An exact sequence flanked by trivial groups.** If `A → B → C → D` is exact at `B` and at
    `C` (kernel = image) and `A`, `D` are trivial, then `g : B → C` is bijective. In the long exact
    sequence of the Hopf fibration, `π₃(S¹) → π₃(S³) → π₃(S²) → π₂(S¹)` with `πₖ(S¹) = 0` for
    `k ≥ 2`, this gives `π₃(S²) ≅ π₃(S³) ≅ ℤ`. -/
    theorem bijective_of_exact {A B C D : Type*} [Group A] [Group B] [Group C] [Group D]
        [Subsingleton A] [Subsingleton D] (f : A →* B) (g : B →* C) (k : C →* D)
        (exactB : ∀ b, g b = 1 ↔ ∃ a, f a = b) (exactC : ∀ c, k c = 1 ↔ ∃ b, g b = c) :
        Function.Bijective g := by
      constructor
      · -- injective: the kernel of `g` is the image of the trivial group `A`
        intro b₁ b₂ h
        have hker : g (b₁⁻¹ * b₂) = 1 := by rw [map_mul, map_inv, h, inv_mul_cancel]
        obtain ⟨a, ha⟩ := (exactB _).1 hker
        have ha1 : a = 1 := Subsingleton.elim a 1
        rw [ha1, map_one] at ha
        -- `1 = b₁⁻¹ * b₂`, so `b₁ = b₂`
        exact inv_mul_eq_one.mp ha.symm
      · -- surjective: everything is in the kernel of the map to the trivial group `D`
        intro c
        exact (exactC c).1 (Subsingleton.elim _ _)
    Axioms used: propextformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor

Formal exercises

Each exercise contains a sorry for you to replace. Open it in the Lean web editor, or clone the repository and run lake build.

eckmann_hilton_unitssorry × 1Try it in the Lean web editor
/-- The first step of the Eckmann–Hilton argument: the two units agree.
Hint: `e₁ = m₁ e₁ e₁ = m₁ (m₂ e₂ e₁) (m₂ e₁ e₂)`; now use the interchange law and the unit laws
once more. A `calc` block works well. -/
theorem eckmann_hilton_units {M : Type*} (m₁ m₂ : M → M → M) (e₁ e₂ : M)
    (h₁l : ∀ a, m₁ e₁ a = a) (h₁r : ∀ a, m₁ a e₁ = a)
    (h₂l : ∀ a, m₂ e₂ a = a) (h₂r : ∀ a, m₂ a e₂ = a)
    (interchange : ∀ a b c d, m₁ (m₂ a b) (m₂ c d) = m₂ (m₁ a c) (m₁ b d)) :
    e₁ = e₂ := by
  sorry
Show the compiled solution
eckmann_hiltonLean 4Proved here from basic factsFormally verified
/-- **Eckmann–Hilton.** If a set carries two binary operations `m₁`, `m₂` with units `e₁`, `e₂`
that satisfy the interchange law `(a ·₂ b) ·₁ (c ·₂ d) = (a ·₁ c) ·₂ (b ·₁ d)`, then the units
agree, the operations agree, and the operation is commutative. For `πₙ` with `n ≥ 2`,
concatenation of cubes in two different coordinate directions gives two such operations. -/
theorem eckmann_hilton {M : Type*} (m₁ m₂ : M → M → M) (e₁ e₂ : M)
    (h₁l : ∀ a, m₁ e₁ a = a) (h₁r : ∀ a, m₁ a e₁ = a)
    (h₂l : ∀ a, m₂ e₂ a = a) (h₂r : ∀ a, m₂ a e₂ = a)
    (interchange : ∀ a b c d, m₁ (m₂ a b) (m₂ c d) = m₂ (m₁ a c) (m₁ b d)) :
    e₁ = e₂ ∧ (∀ a b, m₁ a b = m₂ a b) ∧ (∀ a b, m₁ a b = m₁ b a) := by
  -- the units agree
  have he : e₁ = e₂ :=
    calc e₁ = m₁ e₁ e₁ := (h₁l e₁).symm
      _ = m₁ (m₂ e₂ e₁) (m₂ e₁ e₂) := by rw [h₂l, h₂r]
      _ = m₂ (m₁ e₂ e₁) (m₁ e₁ e₂) := interchange _ _ _ _
      _ = m₂ e₂ e₂ := by rw [h₁r, h₁l]
      _ = e₂ := h₂l e₂
  -- the operations agree
  have hm : ∀ a b, m₁ a b = m₂ a b := fun a b =>
    calc m₁ a b = m₁ (m₂ a e₂) (m₂ e₂ b) := by rw [h₂r, h₂l]
      _ = m₂ (m₁ a e₂) (m₁ e₂ b) := interchange _ _ _ _
      _ = m₂ a b := by rw [← he, h₁r, h₁l]
  refine ⟨he, hm, fun a b => ?_⟩
  -- and the operation is commutative
  calc m₁ a b = m₁ (m₂ e₂ a) (m₂ b e₂) := by rw [h₂l, h₂r]
    _ = m₂ (m₁ e₂ b) (m₁ a e₂) := interchange _ _ _ _
    _ = m₂ b a := by rw [← he, h₁l, h₁r]
    _ = m₁ b a := (hm b a).symm
Axioms used: No axiomsformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor
hopf_circle_invariantsorry × 1Try it in the Lean web editor
/-- Show that the Hopf map is constant on the circle through `(z, w)`.
Hint: `Complex.mul_conj l : l * conj l = ↑(Complex.normSq l)`. After `unfold Lumenary.HomotopyTheory.hopf`
and `ext`, the first component is a `linear_combination` and the second is `Complex.normSq_mul`. -/
theorem hopf_circle_invariant (l z w : ℂ) (hl : Complex.normSq l = 1) :
    Lumenary.HomotopyTheory.hopf (l * z, l * w) = Lumenary.HomotopyTheory.hopf (z, w) := by
  sorry
Show the compiled solution
hopf_circle_invariantLean 4Proved here from basic factsFormally verified
/-- The Hopf map is constant on circles: multiplying `(z, w)` by a unit complex number `λ`
does not change `hopf (z, w)`, because `λ λ̄ = |λ|² = 1`. -/
theorem hopf_circle_invariant (l z w : ℂ) (hl : Complex.normSq l = 1) :
    hopf (l * z, l * w) = hopf (z, w) := by
  have hc : l * conj l = 1 := by rw [Complex.mul_conj, hl, Complex.ofReal_one]
  unfold hopf
  ext
  · -- first component: `2 (λz) conj(λw) = 2 z w̄ · λλ̄`
    simp only [map_mul]
    linear_combination (2 * z * conj w) * hc
  · -- second component: `|λz|² - |λw|² = |λ|² (|z|² - |w|²)`
    simp only [Complex.normSq_mul, hl, one_mul]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/HomotopyTheory.leanTry it in the Lean web editor