-
-
Notifications
You must be signed in to change notification settings - Fork 491
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
speed up logarithms modulo composite integers #32375
Comments
Commit: |
This comment has been minimized.
This comment has been minimized.
Author: Lorenz Panny |
comment:2
I am cc-ing some people who might have an opinion on this. (Sorry if you don't care.) Some quick comments: I don't think we need the I would just copy the error message where appropriate rather than put it in a Split these lines: -n, m = 0, 1
+n = 0
+m = 0 -na, nb = a_red.multiplicative_order(), b_red.multiplicative_order()
+na = a_red.multiplicative_order()
nb = b_red.multiplicative_order() It makes a difference in Cython code. (Related question: do we know anything about the types of some of these variables? This could make the code even faster.) Move the import statement It is only the try:
n = crt(n, v, m, nb)
- m = lcm(m, nb)
except ValueError: # contradictory partial solutions
raise exc(self.modulus())
m = lcm(m, nb) |
comment:3
Overall it looks like a solid improvement, and I agree with Travis's comments. Another minor comment, I would consider storing a list with
but now the code would be more readable and modular. |
comment:5
Thanks for the comments! All done (I think), except for this: Replying to @edgarcosta:
— that's what I had at first, but the current version aborts earlier in some cases. (We don't want to continue running an expensive DLP computation when it's already clear that there will be no solution.) |
comment:6
Makes sense! I will wait for the tests to pass to take a more careful look into it. |
comment:7
Green patchbot. Now to some technical comments: -for kw in kwargs.keys():
+for kw in kwargs: However, while I somewhat understand why you are using Trivial formatting point: We try to follow Python's convention and have error messages starting with a lower case letter. |
comment:8
In terms of math, the code looks good! Once Travis is happy, I will give a positive review. I agree that Optional formatting:
|
comment:9
Replying to @edgarcosta:
I would just leave it out altogether from the documentation since it is deprecated and the warning/code makes it clear that it is. No need to tell a more casual user about something that is disappearing. |
comment:11
Thanks both of you! Done. |
comment:12
Thank you. I am setting this to a positive review from comment:8. Edgar, if there is something else you feel needs to be addressed, feel free to revert the positive review. |
Reviewer: Travis Scrimshaw, Edgar Costa |
comment:13
Thank you, Travis! |
comment:14
|
Branch pushed to git repo; I updated commit sha1. New commits:
|
comment:16
This error is a result of this absolutely hilarious piece of code in except ValueError as ex:
if repr(ex)[12:27] == "No discrete log":
raise The "fix" is easy, but the underlying issue isn't: Has there been any effort to systematize exception types in Sage so that this could be replaced by something along the lines of |
comment:17
That is quite impressive of a failure. The fix LGTM. I don't think there has been, although it could be good to have a |
Changed branch from public/faster_logarithms_in_ZZ_mod_n to |
, sagemath#24483, sagemath#24371, sagemath#24511, sagemath#25848, sagemath#26105, sagemath#28481, sagemath#29010, sagemath#29412, sagemath#30332, sagemath#30372, sagemath#31345, sagemath#32375, sagemath#32606, sagemath#32610, sagemath#32612, sagemath#32641, sagemath#32660, sagemath#32750, sagemath#32869, sagemath#33602 <!-- ^^^^^ Please provide a concise, informative and self-explanatory title. Don't put issue numbers in there, do this in the PR body below. For example, instead of "Fixes sagemath#1234" use "Introduce new method to calculate 1+1" --> <!-- Describe your changes here in detail --> <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes sagemath#12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [ ] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - sagemath#12345: short description why this is a dependency - sagemath#34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: sagemath#36307 Reported by: Matthias Köppe Reviewer(s):
The current logic for
IntegerModRing_abstract.log()
is as follows:logarithm_exists=True
was passed: Call Pari'sznlog
with just the elements.a,b
and (if the logarithm exists) call Pari'sznlog
with the elements and the order ofb
.discrete_log
(i.e., Pohlig–Hellman).The main reason things are done like this appears to be that
znlog
is not guaranteed to terminate if the logarithm doesn't exist, and checking if it exists is not straightforward when the ambient group is non-cyclic. Since we're already at it, here's what Pari does inznlog
:We really shouldn't resort to generic
discrete_log()
right away if the modulus isn't prime: While indeed(ℤ/n)*
is usually non-cyclic, we can typically reduce to the cyclic case using CRT, which we can then pass on to Pari after checking that the logarithm exists (by comparing orders). This patch takes care of this.Summary of the new algorithm:
discrete_log
.znlog
.The reason to treat powers of two differently is that this is the only case where the unit group is not always cyclic, hence we might run into Pari's infinite loop when no solution exists (side note: I'm not sure if this can actually happen, but of course we should rely only on documented behaviour). Since 2-groups are a very easy case for generic
discrete_log()
, we simply deal with that in Sage instead of risking the infinite loop. In all other cases, unit groups modulo prime powers are cyclic, hence we can safely call Pari after checking the orders.I know factoring the modulus looks scary, but let me point out that we're already doing that in all cases:
logarithm_exists=True
is given, the order is factored in Pari first thing.The new doctests introduced in the patch are cases where the old algorithm would take a very long time (if it managed to finish at all without getting killed for lack of memory), whereas the new algorithm takes much less than a second. I also tested the old and new code with thousands of random DLPs modulo (1) random integers, and (2) primes, of sizes up to
2^64
, and there didn't appear to be any noticeable performance degradation even in the previous best case of prime moduli. For composite integers, the new code is unsurprisingly a lot faster on average.I found out about the current, suboptimal implementation here: https://web.archive.org/web/20210813155145/https://cryptohack.gitbook.io/cryptobook/abstract-algebra/groups/untitled
CC: @JohnCremona @kwankyu @defeo @edgarcosta @kedlaya
Component: number theory
Keywords: discrete logarithms, finite rings, composite characteristic
Author: Lorenz Panny
Branch/Commit:
d866118
Reviewer: Travis Scrimshaw, Edgar Costa
Issue created by migration from https://trac.sagemath.org/ticket/32375
The text was updated successfully, but these errors were encountered: