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

Compute composite degree (separable) isogenies of EllipticCurves #35949

Merged
merged 28 commits into from
Nov 3, 2024

Conversation

grhkm21
Copy link
Contributor

@grhkm21 grhkm21 commented Jul 13, 2023

  • Implement .isogenies_degree for EllipticCurves

📝 Checklist

  • The title is concise, informative, and self-explanatory.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation accordingly.

⌛ Dependencies

This supports computing (separable) isogenies of composite degree. It is
generic and calls `.isogenies_prime_degree`.
Copy link
Member

@yyyyx4 yyyyx4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the few small remarks, looks good to me!

src/sage/schemes/elliptic_curves/ell_field.py Outdated Show resolved Hide resolved
src/sage/schemes/elliptic_curves/ell_field.py Show resolved Hide resolved
src/sage/schemes/elliptic_curves/ell_field.py Outdated Show resolved Hide resolved
Thanks Lorenz for the review <3

Co-authored-by: Lorenz Panny <84067835+yyyyx4@users.noreply.github.com>
@grhkm21
Copy link
Contributor Author

grhkm21 commented Nov 6, 2023

Thanks for the review :)

Yes.

Co-authored-by: Lorenz Panny <84067835+yyyyx4@users.noreply.github.com>
Copy link
Member

@yyyyx4 yyyyx4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the smaller code remarks above below, I'm also wondering if this should be an iterator: The list can grow very quickly, so doing it as a depth-first iterator might be a good idea?

src/sage/schemes/elliptic_curves/ell_field.py Outdated Show resolved Hide resolved
src/sage/schemes/elliptic_curves/ell_field.py Outdated Show resolved Hide resolved
src/sage/schemes/elliptic_curves/ell_field.py Outdated Show resolved Hide resolved
src/sage/schemes/elliptic_curves/ell_field.py Outdated Show resolved Hide resolved
@grhkm21
Copy link
Contributor Author

grhkm21 commented Feb 12, 2024

I swear I wrote some code similar to the previous two commits, but somehow didn't commit it, and it's not in my git stash either. Anyways, please kindly review it once again :) it's very short now.

@grhkm21 grhkm21 requested a review from yyyyx4 February 12, 2024 15:54
Copy link

github-actions bot commented Feb 12, 2024

Documentation preview for this PR (built with commit 7391752; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@yyyyx4
Copy link
Member

yyyyx4 commented Feb 13, 2024

There are duplicates in the list as soon as any prime appears with multiplicity 3 or more in the degree:

sage: E = EllipticCurve(GF(11^2), [1,0])
sage: len(list(E.isogenies_degree(2^3)))
27
sage: len(set(E.isogenies_degree(2^3)))
15

To fix it, we could restrict to cyclic isogenies:

sage: P,Q = E.torsion_basis(2)
sage: len([phi for phi in E.isogenies_degree(2^3) if phi(P) or phi(Q)])
12
sage: len({phi for phi in E.isogenies_degree(2^3) if phi(P) or phi(Q)})
12

Returning only cyclic isogenies is arguably "better" anyway, since non-cyclic isogenies could be considered somewhat degenerate among the set of all isogenies of given degree. However, adding this check will make the code quite a bit more complicated. I'm unsure how to proceed.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Feb 13, 2024

Oh right, sorry for missing that. We can have a check to ensure we are not taking the dual isogeny of the previous taken one, since the prime degrees considered are sorted.

@hellman
Copy link

hellman commented Feb 13, 2024

I think it would be useful to have an phi1.is_dual_of(phi2) method (up to isomorphism check). I also need something like for mitm.

But if we add it to the EllipticCurveHom class, it should be generic (e.g. factor the degree?), which could introduce an overhead.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Aug 9, 2024

hi. i am back on this pr

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

Btw one problem I'm trying to fix in the past few commits is that the only way the new compare_via_evaluation calling _has_order_at_least can return False right now is if the ._order (cached order) is computed already, but that's not the case for compare_via_evaluation. As a result, if a point has finite order, your _has_order_at_least will use all $999$ attempts to prove that it has finite order. Therefore, we want to use the information about n.

One method I'm trying is to keep track of P * n as n goes, but over number fields the coefficients go crazy large, even though the polynomial degree is bounded by the number field degree.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

Even simple optimisations like all(not Q.is_zero() for Q in multiples(P, bound)) or something when bound is small just becomes infeasible when the number field degree is say > 10?

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

I have this patch, but I'll experiment more with it first. Back later..

diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py
index 77d9f6e981d..1b8859f166a 100755
--- a/src/sage/schemes/elliptic_curves/ell_point.py
+++ b/src/sage/schemes/elliptic_curves/ell_point.py
@@ -121,6 +121,7 @@ import sage.groups.generic as generic
 import sage.rings.abc
 
 from sage.misc.lazy_import import lazy_import
+from sage.groups.generic import order_from_multiple
 from sage.rings.finite_rings.integer_mod import Mod
 from sage.rings.infinity import Infinity as oo
 from sage.rings.integer import Integer
@@ -134,6 +135,7 @@ from sage.schemes.projective.projective_point import (SchemeMorphism_point_proje
                                                       SchemeMorphism_point_abelian_variety_field)
 from sage.structure.coerce_actions import IntegerMulAction
 from sage.structure.element import AdditiveGroupElement
+from sage.structure.factorization import Factorization
 from sage.structure.richcmp import richcmp
 from sage.structure.sequence import Sequence
 
@@ -2599,7 +2601,6 @@ class EllipticCurvePoint_number_field(EllipticCurvePoint_field):
         from sage.sets.primes import Primes
         from sage.rings.finite_rings.finite_field_constructor import GF
         field_deg = self.curve().base_field().absolute_degree()
-        print("field_deg:", field_deg)
         if field_deg > 1:
             K = self.curve().base_field().absolute_field('T')
             _, iso = K.structure()
@@ -2616,11 +2617,8 @@ class EllipticCurvePoint_number_field(EllipticCurvePoint_field):
             bound = min(bound, 12 + 1)
         assert P.curve() is E
 
-        if bound <= 20:
-            # fast path for testing small orders
-            return not any((P * i).is_zero() for i in range(1, bound))
-
-        n = ZZ.one()
+        n = Factorization([])
+        Pmul = P
         no_progress = 0
         for p in Primes():
             try:
@@ -2636,18 +2634,23 @@ class EllipticCurvePoint_number_field(EllipticCurvePoint_field):
             except (ZeroDivisionError, ArithmeticError):
                 continue
 
-            o = Pred.order()
-            if not o.divides(n):
-                n = n.lcm(o)
+            o = Pred.order().factor()
+            if not o.value().divides(n.value()):
+                g = n.gcd(o)
+                n *= g
+                if n.value() >= bound:
+                    return True
+
+                Pmul *= g.value()
+                if Pmul.is_zero():
+                    self.set_order(n.value())
+                    return n.value() >= bound
                 no_progress = 0
             else:
                 no_progress += 1
 
-            if n >= bound:
-                return True
             if no_progress >= attempts:
                 return
-            print("n:", n)
 
         assert False  # unreachable unless there are only finitely many primes

I'm quite certain Pmul *= g.value() would be very slow when the point order is infinite, so maybe we should defer that multiplication to when no_progress is going on for a long time.

@yyyyx4
Copy link
Member

yyyyx4 commented Oct 17, 2024

Just to clarify, is the version I had still too slow for the tests here? If it isn't, I'd suggest merging this soon, and other speedups for comparing isogenies over number fields could still be added in a later patch.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

Hey, thanks for the reminder. Actually yes your version is fast enough in many cases. I will remove my debug output and let's get this merged. I will continue thinking about faster number field isogeny comparisons in another PR.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

tested the problematic files locally and seems fine.

@yyyyx4
Copy link
Member

yyyyx4 commented Oct 17, 2024

Tiny (optional) suggestion: Rename .isogenies_degree() to .isogenies_of_degree() for grammar?

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

Hmm, then we shouold change to isogenies_of_prime_degree as well. As a user if I found out about isogenies_prime_degree but I don't want prime then I'll probably try isogenies_degree 🤔

@yyyyx4
Copy link
Member

yyyyx4 commented Oct 17, 2024

I'd argue that .isogenies_prime_degree() could eventually become internal, even. It is a special case of this more general method after all.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 17, 2024

Oh, that is true. That'll be a year down the line though

Copy link
Member

@S17A05 S17A05 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one more small thing (plus the name change suggested by @yyyyx4, in case you want to implement it now), then I will approve

src/sage/schemes/elliptic_curves/ell_point.py Outdated Show resolved Hide resolved
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 17, 2024
    
Here we add two fast checks to the generic comparison method for
elliptic-curve morphisms that will quickly detect some pairs of unequal
morphisms. In the context of sagemath#35949, this speeds up the following
example from 5.9 seconds to 1.8 seconds:
```sage
sage: E = EllipticCurve(GF((5, 2)), [0,1])
sage: %time _ = list(E.isogenies_degree(27))
```
    
URL: sagemath#38808
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 18, 2024
    
Here we add two fast checks to the generic comparison method for
elliptic-curve morphisms that will quickly detect some pairs of unequal
morphisms. In the context of sagemath#35949, this speeds up the following
example from 5.9 seconds to 1.8 seconds:
```sage
sage: E = EllipticCurve(GF((5, 2)), [0,1])
sage: %time _ = list(E.isogenies_degree(27))
```
    
URL: sagemath#38808
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 20, 2024
    
Here we add two fast checks to the generic comparison method for
elliptic-curve morphisms that will quickly detect some pairs of unequal
morphisms. In the context of sagemath#35949, this speeds up the following
example from 5.9 seconds to 1.8 seconds:
```sage
sage: E = EllipticCurve(GF((5, 2)), [0,1])
sage: %time _ = list(E.isogenies_degree(27))
```
    
URL: sagemath#38808
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 23, 2024
    
Here we add two fast checks to the generic comparison method for
elliptic-curve morphisms that will quickly detect some pairs of unequal
morphisms. In the context of sagemath#35949, this speeds up the following
example from 5.9 seconds to 1.8 seconds:
```sage
sage: E = EllipticCurve(GF((5, 2)), [0,1])
sage: %time _ = list(E.isogenies_degree(27))
```
    
URL: sagemath#38808
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
vbraun pushed a commit to vbraun/sage that referenced this pull request Oct 26, 2024
    
Here we add two fast checks to the generic comparison method for
elliptic-curve morphisms that will quickly detect some pairs of unequal
morphisms. In the context of sagemath#35949, this speeds up the following
example from 5.9 seconds to 1.8 seconds:
```sage
sage: E = EllipticCurve(GF((5, 2)), [0,1])
sage: %time _ = list(E.isogenies_degree(27))
```
    
URL: sagemath#38808
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
@yyyyx4
Copy link
Member

yyyyx4 commented Oct 27, 2024

Needs rebase, apparently.

@grhkm21
Copy link
Contributor Author

grhkm21 commented Oct 27, 2024

Thanks! Done. Fun fact, the latest commit hash starts with 73917522060. 11 digits! (0.5%)

@yyyyx4
Copy link
Member

yyyyx4 commented Oct 27, 2024

Thanks! Let's finally get this merged. 🥳

@vbraun vbraun merged commit a6ada92 into sagemath:develop Nov 3, 2024
17 of 22 checks passed
yyyyx4 added a commit to yyyyx4/sage that referenced this pull request Nov 22, 2024
vbraun pushed a commit to vbraun/sage that referenced this pull request Dec 6, 2024
…h#35949

    
...as suggested by the comment in the code.
    
URL: sagemath#39019
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
vbraun pushed a commit to vbraun/sage that referenced this pull request Dec 8, 2024
…h#35949

    
...as suggested by the comment in the code.
    
URL: sagemath#39019
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
vbraun pushed a commit to vbraun/sage that referenced this pull request Dec 8, 2024
…h#35949

    
...as suggested by the comment in the code.
    
URL: sagemath#39019
Reported by: Lorenz Panny
Reviewer(s): Sebastian A. Spindler
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants