Zulip Chat Archive

Stream: mathlib4

Topic: crazy coercion


Kevin Buzzard (Jul 06 2023 at 12:36):

You'll know the question if you look at the output to this:

import Mathlib

def foo (q : ) (a : ZMod q) :  := a
#print foo

Why?? And should I worry about this?

Anne Baanen (Jul 06 2023 at 12:41):

Does this return a whole real number between 0 and q because we get a composition along the lines of ZMod q → Fin q → ℕ → ℂ?

Anne Baanen (Jul 06 2023 at 12:41):

(Substituting if q = 0 of course.)

Oliver Nash (Jul 06 2023 at 13:10):

@Kevin Buzzard Do I understand correctly that the point you're making is that this fails:

example (q : ) (a : ZMod q) : foo q a = @ZMod.cast  _ q a := rfl -- fails

because Lean has instead decided on:

example (q : ) (a : ZMod q) : foo q a = Complex.ofReal (@ZMod.cast  _ q a) := rfl -- succeeds

It seems wrong to me that the real numbers should be involved.

Jireh Loreaux (Jul 06 2023 at 13:31):

This strikes me as maybe being a CoeHead vs. CoeTail vs. CoeTC problem, but I'm not sure exactly where.

Kevin Buzzard (Jul 06 2023 at 15:50):

For me the coercion was going through the Gaussian integers! Is that not the case for other people??

Oliver Nash (Jul 06 2023 at 15:56):

If I use your import Mathlib then it does indeed go through the Gaussian integers. However when I wrote my comment above, I just pasted the definition into a file I was working on with some other imports and it went through the reals. So unfortunately it seems to depend on imports.

Kyle Miller (Jul 06 2023 at 15:56):

For reference (using set_option pp.coercions false):

def foo : (q : )  ZMod q   :=
fun q a  FunLike.coe GaussianInt.toComplex (ZMod.cast a)

Yury G. Kudryashov (Jul 06 2023 at 16:01):

Did we have a diamond in Lean 3?

Kevin Buzzard (Jul 07 2023 at 11:27):

I don't know, but right now in mathlib4 we have this (and this is blocking some work of a student):

import Mathlib -- to import some awful coercion

variable (q : )

example (a : ZMod q) : (a : ) = GaussianInt.toComplex a := by
  rfl -- a syntactic equality

example (a : ZMod q) : (a : ) = ZMod.cast a := by
  sorry -- I'm stuck on this. Can assume 0 < q if necessary

Johan Commelin (Jul 07 2023 at 11:33):

Pretty terrible indeed!

Johan Commelin (Jul 07 2023 at 11:33):

We really need to remove the automated coercion from ZMod to random rings.

Johan Commelin (Jul 07 2023 at 11:34):

It should be conditional on some [Fact _]s, or be a local instance, or both

Kevin Buzzard (Jul 07 2023 at 11:34):

But we're doing Kloosterman sums and there it's really handy to be able to go from ZMod q to R\R so I am going to have to eat my words :-)

Kevin Buzzard (Jul 07 2023 at 11:34):

Actually maybe not -- perhaps we should just be using val really.

Johan Commelin (Jul 07 2023 at 11:36):

I don't know Kloosterman sums. But that sounds like a pretty non-canonical thing that Kloosterman was doing...

Kevin Buzzard (Jul 07 2023 at 11:39):

it's all about things like xZ/qZe(x2/q)\sum_{x\in \Z/q\Z}e(x^2/q) where e(x):=e2πixe(x):=e^{2\pi i x} so everything is well-defined.

Johan Commelin (Jul 07 2023 at 11:42):

But then you want to factor e(_/q) through ZMod q, right?

Kevin Buzzard (Jul 07 2023 at 12:44):

Right.

Kevin Buzzard (Jul 07 2023 at 13:27):

Yeah I think that for all of our sanity I'm just going to build the function Z/qZC×\Z/q\Z\to\mathbb{C}^\times sending nn to r2πin/qr^{2\pi in/q} and make the API for it. But I guess there are still two questions left, namely (1) why does Lean want to go through Z[i] and (2) how do we prove that Z/n -> Z[i] -> C is the cast. Alternatively we could burninate the cast. I'm now back to agreeing with you that it's a completely evil function.

Alex Kontorovich (Jul 07 2023 at 14:08):

This must've been dealt with in the Bloom-Mehta formalization, no? Do I recall they dealt with Kloosterman sums (or perhaps more general exponential sums)? How did they do it?

Alex Kontorovich (Jul 07 2023 at 14:12):

Sorry, theirs was Lean3 and this is presumably a new Lean4 issue. Nevermind.

Eric Wieser (Jul 07 2023 at 14:51):

Don't we already have that map as docs3#real.angle.exp_map_circle?

Kevin Buzzard (Jul 07 2023 at 17:55):

I want the source to be Z/qZ\Z/q\Z, so I think that's different?

Eric Wieser (Jul 07 2023 at 17:59):

I assume you don't mean AddCircle (q : ℤ), even though that's defined as what you wrote?

Kevin Buzzard (Jul 07 2023 at 18:01):

The Lean 3 thing you linked to is eating a real.angle.

Kevin Buzzard (Jul 07 2023 at 18:42):

Just to be clear: the thing I want is def eZMod (q : ℕ) (x : ZMod q) : ℂ := Complex.exp (2 * Real.pi * Complex.I * x.val / q). Do you think we have it? (and the proof that it sends x+y to e(x)*e(y)?)

Eric Wieser (Jul 07 2023 at 18:58):

Don't you want the result to live in docs#Circle ?

Kevin Buzzard (Jul 08 2023 at 00:01):

No, because I immediately want to add them up.

Eric Wieser (Jul 09 2023 at 23:59):

What I'm suggesting is:

import Mathlib.Analysis.SpecialFunctions.Complex.Circle
import Mathlib.Analysis.Fourier.AddCircle

@[simps!]
def ZMod.toQuotient (A) [AddCommGroupWithOne A] (q : ) :
    ZMod q →+ A  AddSubgroup.zmultiples (q : A) :=
  ZMod.lift _ ⟨(QuotientAddGroup.mk' _).comp (Int.castAddHom A), by simp

/-- A bundled version of `AddCircle.toCircle` -/
@[simps!]
noncomputable def AddCircle.toCircleHom (r : ) : AddCircle r →+ Additive circle :=
  AddMonoidHom.mk' AddCircle.toCircle AddCircle.toCircle_add

-- note that we need to introduce `K` and all the extra assumptions since `AddCircle` isn't allowed on `ℤ`.
noncomputable abbrev ZMod.toAddCircle (K) [LinearOrderedRing K] [TopologicalSpace K] [OrderTopology K] (q : ) :
    ZMod q →+ AddCircle (q : K) :=
  ZMod.toQuotient K q

noncomputable abbrev ZMod.toCircle {q : } (z : ZMod q) : circle :=
  (ZMod.toAddCircle _ _ z).toCircle

noncomputable abbrev ZMod.toCircleHom (q : ) : ZMod q →+ Additive circle :=
  (AddCircle.toCircleHom _).comp (ZMod.toAddCircle _ _)

Kevin Buzzard (Jul 10 2023 at 00:10):

But where's the map I actually want, sending x to e2πix/qe^{2\pi i x/q}?

Kevin Buzzard (Jul 10 2023 at 00:11):

oh is circle some subtype of C?

Eric Wieser (Jul 10 2023 at 00:21):

circle : SubGroup C

Eric Wieser (Jul 10 2023 at 00:21):

docs#circle

Eric Wieser (Jul 10 2023 at 00:22):

docs#AddCircle.toCircle is _almost_ the map you asked for, but we have two different spellings of ZMod and it's the wrong one

Eric Wieser (Jul 10 2023 at 00:32):

In particular we seem to be missing

@[simps!]
def ZMod.toIntQuotient (q : ) :
    ZMod q ≃+   AddSubgroup.zmultiples (q : ) :=
  AddMonoidHom.toAddEquiv
    (ZMod.lift _ QuotientAddGroup.mk' _, by simp⟩)
    ({ toFun := (sorry : Function.Periodic (Int.cast :   ZMod q) q).lift
       map_zero' := sorry
       map_add' := sorry })
    sorry
    sorry

Anne Baanen (Jul 10 2023 at 09:44):

Is this not docs#Int.quotientZmultiplesEquivZMod ?

Anne Baanen (Jul 10 2023 at 09:45):

Or is the Periodic part important?

Eric Wieser (Jul 10 2023 at 10:00):

It's the neighbouring docs#Int.quotientZmultiplesNatEquivZMod


Last updated: Dec 20 2023 at 11:08 UTC