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 #180

Merged
merged 70 commits into from
Jan 13, 2020
Merged

Dirichlet characters #180

merged 70 commits into from
Jan 13, 2020

Conversation

b-mehta
Copy link
Contributor

@b-mehta b-mehta commented Jan 5, 2020

  • Create M.NT.Moduli.Internal module, for discreteLogarithmPP and isPrimitiveRoot', so we can work with these internally without needing to use CyclicGroup.
  • I created Template a while ago, but since then SFactors was introduced - this can be adapted to make a nicer version of Template. It's unclear if Template should have the modulus on type level though, considering induced might be easier to write without that. Edit: This turned out to be a bad idea, due to the reason mentioned.
  • Figure out how to do isPrimitive
  • Bulk evaluation test currently fails. The branch here might have the fix for this.

@b-mehta b-mehta mentioned this pull request Jan 10, 2020
@b-mehta b-mehta changed the title (WIP) Dirichlet characters Dirichlet characters Jan 10, 2020
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
arithmoi.cabal Outdated Show resolved Hide resolved
Math/NumberTheory/Moduli/JacobiSymbol.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
@Bodigrim
Copy link
Owner

Do you have a preference for a Show instance for DirichletCharacter?

I would probably just dump its internal representation, but no strong opinion here.

It's also tempting to implement OrZero with newtypes, so that a custom Show instance can be given, do you think this is a good idea?

Not realy. Too many layers and new newtypes make users struggle. However, you can probably define instance {-# OVERLAPPING #-} Show (Ap (Maybe RootOfUnity)).

@b-mehta
Copy link
Contributor Author

b-mehta commented Jan 10, 2020

I would consider using overlapping instances significantly worse, since this extension can lead to incoherence. I think I'll just avoid a Show instance altogether.

@Bodigrim
Copy link
Owner

Bodigrim commented Jan 11, 2020

Yeah this is a good point, but I'm hesitant to make the RootOfUnity here be parametrised on type level. In particular, it would make

evaluate :: DirichletCharacter n -> MultMod n -> RootOfUnity (Phi n)

which would be a pain (I did try).

Actually I think it is possible to avoid Phi along these lines:

-- | RootOfUnity m :: RootOfUnity n represents \(e^{2 \pi i m / \phi(n)}\).
newtype RootOfUnity n = RootOfUnity Integer
  deriving (Eq)

instance KnownNat n => Show (RootOfUnity n) where
  show (RootOfUnity m) = "e^(" ++ show (numerator r) ++ "πi/" ++ show (denominator r) ++ ")"
    where
      r = 2 * m % totient (natVal (Proxy :: Proxy n))

toComplex :: Floating a => SFactors Integer n -> RootOfUnity n -> Complex a
toComplex fact (RootOfUnity m) = cis (2 * pi * m / d)
  where
    d = runFunctionOnFactors totientA (unSFactors fact)

evaluate :: DirichletCharacter n -> MultMod n -> RootOfUnity n
evaluate = undefined

(I do not mean this to be done in this branch)

Math/NumberTheory/Moduli/Internal.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Outdated Show resolved Hide resolved
Math/NumberTheory/DirichletCharacters.hs Show resolved Hide resolved
@Bodigrim
Copy link
Owner

Overall a very nice code. I really appreciate the amount of work and engineering.

@b-mehta
Copy link
Contributor Author

b-mehta commented Jan 11, 2020

Yeah this is a good point, but I'm hesitant to make the RootOfUnity here be parametrised on type level. In particular, it would make

evaluate :: DirichletCharacter n -> MultMod n -> RootOfUnity (Phi n)

which would be a pain (I did try).

Actually I think it is possible to avoid Phi along these lines:

-- | RootOfUnity m :: RootOfUnity n represents \(e^{2 \pi i m / \phi(n)}\).
newtype RootOfUnity n = RootOfUnity Integer
  deriving (Eq)

instance KnownNat n => Show (RootOfUnity n) where
  show (RootOfUnity m) = "e^(" ++ show (numerator r) ++ "πi/" ++ show (denominator r) ++ ")"
    where
      r = 2 * m % totient (natVal (Proxy :: Proxy n))

toComplex :: Floating a => SFactors Integer n -> RootOfUnity n -> Complex a
toComplex fact (RootOfUnity m) = cis (2 * pi * m / d)
  where
    d = runFunctionOnFactors totientA (unSFactors fact)

evaluate :: DirichletCharacter n -> MultMod n -> RootOfUnity n
evaluate = undefined

(I do not mean this to be done in this branch)

This would work but it would mean RootOfUnity isn't the ideal name and we cannot represent cubic residues... I attempted a few other versions of this module which would be more typed, but they turned out to be awkward to use - you can see some attempts in my wip branch. I opted instead for a version without putting much on type level, but with tests that it all works (using validChar) instead

@b-mehta b-mehta closed this Jan 11, 2020
@b-mehta b-mehta reopened this Jan 11, 2020
@b-mehta
Copy link
Contributor Author

b-mehta commented Jan 12, 2020

I've added fromTable, which allows one to construct a DirichletCharacter from its table of values, if a valid character exists, and also I've adjusted iterateMaybe to use unfoldr as opposed to manual list creation.

Here's a list of improvements that can be turned into issues after merge.

  • fromTable currently requires the whole table, but only uses part of it to get the underlying character (and we verify the generated character is correct). In fact, it suffices to only supply a very small number of values to uniquely specify a character. If one specifies chi at a collection of points which generates (Z/nZ)*, this would uniquely define the character (although this might be hard to do in practice). With this in mind, we can make fromTable more general:
data DirichletError = UnderSpecified | OverSpecified | InvalidValues
fromTable :: forall n. KnownNat n => Vector (OrZero RootOfUnity) -> Either DirichletError (DirichletCharacter n)
  • toRealFunction uses evalGeneral, but it should be possible to calculate it without doing any discrete log calculations - I believe we can use jacobiSymbol to do the odd prime power cases for instance - which would make it more efficient
  • (Easy) Conversion to/from the right sort of ArithmeticFunction (the conversion from ought to be partial, using fromTable) - this was mentioned in the original issue. If it's still desired, the conversion from would need an unchecked precondition that the given function is periodic. The conversion to should use evalAll since we might need to evaluate it at every prime, which cover almost all of MultMod n.

The following aren't directly related to characters, but they came up while working on this.

  • It would be nice to have a generalised version of chineseCoprime which works on more than two cases
  • It might be useful to export
reduceMod :: forall a b. (KnownNat a, KnownNat b) => Mod (a*b) -> (Mod a, Mod b)
reduceMod (Mod n) = (fromIntegral n, fromIntegral n)

reduceMult :: forall a b. (KnownNat a, KnownNat b) => MultMod (a*b) -> (MultMod a, MultMod b)
reduceMult (MultMod n) = (MultMod a, MultMod b)
  where (a,b) = reduceMod n

@Bodigrim Bodigrim merged commit 54a4448 into Bodigrim:master Jan 13, 2020
@Bodigrim
Copy link
Owner

Bodigrim commented Jan 13, 2020

Great job, thanks for your efforts and time!


fromTable currently requires the whole table, but only uses part of it

I'd probably go for

fromTable :: forall n. KnownNat n => (Mod n -> OrZero RootOfUnity) -> DirichletCharacter n
fromTable f = undefined

such that fromTable evaluates f on each group generator and reconstructs all the rest. And f may lookup into a vector or whatever it likes.

toRealFunction uses evalGeneral, but it should be possible to calculate it without doing any discrete log calculations

That's a good point.

Conversion to/from the right sort of ArithmeticFunction

I think there are enough helpers for a user willing to implement it himself, so this is of a low priority probably.

It would be nice to have a generalised version of chineseCoprime which works on more than two cases

What exactly do you have in mind?

It might be useful to export reduceMod

This could make a nice addition to https://github.com/Bodigrim/mod

@b-mehta
Copy link
Contributor Author

b-mehta commented Jan 13, 2020

such that fromTable evaluates f on each group generator and reconstructs all the rest. And f may lookup into a vector or whatever it likes.

I don't think this makes much of a difference; besides fromTable still checks that the character is valid, which is done by ensuring the whole table matches.
What I had in mind was more that some values can be unspecified while still giving the character - but it would need a more advanced method than the one I used here.

What exactly do you have in mind?

This is what I'd quickly guessed earlier, though I don't doubt something better exists

chineseCoprimeList :: (Eq a, Ring a, Euclidean a) => [(a, a)] -> Maybe a
chineseCoprimeList xs = fmap fst $ foldM (\x y -> fmap (,snd x `times` snd y) (chineseCoprime x y)) (zero, one) xs

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

Successfully merging this pull request may close these issues.

2 participants