Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dirichlet characters #119

Closed
Bodigrim opened this issue Jul 31, 2018 · 6 comments
Closed

Dirichlet characters #119

Bodigrim opened this issue Jul 31, 2018 · 6 comments

Comments

@Bodigrim
Copy link
Owner

https://en.wikipedia.org/wiki/Dirichlet_character

Despite of rather complicated applications, Dirichlet characters itself are a simple algebraic concept.
It would be nice to have a data type, representing them, annotated by modulo on type level:

data DirichletCharacter (mod :: Nat) = TBD

Since Dirichlet characters of given modulo form a group by multiplication, we should be able to define correspondent Semigroup and Monoid instances. Moreover, it is useful to be able to enumerate all Dirichlet characters, which can be reflected in Haskell by Enum and Bounded instances. Finally, each character is a multiplicative function, so there is a mapping between DirichletCharacter and ArithmeticFunction from Math.NumberTheory.ArithmeticFunctions.

@b-mehta
Copy link
Contributor

b-mehta commented Aug 12, 2018

I'm happy to take this on. My current idea is to store a DirichletCharacter mod n as follows: A Dirichlet Character is determined by its values on generators of the group of units mod n. So for a given n we factorise it and find generators of its unit group using Moduli.PrimitiveRoot and the chinese remainder theorem. On these generators we can freely define the values of the Dirichlet character (using cyclotomic numbers to represent roots of unity).

data DirichletCharacter (mod :: Nat) = Generated (Map (Mod mod) Cyclotomic)

(with the data constructor hidden). Does this sound sensible?

I'd also like to make a change in Moduli.PrimitiveRoot: the function isPrimitiveRoot' can be optimised for large prime powers, determining primitive roots mod p^k (and 2p^k) for k > 1 should take roughly the same amount of time compared to determining primitive roots mod p^2.

@Bodigrim
Copy link
Owner Author

Since cyclotomic utilizes arithmoi for factorisation, we cannot reuse Cyclotomic type. Because otherwise it would cause a circular dependency between packages. This is not a big deal, we can represent a root of unity exp(2pim/n) as RootOfUnit { m :: Natural, n :: Natural } or something similar.

It would be desirable to have a unique representation for each Dirichlet character. From this point of view the ability to choose any primitive root looks like a redundant degree of freedom. IMHO we can assume that the smallest primitive root is always used and represent Dirichlet character just by a Map Natural Natural, where each key-value pair (m, n) means that the value of a character on the smallest primitive root modulo n is exp(2pim/n).

As a bonus level, one can represent moduli on type level, possibly include some proof that their product matches the order of a character, etc. Not sure which degree of type-foo is reasonable here.


It seems that there is no way to evaluate a Dirichlet character without computing discreet logarithms (#88). There is an unfinished PR #110. @b-mehta are you be interested to take it over, if @Taneb would not mind?


W.r.t. isPrimitiveRoot': sure, go ahead, possibly as a separate PR.

@b-mehta
Copy link
Contributor

b-mehta commented Aug 12, 2018

The root of unity representation sounds fine to me.

The choice of primitive roots is not necessarily as simple as you describe, since the modulus may not form a cyclic group of units. For instance, mod 35 the group of units is isomorphic (under CRT) to (Z/5Z)* x (Z/7Z)* and thus is generated by the pairs (2,1) and (1,3) since 2 generates (Z/5Z)* and 3 generates (Z/7Z)* (and are the smallest such). Using the CRT isomorphism, this gives that 22 and 31 together generate (Z/35Z)*. But, if the generator of (Z/5Z)* was chosen to be 3 instead, then CRT would give 8 as the corresponding generator of (Z/35Z)*.
That said, we still have a canonical choice which should work fine. The map would represent something slightly different, but that idea would work well.

I'm not comfortable enough with type magic to work that out myself, but it does sound promising. We could possibly extend CyclicGroup to represent general multiplicative groups mod n for any n instead of just for certain n as well.

I'll have a look at that PR, I may implement a naive method for now in the meantime. I'm unsure about some of the difficulties described there, the Pollard algorithm should to my knowledge work just as well if the base is not a primitive root and the target value is a power of the base.

@b-mehta b-mehta mentioned this issue Aug 22, 2018
7 tasks
@b-mehta
Copy link
Contributor

b-mehta commented Sep 12, 2018

Once #130 is merged, I plan to work on this in parallel with #136.

@b-mehta
Copy link
Contributor

b-mehta commented Jan 10, 2020

This is implemented in #180, except for

there is a mapping between DirichletCharacter and ArithmeticFunction from Math.NumberTheory.ArithmeticFunctions

which I'll create an issue for, once #180 is merged.

@b-mehta
Copy link
Contributor

b-mehta commented Jan 14, 2020

I believe this issue can be closed by #180 now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants