Zulip Chat Archive

Stream: mathlib4

Topic: Roots of unity of Circle


Michael Stoll (Nov 08 2024 at 15:32):

With a view of adding a docs#HasEnoughRootsOfUnity instance for docs#Circle, I was trying to define the obvious isomorphism between the docs#rootsOfUnity of Circle and those of the complex numbers, and I found it rather painful:

noncomputable
def Circle.rootsOfUnityMulEquiv {n : } [NeZero n] : rootsOfUnity n Circle ≃* rootsOfUnity n  := by
  refine MulEquiv.ofBijective (restrictRootsOfUnity coeHom n) ⟨?_, fun ζ  ?_⟩
  · refine (injective_iff_map_eq_one _).mpr fun ζ   Subtype.ext ?_
    rw [Subgroup.coe_one]
    simp only [restrictRootsOfUnity, MonoidHom.coe_mk, OneHom.coe_mk, Subgroup.mk_eq_one,
       map_one (Units.map coeHom)] at 
    exact (Units.map_injective <| (Set.injective_codRestrict Subtype.property).mp
      fun _ _ a  a) 
  · let z := ζ.val
    have hz : z.val ^ n = 1 := by
      norm_cast
      rw [show z ^ n = 1 from ζ.prop, Units.val_eq_one]
    have hz' : z.val  Submonoid.unitSphere  := by
      simp only [Submonoid.unitSphere, Submonoid.mem_mk, Subsemigroup.mem_mk, mem_sphere_iff_norm,
        sub_zero, Complex.norm_eq_abs]
      apply_fun Complex.abs at hz
      simp only [AbsoluteValue.map_pow, AbsoluteValue.map_one] at hz
      exact (pow_eq_one_iff_of_nonneg (AbsoluteValue.nonneg Complex.abs z) (NeZero.ne n)).mp hz
    let zz : Circle := z.val, hz'
    have hzz : zz ^ n = 1 := by
      ext
      rw [SubmonoidClass.coe_pow]
      simp only [hz, OneMemClass.coe_one]
    use rootsOfUnity.mkOfPowEq zz hzz
    ext
    simp only [restrictRootsOfUnity_coe_apply, rootsOfUnity.val_mkOfPowEq_coe, coeHom_apply]

I'm feeling that I must have missed a couple tricks here. Any pointers?

Bhavik Mehta (Nov 08 2024 at 20:00):

@[simp, norm_cast] lemma Circle.coe_pow (z : Circle) (n : ) : ((z ^ n) : ) = z ^ n := rfl

@[simp] lemma mem_unitSphere {R} {x} [NormedDivisionRing R] :
    x  Submonoid.unitSphere R  x = 1 := by simp [Submonoid.unitSphere]

noncomputable def Circle.rootsOfUnityMulEquiv {n : } [NeZero n] :
    rootsOfUnity n Circle ≃* rootsOfUnity n  := by
  refine MulEquiv.ofBijective (restrictRootsOfUnity coeHom n) ⟨?_, ?_⟩
  · refine (Set.injective_codRestrict ?_).2 ?_
    exact (Units.map_injective coe_injective).comp Subtype.coe_injective
  · rintro ζ, 
    suffices  a : Circleˣ, (a : Circle) ^ n = 1  ((a : Circle) : ) = ζ by
      simpa [Subtype.ext_iff, Units.ext_iff]
    have hζ' : (ζ : )  Submonoid.unitSphere  := by
      simpa using Complex.norm_eq_one_of_mem_rootsOfUnity 
    refine ⟨_root_.toUnits ζ, hζ', ?_, by simp
    simpa [Units.ext_iff, Circle.ext_iff, coe_pow] using 

Here's my attempt; it seems like those two at the top are missing simp lemmas

Bhavik Mehta (Nov 08 2024 at 20:01):

Perhaps docs#Complex.norm_eq_one_of_mem_rootsOfUnity was the trick you missed?

Bhavik Mehta (Nov 08 2024 at 20:09):

now that I look at your code again, I realised I missed the trick of rootsOfUnity.mkOfPowEq:

noncomputable def Circle.rootsOfUnityMulEquiv {n : } [NeZero n] :
    rootsOfUnity n Circle ≃* rootsOfUnity n  := by
  refine MulEquiv.ofBijective (restrictRootsOfUnity coeHom n) ⟨?_, ?_⟩
  · refine (Set.injective_codRestrict ?_).2 ?_
    exact (Units.map_injective coe_injective).comp Subtype.coe_injective
  · rintro ζ, 
    have hζ' : (ζ : )  Submonoid.unitSphere  := by
      simpa using Complex.norm_eq_one_of_mem_rootsOfUnity 
    exact rootsOfUnity.mkOfPowEq ζ, hζ' (by aesop (add simp Units.ext_iff)), by aesop

Michael Stoll (Nov 08 2024 at 20:12):

With import Mathlib, your code gives two errors in the playground.

Junyan Xu (Nov 08 2024 at 20:12):

This shouldn't be noncomputable, right?

Michael Stoll (Nov 08 2024 at 20:13):

failed to compile definition, consider marking it as 'noncomputable' because it depends on 'Circle.instCommGroup', and it does not have executable code

Michael Stoll (Nov 08 2024 at 20:13):

Complex numbers are not really computable anyway...

Bhavik Mehta (Nov 08 2024 at 20:14):

Michael Stoll said:

With import Mathlib, your code gives two errors in the playground.

It works fine for me in the playground on latest mathlib. Make sure to include the two lemmas at the beginning of the earlier message.

Junyan Xu (Nov 08 2024 at 20:14):

I mean you can make it computable using something other than MulEquiv.ofBijective. The backwards map doesn't have good defeq property with it.

Michael Stoll (Nov 08 2024 at 20:19):

I don't think this would get rid of the noncomputable semigroup instance.

Bhavik Mehta (Nov 08 2024 at 20:26):

Indeed it doesn't, but you end up with something shorter and with better defeqs for the inverse:

import Mathlib

@[simp, norm_cast] lemma Circle.coe_pow (z : Circle) (n : ) : ((z ^ n) : ) = z ^ n := rfl

@[simp] lemma mem_unitSphere {R} {x} [NormedDivisionRing R] :
    x  Submonoid.unitSphere R  x = 1 := by simp [Submonoid.unitSphere]

noncomputable def Circle.rootsOfUnityMulEquiv {n : } [NeZero n] :
    rootsOfUnity n Circle ≃* rootsOfUnity n  where
  __ := restrictRootsOfUnity coeHom n
  invFun ζ := rootsOfUnity.mkOfPowEq (ζ : ˣ),
      mem_unitSphere.2 (Complex.norm_eq_one_of_mem_rootsOfUnity ζ.2)
      (by aesop (add simp Units.ext_iff))
  left_inv ζ := by ext; simp
  right_inv ζ := by ext; simp

Junyan Xu (Nov 08 2024 at 20:47):

Interesting, even if I do

def Circle.rootsOfUnityMulEquiv {n : } [NeZero n] :
    rootsOfUnity n Circle ≃* rootsOfUnity n  where
  toFun x := ⟨⟨x.1, x.1.inv, sorry, sorry, sorry
  invFun x := ⟨⟨⟨x.1, sorry, x.1.inv, sorry, sorry, sorry, sorry
  left_inv := sorry
  right_inv := sorry
  map_mul' := sorry

Lean still complains

failed to compile definition, consider marking it as 'noncomputable' because it depends on 'Circle.instCommGroup', and it does not have executable code

Yuyang Zhao (Nov 09 2024 at 04:42):

This may be because docs#CauSeq.Completion.instInvCauchy is not computable. It may be possible to define computable inv that require a non-zero proof, and thus obtain computable docs#Circle.instCommGroup.

Junyan Xu (Nov 09 2024 at 12:25):

The inv I use is docs#Units.inv which should absolutely be computable ... And the ⁻¹ on Units should also be computable.


Last updated: May 02 2025 at 03:31 UTC