Clifford project

2. Roots of unity🔗

This section defines roots of unity and proves various basic facts about them. Throughout this section we assume that d ≥ 1.

Lean code-- This instance is referred to later, needs naming variable (d : ℕ) [hnezero : NeZero d]
Lemma2.1
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Definition 2.2
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

d is invertible in ℂ.

Proof for Lemma 2.1
uses 0

The inverse of d exists since d ∈ ℕ and d ≠ 0.

Lean code for Lemma2.1lemma d_invertible : IsUnit (d : ℂ) := d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ ¬d = 0 All goals completed! 🐙

Define the primitive d-th root of unity.

Definition2.2
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0
Used by 3
Reverse dependency previews
Preview
Definition 4.5
Loading preview
Reverse dependency preview content is loaded from the rendered-fragment cache.
✓L∃∀N

Let ω = \exp(2πi/d) be the primitive d-th root of unity.

Lean code for Definition2.2noncomputable def ω : ℂˣ := .mk (Complex.exp (2 * Real.pi * Complex.I / d)) (Complex.exp (- 2 * Real.pi * Complex.I / d)) (d:ℕhnezero:NeZero d⊢ Complex.exp (2 * ↑Real.pi * Complex.I / ↑d) * Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d) = 1 d:ℕhnezero:NeZero d⊢ Complex.exp (2 * ↑Real.pi * Complex.I / ↑d + -2 * ↑Real.pi * Complex.I / ↑d) = 1; d:ℕhnezero:NeZero d⊢ Complex.exp (2 * ↑Real.pi * Complex.I / ↑d + -(2 * ↑Real.pi * Complex.I) / ↑d) = 1; Try this: [apply] ring_nf The `ring` tactic failed to close the goal. Use `ring_nf` to obtain a normal form. Note that `ring` works primarily in *commutative* rings. If you have a noncommutative ring, abelian group or module, consider using `noncomm_ring`, `abel` or `module` instead.d:ℕhnezero:NeZero d⊢ Complex.exp 0 = 1; All goals completed! 🐙) (d:ℕhnezero:NeZero d⊢ Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d) * Complex.exp (2 * ↑Real.pi * Complex.I / ↑d) = 1 d:ℕhnezero:NeZero d⊢ Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d + 2 * ↑Real.pi * Complex.I / ↑d) = 1; d:ℕhnezero:NeZero d⊢ Complex.exp (-(2 * ↑Real.pi * Complex.I) / ↑d + 2 * ↑Real.pi * Complex.I / ↑d) = 1; Try this: [apply] ring_nf The `ring` tactic failed to close the goal. Use `ring_nf` to obtain a normal form. Note that `ring` works primarily in *commutative* rings. If you have a noncommutative ring, abelian group or module, consider using `noncomm_ring`, `abel` or `module` instead.d:ℕhnezero:NeZero d⊢ Complex.exp 0 = 1; All goals completed! 🐙)

Some basic lemmas about \omega

Lemma2.3
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

When d = 1, \omega = 1

Lean code for Lemma2.3@[simp] lemma omega_one : (ω 1) = 1 := ⊢ ω 1 = 1 ⊢ ↑(ω 1) = ↑1; ⊢ ↑{ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑1), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑1), val_inv := ⋯, inv_val := ⋯ } = ↑1; All goals completed! 🐙; omit [NeZero d] in @[simp] lemma omega_one' (hd : d = 1) : ω d = 1 := d:ℕhd:d = 1⊢ ω d = 1 d:ℕhd:d = 1⊢ ω 1 = 1; All goals completed! 🐙
Lean codeomit [NeZero d] in lemma omega_val_pow_commutes (i : ℕ) : ((ω d) ^ i).val = (ω d).val ^ i := d:ℕi:ℕ⊢ ↑(ω d ^ i) = ↑(ω d) ^ i All goals completed! 🐙
Lemma2.4
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

ω^d = 1.

Proof for Lemma 2.4
uses 0

ω^d = (\exp(2πi/d))^d = \exp(d(2πi/d)) = \exp(2πi) = 1 where we could cancel d since d ≠ 0.

Lean code for Lemma2.4omit [NeZero d] in @[simp] lemma omega_pow_d_eq_one : (ω d)^d = 1 := d:ℕ⊢ ω d ^ d = 1 d:ℕ⊢ { val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ d = 1; d:ℕ⊢ ↑({ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ d) = ↑1; d:ℕ⊢ Complex.exp (2 * ↑Real.pi * Complex.I / ↑d) ^ d = 1 d:ℕ⊢ Complex.exp (↑d * (2 * ↑Real.pi * Complex.I / ↑d)) = 1; d:ℕhd:d = 0⊢ Complex.exp (↑d * (2 * ↑Real.pi * Complex.I / ↑d)) = 1d:ℕhd:¬d = 0⊢ Complex.exp (↑d * (2 * ↑Real.pi * Complex.I / ↑d)) = 1 d:ℕhd:d = 0⊢ Complex.exp (↑d * (2 * ↑Real.pi * Complex.I / ↑d)) = 1 d:ℕhd:d = 0⊢ Complex.exp (↑0 * (2 * ↑Real.pi * Complex.I / ↑0)) = 1; All goals completed! 🐙 d:ℕhd:¬d = 0⊢ Complex.exp (↑d * (2 * ↑Real.pi * Complex.I / ↑d)) = 1 d:ℕhd:¬d = 0⊢ Complex.exp (↑d * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2) = 1; calc Complex.exp (↑d * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2) = Complex.exp (↑d * (↑d)⁻¹ * ↑Real.pi * Complex.I * 2) := d:ℕhd:¬d = 0⊢ Complex.exp (↑d * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2) = Complex.exp (↑d * (↑d)⁻¹ * ↑Real.pi * Complex.I * 2) All goals completed! 🐙 _ = Complex.exp (↑Real.pi * Complex.I * 2) := d:ℕhd:¬d = 0⊢ Complex.exp (↑d * (↑d)⁻¹ * ↑Real.pi * Complex.I * 2) = Complex.exp (↑Real.pi * Complex.I * 2) d:ℕhd:¬d = 0⊢ ↑d ≠ 0; d:ℕhd:¬d = 0⊢ ¬d = 0; All goals completed! 🐙 _ = 1 := d:ℕhd:¬d = 0⊢ Complex.exp (↑Real.pi * Complex.I * 2) = 1 All goals completed! 🐙; omit [NeZero d] in @[simp] lemma omega_val_pow_d_eq_one : ((ω d).val) ^ d = 1 := d:ℕ⊢ ↑(ω d) ^ d = 1 d:ℕ⊢ ↑1 = 1; All goals completed! 🐙
Lemma2.5
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

Let i ∈ ℤ, then \left(\omega^{-1}\right)^i = \omega^{d - i}

Lean code for Lemma2.5omit [NeZero d] in lemma omega_pow_of_inv (i : ℤ) : (ω d)⁻¹ ^ i = (ω d) ^ (-i) := d:ℕi:ℤ⊢ (ω d)⁻¹ ^ i = ω d ^ (-i) d:ℕi:ℤ⊢ (ω d)⁻¹ ^ i = (ω d ^ i)⁻¹; All goals completed! 🐙
Lemma2.6
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

Let i ∈ ℤ_d, then \left(\omega^{i}\right)^{-1} = \omega^{-i}

Lean code for Lemma2.6lemma omega_inv_pow (i : ZMod d) : ((ω d) ^ i.val)⁻¹ = (ω d) ^ (-i).val := d:ℕhnezero:NeZero di:ZMod d⊢ (ω d ^ i.val)⁻¹ = ω d ^ (-i).val d:ℕhnezero:NeZero di:ZMod d⊢ (ω d)⁻¹ ^ i.val = ω d ^ (-i).val; d:ℕhnezero:NeZero di:ZMod d⊢ { val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ }⁻¹ ^ i.val = { val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ (-i).val; d:ℕhnezero:NeZero di:ZMod d⊢ ↑({ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ }⁻¹ ^ i.val) = ↑({ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ (-i).val); d:ℕhnezero:NeZero di:ZMod d⊢ Complex.exp (-(2 * ↑Real.pi * Complex.I) / ↑d) ^ i.val = Complex.exp (2 * ↑Real.pi * Complex.I / ↑d) ^ (-i).val; d:ℕhnezero:NeZero di:ZMod d⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(-i).val * (2 * ↑Real.pi * Complex.I / ↑d)); d:ℕhnezero:NeZero di:ZMod d⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(if i = 0 then 0 else d - i.val) * (2 * ↑Real.pi * Complex.I / ↑d)); d:ℕhnezero:NeZero di:ZMod dhi:i = 0⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(if i = 0 then 0 else d - i.val) * (2 * ↑Real.pi * Complex.I / ↑d))d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(if i = 0 then 0 else d - i.val) * (2 * ↑Real.pi * Complex.I / ↑d)) d:ℕhnezero:NeZero di:ZMod dhi:i = 0⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(if i = 0 then 0 else d - i.val) * (2 * ↑Real.pi * Complex.I / ↑d)) d:ℕhnezero:NeZero di:ZMod dhi:i = 0⊢ Complex.exp (↑(ZMod.val 0) * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(if 0 = 0 then 0 else d - ZMod.val 0) * (2 * ↑Real.pi * Complex.I / ↑d)); All goals completed! 🐙 d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑(if i = 0 then 0 else d - i.val) * (2 * ↑Real.pi * Complex.I / ↑d)) d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (↑i.val * (-(2 * ↑Real.pi * Complex.I) / ↑d)) = Complex.exp (↑d * (2 * ↑Real.pi * Complex.I / ↑d) - ↑i.val * (2 * ↑Real.pi * Complex.I / ↑d))d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (-(↑i.val * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2)) = Complex.exp (-(↑i.val * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2) + ↑Real.pi * Complex.I * ↑d * (↑d)⁻¹ * 2)d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (-(↑i.val * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2)) = Complex.exp (-(↑i.val * ↑Real.pi * Complex.I * (↑d)⁻¹ * 2)) * Complex.exp (↑Real.pi * Complex.I * ↑d * (↑d)⁻¹ * 2)d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (↑Real.pi * Complex.I * ↑d * (↑d)⁻¹ * 2) = 1d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (2 * (↑Real.pi * Complex.I * (↑d * (↑d)⁻¹))) = 1d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ Complex.exp (2 * (↑Real.pi * Complex.I)) = 1d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ i.val ≤ dd:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; d:ℕhnezero:NeZero di:ZMod dhi:¬i = 0⊢ (i = 0) = False; All goals completed! 🐙 lemma omega_inv_pow_val (i : ZMod d) : ((ω d).val ^ i.val)⁻¹ = (ω d).val ^ (-i).val := d:ℕhnezero:NeZero di:ZMod d⊢ (↑(ω d) ^ i.val)⁻¹ = ↑(ω d) ^ (-i).val calc ((ω d).val ^ i.val)⁻¹ = (((ω d) ^ i.val)⁻¹).val := d:ℕhnezero:NeZero di:ZMod d⊢ (↑(ω d) ^ i.val)⁻¹ = ↑(ω d ^ i.val)⁻¹ All goals completed! 🐙 _ = ((ω d) ^ (-i).val).val := d:ℕhnezero:NeZero di:ZMod d⊢ ↑(ω d ^ i.val)⁻¹ = ↑(ω d ^ (-i).val) All goals completed! 🐙 _ = (ω d).val ^ (-i).val := d:ℕhnezero:NeZero di:ZMod d⊢ ↑(ω d ^ (-i).val) = ↑(ω d) ^ (-i).val All goals completed! 🐙
Lemma2.7
uses 0used by 0✓L∃∀N

For z ∈ \mathbb{C}, let z^* denote the usual complex conjugate of z. Then \omega^* = \omega^{-1}

Lean code for Lemma2.7omit [NeZero d] in @[simp] lemma omega_star : star ((ω d).val) = (ω d).val⁻¹ := d:ℕ⊢ star ↑(ω d) = (↑(ω d))⁻¹ d:ℕ⊢ star ↑(ω d) = (starRingEnd ℂ) ↑(ω d) * ↑(Complex.normSq ↑(ω d))⁻¹; d:ℕ⊢ Complex.normSq ↑(ω d) = 1; d:ℕ⊢ Complex.normSq ↑{ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } = 1; d:ℕ⊢ Complex.normSq (Complex.exp (2 * ↑Real.pi * Complex.I / ↑d)) = 1; d:ℕ⊢ Real.exp (2 * ↑Real.pi * Complex.I / ↑d).re ^ 2 = 1; All goals completed! 🐙 omit [NeZero d] in @[simp] lemma omega_pow_star (i : ℕ) : star (((ω d).val) ^ i) = ((ω d).val ^ i)⁻¹ := d:ℕi:ℕ⊢ star (↑(ω d) ^ i) = (↑(ω d) ^ i)⁻¹ All goals completed! 🐙;
Lean codelemma declaration uses `sorry`order_omega : orderOf (ω d) = d := d:ℕhnezero:NeZero d⊢ orderOf (ω d) = d d:ℕhnezero:NeZero d⊢ ω d ^ d = 1 ∧ ∀ m < d, 0 < m → ω d ^ m ≠ 1d:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero d⊢ ω d ^ d = 1d:ℕhnezero:NeZero d⊢ ∀ m < d, 0 < m → ω d ^ m ≠ 1d:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero d⊢ ∀ m < d, 0 < m → ω d ^ m ≠ 1d:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < m⊢ ω d ^ m ≠ 1d:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:ω d ^ m = 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:↑(ω d ^ m) = ↑1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:↑(ω d) ^ m = 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:↑{ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ m = 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:Complex.exp (2 * ↑Real.pi * Complex.I / ↑d) ^ m = 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:Complex.exp (m • (2 * ↑Real.pi * Complex.I / ↑d)) = 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:Complex.exp (↑m * (2 * ↑Real.pi * Complex.I / ↑d)) = 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mhAbs:∃ n, ↑m * (2 * ↑Real.pi * Complex.I / ↑d) = ↑n * (2 * ↑Real.pi * Complex.I)⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mn:ℤhn:↑m * (2 * ↑Real.pi * Complex.I / ↑d) = ↑n * (2 * ↑Real.pi * Complex.I)⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mn:ℤhn:↑m * (2 * ↑Real.pi * Complex.I / ↑d) = ↑n * (2 * ↑Real.pi * Complex.I)calc_md:↑↑m / ↑↑d = ↑n⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mn:ℤhn:↑m * (2 * ↑Real.pi * Complex.I / ↑d) = ↑n * (2 * ↑Real.pi * Complex.I)calc_md:↑↑m / ↑↑d = ↑nd_ge_zero:0 < d⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mn:ℤhn:↑m * (2 * ↑Real.pi * Complex.I / ↑d) = ↑n * (2 * ↑Real.pi * Complex.I)calc_md:↑↑m / ↑↑d = ↑nd_ge_zero:0 < dratio_between:↑m / ↑d > 0 ∧ ↑m / ↑d < 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d -- apply And.intro; d:ℕhnezero:NeZero dm:ℕhm:m < dhm':0 < mn:ℤhn:↑m * (2 * ↑Real.pi * Complex.I / ↑d) = ↑n * (2 * ↑Real.pi * Complex.I)calc_md:↑m / ↑d = ↑nd_ge_zero:0 < dratio_between:↑m / ↑d > 0 ∧ ↑m / ↑d < 1⊢ Falsed:ℕhnezero:NeZero d⊢ 0 < d; --rw[calc_md] at ratio_between; d:ℕhnezero:NeZero d⊢ 0 < d; d:ℕhnezero:NeZero d⊢ d ≠ 0; All goals completed! 🐙 -- apply d_ge_zero; rw[div_lt_one m d]

This is an additional corrolary that is nice to have.

Lemma2.8
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

ω^n = ω^{n \mod d}.

Lean code for Lemma2.8automatically included section variable(s) unused in theorem `omega_pow_n_mod_d`: hnezero consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them: omit hnezero in theorem ... Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma omega_pow_n_mod_d : ∀ n : ℕ, (ω d) ^ n = (ω d) ^ (n % d) := d:ℕhnezero:NeZero d⊢ ∀ (n : ℕ), ω d ^ n = ω d ^ (n % d) d:ℕhnezero:NeZero dn:ℕ⊢ ω d ^ n = ω d ^ (n % d) nth_rw 1 [d:ℕhnezero:NeZero dn:ℕ⊢ ω d ^ (n % d + d * (n / d)) = ω d ^ (n % d)d:ℕhnezero:NeZero dn:ℕ⊢ ω d ^ (n % d + d * (n / d)) = ω d ^ (n % d) All goals completed! 🐙 automatically included section variable(s) unused in theorem `omega_val_pow_n_mod_d`: hnezero consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them: omit hnezero in theorem ... Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma omega_val_pow_n_mod_d : ∀ n : ℕ, (ω d).val ^ n = (ω d).val ^ (n % d) := d:ℕhnezero:NeZero d⊢ ∀ (n : ℕ), ↑(ω d) ^ n = ↑(ω d) ^ (n % d) d:ℕhnezero:NeZero dn:ℕ⊢ ↑(ω d) ^ n = ↑(ω d) ^ (n % d) nth_rw 1 [d:ℕhnezero:NeZero dn:ℕ⊢ ↑(ω d) ^ (n % d + d * (n / d)) = ↑(ω d) ^ (n % d)d:ℕhnezero:NeZero dn:ℕ⊢ ↑(ω d) ^ (n % d + d * (n / d)) = ↑(ω d) ^ (n % d) All goals completed! 🐙
Lean codeautomatically included section variable(s) unused in theorem `omega_pow_k_mod_d_eq_pow_k_int`: hnezero consider restructuring your `variable` declarations so that the variables are not in scope or explicitly omit them: omit hnezero in theorem ... Note: This linter can be disabled with `set_option linter.unusedSectionVars false`lemma omega_pow_k_mod_d_eq_pow_k_int : ∀ k : ℤ, (ω d) ^ k = (ω d) ^ (k % d) := d:ℕhnezero:NeZero d⊢ ∀ (k : ℤ), ω d ^ k = ω d ^ (k % ↑d) d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ k = ω d ^ (k % ↑d); --unfold ω; ext; simp nth_rw 1 [d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ (k % ↑d + k / ↑d * ↑d) = ω d ^ (k % ↑d)d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ (k % ↑d + k / ↑d * ↑d) = ω d ^ (k % ↑d) d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ (k % ↑d) * ω d ^ (k / ↑d * ↑d) = ω d ^ (k % ↑d); d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ (k / ↑d * ↑d) = 1 d:ℕhnezero:NeZero dk:ℤ⊢ (ω d ^ ↑d) ^ (k / ↑d) = 1 All goals completed! 🐙
Lean codelemma omega_pow_k_mod_d_eq_pow_k_zmod : ∀ k : ℤ, (ω d) ^ k = (ω d) ^ (k : ZMod d).val := d:ℕhnezero:NeZero d⊢ ∀ (k : ℤ), ω d ^ k = ω d ^ (↑k).val d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ k = ω d ^ (↑k).val d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ (k % ↑d) = ω d ^ (↑k).val d:ℕhnezero:NeZero dk:ℤ⊢ ω d ^ ↑(↑k).val = ω d ^ (↑k).val All goals completed! 🐙

We will also need another root of unity which we call τ.

Definition2.9
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0
Used by 3
Reverse dependency previews
Preview
Definition 5.1
Loading preview
Reverse dependency preview content is loaded from the rendered-fragment cache.
✓L∃∀N

Let τ = -\exp(πi/d).

Lean code for Definition2.9noncomputable def τ : ℂˣ := .mk (- Complex.exp (Real.pi * Complex.I / d)) (- Complex.exp (- Real.pi * Complex.I / d)) (d:ℕhnezero:NeZero d⊢ -Complex.exp (↑Real.pi * Complex.I / ↑d) * -Complex.exp (-↑Real.pi * Complex.I / ↑d) = 1 d:ℕhnezero:NeZero d⊢ Complex.exp (↑Real.pi * Complex.I / ↑d) * Complex.exp (-(↑Real.pi * Complex.I) / ↑d) = 1; d:ℕhnezero:NeZero d⊢ Complex.exp (↑Real.pi * Complex.I / ↑d + -(↑Real.pi * Complex.I) / ↑d) = 1; Try this: [apply] ring_nf The `ring` tactic failed to close the goal. Use `ring_nf` to obtain a normal form. Note that `ring` works primarily in *commutative* rings. If you have a noncommutative ring, abelian group or module, consider using `noncomm_ring`, `abel` or `module` instead.d:ℕhnezero:NeZero d⊢ Complex.exp 0 = 1; All goals completed! 🐙) (d:ℕhnezero:NeZero d⊢ -Complex.exp (-↑Real.pi * Complex.I / ↑d) * -Complex.exp (↑Real.pi * Complex.I / ↑d) = 1 d:ℕhnezero:NeZero d⊢ Complex.exp (-(↑Real.pi * Complex.I) / ↑d) * Complex.exp (↑Real.pi * Complex.I / ↑d) = 1; d:ℕhnezero:NeZero d⊢ Complex.exp (-(↑Real.pi * Complex.I) / ↑d + ↑Real.pi * Complex.I / ↑d) = 1; Try this: [apply] ring_nf The `ring` tactic failed to close the goal. Use `ring_nf` to obtain a normal form. Note that `ring` works primarily in *commutative* rings. If you have a noncommutative ring, abelian group or module, consider using `noncomm_ring`, `abel` or `module` instead.d:ℕhnezero:NeZero d⊢ Complex.exp 0 = 1; All goals completed! 🐙)

Some basic lemmas about \tau

Lemma2.10
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0XL∃∀N

Much like \omega, since τ lies on the Unit circle, one has \tau^* = \tau^{-1}

Lean codeomit [NeZero d] in @[simp] lemma tau_star_val : star (τ d).val = (τ d).val⁻¹ := d:ℕ⊢ star ↑(τ d) = (↑(τ d))⁻¹ d:ℕ⊢ star ↑(τ d) = (starRingEnd ℂ) ↑(τ d) * ↑(Complex.normSq ↑(τ d))⁻¹; d:ℕ⊢ Complex.normSq ↑(τ d) = 1; d:ℕ⊢ Complex.normSq ↑{ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } = 1; d:ℕ⊢ Complex.normSq (Complex.exp (↑Real.pi * Complex.I / ↑d)) = 1; d:ℕ⊢ Real.exp (↑Real.pi * Complex.I / ↑d).re ^ 2 = 1; All goals completed! 🐙 omit [NeZero d] in @[simp] lemma tau_star : star (τ d) = (τ d)⁻¹ := d:ℕ⊢ star (τ d) = (τ d)⁻¹ d:ℕ⊢ ↑(star (τ d)) = ↑(τ d)⁻¹; All goals completed! 🐙 lemma declaration uses `sorry`tau_star_pow (d : ℕ) (n : ℤ) [NeZero d] : star (τ d ^ n) = (τ d)^(-n) := d:ℕn:ℤinst✝:NeZero d⊢ star (τ d ^ n) = τ d ^ (-n) d:ℕn:ℤinst✝:NeZero d⊢ star ({ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ n) = { val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ (-n); d:ℕn:ℤinst✝:NeZero d⊢ ↑(star ({ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ n)) = ↑({ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ (-n)); d:ℕn:ℤinst✝:NeZero d⊢ (-(starRingEnd ℂ) (Complex.exp (↑Real.pi * Complex.I / ↑d))) ^ n = ((-Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ (-Complex.exp ((starRingEnd ℂ) (↑Real.pi * Complex.I / ↑d))) ^ n = ((-Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ (-Complex.exp (-(↑Real.pi * Complex.I) / ↑d)) ^ n = ((-Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ (-1) ^ n * Complex.exp (-(↑Real.pi * Complex.I) / ↑d) ^ n = ((-Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ n)⁻¹; nth_rw 3 [d:ℕn:ℤinst✝:NeZero d⊢ (-1) ^ n * Complex.exp (-(↑Real.pi * Complex.I) / ↑d) ^ n = ((-1 * Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ n)⁻¹d:ℕn:ℤinst✝:NeZero d⊢ (-1) ^ n * Complex.exp (-(↑Real.pi * Complex.I) / ↑d) ^ n = ((-1 * Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ (-1) ^ n * Complex.exp (-(↑Real.pi * Complex.I) / ↑d) ^ n = ((-1) ^ n * Complex.exp (↑Real.pi * Complex.I / ↑d) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ (-1) ^ n * Complex.exp (-(↑Real.pi * Complex.I) / ↑d) ^ n = (Complex.exp (↑Real.pi * Complex.I / ↑d) ^ n)⁻¹ * ((-1) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ (-1) ^ n * Complex.exp (↑n * (-(↑Real.pi * Complex.I) / ↑d)) = Complex.exp (-(↑n * (↑Real.pi * Complex.I / ↑d))) * ((-1) ^ n)⁻¹; d:ℕn:ℤinst✝:NeZero d⊢ Complex.exp (↑n * (-1 * (↑Real.pi * Complex.I) / ↑d)) * (-1) ^ n = Complex.exp (-(↑n * (↑Real.pi * Complex.I / ↑d))) * ((-1) ^ n)⁻¹; nth_rw 3 [d:ℕn:ℤinst✝:NeZero d⊢ Complex.exp (↑n * (-1 * (↑Real.pi * Complex.I) / ↑d)) * (-1) ^ n = Complex.exp (-1 * (↑n * (↑Real.pi * Complex.I / ↑d))) * ((-1) ^ n)⁻¹d:ℕn:ℤinst✝:NeZero d⊢ Complex.exp (↑n * (-1 * (↑Real.pi * Complex.I) / ↑d)) * (-1) ^ n = Complex.exp (-1 * (↑n * (↑Real.pi * Complex.I / ↑d))) * ((-1) ^ n)⁻¹; All goals completed! 🐙 -- rw[Units.inv_pow_eq_pow_inv (-1) n]
Lemma2.11
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0
Used by 3
Reverse dependency previews
Preview
Theorem 7.1
Loading preview
Reverse dependency preview content is loaded from the rendered-fragment cache.
✓L∃∀N

τ^2 = ω.

Proof for Lemma 2.11
uses 0

τ^2 = (-\exp(πi/d))^2 = (-1)^2 · (\exp(πi/d))^2 = 1 · \exp(2πi/d) = ω.

Lean code for Lemma2.11@[simp] lemma tau_sq_eq_omega (d : ℕ) [NeZero d] : (τ d)^2 = ω d := d:ℕinst✝:NeZero d⊢ τ d ^ 2 = ω d d:ℕinst✝:NeZero d⊢ { val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ 2 = { val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ }; d:ℕinst✝:NeZero d⊢ ↑({ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ 2) = ↑{ val := Complex.exp (2 * ↑Real.pi * Complex.I / ↑d), inv := Complex.exp (-2 * ↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ }; d:ℕinst✝:NeZero d⊢ Complex.exp (↑Real.pi * Complex.I / ↑d) ^ 2 = Complex.exp (2 * ↑Real.pi * Complex.I / ↑d); d:ℕinst✝:NeZero d⊢ Complex.exp (2 • (↑Real.pi * Complex.I / ↑d)) = Complex.exp (2 * ↑Real.pi * Complex.I / ↑d); d:ℕinst✝:NeZero d⊢ Complex.exp (2 * (↑Real.pi * Complex.I / ↑d)) = Complex.exp (2 * ↑Real.pi * Complex.I / ↑d); All goals completed! 🐙;
Lemma2.12
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 1✓L∃∀N

If d is odd then τ^d = 1.

Proof for Lemma 2.12
uses 0

τ^d = (-\exp(πi/d))^d = (-1)^d · (\exp(πi/d))^d = (-1)^d · \exp(πi) = (-1)^d · (-1) = (-1)^{d+1} = 1 when d is odd.

Lean code for Lemma2.12@[simp] lemma tau_pow_d_eq_one_of_odd (hodd : Odd d) : (τ d)^d = 1 := d:ℕhnezero:NeZero dhodd:Odd d⊢ τ d ^ d = 1 d:ℕhnezero:NeZero dhodd:Odd d⊢ { val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ d = 1; d:ℕhnezero:NeZero dhodd:Odd d⊢ ↑({ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ d) = ↑1; d:ℕhnezero:NeZero dhodd:Odd d⊢ (-Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ d = 1; d:ℕhnezero:NeZero dhodd:Odd d⊢ -1 * Complex.exp (↑Real.pi * Complex.I / ↑d) ^ d = 1 d:ℕhnezero:NeZero dhodd:Odd d⊢ -1 * Complex.exp (d • (↑Real.pi * Complex.I / ↑d)) = 1; d:ℕhnezero:NeZero dhodd:Odd d⊢ -Complex.exp (↑d * (↑Real.pi * Complex.I / ↑d)) = 1; d:ℕhnezero:NeZero dhodd:Odd d⊢ -Complex.exp (↑Real.pi * Complex.I / ↑d * ↑d) = 1; All goals completed! 🐙 where neg_one_pow_odd : ∀ x : ℕ, Odd x → (((-1) : ℂ)) ^ x = (-1) := d:ℕhnezero:NeZero dhodd:Odd d⊢ ∀ (x : ℕ), Odd x → (-1) ^ x = -1 d:ℕhnezero:NeZero dhodd:Odd dx:ℕhoddx:Odd x⊢ (-1) ^ x = -1; d:ℕhnezero:NeZero dhodd:Odd dx:ℕhoddx:Odd x⊢ Odd xd:ℕhnezero:NeZero dhodd:Odd dx:ℕhoddx:Odd x⊢ -1 ≠ 1; d:ℕhnezero:NeZero dhodd:Odd dx:ℕhoddx:Odd x⊢ -1 ≠ 1; All goals completed! 🐙
Lemma2.13
Group: Roots of unity and their basic properties. (11)
Group member previews
Preview
Lemma 2.1
Loading preview
Group member preview content is loaded from the rendered-fragment cache.
uses 0used by 0✓L∃∀N

τ^{d^2} = 1.

Proof for Lemma 2.13
uses 0

τ^{d^2} = (-\exp(πi/d))^{d^2} = (-1)^{d^2} · (-1)^d = (-1)^{d(d+1)} = 1 since either d or d+1 is even.

Lean code for Lemma2.13lemma tau_pow_d2_one : (τ d) ^ (d ^ 2) = 1 := d:ℕhnezero:NeZero d⊢ τ d ^ d ^ 2 = 1 d:ℕhnezero:NeZero d⊢ { val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ d ^ 2 = 1; d:ℕhnezero:NeZero d⊢ ↑({ val := -Complex.exp (↑Real.pi * Complex.I / ↑d), inv := -Complex.exp (-↑Real.pi * Complex.I / ↑d), val_inv := ⋯, inv_val := ⋯ } ^ d ^ 2) = ↑1; d:ℕhnezero:NeZero d⊢ (-Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ d ^ 2 = 1 d:ℕhnezero:NeZero d⊢ (-1 * Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ d ^ 2 = 1 d:ℕhnezero:NeZero d⊢ (-1 * Complex.exp (↑Real.pi * Complex.I / ↑d)) ^ (d * d) = 1 d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * Complex.exp (↑Real.pi * Complex.I / ↑d) ^ (d * d) = 1; d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * Complex.exp (↑(d * d) * (↑Real.pi * Complex.I / ↑d)) = 1 d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * Complex.exp (↑d * ↑d * (↑Real.pi * Complex.I / ↑d)) = 1 d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * Complex.exp (↑d * (↑d * (↑Real.pi * Complex.I / ↑d))) = 1 d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * Complex.exp (↑d * (↑Real.pi * Complex.I)) = 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * Complex.exp (↑Real.pi * Complex.I) ^ d = 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d) * (-1) ^ d = 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ (-1) ^ (d * d + d) = 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ (-1) ^ (d * (d + 1)) = 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ Even (d * (d + 1))d:ℕhnezero:NeZero d⊢ -1 ≠ 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ -1 ≠ 1d:ℕhnezero:NeZero d⊢ IsUnit ↑d d:ℕhnezero:NeZero d⊢ -1 ≠ 1 All goals completed! 🐙 d:ℕhnezero:NeZero d⊢ IsUnit ↑d All goals completed! 🐙
Lean codelemma mod_d_nonneg (a : ℤ) : 0 ≤ a % ↑d := d:ℕhnezero:NeZero da:ℤ⊢ 0 ≤ a % ↑d d:ℕhnezero:NeZero da:ℤ⊢ ↑d ≠ 0 All goals completed! 🐙 theorem tau_pow_n_mod_d_of_d_odd (n d : ℕ) (hodd : Odd d) [NeZero d] : τ d ^ n = τ d ^ (n % ↑d) := pow_eq_pow_mod n (tau_pow_d_eq_one_of_odd d hodd)