Skip to content

Commit d4075f1

Browse files
author
Release Manager
committed
gh-37242: Improved algorithm choice for isogeny computation Improved the logic for algorithm choice in `EllipticCurve_field.isogeny()`: - if we have multiple points, `factored` is used; - if the order is known and composite, `factored` is used; - if the order is known and (pseudo-)prime, we chose between the traditional Velù formulae and Velù-sqrt, depending on a parameter; this parameter may be supplied by the user with the `velu_sqrt_bound` argument, and if `None` a global parameter is used (see below); - in all the other cases we fall back to the traditional isogeny algorithm. The new `velu_sqrt_bound`: - can be supplied as a parameter when calling `.isogeny()`; - if supplied, is recursively passed to all calls to `factored`, such that each single isogeny computation has the same bound; - if not supplied, a global value is used instead; this is stored in the object `_velu_sqrt_bound` from `sage.schemes.elliptic_curves.hom_velusqrt`, and is initially set to 1000 (due to empirical observations) but can be manually set at runtime by the user #sd123 URL: #37242 Reported by: Riccardo Invernizzi Reviewer(s): Giacomo Pope, grhkm21, Riccardo Invernizzi
2 parents 5430775 + b4408ab commit d4075f1

File tree

6 files changed

+238
-41
lines changed

6 files changed

+238
-41
lines changed

src/sage/schemes/elliptic_curves/ell_curve_isogeny.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -867,9 +867,9 @@ class EllipticCurveIsogeny(EllipticCurveHom):
867867
868868
sage: E = EllipticCurve(j=GF(7)(0))
869869
sage: phi = E.isogeny([E(0), E((0,1)), E((0,-1))]); phi
870-
Isogeny of degree 3
871-
from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
872-
to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
870+
Composite morphism of degree 3:
871+
From: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
872+
To: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
873873
sage: phi2 = phi * phi; phi2
874874
Composite morphism of degree 9 = 3^2:
875875
From: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7

src/sage/schemes/elliptic_curves/ell_field.py

Lines changed: 155 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,17 +1157,28 @@ def _Hom_(self, other, category=None):
11571157
from sage.schemes.generic.homset import SchemeHomset_generic
11581158
return SchemeHomset_generic(self, other, category=category)
11591159

1160-
def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, algorithm=None):
1160+
def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, algorithm=None, velu_sqrt_bound=None):
11611161
r"""
11621162
Return an elliptic-curve isogeny from this elliptic curve.
11631163
11641164
The isogeny can be specified in two ways, by passing either a
11651165
polynomial or a set of torsion points. The methods used are:
11661166
1167+
- Factored Isogenies (see
1168+
:mod:`~sage.schemes.elliptic_curves.hom_composite`):
1169+
Given a point, or a list of points which generate a
1170+
composite-order subgroup, decomposes the isogeny into
1171+
prime-degree steps. This can be used to construct isogenies
1172+
of extremely large, smooth degree. When applicable, this
1173+
algorithm is selected as default (see below). After factoring
1174+
the degree single isogenies are computed using the other
1175+
methods.
1176+
This algorithm is selected using ``algorithm="factored"``.
1177+
11671178
- Vélu's Formulas: Vélu's original formulas for computing
11681179
isogenies. This algorithm is selected by giving as the
1169-
``kernel`` parameter a single point, or a list of points,
1170-
generating a finite subgroup.
1180+
``kernel`` parameter a single point generating a finite
1181+
subgroup.
11711182
11721183
- Kohel's Formulas: Kohel's original formulas for computing
11731184
isogenies. This algorithm is selected by giving as the
@@ -1184,14 +1195,6 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
11841195
kernel point of odd order `\geq 5`.
11851196
This algorithm is selected using ``algorithm="velusqrt"``.
11861197
1187-
- Factored Isogenies (see
1188-
:mod:`~sage.schemes.elliptic_curves.hom_composite`):
1189-
Given a list of points which generate a composite-order
1190-
subgroup, decomposes the isogeny into prime-degree steps.
1191-
This can be used to construct isogenies of extremely large,
1192-
smooth degree.
1193-
This algorithm is selected using ``algorithm="factored"``.
1194-
11951198
INPUT:
11961199
11971200
- ``kernel`` -- a kernel: either a point on this curve, a list of
@@ -1234,10 +1237,7 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
12341237
- ``check`` (default: ``True``) -- check whether the input is valid.
12351238
Setting this to ``False`` can lead to significant speedups.
12361239
1237-
- ``algorithm`` -- string (optional). By default (when ``algorithm``
1238-
is omitted), the "traditional" implementation
1239-
:class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny`
1240-
is used. The other choices are:
1240+
- ``algorithm`` -- string (optional). The possible choices are:
12411241
12421242
- ``"velusqrt"``: Use
12431243
:class:`~sage.schemes.elliptic_curves.hom_velusqrt.EllipticCurveHom_velusqrt`.
@@ -1246,8 +1246,36 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
12461246
:class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite`
12471247
to decompose the isogeny into prime-degree steps.
12481248
1249-
The ``degree`` parameter is not supported when an ``algorithm``
1250-
is specified.
1249+
- ``"traditional"``: Use
1250+
:class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny`.
1251+
1252+
When ``algorithm`` is not specified, and ``kernel`` is not ``None``, an
1253+
algorithm is selected using the following criteria:
1254+
1255+
- if ``kernel`` is a list of multiple points, ``"factored"`` is selected.
1256+
1257+
- If ``kernel`` is a single point, or a list containing a single point:
1258+
1259+
- if the order of the point is unknown, ``"traditional"`` is selected.
1260+
1261+
- If the order is known and composite, ``"factored"`` is selected.
1262+
1263+
- If the order is known and prime, a choice between ``"velusqrt"`` and
1264+
``"traditional"`` is done according to the ``velu_sqrt_bound``
1265+
parameter (see below).
1266+
1267+
If none of the previous apply, ``"traditional"`` is selected.
1268+
1269+
- ``velu_sqrt_bound`` -- an integer (default: ``None``). Establish the highest
1270+
(prime) degree for which the ``"traditional"`` algorithm should be selected
1271+
instead of ``"velusqrt"``. If ``None``, the default value from
1272+
:class:`~sage.schemes.elliptic_curves.hom_velusqrt._VeluBoundObj` is used.
1273+
This value is initially set to 1000, but can be modified by the user.
1274+
If an integer is supplied and the isogeny computation goes through the
1275+
``"factored"`` algorithm, the same integer is supplied to each factor.
1276+
1277+
The ``degree`` parameter is not supported when an ``algorithm`` is
1278+
specified.
12511279
12521280
OUTPUT:
12531281
@@ -1283,9 +1311,9 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
12831311
sage: (P.order(), Q.order())
12841312
(7, 3)
12851313
sage: phi = E.isogeny([P,Q]); phi
1286-
Isogeny of degree 21
1287-
from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
1288-
to Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
1314+
Composite morphism of degree 21 = 7*3:
1315+
From: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
1316+
To: Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
12891317
sage: phi(E.random_point()) # all points defined over GF(19) are in the kernel
12901318
(0 : 1 : 0)
12911319
@@ -1310,6 +1338,62 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
13101338
subgroup of Elliptic Curve defined by y^2 + x*y = x^3 + x + 2
13111339
over Finite Field of size 31
13121340
1341+
Order of the point known and composite::
1342+
1343+
sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
1344+
sage: P = E(26, 4)
1345+
sage: assert P.order() == 12
1346+
sage: print(P._order)
1347+
12
1348+
sage: E.isogeny(P)
1349+
Composite morphism of degree 12 = 2^2*3:
1350+
From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
1351+
To: Elliptic Curve defined by y^2 + x*y = x^3 + 26*x + 8 over Finite Field of size 31
1352+
1353+
``kernel`` is a list of points::
1354+
1355+
sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
1356+
sage: P = E(21,2)
1357+
sage: Q = E(7, 12)
1358+
sage: print(P.order())
1359+
6
1360+
sage: print(Q.order())
1361+
2
1362+
sage: E.isogeny([P, Q])
1363+
Composite morphism of degree 12 = 2*3*2:
1364+
From: Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
1365+
To: Elliptic Curve defined by y^2 + x*y = x^3 + 2*x + 26 over Finite Field of size 31
1366+
1367+
Multiple ways to set the `velu_sqrt_bound`::
1368+
1369+
sage: E = EllipticCurve_from_j(GF(97)(42))
1370+
sage: P = E.gens()[0]*4
1371+
sage: print(P.order())
1372+
23
1373+
sage: E.isogeny(P)
1374+
Isogeny of degree 23 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 72*x + 29 over Finite Field of size 97
1375+
sage: E.isogeny(P, velu_sqrt_bound=10)
1376+
Elliptic-curve isogeny (using square-root Vélu) of degree 23:
1377+
From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
1378+
To: Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
1379+
sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1380+
sage: _velu_sqrt_bound.set(10)
1381+
sage: E.isogeny(P)
1382+
Elliptic-curve isogeny (using square-root Vélu) of degree 23:
1383+
From: Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97
1384+
To: Elliptic Curve defined by y^2 = x^3 + 95*x + 68 over Finite Field of size 97
1385+
sage: _velu_sqrt_bound.set(1000) # Reset bound
1386+
1387+
If the order of the point is unknown, fall back to ``"traditional"``::
1388+
1389+
sage: E = EllipticCurve_from_j(GF(97)(42))
1390+
sage: P = E(2, 39)
1391+
sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1392+
sage: _velu_sqrt_bound.set(1)
1393+
sage: E.isogeny(P)
1394+
Isogeny of degree 46 from Elliptic Curve defined by y^2 = x^3 + 6*x + 46 over Finite Field of size 97 to Elliptic Curve defined by y^2 = x^3 + 87*x + 47 over Finite Field of size 97
1395+
sage: _velu_sqrt_bound.set(1000) # Reset bound
1396+
13131397
.. SEEALSO::
13141398
13151399
- :class:`~sage.schemes.elliptic_curves.hom.EllipticCurveHom`
@@ -1342,6 +1426,27 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
13421426
sage: phi = E.isogeny(E.lift_x(77347718128277853096420969229987528666))
13431427
sage: phi.codomain()._order
13441428
170141183460469231746191640949390434666
1429+
1430+
Check that ``"factored"`` recursively apply `velu_sqrt_bound`::
1431+
1432+
sage: from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1433+
sage: _velu_sqrt_bound.get()
1434+
1000
1435+
sage: _velu_sqrt_bound.set(50)
1436+
sage: _velu_sqrt_bound.get()
1437+
50
1438+
sage: from sage.schemes.elliptic_curves import hom_composite
1439+
sage: p = 3217
1440+
sage: E = EllipticCurve_from_j(GF(p)(42))
1441+
sage: P = E.gens()[0]
1442+
sage: phis = hom_composite._compute_factored_isogeny_single_generator(P, velu_sqrt_bound=50)
1443+
sage: for phi in phis:
1444+
....: print(phi)
1445+
....:
1446+
Isogeny of degree 31 from Elliptic Curve defined by y^2 = x^3 + 114*x + 544 over Finite Field of size 3217 to Elliptic Curve defined by y^2 = x^3 + 277*x + 1710 over Finite Field of size 3217
1447+
Elliptic-curve isogeny (using square-root Vélu) of degree 103:
1448+
From: Elliptic Curve defined by y^2 = x^3 + 277*x + 1710 over Finite Field of size 3217
1449+
To: Elliptic Curve defined by y^2 = x^3 + 2979*x + 1951 over Finite Field of size 3217
13451450
"""
13461451
if algorithm is not None and degree is not None:
13471452
raise TypeError('cannot pass "degree" and "algorithm" parameters simultaneously')
@@ -1350,7 +1455,36 @@ def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, al
13501455
return EllipticCurveHom_velusqrt(self, kernel, codomain=codomain, model=model)
13511456
if algorithm == "factored":
13521457
from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
1353-
return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model)
1458+
return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model, velu_sqrt_bound=velu_sqrt_bound)
1459+
if algorithm == "traditional":
1460+
return EllipticCurveIsogeny(self, kernel, codomain, degree, model, check=check)
1461+
1462+
if kernel is not None:
1463+
# Check for multiple points or point of known order
1464+
kernel_is_list = isinstance(kernel, list) or isinstance(kernel, tuple)
1465+
if kernel_is_list and kernel[0] in self and len(kernel) > 1:
1466+
from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
1467+
return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model, velu_sqrt_bound=velu_sqrt_bound)
1468+
1469+
if not kernel_is_list or (len(kernel) == 1 and kernel[0] in self):
1470+
# Single point on the curve; unpack the list for compatibility with velusqrt
1471+
if kernel_is_list:
1472+
kernel = kernel[0]
1473+
1474+
known_order = hasattr(kernel, "_order")
1475+
1476+
if known_order and kernel._order.is_pseudoprime():
1477+
if not velu_sqrt_bound:
1478+
from sage.schemes.elliptic_curves.hom_velusqrt import _velu_sqrt_bound
1479+
velu_sqrt_bound = _velu_sqrt_bound.get()
1480+
1481+
if kernel._order > velu_sqrt_bound:
1482+
from sage.schemes.elliptic_curves.hom_velusqrt import EllipticCurveHom_velusqrt
1483+
return EllipticCurveHom_velusqrt(self, kernel, codomain=codomain, model=model)
1484+
# Otherwise fall back to the standard case
1485+
elif known_order:
1486+
from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
1487+
return EllipticCurveHom_composite(self, kernel, codomain=codomain, model=model, velu_sqrt_bound=velu_sqrt_bound)
13541488
try:
13551489
return EllipticCurveIsogeny(self, kernel, codomain, degree, model, check=check)
13561490
except AttributeError as e:

src/sage/schemes/elliptic_curves/ell_point.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,8 @@ def order(self):
487487
sage: E(0).order() == 1
488488
True
489489
"""
490-
try:
490+
if hasattr(self, "_order"):
491491
return self._order
492-
except AttributeError:
493-
pass
494492
if self.is_zero():
495493
self._order = Integer(1)
496494
return self._order

src/sage/schemes/elliptic_curves/hom.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def __init__(self, *args, **kwds):
5656
sage: E.isogeny(P) # indirect doctest
5757
Isogeny of degree 127 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field in z2 of size 257^2 to Elliptic Curve defined by y^2 = x^3 + 151*x + 22 over Finite Field in z2 of size 257^2
5858
sage: E.isogeny(P, algorithm='factored') # indirect doctest
59-
Composite morphism of degree 127 = 127:
59+
Composite morphism of degree 127:
6060
From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field in z2 of size 257^2
6161
To: Elliptic Curve defined by y^2 = x^3 + 151*x + 22 over Finite Field in z2 of size 257^2
6262
sage: E.isogeny(P, algorithm='velusqrt') # indirect doctest
@@ -755,11 +755,9 @@ def is_separable(self):
755755
sage: E = EllipticCurve(GF(7^2), [3,2])
756756
sage: P = E.lift_x(1)
757757
sage: phi = EllipticCurveHom_composite(E, P); phi
758-
Composite morphism of degree 7 = 7:
759-
From: Elliptic Curve defined by y^2 = x^3 + 3*x + 2
760-
over Finite Field in z2 of size 7^2
761-
To: Elliptic Curve defined by y^2 = x^3 + 3*x + 2
762-
over Finite Field in z2 of size 7^2
758+
Composite morphism of degree 7:
759+
From: Elliptic Curve defined by y^2 = x^3 + 3*x + 2 over Finite Field in z2 of size 7^2
760+
To: Elliptic Curve defined by y^2 = x^3 + 3*x + 2 over Finite Field in z2 of size 7^2
763761
sage: phi.is_separable()
764762
True
765763

0 commit comments

Comments
 (0)