Skip to content

Commit 795383f

Browse files
author
Release Manager
committed
Trac #34728: change sorting for WeierstrassIsomorphism
Currently, `EllipticCurve_generic.automorphisms()` returns the automorphisms in a more or less arbitrary (albeit deterministic) order. It is much more natural to users to receive a list with the identity and negation first, since they exist for any curve, then any other automorphisms that may exist. (I have personally seen code making this incorrect assumption.) In this patch, we change `._comparison_impl()` for `WeierstrassIsomorphism` in such a way that `[1]` and `[-1]` will appear first in a sorted list of automorphisms. Diff without the dependencies: https://git.sagemath.org/sage.git/diff?id 2=d92c9f4e4f671409ff695f4f294240492dbe7c86&id=c9e964632bdfd95c1f89557a5c 7e1ef1c78a794a URL: https://trac.sagemath.org/34728 Reported by: lorenz Ticket author(s): Lorenz Panny Reviewer(s): John Cremona
2 parents 2cec793 + c9e9646 commit 795383f

File tree

2 files changed

+59
-48
lines changed

2 files changed

+59
-48
lines changed

src/sage/schemes/elliptic_curves/ell_generic.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,6 +2429,9 @@ def automorphisms(self, field=None):
24292429
"""
24302430
Return the set of isomorphisms from self to itself (as a list).
24312431
2432+
The identity and negation morphisms are guaranteed to appear
2433+
as the first and second entry of the returned list.
2434+
24322435
INPUT:
24332436
24342437
- ``field`` (default ``None``) -- a field into which the
@@ -2446,23 +2449,52 @@ def automorphisms(self, field=None):
24462449
sage: E = EllipticCurve_from_j(QQ(0)) # a curve with j=0 over QQ
24472450
sage: E.automorphisms()
24482451
[Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2449-
Via: (u,r,s,t) = (-1, 0, 0, -1), Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2450-
Via: (u,r,s,t) = (1, 0, 0, 0)]
2452+
Via: (u,r,s,t) = (1, 0, 0, 0),
2453+
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2454+
Via: (u,r,s,t) = (-1, 0, 0, -1)]
24512455
24522456
We can also find automorphisms defined over extension fields::
24532457
24542458
sage: K.<a> = NumberField(x^2+3) # adjoin roots of unity
24552459
sage: E.automorphisms(K)
24562460
[Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2457-
Via: (u,r,s,t) = (-1, 0, 0, -1),
2458-
...
2459-
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2460-
Via: (u,r,s,t) = (1, 0, 0, 0)]
2461+
Via: (u,r,s,t) = (1, 0, 0, 0),
2462+
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2463+
Via: (u,r,s,t) = (-1, 0, 0, -1),
2464+
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2465+
Via: (u,r,s,t) = (-1/2*a - 1/2, 0, 0, 0),
2466+
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2467+
Via: (u,r,s,t) = (1/2*a + 1/2, 0, 0, -1),
2468+
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2469+
Via: (u,r,s,t) = (1/2*a - 1/2, 0, 0, 0),
2470+
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^2 + 3
2471+
Via: (u,r,s,t) = (-1/2*a + 1/2, 0, 0, -1)]
24612472
24622473
::
24632474
24642475
sage: [len(EllipticCurve_from_j(GF(q,'a')(0)).automorphisms()) for q in [2,4,3,9,5,25,7,49]]
24652476
[2, 24, 2, 12, 2, 6, 6, 6]
2477+
2478+
TESTS:
2479+
2480+
Random testing::
2481+
2482+
sage: p = random_prime(100)
2483+
sage: k = randrange(1,30)
2484+
sage: F.<t> = GF((p,k))
2485+
sage: while True:
2486+
....: try:
2487+
....: E = EllipticCurve(list((F^5).random_element()))
2488+
....: except ArithmeticError:
2489+
....: continue
2490+
....: break
2491+
sage: Aut = E.automorphisms()
2492+
sage: Aut[0] == E.multiplication_by_m_isogeny(1)
2493+
True
2494+
sage: Aut[1] == E.multiplication_by_m_isogeny(-1)
2495+
True
2496+
sage: sorted(Aut) == Aut
2497+
True
24662498
"""
24672499
if field is not None:
24682500
self = self.change_ring(field)
@@ -2492,9 +2524,9 @@ def isomorphisms(self, other, field=None):
24922524
sage: F = EllipticCurve('27a3') # should be the same one
24932525
sage: E.isomorphisms(F)
24942526
[Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2495-
Via: (u,r,s,t) = (-1, 0, 0, -1),
2527+
Via: (u,r,s,t) = (1, 0, 0, 0),
24962528
Elliptic-curve endomorphism of Elliptic Curve defined by y^2 + y = x^3 over Rational Field
2497-
Via: (u,r,s,t) = (1, 0, 0, 0)]
2529+
Via: (u,r,s,t) = (-1, 0, 0, -1)]
24982530
24992531
We can also find isomorphisms defined over extension fields::
25002532

src/sage/schemes/elliptic_curves/weierstrass_morphism.py

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,10 @@
2727

2828
from .constructor import EllipticCurve
2929
from sage.schemes.elliptic_curves.hom import EllipticCurveHom
30-
from sage.structure.richcmp import (richcmp_method, richcmp, richcmp_not_equal,
31-
op_NE)
30+
from sage.structure.richcmp import (richcmp, richcmp_not_equal, op_EQ, op_NE)
3231
from sage.structure.sequence import Sequence
3332
from sage.rings.all import Integer, PolynomialRing
3433

35-
36-
@richcmp_method
3734
class baseWI():
3835
r"""
3936
This class implements the basic arithmetic of isomorphisms between
@@ -87,38 +84,6 @@ def __init__(self, u=1, r=0, s=0, t=0):
8784
self.s = s
8885
self.t = t
8986

90-
def __richcmp__(self, other, op):
91-
"""
92-
Standard comparison function.
93-
94-
The ordering is just lexicographic on the tuple `(u,r,s,t)`.
95-
96-
.. NOTE::
97-
98-
In a list of automorphisms, there is no guarantee that the
99-
identity will be first!
100-
101-
EXAMPLES::
102-
103-
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import baseWI
104-
sage: baseWI(1,2,3,4) == baseWI(1,2,3,4)
105-
True
106-
sage: baseWI(1,2,3,4) != baseWI(1,2,3,4)
107-
False
108-
sage: baseWI(1,2,3,4) < baseWI(1,2,3,5)
109-
True
110-
sage: baseWI(1,2,3,4) > baseWI(1,2,3,4)
111-
False
112-
113-
It will never return equality if ``other`` is of another type::
114-
115-
sage: baseWI() == 1
116-
False
117-
"""
118-
if not isinstance(other, baseWI):
119-
return op == op_NE
120-
return richcmp(self.tuple(), other.tuple(), op)
121-
12287
def tuple(self):
12388
r"""
12489
Return the parameters `u,r,s,t` as a tuple.
@@ -310,8 +275,8 @@ def _isomorphisms(E, F):
310275
....: 2: j not in (0, 1728),
311276
....: 4: p >= 5 and j == 1728,
312277
....: 6: p >= 5 and j == 0,
313-
....: 12: p == 3 and j in (0, 1728),
314-
....: 24: p == 2 and j in (0, 1728),
278+
....: 12: p == 3 and j == 0, # note 1728 == 0
279+
....: 24: p == 2 and j == 0, # note 1728 == 0
315280
....: }[len(Aut)]
316281
True
317282
sage: u,r,s,t = (F^4).random_element()
@@ -543,7 +508,7 @@ def _comparison_impl(left, right, op):
543508
sage: w1 = E.isomorphism_to(F)
544509
sage: w1 == w1
545510
True
546-
sage: w2 = F.automorphisms()[0] * w1
511+
sage: w2 = F.automorphisms()[1] * w1
547512
sage: w1 == w2
548513
False
549514
@@ -572,7 +537,21 @@ def _comparison_impl(left, right, op):
572537
if lx != rx:
573538
return richcmp_not_equal(lx, rx, op)
574539

575-
return baseWI.__richcmp__(left, right, op)
540+
if op in (op_EQ, op_NE):
541+
return richcmp(left.tuple(), right.tuple(), op)
542+
543+
# This makes sure that the identity and negation morphisms
544+
# come first in a sorted list of WeierstrassIsomorphisms.
545+
# More generally, we're making sure that a morphism and its
546+
# negative appear next to each other, and that those pairs
547+
# of isomorphisms satisfying u=+-1 come first.
548+
def _sorting_key(iso):
549+
v, w = iso.tuple(), (-iso).tuple()
550+
i = 0 if (1,0,0,0) in (v,w) else 1
551+
j = 0 if v[0] == 1 else 1 if w[0] == 1 else 2
552+
return (i,) + min(v,w) + (j,) + v
553+
554+
return richcmp(_sorting_key(left), _sorting_key(right), op)
576555

577556
def _eval(self, P):
578557
r"""

0 commit comments

Comments
 (0)