Zulip Chat Archive

Stream: Is there code for X?

Topic: Complex roots of unity as a finset


Eric Wieser (Oct 19 2022 at 21:39):

Do we have a result that expresses the nth roots of unity as exp (2 * π * I * (↑(i : ℕ) / n) over the obvious choice of i?

docs#complex.mem_roots_of_unity is obviously close, but I want it as an equality of finsets.

My attempt was:

import analysis.complex.roots_of_unity

namespace complex

open_locale real

lemma exp_two_pi_mul_div_inj_on (n : +):
  (set.Iio (n : )).inj_on (λ i, exp (2 * π * I * ((i : ) / n))) :=
λ i (hi : i < n) j (hj : j < n) h, begin
  dsimp at h,
  simp_rw [exp_eq_exp_iff_exists_int, mul_comm _ (2 * π * I), mul_add] at h,
  obtain k, h := h,
  rw mul_right_inj' at h,
  field_simp at h,
  norm_cast at h,
  obtain _ | k, hk := int.eq_coe_or_neg k,
  { simp * at * },
  exfalso,
  obtain rfl | rfl := hk,
  { rw hk at h,
    norm_cast at h,
    rw [nat.succ_mul, add_assoc] at h,
    subst h,
    apply hi.not_le,
    apply self_le_add_left },
  { rw [hk, neg_mul, sub_eq_add_neg, eq_sub_iff_add_eq] at h,
    norm_cast at h,
    rw [nat.succ_mul, add_assoc] at h,
    subst h,
    apply hj.not_le,
    apply self_le_add_left },
  norm_num [real.pi_ne_zero, complex.ext_iff],
end

/-- The nth roots of `1 : ℂ` are all of the form `exp (2 * π * I * (↑(i : ℕ) / n)` -/
lemma roots_of_unity_to_finset (n : +) :
  (polynomial.nth_roots_finset n ) =
    (finset.univ : finset (fin n)).map
      λ i, exp (2 * π * I * ((i : ) / n)),
        λ i j h, fin.ext $ exp_two_pi_mul_div_inj_on n i.prop j.prop h :=
begin
  ext,
  simp only [fin.exists_iff, polynomial.mem_nth_roots_finset, pnat.pos, finset.mem_map,
    finset.mem_univ, function.embedding.coe_fn_mk, exists_true_left, fin.coe_mk],
  by_cases ha : a = 0,
  { simp [ha, exp_ne_zero] },
  lift a to ˣ using (is_unit.mk0 _ ha),
  rw [complex.mem_roots_of_unity n a, _root_.mem_roots_of_unity,
    units.coe_pow, units.coe_eq_one],
end

end complex

Is there a faster way to get there via docs#is_cyclic and showing that exp (2 * π * I / n) is the generator of the group?

Junyan Xu (Oct 19 2022 at 21:55):

If you use docs#finset.image you don't have to prove it's injective right? We also have docs#pow_injective_of_lt_order_of but you need to first show that the order_of exp(2πI/n) is n.

Johan Commelin (Oct 19 2022 at 21:56):

Hasn't that been done yet???

Junyan Xu (Oct 19 2022 at 21:57):

Actually I think docs#is_primitive_root can simply be defined to be order_of ζ = k.

Johan Commelin (Oct 19 2022 at 21:57):

I don't remember, but I think I used stuff like that when I did things with Chebyshev polynomials. Those things have later been generalised. So maybe those ingredients didn't survive. But the bare result about e ^ (2pi i / n) is probably still there.

Junyan Xu (Oct 19 2022 at 22:00):

Indeed we have docs#is_primitive_root.not_iff but not the version without not on both sides ... but you may use docs#is_primitive_root.eq_order_of for the direction you want.

Eric Rodriguez (Oct 19 2022 at 22:14):

there's also docs#is_primitive_root.unique somewhere

Eric Rodriguez (Oct 19 2022 at 22:14):

oh that different nvm

Eric Rodriguez (Oct 19 2022 at 22:15):

docs#is_primitive_root.order_of

Yaël Dillies (Oct 19 2022 at 22:15):

At least, its proof through the order_of spelling would be much shorter.

Eric Wieser (Oct 19 2022 at 22:20):

If you use docs#finset.image you don't have to prove it's injective right?

Sure, but then you end up needing to prove it's injective downstream if you want to talk about finset.sum or similar

Junyan Xu (Oct 19 2022 at 22:23):

Indeed and I think the problem arises earlier, because finset.image requires decidable_eq ℂ. But if you're satisfied with a multiset then multiset.map should be good enough.

Yaël Dillies (Oct 19 2022 at 22:24):

Surely we have that as a (noncomputable) instance?

Junyan Xu (Oct 19 2022 at 22:24):

docs#complex.decidable_eq :exploding_head:

Eric Wieser (Oct 19 2022 at 22:25):

image would be easier, but only because it puts off proving other helpful results. But both would work here

Eric Wieser (Oct 19 2022 at 23:33):

Thanks for the suggestions @Junyan Xu , this is certainly better:

lemma exp_two_pi_mul_div_inj_on (n : ):
  (set.Iio (n : )).inj_on (λ i, exp (2 * π * I * ((i : ) / n))) :=
λ i (hi : i < n) j (hj : j < n) h, begin
  have : order_of (units.mk0 (exp (2 * π * I / n)) (exp_ne_zero _)) = n,
  { rw [order_of_units, units.coe_mk0],
    refine (is_primitive_root_exp _ $ ne_zero_of_lt hi).eq_order_of.symm },
  refine pow_injective_of_lt_order_of _ (hi.trans_eq this.symm) (hj.trans_eq this.symm) _,
  ext1,
  simp_rw [units.coe_pow, units.coe_mk0],
  simp_rw [exp_nat_mul, mul_comm (i : ), mul_comm (j : ),
    div_eq_mul_inv, mul_right_comm _ (n⁻¹ : ) _, mul_assoc _ _ (n⁻¹ : ), div_eq_mul_inv],
  exact h,
end

Eric Rodriguez (Oct 19 2022 at 23:38):

shouldn't there be glue between nth_roots_finset and roots_of_unity.to_finset?

Eric Wieser (Oct 20 2022 at 01:34):

docs#roots_of_unity.fintype already exists, but I don't think you can use to_finset in a sensible way


Last updated: Dec 20 2023 at 11:08 UTC