Isogeny class of elliptic curves over number fields#

AUTHORS:

  • David Roe (2012-03-29) – initial version.

  • John Cremona (2014-08) – extend to number fields.

class sage.schemes.elliptic_curves.isogeny_class.IsogenyClass_EC(E, label=None, empty=False)#

Bases: SageObject

Isogeny class of an elliptic curve.

Note

The current implementation chooses a curve from each isomorphism class in the isogeny class. Over \(\QQ\) this is a unique reduced minimal model in each isomorphism class. Over number fields the model chosen may change in future.

graph()#

Return a graph whose vertices correspond to curves in this class, and whose edges correspond to prime degree isogenies.

Note

There are only finitely many possible isogeny graphs for curves over \(\QQ\) [Maz1978b]. This function tries to lay out the graph nicely by special casing each isogeny graph. This could also be done over other number fields, such as quadratic fields.

Note

The vertices are labeled 1 to n rather than 0 to n-1 to match LMFDB and Cremona labels for curves over \(\QQ\).

EXAMPLES:

sage: isocls = EllipticCurve('15a3').isogeny_class()
sage: G = isocls.graph()
sage: sorted(G._pos.items())
[(1, [-0.8660254, 0.5]), (2, [-0.8660254, 1.5]), (3, [-1.7320508, 0]),
 (4, [0, 0]), (5, [0, -1]), (6, [0.8660254, 0.5]),
 (7, [0.8660254, 1.5]), (8, [1.7320508, 0])]
index(C)#

Return the index of a curve in this class.

INPUT:

  • C – an elliptic curve in this isogeny class.

OUTPUT:

  • i – an integer so that the i th curve in the class is isomorphic to C

EXAMPLES:

sage: E = EllipticCurve('990j1')
sage: iso = E.isogeny_class(order="lmfdb") # orders lexicographically on a-invariants
sage: iso.index(E.short_weierstrass_model())
2
isogenies(fill=False)#

Return a list of lists of isogenies and 0s, corresponding to the entries of matrix()

INPUT:

  • fill – boolean (default False). Whether to only return prime degree isogenies. Currently only implemented for fill=False.

OUTPUT:

  • a list of lists, where the j th entry of the i th list is either zero or a prime degree isogeny from the i th curve in this class to the j th curve.

Warning

The domains and codomains of the isogenies will have the same Weierstrass equation as the curves in this class, but they may not be identical python objects in the current implementation.

EXAMPLES:

sage: isocls = EllipticCurve('15a3').isogeny_class()
sage: f = isocls.isogenies()[0][1]; f
Isogeny of degree 2
  from Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 5*x + 2 over Rational Field
    to Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 80*x + 242 over Rational Field
sage: f.domain() == isocls.curves[0] and f.codomain() == isocls.curves[1]
True
matrix(fill=True)#

Return the matrix whose entries give the minimal degrees of isogenies between curves in this class.

INPUT:

  • fill – boolean (default True). If False then the matrix will contain only zeros and prime entries; if True it will fill in the other degrees.

EXAMPLES:

sage: isocls = EllipticCurve('15a3').isogeny_class()
sage: isocls.matrix()
[ 1  2  2  2  4  4  8  8]
[ 2  1  4  4  8  8 16 16]
[ 2  4  1  4  8  8 16 16]
[ 2  4  4  1  2  2  4  4]
[ 4  8  8  2  1  4  8  8]
[ 4  8  8  2  4  1  2  2]
[ 8 16 16  4  8  2  1  4]
[ 8 16 16  4  8  2  4  1]
sage: isocls.matrix(fill=False)
[0 2 2 2 0 0 0 0]
[2 0 0 0 0 0 0 0]
[2 0 0 0 0 0 0 0]
[2 0 0 0 2 2 0 0]
[0 0 0 2 0 0 0 0]
[0 0 0 2 0 0 2 2]
[0 0 0 0 0 2 0 0]
[0 0 0 0 0 2 0 0]
qf_matrix()#

Return the array whose entries are quadratic forms representing the degrees of isogenies between curves in this class (CM case only).

OUTPUT:

a \(2x2\) array (list of lists) of list, each of the form [2] or [2,1,3] representing the coefficients of an integral quadratic form in 1 or 2 variables whose values are the possible isogeny degrees between the i’th and j’th curve in the class.

EXAMPLES:

sage: pol = PolynomialRing(QQ,'x')([1,0,3,0,1])
sage: K.<c> = NumberField(pol)
sage: j = 1480640 + 565760*c^2
sage: E = EllipticCurve(j=j)
sage: C = E.isogeny_class()
sage: C.qf_matrix()
[[[1], [2, 2, 3]], [[2, 2, 3], [1]]]
reorder(order)#

Return a new isogeny class with the curves reordered.

INPUT:

OUTPUT:

  • Another IsogenyClass_EC with the curves reordered (and matrices and maps changed as appropriate)

EXAMPLES:

sage: isocls = EllipticCurve('15a1').isogeny_class()
sage: print("\n".join(repr(C) for C in isocls.curves))
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 10*x - 10 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 5*x + 2 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + 35*x - 28 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 135*x - 660 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 80*x + 242 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 110*x - 880 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 2160*x - 39540 over Rational Field
sage: isocls2 = isocls.reorder('lmfdb')
sage: print("\n".join(repr(C) for C in isocls2.curves))
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 2160*x - 39540 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 135*x - 660 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 110*x - 880 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 80*x + 242 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 10*x - 10 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 5*x + 2 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 over Rational Field
Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 + 35*x - 28 over Rational Field
class sage.schemes.elliptic_curves.isogeny_class.IsogenyClass_EC_NumberField(E, reducible_primes=None, algorithm='Billerey', minimal_models=True)#

Bases: IsogenyClass_EC

Isogeny classes for elliptic curves over number fields.

copy()#

Return a copy (mostly used in reordering).

EXAMPLES:

sage: K.<i> = QuadraticField(-1)
sage: E = EllipticCurve(K, [0,0,0,0,1])
sage: C = E.isogeny_class()
sage: C2 = C.copy()
sage: C is C2
False
sage: C == C2
True
class sage.schemes.elliptic_curves.isogeny_class.IsogenyClass_EC_Rational(E, algorithm='sage', label=None, empty=False)#

Bases: IsogenyClass_EC_NumberField

Isogeny classes for elliptic curves over \(\QQ\).

copy()#

Return a copy (mostly used in reordering).

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: C = E.isogeny_class()
sage: C2 = C.copy()
sage: C is C2
False
sage: C == C2
True
sage.schemes.elliptic_curves.isogeny_class.isogeny_degrees_cm(E, verbose=False)#

Return a list of primes \(\ell\) sufficient to generate the isogeny class of \(E\), where \(E\) has CM.

INPUT:

  • E – An elliptic curve defined over a number field.

OUTPUT:

A finite list of primes \(\ell\) such that every curve isogenous to this curve can be obtained by a finite sequence of isogenies of degree one of the primes in the list. This list is not necessarily minimal.

ALGORITHM:

For curves with CM by the order \(O\) of discriminant \(d\), the Galois representation is always non-surjective and the curve will admit \(\ell\)-isogenies for infinitely many primes \(\ell\), but there are only finitely many codomains \(E'\). The primes can be divided according to the discriminant \(d'\) of the CM order \(O'\) associated to \(E\): either \(O=O'\), or one contains the other with index \(\ell\), since \(\ell O\subset O'\) and vice versa.

Case (1): \(O=O'\). The degrees of all isogenies between \(E\) and \(E'\) are precisely the integers represented by one of the classes of binary quadratic forms \(Q\) of discriminant \(d\). Hence to obtain all possible isomorphism classes of codomain \(E'\), we need only use one prime \(\ell\) represented by each such class \(Q\). It would in fact suffice to use primes represented by forms which generate the class group. Here we simply omit the principal class and one from each pair of inverse classes, and include a prime represented by each of the remaining forms.

Case (2): \([O':O]=\ell\): so \(d=\ell^2d;\). We include all prime divisors of \(d\).

Case (3): \([O:O']=\ell\): we may assume that \(\ell\) does not divide \(d\) as we have already included these, so \(\ell\) either splits or is inert in \(O\); the class numbers satisfy \(h(O')=(\ell\pm1)h(O)\) accordingly. We include all primes \(\ell\) such that \(\ell\pm1\) divides the degree \([K:\QQ]\).

For curves with only potential CM we proceed as in the CM case, using \(2[K:\QQ]\) instead of \([K:\QQ]\).

EXAMPLES:

For curves with CM by a quadratic order of class number greater than \(1\), we use the structure of the class group to only give one prime in each ideal class:

sage: pol = PolynomialRing(QQ,'x')([1,-3,5,-5,5,-3,1])
sage: L.<a> = NumberField(pol)
sage: j = hilbert_class_polynomial(-23).roots(L, multiplicities=False)[0]
sage: E = EllipticCurve(j=j)
sage: from sage.schemes.elliptic_curves.isogeny_class import isogeny_degrees_cm
sage: isogeny_degrees_cm(E, verbose=True)
CM case, discriminant = -23
initial primes: {2}
upward primes: {}
downward ramified primes: {}
downward split primes: {2, 3}
downward inert primes: {5}
primes generating the class group: [2]
Set of primes before filtering: {2, 3, 5}
List of primes after filtering: [2, 3]
[2, 3]
sage.schemes.elliptic_curves.isogeny_class.possible_isogeny_degrees(E, algorithm='Billerey', max_l=None, num_l=None, exact=True, verbose=False)#

Return a list of primes \(\ell\) sufficient to generate the isogeny class of \(E\).

INPUT:

  • E – An elliptic curve defined over a number field.

  • algorithm (string, default 'Billerey') – Algorithm to be used for non-CM curves: either 'Billerey', 'Larson', or 'heuristic'. Only relevant for non-CM curves and base fields other than \(\QQ\).

  • max_l (int or None) – only relevant for non-CM curves and algorithms 'Billerey' and 'heuristic'. Controls the maximum prime used in either algorithm. If None, use the default for that algorithm.

  • num_l (int or None) – only relevant for non-CM curves and algorithm 'Billerey'. Controls the maximum number of primes used in the algorithm. If None, use the default for that algorithm.

  • exact (bool, default True) – if True, perform an additional check that the primes returned are all reducible. If False, skip this step, in which case some of the primes returned may be irreducible.

OUTPUT:

A finite list of primes \(\ell\) such that every curve isogenous to this curve can be obtained by a finite sequence of isogenies of degree one of the primes in the list.

ALGORITHM:

For curves without CM, the set may be taken to be the finite set of primes at which the Galois representation is not surjective, since the existence of an \(\ell\)-isogeny is equivalent to the image of the mod-\(\ell\) Galois representation being contained in a Borel subgroup. Two rigorous algorithms have been implemented to determine this set, due to Larson and Billeray respectively. We also provide a non-rigorous ‘heuristic’ algorithm which only tests reducible primes up to a bound depending on the degree of the base field.

For curves with CM see the documentation for isogeny_degrees_cm().

EXAMPLES:

For curves without CM we determine the primes at which the mod \(p\) Galois representation is reducible, i.e. contained in a Borel subgroup:

sage: from sage.schemes.elliptic_curves.isogeny_class import possible_isogeny_degrees
sage: E = EllipticCurve('11a1')
sage: possible_isogeny_degrees(E)
[5]
sage: possible_isogeny_degrees(E, algorithm='Larson')
[5]
sage: possible_isogeny_degrees(E, algorithm='Billerey')
[5]
sage: possible_isogeny_degrees(E, algorithm='heuristic')
[5]

We check that in this case \(E\) really does have rational \(5\)-isogenies:

sage: [phi.degree() for phi in E.isogenies_prime_degree()]
[5, 5]

Over an extension field:

sage: E3 = E.change_ring(CyclotomicField(3))
sage: possible_isogeny_degrees(E3)
[5]
sage: [phi.degree() for phi in E3.isogenies_prime_degree()]
[5, 5]

A higher degree example (LMFDB curve 5.5.170701.1-4.1-b1):

sage: K.<a> = NumberField(x^5 - x^4 - 6*x^3 + 4*x + 1)
sage: E = EllipticCurve(K, [a^3 - a^2 - 5*a + 1, a^4 - a^3 - 5*a^2 - a + 1,
....:                       -a^4 + 2*a^3 + 5*a^2 - 5*a - 3, a^4 - a^3 - 5*a^2 - a,
....:                       -3*a^4 + 4*a^3 + 17*a^2 - 6*a - 12])
sage: possible_isogeny_degrees(E, algorithm='heuristic')
[2]
sage: possible_isogeny_degrees(E, algorithm='Billerey')
[2]
sage: possible_isogeny_degrees(E, algorithm='Larson')
[2]

LMFDB curve 4.4.8112.1-108.1-a5:

sage: K.<a> = NumberField(x^4 - 5*x^2 + 3)
sage: E = EllipticCurve(K, [a^2 - 2, -a^2 + 3, a^2 - 2, -50*a^2 + 35, 95*a^2 - 67])
sage: possible_isogeny_degrees(E, exact=False, algorithm='Billerey')
[2, 5]
sage: possible_isogeny_degrees(E, exact=False, algorithm='Larson')
[2, 5]
sage: possible_isogeny_degrees(E, exact=False, algorithm='heuristic')
[2, 5]
sage: possible_isogeny_degrees(E)
[2, 5]

This function only returns the primes which are isogeny degrees:

sage: Set(E.isogeny_class().matrix().list())
{1, 2, 4, 5, 20, 10}

For curves with CM by a quadratic order of class number greater than \(1\), we use the structure of the class group to only give one prime in each ideal class:

sage: pol = PolynomialRing(QQ,'x')([1,-3,5,-5,5,-3,1])
sage: L.<a> = NumberField(pol)
sage: j = hilbert_class_polynomial(-23).roots(L, multiplicities=False)[0]
sage: E = EllipticCurve(j=j)
sage: from sage.schemes.elliptic_curves.isogeny_class import possible_isogeny_degrees
sage: possible_isogeny_degrees(E, verbose=True)
CM case, discriminant = -23
initial primes: {2}
upward primes: {}
downward ramified primes: {}
downward split primes: {2, 3}
downward inert primes: {5}
primes generating the class group: [2]
Set of primes before filtering: {2, 3, 5}
List of primes after filtering: [2, 3]
[2, 3]