Elliptic curves over a general field#

This module defines the class EllipticCurve_field, based on EllipticCurve_generic, for elliptic curves over general fields.

class sage.schemes.elliptic_curves.ell_field.EllipticCurve_field(K, ainvs)#

Bases: EllipticCurve_generic, ProjectivePlaneCurve_field

base_field()#

Return the base ring of the elliptic curve.

EXAMPLES:

sage: E = EllipticCurve(GF(49, 'a'), [3,5])                                 # needs sage.rings.finite_rings
sage: E.base_ring()                                                         # needs sage.rings.finite_rings
Finite Field in a of size 7^2
E = EllipticCurve(GF(49, 'a'), [3,5])                                 # needs sage.rings.finite_rings
E.base_ring()                                                         # needs sage.rings.finite_rings
sage: E = EllipticCurve([1,1])
sage: E.base_ring()
Rational Field
E = EllipticCurve([1,1])
E.base_ring()
sage: E = EllipticCurve(ZZ, [3,5])
sage: E.base_ring()
Integer Ring
E = EllipticCurve(ZZ, [3,5])
E.base_ring()
descend_to(K, f=None)#

Given an elliptic curve self defined over a field L and a subfield K of L, return all elliptic curves over K which are isomorphic over L to self.

INPUT:

  • K – a field which embeds into the base field L of self.

  • f (optional) – an embedding of K into L. Ignored if K is Q.

OUTPUT:

A list (possibly empty) of elliptic curves defined over K which are isomorphic to self over L, up to isomorphism over K.

Note

Currently only implemented over number fields. To extend to other fields of characteristic not 2 or 3, what is needed is a method giving the preimages in K/(K)m of an element of the base field, for m=2,4,6.

EXAMPLES:

sage: E = EllipticCurve([1,2,3,4,5])
sage: E.descend_to(ZZ)
Traceback (most recent call last):
...
TypeError: Input must be a field.
E = EllipticCurve([1,2,3,4,5])
E.descend_to(ZZ)
sage: # needs sage.rings.number_field
sage: F.<b> = QuadraticField(23)
sage: x = polygen(ZZ, 'x')
sage: G.<a> = F.extension(x^3 + 5)
sage: E = EllipticCurve(j=1728*b).change_ring(G)
sage: EF = E.descend_to(F); EF
[Elliptic Curve defined by y^2 = x^3 + (27*b-621)*x + (-1296*b+2484)
  over Number Field in b with defining polynomial x^2 - 23
  with b = 4.795831523312720?]
sage: all(Ei.change_ring(G).is_isomorphic(E) for Ei in EF)
True
# needs sage.rings.number_field
F.<b> = QuadraticField(23)
x = polygen(ZZ, 'x')
G.<a> = F.extension(x^3 + 5)
E = EllipticCurve(j=1728*b).change_ring(G)
EF = E.descend_to(F); EF
all(Ei.change_ring(G).is_isomorphic(E) for Ei in EF)
sage: # needs sage.rings.number_field
sage: L.<a> = NumberField(x^4 - 7)
sage: K.<b> = NumberField(x^2 - 7, embedding=a^2)
sage: E = EllipticCurve([a^6, 0])
sage: EK = E.descend_to(K); EK
[Elliptic Curve defined by y^2 = x^3 + b*x over Number Field in b
  with defining polynomial x^2 - 7 with b = a^2,
 Elliptic Curve defined by y^2 = x^3 + 7*b*x over Number Field in b
  with defining polynomial x^2 - 7 with b = a^2]
sage: all(Ei.change_ring(L).is_isomorphic(E) for Ei in EK)
True
# needs sage.rings.number_field
L.<a> = NumberField(x^4 - 7)
K.<b> = NumberField(x^2 - 7, embedding=a^2)
E = EllipticCurve([a^6, 0])
EK = E.descend_to(K); EK
all(Ei.change_ring(L).is_isomorphic(E) for Ei in EK)
sage: K.<a> = QuadraticField(17)                                            # needs sage.rings.number_field
sage: E = EllipticCurve(j=2*a)                                              # needs sage.rings.number_field
sage: E.descend_to(QQ)                                                      # needs sage.rings.number_field
[]
K.<a> = QuadraticField(17)                                            # needs sage.rings.number_field
E = EllipticCurve(j=2*a)                                              # needs sage.rings.number_field
E.descend_to(QQ)                                                      # needs sage.rings.number_field
division_field(l, names='t', map=False, **kwds)#

Given an elliptic curve over a number field or finite field F and a prime number , construct the -division field F(E[]).

The -division field is the smallest extension of F over which all -torsion points of E are defined.

INPUT:

  • – a prime number (an element of Z)

  • names – (default: 't') a variable name for the division field

  • map – (default: False) also return an embedding of the base_field() into the resulting field

  • kwds – additional keyword arguments passed to splitting_field()

OUTPUT:

If map is False, the division field K as an absolute number field or a finite field. If map is True, a tuple (K,ϕ) where ϕ is an embedding of the base field in the division field K.

Warning

This can take a very long time when the degree of the division field is large (e.g. when is large or when the Galois representation is surjective). The simplify flag also has a big influence on the running time over number fields: sometimes simplify=False is faster, sometimes the default simplify=True is faster.

EXAMPLES:

The 2-division field is the same as the splitting field of the 2-division polynomial (therefore, it has degree 1, 2, 3 or 6):

sage: # needs sage.rings.number_field
sage: E = EllipticCurve('15a1')
sage: K.<b> = E.division_field(2); K
Number Field in b with defining polynomial x
sage: E = EllipticCurve('14a1')
sage: K.<b> = E.division_field(2); K
Number Field in b with defining polynomial x^2 + 5*x + 92
sage: E = EllipticCurve('196b1')
sage: K.<b> = E.division_field(2); K
Number Field in b with defining polynomial x^3 + x^2 - 114*x - 127
sage: E = EllipticCurve('19a1')
sage: K.<b> = E.division_field(2); K
Number Field in b with defining polynomial
 x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292
# needs sage.rings.number_field
E = EllipticCurve('15a1')
K.<b> = E.division_field(2); K
E = EllipticCurve('14a1')
K.<b> = E.division_field(2); K
E = EllipticCurve('196b1')
K.<b> = E.division_field(2); K
E = EllipticCurve('19a1')
K.<b> = E.division_field(2); K

For odd primes , the division field is either the splitting field of the -division polynomial, or a quadratic extension of it.

sage: # needs sage.rings.number_field
sage: E = EllipticCurve('50a1')
sage: F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
Number Field in a
 with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
sage: K.<b> = E.division_field(3, simplify_all=True); K
Number Field in b
 with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
# needs sage.rings.number_field
E = EllipticCurve('50a1')
F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
K.<b> = E.division_field(3, simplify_all=True); K

If we take any quadratic twist, the splitting field of the 3-division polynomial remains the same, but the 3-division field becomes a quadratic extension:

sage: # needs sage.rings.number_field
sage: E = E.quadratic_twist(5)  # 50b3
sage: F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
Number Field in a
 with defining polynomial x^6 - 3*x^5 + 4*x^4 - 3*x^3 - 2*x^2 + 3*x + 3
sage: K.<b> = E.division_field(3, simplify_all=True); K
Number Field in b with defining polynomial x^12 - 3*x^11 + 8*x^10 - 15*x^9
 + 30*x^8 - 63*x^7 + 109*x^6 - 144*x^5 + 150*x^4 - 120*x^3 + 68*x^2 - 24*x + 4
# needs sage.rings.number_field
E = E.quadratic_twist(5)  # 50b3
F.<a> = E.division_polynomial(3).splitting_field(simplify_all=True); F
K.<b> = E.division_field(3, simplify_all=True); K

Try another quadratic twist, this time over a subfield of F:

sage: # needs sage.rings.number_field
sage: G.<c>,_,_ = F.subfields(3)[0]
sage: E = E.base_extend(G).quadratic_twist(c); E
Elliptic Curve defined
 by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000)
 over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9
sage: K.<b> = E.division_field(3, simplify_all=True); K
Number Field in b with defining polynomial
 x^12 + 5*x^10 + 40*x^8 + 315*x^6 + 750*x^4 + 675*x^2 + 2025
# needs sage.rings.number_field
G.<c>,_,_ = F.subfields(3)[0]
E = E.base_extend(G).quadratic_twist(c); E
K.<b> = E.division_field(3, simplify_all=True); K

Some higher-degree examples:

sage: # needs sage.rings.number_field
sage: E = EllipticCurve('11a1')
sage: K.<b> = E.division_field(2); K
Number Field in b with defining polynomial
 x^6 + 2*x^5 - 48*x^4 - 436*x^3 + 1668*x^2 + 28792*x + 73844
sage: K.<b> = E.division_field(3); K        # long time
Number Field in b with defining polynomial x^48 ...
sage: K.<b> = E.division_field(5); K
Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1
sage: E.division_field(5, 'b', simplify=False)
Number Field in b with defining polynomial x^4 + x^3 + 11*x^2 + 41*x + 101
sage: E.base_extend(K).torsion_subgroup()   # long time
Torsion Subgroup isomorphic to Z/5 + Z/5 associated to the Elliptic Curve
 defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20)
 over Number Field in b with defining polynomial x^4 - x^3 + x^2 - x + 1

sage: # needs sage.rings.number_field
sage: E = EllipticCurve('27a1')
sage: K.<b> = E.division_field(3); K
Number Field in b with defining polynomial x^2 + 3*x + 9
sage: K.<b> = E.division_field(2); K
Number Field in b with defining polynomial
 x^6 + 6*x^5 + 24*x^4 - 52*x^3 - 228*x^2 + 744*x + 3844
sage: K.<b> = E.division_field(2, simplify_all=True); K
Number Field in b with defining polynomial x^6 - 3*x^5 + 5*x^3 - 3*x + 1
sage: K.<b> = E.division_field(5); K        # long time
Number Field in b with defining polynomial x^48 ...
sage: K.<b> = E.division_field(7); K        # long time
Number Field in b with defining polynomial x^72 ...
# needs sage.rings.number_field
E = EllipticCurve('11a1')
K.<b> = E.division_field(2); K
K.<b> = E.division_field(3); K        # long time
K.<b> = E.division_field(5); K
E.division_field(5, 'b', simplify=False)
E.base_extend(K).torsion_subgroup()   # long time
# needs sage.rings.number_field
E = EllipticCurve('27a1')
K.<b> = E.division_field(3); K
K.<b> = E.division_field(2); K
K.<b> = E.division_field(2, simplify_all=True); K
K.<b> = E.division_field(5); K        # long time
K.<b> = E.division_field(7); K        # long time

Over a number field:

sage: # needs sage.rings.number_field
sage: R.<x> = PolynomialRing(QQ)
sage: K.<i> = NumberField(x^2 + 1)
sage: E = EllipticCurve([0,0,0,0,i])
sage: L.<b> = E.division_field(2); L
Number Field in b with defining polynomial x^4 - x^2 + 1
sage: L.<b>, phi = E.division_field(2, map=True); phi
Ring morphism:
  From: Number Field in i with defining polynomial x^2 + 1
  To:   Number Field in b with defining polynomial x^4 - x^2 + 1
  Defn: i |--> -b^3
sage: L.<b>, phi = E.division_field(3, map=True)
sage: L
Number Field in b with defining polynomial x^24 - 6*x^22 - 12*x^21
 - 21*x^20 + 216*x^19 + 48*x^18 + 804*x^17 + 1194*x^16 - 13488*x^15
 + 21222*x^14 + 44196*x^13 - 47977*x^12 - 102888*x^11 + 173424*x^10
 - 172308*x^9 + 302046*x^8 + 252864*x^7 - 931182*x^6 + 180300*x^5
 + 879567*x^4 - 415896*x^3 + 1941012*x^2 + 650220*x + 443089
sage: phi
Ring morphism:
  From: Number Field in i with defining polynomial x^2 + 1
  To:   Number Field in b with defining polynomial x^24 ...
  Defn: i |--> -215621657062634529/183360797284413355040732*b^23 ...
# needs sage.rings.number_field
R.<x> = PolynomialRing(QQ)
K.<i> = NumberField(x^2 + 1)
E = EllipticCurve([0,0,0,0,i])
L.<b> = E.division_field(2); L
L.<b>, phi = E.division_field(2, map=True); phi
L.<b>, phi = E.division_field(3, map=True)
L
phi

Over a finite field:

sage: E = EllipticCurve(GF(431^2), [1,0])                                   # needs sage.rings.finite_rings
sage: E.division_field(5, map=True)                                         # needs sage.rings.finite_rings
(Finite Field in t of size 431^4,
 Ring morphism:
   From: Finite Field in z2 of size 431^2
   To:   Finite Field in t of size 431^4
   Defn: z2 |--> 52*t^3 + 222*t^2 + 78*t + 105)
E = EllipticCurve(GF(431^2), [1,0])                                   # needs sage.rings.finite_rings
E.division_field(5, map=True)                                         # needs sage.rings.finite_rings
sage: E = EllipticCurve(GF(433^2), [1,0])                                   # needs sage.rings.finite_rings
sage: K.<v> = E.division_field(7); K                                        # needs sage.rings.finite_rings
Finite Field in v of size 433^16
E = EllipticCurve(GF(433^2), [1,0])                                   # needs sage.rings.finite_rings
K.<v> = E.division_field(7); K                                        # needs sage.rings.finite_rings

AUTHORS:

  • Jeroen Demeyer (2014-01-06): github issue #11905, use splitting_field method, moved from gal_reps.py, make it work over number fields.

  • Lorenz Panny (2022): extend to finite fields

genus()#

Return 1 for elliptic curves.

EXAMPLES:

sage: E = EllipticCurve(GF(3), [0, -1, 0, -346, 2652])
sage: E.genus()
1

sage: R = FractionField(QQ['z'])
sage: E = EllipticCurve(R, [0, -1, 0, -346, 2652])
sage: E.genus()
1
E = EllipticCurve(GF(3), [0, -1, 0, -346, 2652])
E.genus()
R = FractionField(QQ['z'])
E = EllipticCurve(R, [0, -1, 0, -346, 2652])
E.genus()
hasse_invariant()#

Return the Hasse invariant of this elliptic curve.

OUTPUT:

The Hasse invariant of this elliptic curve, as an element of the base field. This is only defined over fields of positive characteristic, and is an element of the field which is zero if and only if the curve is supersingular. Over a field of characteristic zero, where the Hasse invariant is undefined, a ValueError is raised.

EXAMPLES:

sage: E = EllipticCurve([Mod(1,2), Mod(1,2), 0, 0, Mod(1,2)])
sage: E.hasse_invariant()
1
sage: E = EllipticCurve([0, 0, Mod(1,3), Mod(1,3), Mod(1,3)])
sage: E.hasse_invariant()
0
sage: E = EllipticCurve([0, 0, Mod(1,5), 0, Mod(2,5)])
sage: E.hasse_invariant()
0
sage: E = EllipticCurve([0, 0, Mod(1,5), Mod(1,5), Mod(2,5)])
sage: E.hasse_invariant()
2
E = EllipticCurve([Mod(1,2), Mod(1,2), 0, 0, Mod(1,2)])
E.hasse_invariant()
E = EllipticCurve([0, 0, Mod(1,3), Mod(1,3), Mod(1,3)])
E.hasse_invariant()
E = EllipticCurve([0, 0, Mod(1,5), 0, Mod(2,5)])
E.hasse_invariant()
E = EllipticCurve([0, 0, Mod(1,5), Mod(1,5), Mod(2,5)])
E.hasse_invariant()

Some examples over larger fields:

sage: # needs sage.rings.finite_rings
sage: EllipticCurve(GF(101), [0,0,0,0,1]).hasse_invariant()
0
sage: EllipticCurve(GF(101), [0,0,0,1,1]).hasse_invariant()
98
sage: EllipticCurve(GF(103), [0,0,0,0,1]).hasse_invariant()
20
sage: EllipticCurve(GF(103), [0,0,0,1,1]).hasse_invariant()
17
sage: F.<a> = GF(107^2)
sage: EllipticCurve(F, [0,0,0,a,1]).hasse_invariant()
62*a + 75
sage: EllipticCurve(F, [0,0,0,0,a]).hasse_invariant()
0
# needs sage.rings.finite_rings
EllipticCurve(GF(101), [0,0,0,0,1]).hasse_invariant()
EllipticCurve(GF(101), [0,0,0,1,1]).hasse_invariant()
EllipticCurve(GF(103), [0,0,0,0,1]).hasse_invariant()
EllipticCurve(GF(103), [0,0,0,1,1]).hasse_invariant()
F.<a> = GF(107^2)
EllipticCurve(F, [0,0,0,a,1]).hasse_invariant()
EllipticCurve(F, [0,0,0,0,a]).hasse_invariant()

Over fields of characteristic zero, the Hasse invariant is undefined:

sage: E = EllipticCurve([0,0,0,0,1])
sage: E.hasse_invariant()
Traceback (most recent call last):
...
ValueError: Hasse invariant only defined in positive characteristic
E = EllipticCurve([0,0,0,0,1])
E.hasse_invariant()
is_isogenous(other, field=None)#

Return whether or not self is isogenous to other.

INPUT:

  • other – another elliptic curve.

  • field (default None) – Currently not implemented. A field containing the base fields of the two elliptic curves onto which the two curves may be extended to test if they are isogenous over this field. By default is_isogenous will not try to find this field unless one of the curves can be be extended into the base field of the other, in which case it will test over the larger base field.

OUTPUT:

(bool) True if there is an isogeny from curve self to curve other defined over field.

METHOD:

Over general fields this is only implemented in trivial cases.

EXAMPLES:

sage: E1 = EllipticCurve(CC, [1,18]); E1
Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
 over Complex Field with 53 bits of precision
sage: E2 = EllipticCurve(CC, [2,7]); E2
Elliptic Curve defined by y^2 = x^3 + 2.00000000000000*x + 7.00000000000000
 over Complex Field with 53 bits of precision
sage: E1.is_isogenous(E2)
Traceback (most recent call last):
...
NotImplementedError: Only implemented for isomorphic curves over general fields.

sage: E1 = EllipticCurve(Frac(PolynomialRing(ZZ,'t')), [2,19]); E1
Elliptic Curve defined by y^2 = x^3 + 2*x + 19
 over Fraction Field of Univariate Polynomial Ring in t over Integer Ring
sage: E2 = EllipticCurve(CC, [23,4]); E2
Elliptic Curve defined by y^2 = x^3 + 23.0000000000000*x + 4.00000000000000
 over Complex Field with 53 bits of precision
sage: E1.is_isogenous(E2)
Traceback (most recent call last):
...
NotImplementedError: Only implemented for isomorphic curves over general fields.
E1 = EllipticCurve(CC, [1,18]); E1
E2 = EllipticCurve(CC, [2,7]); E2
E1.is_isogenous(E2)
E1 = EllipticCurve(Frac(PolynomialRing(ZZ,'t')), [2,19]); E1
E2 = EllipticCurve(CC, [23,4]); E2
E1.is_isogenous(E2)
is_quadratic_twist(other)#

Determine whether this curve is a quadratic twist of another.

INPUT:

  • other – an elliptic curve with the same base field as self.

OUTPUT:

Either 0, if the curves are not quadratic twists, or D if other is self.quadratic_twist(D) (up to isomorphism). If self and other are isomorphic, returns 1.

If the curves are defined over Q, the output D is a squarefree integer.

Note

Not fully implemented in characteristic 2, or in characteristic 3 when both j-invariants are 0.

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: Et = E.quadratic_twist(-24)
sage: E.is_quadratic_twist(Et)
-6

sage: E1 = EllipticCurve([0,0,1,0,0])
sage: E1.j_invariant()
0
sage: E2 = EllipticCurve([0,0,0,0,2])
sage: E1.is_quadratic_twist(E2)
2
sage: E1.is_quadratic_twist(E1)
1
sage: type(E1.is_quadratic_twist(E1)) == type(E1.is_quadratic_twist(E2))   # Issue #6574
True
E = EllipticCurve('11a1')
Et = E.quadratic_twist(-24)
E.is_quadratic_twist(Et)
E1 = EllipticCurve([0,0,1,0,0])
E1.j_invariant()
E2 = EllipticCurve([0,0,0,0,2])
E1.is_quadratic_twist(E2)
E1.is_quadratic_twist(E1)
type(E1.is_quadratic_twist(E1)) == type(E1.is_quadratic_twist(E2))   # Issue #6574
sage: E1 = EllipticCurve([0,0,0,1,0])
sage: E1.j_invariant()
1728
sage: E2 = EllipticCurve([0,0,0,2,0])
sage: E1.is_quadratic_twist(E2)
0
sage: E2 = EllipticCurve([0,0,0,25,0])
sage: E1.is_quadratic_twist(E2)
5
E1 = EllipticCurve([0,0,0,1,0])
E1.j_invariant()
E2 = EllipticCurve([0,0,0,2,0])
E1.is_quadratic_twist(E2)
E2 = EllipticCurve([0,0,0,25,0])
E1.is_quadratic_twist(E2)
sage: # needs sage.rings.finite_rings
sage: F = GF(101)
sage: E1 = EllipticCurve(F, [4,7])
sage: E2 = E1.quadratic_twist()
sage: D = E1.is_quadratic_twist(E2); D != 0
True
sage: F = GF(101)
sage: E1 = EllipticCurve(F, [4,7])
sage: E2 = E1.quadratic_twist()
sage: D = E1.is_quadratic_twist(E2)
sage: E1.quadratic_twist(D).is_isomorphic(E2)
True
sage: E1.is_isomorphic(E2)
False
sage: F2 = GF(101^2,'a')
sage: E1.change_ring(F2).is_isomorphic(E2.change_ring(F2))
True
# needs sage.rings.finite_rings
F = GF(101)
E1 = EllipticCurve(F, [4,7])
E2 = E1.quadratic_twist()
D = E1.is_quadratic_twist(E2); D != 0
F = GF(101)
E1 = EllipticCurve(F, [4,7])
E2 = E1.quadratic_twist()
D = E1.is_quadratic_twist(E2)
E1.quadratic_twist(D).is_isomorphic(E2)
E1.is_isomorphic(E2)
F2 = GF(101^2,'a')
E1.change_ring(F2).is_isomorphic(E2.change_ring(F2))

A characteristic 3 example:

sage: # needs sage.rings.finite_rings
sage: F = GF(3^5,'a')
sage: E1 = EllipticCurve_from_j(F(1))
sage: E2 = E1.quadratic_twist(-1)
sage: D = E1.is_quadratic_twist(E2); D != 0
True
sage: E1.quadratic_twist(D).is_isomorphic(E2)
True
# needs sage.rings.finite_rings
F = GF(3^5,'a')
E1 = EllipticCurve_from_j(F(1))
E2 = E1.quadratic_twist(-1)
D = E1.is_quadratic_twist(E2); D != 0
E1.quadratic_twist(D).is_isomorphic(E2)
sage: # needs sage.rings.finite_rings
sage: E1 = EllipticCurve_from_j(F(0))
sage: E2 = E1.quadratic_twist()
sage: D = E1.is_quadratic_twist(E2); D
1
sage: E1.is_isomorphic(E2)
True
# needs sage.rings.finite_rings
E1 = EllipticCurve_from_j(F(0))
E2 = E1.quadratic_twist()
D = E1.is_quadratic_twist(E2); D
E1.is_isomorphic(E2)
is_quartic_twist(other)#

Determine whether this curve is a quartic twist of another.

INPUT:

  • other – an elliptic curves with the same base field as self.

OUTPUT:

Either 0, if the curves are not quartic twists, or D if other is self.quartic_twist(D) (up to isomorphism). If self and other are isomorphic, returns 1.

Note

Not fully implemented in characteristics 2 or 3.

EXAMPLES:

sage: E = EllipticCurve_from_j(GF(13)(1728))
sage: E1 = E.quartic_twist(2)
sage: D = E.is_quartic_twist(E1); D!=0
True
sage: E.quartic_twist(D).is_isomorphic(E1)
True
E = EllipticCurve_from_j(GF(13)(1728))
E1 = E.quartic_twist(2)
D = E.is_quartic_twist(E1); D!=0
E.quartic_twist(D).is_isomorphic(E1)
sage: E = EllipticCurve_from_j(1728)
sage: E1 = E.quartic_twist(12345)
sage: D = E.is_quartic_twist(E1); D
15999120
sage: (D/12345).is_perfect_power(4)
True
E = EllipticCurve_from_j(1728)
E1 = E.quartic_twist(12345)
D = E.is_quartic_twist(E1); D
(D/12345).is_perfect_power(4)
is_sextic_twist(other)#

Determine whether this curve is a sextic twist of another.

INPUT:

  • other – an elliptic curves with the same base field as self.

OUTPUT:

Either 0, if the curves are not sextic twists, or D if other is self.sextic_twist(D) (up to isomorphism). If self and other are isomorphic, returns 1.

Note

Not fully implemented in characteristics 2 or 3.

EXAMPLES:

sage: E = EllipticCurve_from_j(GF(13)(0))
sage: E1 = E.sextic_twist(2)
sage: D = E.is_sextic_twist(E1); D != 0
True
sage: E.sextic_twist(D).is_isomorphic(E1)
True
E = EllipticCurve_from_j(GF(13)(0))
E1 = E.sextic_twist(2)
D = E.is_sextic_twist(E1); D != 0
E.sextic_twist(D).is_isomorphic(E1)
sage: E = EllipticCurve_from_j(0)
sage: E1 = E.sextic_twist(12345)
sage: D = E.is_sextic_twist(E1); D
575968320
sage: (D/12345).is_perfect_power(6)
True
E = EllipticCurve_from_j(0)
E1 = E.sextic_twist(12345)
D = E.is_sextic_twist(E1); D
(D/12345).is_perfect_power(6)
isogenies_prime_degree(l=None, max_l=31)#

Return a list of all separable isogenies of given prime degree(s) with domain equal to self, which are defined over the base field of self.

INPUT:

  • l – a prime or a list of primes.

  • max_l – (default: 31) a bound on the primes to be tested. This is only used if l is None.

OUTPUT:

(list) All separable l-isogenies for the given l with domain self.

ALGORITHM:

Calls the generic function isogenies_prime_degree(). This is generic code, valid for all fields. It requires that certain operations have been implemented over the base field, such as root-finding for univariate polynomials.

EXAMPLES:

Examples over finite fields:

sage: # needs sage.libs.pari
sage: E = EllipticCurve(GF(next_prime(1000000)), [7,8])
sage: E.isogenies_prime_degree(2)
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003]
sage: E.isogenies_prime_degree(3)
[]
sage: E.isogenies_prime_degree(5)
[]
sage: E.isogenies_prime_degree(7)
[]
sage: E.isogenies_prime_degree(11)
[]
sage: E.isogenies_prime_degree(13)
[Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
 Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
sage: E.isogenies_prime_degree(max_l=13)
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
 Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
 Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003]
sage: E.isogenies_prime_degree()  # Default limit of 31
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 970389*x + 794257 over Finite Field of size 1000003,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 29783*x + 206196 over Finite Field of size 1000003,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 999960*x + 78 over Finite Field of size 1000003,
 Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 878063*x + 845666 over Finite Field of size 1000003,
 Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 375648*x + 342776 over Finite Field of size 1000003,
 Isogeny of degree 17
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 347438*x + 594729 over Finite Field of size 1000003,
 Isogeny of degree 17
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 674846*x + 7392 over Finite Field of size 1000003,
 Isogeny of degree 23
  from Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 1000003
    to Elliptic Curve defined by y^2 = x^3 + 390065*x + 605596 over Finite Field of size 1000003]

sage: E = EllipticCurve(GF(17), [2,0])
sage: E.isogenies_prime_degree(3)
[]
sage: E.isogenies_prime_degree(2)
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
  to Elliptic Curve defined by y^2 = x^3 + 9*x over Finite Field of size 17,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
  to Elliptic Curve defined by y^2 = x^3 + 5*x + 9 over Finite Field of size 17,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 17
  to Elliptic Curve defined by y^2 = x^3 + 5*x + 8 over Finite Field of size 17]
# needs sage.libs.pari
E = EllipticCurve(GF(next_prime(1000000)), [7,8])
E.isogenies_prime_degree(2)
E.isogenies_prime_degree(3)
E.isogenies_prime_degree(5)
E.isogenies_prime_degree(7)
E.isogenies_prime_degree(11)
E.isogenies_prime_degree(13)
E.isogenies_prime_degree(max_l=13)
E.isogenies_prime_degree()  # Default limit of 31
E = EllipticCurve(GF(17), [2,0])
E.isogenies_prime_degree(3)
E.isogenies_prime_degree(2)

The base field matters, over a field extension we find more isogenies:

sage: E = EllipticCurve(GF(13), [2,8])
sage: E.isogenies_prime_degree(max_l=3)
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
    to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field of size 13,
 Isogeny of degree 3
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
    to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field of size 13]

sage: # needs sage.rings.finite_rings
sage: E = EllipticCurve(GF(13^6), [2,8])
sage: E.isogenies_prime_degree(max_l=3)
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + 7*x + 4 over Finite Field in z6 of size 13^6,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + (2*z6^5+6*z6^4+9*z6^3+8*z6+7)*x + (3*z6^5+9*z6^4+7*z6^3+12*z6+7) over Finite Field in z6 of size 13^6,
 Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + (11*z6^5+7*z6^4+4*z6^3+5*z6+9)*x + (10*z6^5+4*z6^4+6*z6^3+z6+10) over Finite Field in z6 of size 13^6,
 Isogeny of degree 3
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + 9*x + 11 over Finite Field in z6 of size 13^6,
 Isogeny of degree 3
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + (3*z6^5+5*z6^4+8*z6^3+11*z6^2+5*z6+12)*x + (12*z6^5+6*z6^4+8*z6^3+4*z6^2+7*z6+6) over Finite Field in z6 of size 13^6,
 Isogeny of degree 3
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + (7*z6^4+12*z6^3+7*z6^2+4)*x + (6*z6^5+10*z6^3+12*z6^2+10*z6+8) over Finite Field in z6 of size 13^6,
 Isogeny of degree 3
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field in z6 of size 13^6
    to Elliptic Curve defined by y^2 = x^3 + (10*z6^5+z6^4+6*z6^3+8*z6^2+8*z6)*x + (8*z6^5+7*z6^4+8*z6^3+10*z6^2+9*z6+7) over Finite Field in z6 of size 13^6]
E = EllipticCurve(GF(13), [2,8])
E.isogenies_prime_degree(max_l=3)
# needs sage.rings.finite_rings
E = EllipticCurve(GF(13^6), [2,8])
E.isogenies_prime_degree(max_l=3)

If the degree equals the characteristic, we find only separable isogenies:

sage: E = EllipticCurve(GF(13), [2,8])
sage: E.isogenies_prime_degree(13)
[Isogeny of degree 13
  from Elliptic Curve defined by y^2 = x^3 + 2*x + 8 over Finite Field of size 13
    to Elliptic Curve defined by y^2 = x^3 + 6*x + 5 over Finite Field of size 13]
sage: E = EllipticCurve(GF(5), [1,1])
sage: E.isogenies_prime_degree(5)
[Isogeny of degree 5
  from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 5
    to Elliptic Curve defined by y^2 = x^3 + x + 4 over Finite Field of size 5]

sage: # needs sage.rings.finite_rings
sage: k.<a> = GF(3^4)
sage: E = EllipticCurve(k, [0,1,0,0,a])
sage: E.isogenies_prime_degree(3)
[Isogeny of degree 3
  from Elliptic Curve defined by y^2 = x^3 + x^2 + a
       over Finite Field in a of size 3^4
    to Elliptic Curve defined by y^2 = x^3 + x^2 + (2*a^3+a^2+2)*x + (a^2+2)
       over Finite Field in a of size 3^4]
E = EllipticCurve(GF(13), [2,8])
E.isogenies_prime_degree(13)
E = EllipticCurve(GF(5), [1,1])
E.isogenies_prime_degree(5)
# needs sage.rings.finite_rings
k.<a> = GF(3^4)
E = EllipticCurve(k, [0,1,0,0,a])
E.isogenies_prime_degree(3)

In the supersingular case, there are no separable isogenies of degree equal to the characteristic:

sage: E = EllipticCurve(GF(5), [0,1])
sage: E.isogenies_prime_degree(5)
[]
E = EllipticCurve(GF(5), [0,1])
E.isogenies_prime_degree(5)

An example over a rational function field:

sage: R.<t> = GF(5)[]
sage: K = R.fraction_field()
sage: E = EllipticCurve(K, [1, t^5])
sage: E.isogenies_prime_degree(5)
[Isogeny of degree 5
  from Elliptic Curve defined by y^2 = x^3 + x + t^5 over Fraction Field
       of Univariate Polynomial Ring in t over Finite Field of size 5
    to Elliptic Curve defined by y^2 = x^3 + x + 4*t over Fraction Field
       of Univariate Polynomial Ring in t over Finite Field of size 5]
R.<t> = GF(5)[]
K = R.fraction_field()
E = EllipticCurve(K, [1, t^5])
E.isogenies_prime_degree(5)

Examples over number fields (other than QQ):

sage: # needs sage.rings.number_field
sage: x = polygen(ZZ, 'x')
sage: QQroot2.<e> = NumberField(x^2 - 2)
sage: E = EllipticCurve(QQroot2, j=8000)
sage: E.isogenies_prime_degree()
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
       over Number Field in e with defining polynomial x^2 - 2
    to Elliptic Curve defined by y^2 = x^3 + (-36750)*x + 2401000
       over Number Field in e with defining polynomial x^2 - 2,
Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
       over Number Field in e with defining polynomial x^2 - 2
    to Elliptic Curve defined by y^2 = x^3 + (220500*e-257250)*x + (54022500*e-88837000)
       over Number Field in e with defining polynomial x^2 - 2,
Isogeny of degree 2
  from Elliptic Curve defined by y^2 = x^3 + (-150528000)*x + (-629407744000)
       over Number Field in e with defining polynomial x^2 - 2
    to Elliptic Curve defined by y^2 = x^3 + (-220500*e-257250)*x + (-54022500*e-88837000)
       over Number Field in e with defining polynomial x^2 - 2]
sage: E = EllipticCurve(QQroot2, [1,0,1,4, -6]); E
Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
 over Number Field in e with defining polynomial x^2 - 2
sage: E.isogenies_prime_degree(2)
[Isogeny of degree 2
  from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
       over Number Field in e with defining polynomial x^2 - 2
    to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-36)*x + (-70)
       over Number Field in e with defining polynomial x^2 - 2]
sage: E.isogenies_prime_degree(3)
[Isogeny of degree 3
  from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
       over Number Field in e with defining polynomial x^2 - 2
    to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-1)*x
       over Number Field in e with defining polynomial x^2 - 2,
 Isogeny of degree 3
  from Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + (-6)
       over Number Field in e with defining polynomial x^2 - 2
    to Elliptic Curve defined by y^2 + x*y + y = x^3 + (-171)*x + (-874)
       over Number Field in e with defining polynomial x^2 - 2]
# needs sage.rings.number_field
x = polygen(ZZ, 'x')
QQroot2.<e> = NumberField(x^2 - 2)
E = EllipticCurve(QQroot2, j=8000)
E.isogenies_prime_degree()
E = EllipticCurve(QQroot2, [1,0,1,4, -6]); E
E.isogenies_prime_degree(2)
E.isogenies_prime_degree(3)

These are not implemented yet:

sage: E = EllipticCurve(QQbar, [1,18]); E                                   # needs sage.rings.number_field
Elliptic Curve defined by y^2 = x^3 + x + 18 over Algebraic Field
sage: E.isogenies_prime_degree()                                            # needs sage.rings.number_field
Traceback (most recent call last):
...
NotImplementedError: This code could be implemented for QQbar, but has not been yet.

sage: E = EllipticCurve(CC, [1,18]); E
Elliptic Curve defined by y^2 = x^3 + 1.00000000000000*x + 18.0000000000000
over Complex Field with 53 bits of precision
sage: E.isogenies_prime_degree(11)
Traceback (most recent call last):
...
NotImplementedError: This code could be implemented for general complex fields,
but has not been yet.
E = EllipticCurve(QQbar, [1,18]); E                                   # needs sage.rings.number_field
E.isogenies_prime_degree()                                            # needs sage.rings.number_field
E = EllipticCurve(CC, [1,18]); E
E.isogenies_prime_degree(11)
isogeny(kernel, codomain=None, degree=None, model=None, check=True, algorithm=None)#

Return an elliptic-curve isogeny from this elliptic curve.

The isogeny can be specified in two ways, by passing either a polynomial or a set of torsion points. The methods used are:

  • Vélu’s Formulas: Vélu’s original formulas for computing isogenies. This algorithm is selected by giving as the kernel parameter a single point, or a list of points, generating a finite subgroup.

  • Kohel’s Formulas: Kohel’s original formulas for computing isogenies. This algorithm is selected by giving as the kernel parameter a monic polynomial (or a coefficient list in little endian) which will define the kernel of the isogeny. Kohel’s algorithm is currently only implemented for cyclic isogenies, with the exception of [2].

  • √élu Algorithm (see hom_velusqrt): A variant of Vélu’s formulas with essentially square-root instead of linear complexity (in the degree). Currently only available over finite fields. The input must be a single kernel point of odd order 5. This algorithm is selected using algorithm="velusqrt".

  • Factored Isogenies (see hom_composite): Given a list of points which generate a composite-order subgroup, decomposes the isogeny into prime-degree steps. This can be used to construct isogenies of extremely large, smooth degree. This algorithm is selected using algorithm="factored".

INPUT:

  • kernel – a kernel: either a point on this curve, a list of points on this curve, a monic kernel polynomial, or None. If initializing from a codomain, this must be None.

  • codomain – an elliptic curve (default: None).

    • If kernel is None, then degree must be given as well and the given codomain must be the codomain of a cyclic, separable, normalized isogeny of the given degree.

    • If kernel is not None, then this must be isomorphic to the codomain of the separable isogeny defined by kernel; in this case, the isogeny is post-composed with an isomorphism so that the codomain equals the given curve.

  • degree – an integer (default: None).

    • If kernel is None, then this is the degree of the isogeny from this curve to codomain.

    • If kernel is not None, then this is used to determine whether or not to skip a gcd of the given kernel polynomial with the two-torsion polynomial of this curve.

  • model – a string (default: None). Supported values (cf. compute_model()):

    • "minimal": If self is a curve over the rationals or over a number field, then the codomain is a global minimal model where this exists.

    • "short_weierstrass": The codomain is a short Weierstrass curve, assuming one exists.

    • "montgomery": The codomain is an (untwisted) Montgomery curve, assuming one exists over this field.

  • check (default: True) – check whether the input is valid. Setting this to False can lead to significant speedups.

  • algorithm – string (optional). By default (when algorithm is omitted), the “traditional” implementation EllipticCurveIsogeny is used. The other choices are:

    The degree parameter is not supported when an algorithm is specified.

OUTPUT:

An isogeny between elliptic curves. This is a morphism of curves. (In all cases, the returned object will be an instance of EllipticCurveHom.)

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: F = GF(2^5, 'alpha'); alpha = F.gen()
sage: E = EllipticCurve(F, [1,0,1,1,1])
sage: R.<x> = F[]
sage: phi = E.isogeny(x + 1)
sage: phi.rational_maps()
((x^2 + x + 1)/(x + 1), (x^2*y + x)/(x^2 + 1))
# needs sage.rings.finite_rings
F = GF(2^5, 'alpha'); alpha = F.gen()
E = EllipticCurve(F, [1,0,1,1,1])
R.<x> = F[]
phi = E.isogeny(x + 1)
phi.rational_maps()
sage: E = EllipticCurve('11a1')
sage: P = E.torsion_points()[1]
sage: E.isogeny(P)
Isogeny of degree 5
 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20
      over Rational Field
   to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580
      over Rational Field
E = EllipticCurve('11a1')
P = E.torsion_points()[1]
E.isogeny(P)
sage: E = EllipticCurve(GF(19),[1,1])
sage: P = E(15,3); Q = E(2,12)
sage: (P.order(), Q.order())
(7, 3)
sage: phi = E.isogeny([P,Q]); phi
Isogeny of degree 21
 from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
   to Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 19
sage: phi(E.random_point())  # all points defined over GF(19) are in the kernel
(0 : 1 : 0)
E = EllipticCurve(GF(19),[1,1])
P = E(15,3); Q = E(2,12)
(P.order(), Q.order())
phi = E.isogeny([P,Q]); phi
phi(E.random_point())  # all points defined over GF(19) are in the kernel
sage: E = EllipticCurve(GF(2^32 - 5), [170246996, 2036646110])              # needs sage.rings.finite_rings
sage: P = E.lift_x(2)                                                       # needs sage.rings.finite_rings
sage: E.isogeny(P, algorithm="factored")                                    # needs sage.rings.finite_rings
Composite morphism of degree 1073721825 = 3^4*5^2*11*19*43*59:
  From: Elliptic Curve defined by y^2 = x^3 + 170246996*x + 2036646110
         over Finite Field of size 4294967291
  To:   Elliptic Curve defined by y^2 = x^3 + 272790262*x + 1903695400
         over Finite Field of size 4294967291
E = EllipticCurve(GF(2^32 - 5), [170246996, 2036646110])              # needs sage.rings.finite_rings
P = E.lift_x(2)                                                       # needs sage.rings.finite_rings
E.isogeny(P, algorithm="factored")                                    # needs sage.rings.finite_rings

Not all polynomials define a finite subgroup (github issue #6384):

sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
sage: phi = E.isogeny([14,27,4,1])
Traceback (most recent call last):
...
ValueError: the polynomial x^3 + 4*x^2 + 27*x + 14 does not define a finite
subgroup of Elliptic Curve defined by y^2 + x*y = x^3 + x + 2
over Finite Field of size 31
E = EllipticCurve(GF(31), [1,0,0,1,2])
phi = E.isogeny([14,27,4,1])
isogeny_codomain(kernel)#

Return the codomain of the isogeny from self with given kernel.

INPUT:

  • kernel – Either a list of points in the kernel of the isogeny, or a kernel polynomial (specified as either a univariate polynomial or a coefficient list.)

OUTPUT:

An elliptic curve, the codomain of the separable normalized isogeny defined by this kernel.

EXAMPLES:

sage: E = EllipticCurve('17a1')
sage: R.<x> = QQ[]
sage: E2 = E.isogeny_codomain(x - 11/4); E2
Elliptic Curve defined by y^2 + x*y + y = x^3 - x^2 - 1461/16*x - 19681/64
 over Rational Field
E = EllipticCurve('17a1')
R.<x> = QQ[]
E2 = E.isogeny_codomain(x - 11/4); E2
isogeny_ell_graph(l, directed=True, label_by_j=False)#

Return a graph representing the l-degree K-isogenies between K-isomorphism classes of elliptic curves for K = self.base_field().

INPUT:

  • l – prime degree of isogenies

  • directed – boolean (default: True); whether to return a directed or undirected graph. In the undirected case, the in-degrees and out-degrees of the vertices must be balanced and therefore the number of out-edges from the vertices corresponding to j-invariants 0 and 1728 (if they are part of the graph) are reduced to match the number of in-edges.

  • label_by_j – boolean (default: False); whether to label graph vertices by the j-invariant corresponding to the isomorphism class of curves. If the j-invariant is not unique in the isogeny class, append * to it to indicate a twist. Otherwise, if False label vertices by the equation of a representative curve.

OUTPUT: A Graph or DiGraph.

EXAMPLES:

Ordinary curve over finite extension field of degree 2:

sage: # needs sage.graphs sage.rings.finite_rings
sage: x = polygen(ZZ, 'x')
sage: E = EllipticCurve(GF(59^2, "i", x^2 + 1), j=5)
sage: G = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G
Graph on 20 vertices
sage: G.vertices(sort=True)
['1',
 '12',
 ...
 'i + 55']
sage: G.edges(sort=True)
[('1', '28*i + 11', None),
 ('1', '31*i + 11', None),
 ...
 ('8', 'i + 1', None)]
# needs sage.graphs sage.rings.finite_rings
x = polygen(ZZ, 'x')
E = EllipticCurve(GF(59^2, "i", x^2 + 1), j=5)
G = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G
G.vertices(sort=True)
G.edges(sort=True)

Supersingular curve over prime field:

sage: # needs sage.graphs sage.rings.finite_rings
sage: E = EllipticCurve(GF(419), j=1728)
sage: G3 = E.isogeny_ell_graph(3, directed=False, label_by_j=True); G3
Graph on 27 vertices
sage: G3.vertices(sort=True)
['0',
 '0*',
 ...
 '98*']
sage: G3.edges(sort=True)
[('0', '0*', None),
 ('0', '13', None),
 ...
 ('48*', '98*', None)]
 sage: G5 = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G5
 Graph on 9 vertices
 sage: G5.vertices(sort=True)
 ['13', '13*', '407', '407*', '52', '62', '62*', '98', '98*']
 sage: G5.edges(sort=True)
 [('13', '52', None),
  ('13', '98', None),
  ...
  ('62*', '98*', None)]
# needs sage.graphs sage.rings.finite_rings
E = EllipticCurve(GF(419), j=1728)
G3 = E.isogeny_ell_graph(3, directed=False, label_by_j=True); G3
G3.vertices(sort=True)
G3.edges(sort=True)
G5 = E.isogeny_ell_graph(5, directed=False, label_by_j=True); G5
G5.vertices(sort=True)
G5.edges(sort=True)

Supersingular curve over finite extension field of degree 2:

sage: # needs sage.graphs sage.rings.finite_rings
sage: K = GF(431^2, "i", x^2 + 1)
sage: E = EllipticCurve(K, j=0)
sage: E.is_supersingular()
True
sage: G = E.isogeny_ell_graph(2, directed=True, label_by_j=True); G
Looped multi-digraph on 37 vertices
sage: G.vertices(sort=True)
['0',
 '102',
 ...
 '87*i + 190']
sage: G.edges(sort=True)
[('0', '125', None),
 ('0', '125', None),
 ...
 '81*i + 65', None)]
sage: H = E.isogeny_ell_graph(2, directed=False, label_by_j=True); H
Looped multi-graph on 37 vertices
sage: H.vertices(sort=True)
['0',
 '102',
 ...
 '87*i + 190']
sage: H.edges(sort=True)
[('0', '125', None),
 ('102', '125', None),
 ...
 ('81*i + 65', '87*i + 190', None)]
# needs sage.graphs sage.rings.finite_rings
K = GF(431^2, "i", x^2 + 1)
E = EllipticCurve(K, j=0)
E.is_supersingular()
G = E.isogeny_ell_graph(2, directed=True, label_by_j=True); G
G.vertices(sort=True)
G.edges(sort=True)
H = E.isogeny_ell_graph(2, directed=False, label_by_j=True); H
H.vertices(sort=True)
H.edges(sort=True)

Curve over a quadratic number field:

sage: # needs sage.graphs sage.rings.finite_rings sage.rings.number_field
sage: K.<e> = NumberField(x^2 - 2)
sage: E = EllipticCurve(K, [1, 0, 1, 4, -6])
sage: G2 = E.isogeny_ell_graph(2, directed=False)
sage: G2.vertices(sort=True)
['y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
 'y^2 + x*y + y = x^3 + (-36)*x + (-70)',
 'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)',
 'y^2 + x*y + y = x^3 + 4*x + (-6)']
sage: G2.edges(sort=True)
[('y^2 + x*y + y = x^3 + (-130*e-356)*x + (-2000*e-2038)',
  'y^2 + x*y + y = x^3 + (-36)*x + (-70)', None),
 ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
  'y^2 + x*y + y = x^3 + (130*e-356)*x + (2000*e-2038)', None),
 ('y^2 + x*y + y = x^3 + (-36)*x + (-70)',
  'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]
sage: G3 = E.isogeny_ell_graph(3, directed=False)
sage: G3.vertices(sort=True)
['y^2 + x*y + y = x^3 + (-1)*x',
 'y^2 + x*y + y = x^3 + (-171)*x + (-874)',
 'y^2 + x*y + y = x^3 + 4*x + (-6)']
sage: G3.edges(sort=True)
[('y^2 + x*y + y = x^3 + (-1)*x',
  'y^2 + x*y + y = x^3 + 4*x + (-6)', None),
 ('y^2 + x*y + y = x^3 + (-171)*x + (-874)',
  'y^2 + x*y + y = x^3 + 4*x + (-6)', None)]
# needs sage.graphs sage.rings.finite_rings sage.rings.number_field
K.<e> = NumberField(x^2 - 2)
E = EllipticCurve(K, [1, 0, 1, 4, -6])
G2 = E.isogeny_ell_graph(2, directed=False)
G2.vertices(sort=True)
G2.edges(sort=True)
G3 = E.isogeny_ell_graph(3, directed=False)
G3.vertices(sort=True)
G3.edges(sort=True)
quadratic_twist(D=None)#

Return the quadratic twist of this curve by D.

INPUT:

  • D (default None) the twisting parameter (see below).

In characteristics other than 2, D must be nonzero, and the twist is isomorphic to self after adjoining (D) to the base.

In characteristic 2, D is arbitrary, and the twist is isomorphic to self after adjoining a root of x2+x+D to the base.

In characteristic 2 when j=0, this is not implemented.

If the base field F is finite, D need not be specified, and the curve returned is the unique curve (up to isomorphism) defined over F isomorphic to the original curve over the quadratic extension of F but not over F itself. Over infinite fields, an error is raised if D is not given.

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: E = EllipticCurve([GF(1103)(1), 0, 0, 107, 340]); E
Elliptic Curve defined by y^2 + x*y  = x^3 + 107*x + 340
 over Finite Field of size 1103
sage: F = E.quadratic_twist(-1); F
Elliptic Curve defined by y^2  = x^3 + 1102*x^2 + 609*x + 300
 over Finite Field of size 1103
sage: E.is_isomorphic(F)
False
sage: E.is_isomorphic(F, GF(1103^2,'a'))
True
# needs sage.rings.finite_rings
E = EllipticCurve([GF(1103)(1), 0, 0, 107, 340]); E
F = E.quadratic_twist(-1); F
E.is_isomorphic(F)
E.is_isomorphic(F, GF(1103^2,'a'))

A characteristic 2 example:

sage: E = EllipticCurve(GF(2), [1,0,1,1,1])
sage: E1 = E.quadratic_twist(1)
sage: E.is_isomorphic(E1)
False
sage: E.is_isomorphic(E1, GF(4,'a'))
True
E = EllipticCurve(GF(2), [1,0,1,1,1])
E1 = E.quadratic_twist(1)
E.is_isomorphic(E1)
E.is_isomorphic(E1, GF(4,'a'))

Over finite fields, the twisting parameter may be omitted:

sage: # needs sage.rings.finite_rings
sage: k.<a> = GF(2^10)
sage: E = EllipticCurve(k, [a^2,a,1,a+1,1])
sage: Et = E.quadratic_twist()
sage: Et  # random (only determined up to isomorphism)
Elliptic Curve defined
 by y^2 + x*y  = x^3 + (a^7+a^4+a^3+a^2+a+1)*x^2 + (a^8+a^6+a^4+1)
 over Finite Field in a of size 2^10
sage: E.is_isomorphic(Et)
False
sage: E.j_invariant() == Et.j_invariant()
True

sage: # needs sage.rings.finite_rings
sage: p = next_prime(10^10)
sage: k = GF(p)
sage: E = EllipticCurve(k, [1,2,3,4,5])
sage: Et = E.quadratic_twist()
sage: Et  # random (only determined up to isomorphism)
Elliptic Curve defined
 by y^2  = x^3 + 7860088097*x^2 + 9495240877*x + 3048660957
 over Finite Field of size 10000000019
sage: E.is_isomorphic(Et)
False
sage: k2 = GF(p^2,'a')
sage: E.change_ring(k2).is_isomorphic(Et.change_ring(k2))
True
# needs sage.rings.finite_rings
k.<a> = GF(2^10)
E = EllipticCurve(k, [a^2,a,1,a+1,1])
Et = E.quadratic_twist()
Et  # random (only determined up to isomorphism)
E.is_isomorphic(Et)
E.j_invariant() == Et.j_invariant()
# needs sage.rings.finite_rings
p = next_prime(10^10)
k = GF(p)
E = EllipticCurve(k, [1,2,3,4,5])
Et = E.quadratic_twist()
Et  # random (only determined up to isomorphism)
E.is_isomorphic(Et)
k2 = GF(p^2,'a')
E.change_ring(k2).is_isomorphic(Et.change_ring(k2))
quartic_twist(D)#

Return the quartic twist of this curve by D.

INPUT:

  • D (must be nonzero) – the twisting parameter

Note

The characteristic must not be 2 or 3, and the j-invariant must be 1728.

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: E = EllipticCurve_from_j(GF(13)(1728)); E
Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 13
sage: E1 = E.quartic_twist(2); E1
Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 13
sage: E.is_isomorphic(E1)
False
sage: E.is_isomorphic(E1, GF(13^2,'a'))
False
sage: E.is_isomorphic(E1, GF(13^4,'a'))
True
# needs sage.rings.finite_rings
E = EllipticCurve_from_j(GF(13)(1728)); E
E1 = E.quartic_twist(2); E1
E.is_isomorphic(E1)
E.is_isomorphic(E1, GF(13^2,'a'))
E.is_isomorphic(E1, GF(13^4,'a'))
sextic_twist(D)#

Return the sextic twist of this curve by D.

INPUT:

  • D (must be nonzero) – the twisting parameter

Note

The characteristic must not be 2 or 3, and the j-invariant must be 0.

EXAMPLES:

sage: # needs sage.rings.finite_rings
sage: E = EllipticCurve_from_j(GF(13)(0)); E
Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 13
sage: E1 = E.sextic_twist(2); E1
Elliptic Curve defined by y^2 = x^3 + 11 over Finite Field of size 13
sage: E.is_isomorphic(E1)
False
sage: E.is_isomorphic(E1, GF(13^2,'a'))
False
sage: E.is_isomorphic(E1, GF(13^4,'a'))
False
sage: E.is_isomorphic(E1, GF(13^6,'a'))
True
# needs sage.rings.finite_rings
E = EllipticCurve_from_j(GF(13)(0)); E
E1 = E.sextic_twist(2); E1
E.is_isomorphic(E1)
E.is_isomorphic(E1, GF(13^2,'a'))
E.is_isomorphic(E1, GF(13^4,'a'))
E.is_isomorphic(E1, GF(13^6,'a'))
two_torsion_rank()#

Return the dimension of the 2-torsion subgroup of E(K).

This will be 0, 1 or 2.

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: E.two_torsion_rank()
0
sage: K.<alpha> = QQ.extension(E.division_polynomial(2).monic())            # needs sage.rings.number_field
sage: E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
1
sage: E.reduction(53).two_torsion_rank()
2
E = EllipticCurve('11a1')
E.two_torsion_rank()
K.<alpha> = QQ.extension(E.division_polynomial(2).monic())            # needs sage.rings.number_field
E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
E.reduction(53).two_torsion_rank()
sage: E = EllipticCurve('14a1')
sage: E.two_torsion_rank()
1
sage: f = E.division_polynomial(2).monic().factor()[1][0]
sage: K.<alpha> = QQ.extension(f)                                           # needs sage.rings.number_field
sage: E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
2
E = EllipticCurve('14a1')
E.two_torsion_rank()
f = E.division_polynomial(2).monic().factor()[1][0]
K.<alpha> = QQ.extension(f)                                           # needs sage.rings.number_field
E.base_extend(K).two_torsion_rank()                                   # needs sage.rings.number_field
sage: EllipticCurve('15a1').two_torsion_rank()
2
EllipticCurve('15a1').two_torsion_rank()
weierstrass_p(prec=20, algorithm=None)#

Compute the Weierstrass -function of this elliptic curve.

ALGORITHM: sage.schemes.elliptic_curves.ell_wp.weierstrass_p()

INPUT:

  • prec – precision

  • algorithm – string or None (default: None): a choice of algorithm among "pari", "fast", "quadratic"; or None to let this function determine the best algorithm to use.

OUTPUT:

A Laurent series in one variable z with coefficients in the base field k of E.

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: E.weierstrass_p(prec=10)
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8 + O(z^10)
sage: E.weierstrass_p(prec=8)
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + O(z^8)
sage: Esh = E.short_weierstrass_model()
sage: Esh.weierstrass_p(prec=8)
z^-2 + 13392/5*z^2 + 1080432/7*z^4 + 59781888/25*z^6 + O(z^8)
sage: E.weierstrass_p(prec=20, algorithm='fast')
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
+ 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
+ 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
sage: E.weierstrass_p(prec=20, algorithm='pari')
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
+ 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
+ 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
sage: E.weierstrass_p(prec=20, algorithm='quadratic')
z^-2 + 31/15*z^2 + 2501/756*z^4 + 961/675*z^6 + 77531/41580*z^8
+ 1202285717/928746000*z^10 + 2403461/2806650*z^12 + 30211462703/43418875500*z^14
+ 3539374016033/7723451736000*z^16 + 413306031683977/1289540602350000*z^18 + O(z^20)
E = EllipticCurve('11a1')
E.weierstrass_p(prec=10)
E.weierstrass_p(prec=8)
Esh = E.short_weierstrass_model()
Esh.weierstrass_p(prec=8)
E.weierstrass_p(prec=20, algorithm='fast')
E.weierstrass_p(prec=20, algorithm='pari')
E.weierstrass_p(prec=20, algorithm='quadratic')
sage.schemes.elliptic_curves.ell_field.compute_model(E, name)#

Return a model of an elliptic curve E of the type specified in the name parameter.

Used as a helper function in EllipticCurveIsogeny.

INPUT:

  • E (elliptic curve)

  • name (string) – current options:

    • "minimal": Return a global minimal model of E if it exists, and a semi-global minimal model otherwise. For this choice, E must be defined over a number field. See global_minimal_model().

    • "short_weierstrass": Return a short Weierstrass model of E assuming one exists. See short_weierstrass_model().

    • "montgomery": Return an (untwisted) Montgomery model of E assuming one exists over this field. See montgomery_model().

OUTPUT:

An elliptic curve of the specified type isomorphic to E.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_field import compute_model
sage: E = EllipticCurve([12/7, 405/49, 0, -81/8, 135/64])
sage: compute_model(E, 'minimal')
Elliptic Curve defined by y^2 = x^3 - x^2 - 7*x + 10 over Rational Field
sage: compute_model(E, 'short_weierstrass')
Elliptic Curve defined by y^2 = x^3 - 48114*x + 4035015 over Rational Field
sage: compute_model(E, 'montgomery')
Elliptic Curve defined by y^2 = x^3 + 5*x^2 + x over Rational Field
from sage.schemes.elliptic_curves.ell_field import compute_model
E = EllipticCurve([12/7, 405/49, 0, -81/8, 135/64])
compute_model(E, 'minimal')
compute_model(E, 'short_weierstrass')
compute_model(E, 'montgomery')
sage.schemes.elliptic_curves.ell_field.point_of_order(E, l)#

Given an elliptic curve E over a finite field or a number field and an integer 1, construct a point of order on E, possibly defined over an extension of the base field of E.

Currently only prime values of are supported.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_field import point_of_order
sage: E = EllipticCurve(GF(101), [1,2,3,4,5])
sage: P = point_of_order(E, 5); P
(50*Y^5 + 48*Y^4 + 26*Y^3 + 37*Y^2 + 48*Y + 15 : 25*Y^5 + 31*Y^4 + 79*Y^3 + 39*Y^2 + 3*Y + 20 : 1)
sage: P.base_ring()
Finite Field in Y of size 101^6
sage: P.order()
5
sage: P.curve().a_invariants()
(1, 2, 3, 4, 5)
from sage.schemes.elliptic_curves.ell_field import point_of_order
E = EllipticCurve(GF(101), [1,2,3,4,5])
P = point_of_order(E, 5); P
P.base_ring()
P.order()
P.curve().a_invariants()
sage: from sage.schemes.elliptic_curves.ell_field import point_of_order
sage: E = EllipticCurve(QQ, [7,7])
sage: P = point_of_order(E, 3); P  # random
(x : -Y : 1)
sage: P.base_ring()
Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field
sage: P.order()
3
sage: P.curve().a_invariants()
(0, 0, 0, 7, 7)
from sage.schemes.elliptic_curves.ell_field import point_of_order
E = EllipticCurve(QQ, [7,7])
P = point_of_order(E, 3); P  # random
P.base_ring()
P.order()
P.curve().a_invariants()