Isogenies

An isogeny \varphi: E_1\to E_2 between two elliptic curves E_1 and E_2 is a morphism of curves that sends the origin of E_1 to the origin of E_2. Such a morphism is automatically a morphism of group schemes and the kernel is a finite subgroup scheme of E_1. Such a subscheme can either be given by a list of generators, which have to be torsion points, or by a polynomial in the coordinate x of the Weierstrass equation of E_1.

The usual way to create and work with isogenies is illustrated with the following example:

sage: k = GF(11)
sage: E = EllipticCurve(k,[1,1])
sage: Q = E(6,5)
sage: phi = E.isogeny(Q)
sage: phi
Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 11 to Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 11
sage: P = E(4,5)
sage: phi(P)
(10 : 0 : 1)
sage: phi.codomain()
Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 11
sage: phi.rational_maps()
((x^7 + 4*x^6 - 3*x^5 - 2*x^4 - 3*x^3 + 3*x^2 + x - 2)/(x^6 + 4*x^5 - 4*x^4 - 5*x^3 + 5*x^2), (x^9*y - 5*x^8*y - x^7*y + x^5*y - x^4*y - 5*x^3*y - 5*x^2*y - 2*x*y - 5*y)/(x^9 - 5*x^8 + 4*x^6 - 3*x^4 + 2*x^3))

The functions directly accessible from an elliptic curve E over a field are isogeny and isogeny_codomain.

The most useful functions that apply to isogenies are

  • codomain
  • degree
  • domain
  • dual
  • rational_maps
  • kernel_polynomial

Warning

Only cyclic isogenies are implemented (except for [2]). Some algorithms may need the isogeny to be normalized.

AUTHORS:

  • Daniel Shumow <shumow@gmail.com>: 2009-04-19: initial version
  • Chris Wuthrich : 7/09: changes: add check of input, not the full list is needed. 10/09: eliminating some bugs.
  • John Cremona and Jenny Cooley: 2009-07..11: implement l-isogenies for l = 2, 3, 5, 7 13 (the genus 0 cases) and also for l = 11, 17, 19, 37, 43, 67 or 163 over \QQ (the sporadic cases with only finitely many j-invariants each).
class sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny(E, kernel, codomain=None, degree=None, model=None, check=True)

Bases: sage.categories.morphism.Morphism

Class Implementing Isogenies of Elliptic Curves

This class implements cyclic, separable, normalized isogenies of elliptic curves.

Several different algorithms for computing isogenies are available. These include:

  • Velu’s Formulas: Velu’s original formulas for computing isogenies. This algorithm is selected by giving as the kernel parameter a list of points which generate 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 (little endian)) which will define the kernel of the isogeny.

INPUT:

  • E - an elliptic curve, the domain of the isogeny to

    initialize.

  • kernel - a kernel, either a point in E, a list of points

    in E, a monic kernel polynomial, or None. If initializing from a domain/codomain, this must be set to None.

  • codomain - an elliptic curve (default:None). If kernel

    is None, then this must be the codomain of a cyclic, separable, normalized isogeny, furthermore, degree must be the degree of the isogeny from E to codomain. If kernel is not None, then this must be isomorphic to the codomain of the cyclic normalized separable isogeny defined by kernel, in this case, the isogeny is post composed with an isomorphism so that this parameter is the codomain.

  • degree - an integer (default:None).

    If kernel is None, then this is the degree of the isogeny from E to codomain. If kernel is not None, then this is used to determine whether or not to skip a gcd of the kernel polynomial with the two torsion polynomial of E.

  • model - a string (default:None). Only supported variable is

    minimal, in which case if E is a curve over the rationals, then the codomain is set to be the unique global minimum model.

  • check (default: True) checks if the input is valid to define an isogeny

EXAMPLES:

A simple example of creating an isogeny of a field of small characteristic:

sage: E = EllipticCurve(GF(7), [0,0,0,1,0])
sage: phi = EllipticCurveIsogeny(E, E((0,0)) ); phi
Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7 to Elliptic Curve defined by y^2 = x^3 + 3*x over Finite Field of size 7
sage: phi.degree() == 2
True
sage: phi.kernel_polynomial()
x
sage: phi.rational_maps()
((x^2 + 1)/x, (x^2*y - y)/x^2)
sage: phi == loads(dumps(phi))
True

A more complicated example of a characteristic 2 field:

sage: E = EllipticCurve(GF(2^4,'alpha'), [0,0,1,0,1])
sage: P = E((1,1))
sage: phi_v = EllipticCurveIsogeny(E, P); phi_v
Isogeny of degree 3 from Elliptic Curve defined by y^2 + y = x^3 + 1 over Finite Field in alpha of size 2^4 to Elliptic Curve defined by y^2 + y = x^3 over Finite Field in alpha of size 2^4
sage: phi_ker_poly = phi_v.kernel_polynomial()
sage: phi_ker_poly
x + 1
sage: ker_poly_list = phi_ker_poly.list()
sage: phi_k = EllipticCurveIsogeny(E, ker_poly_list)
sage: phi_k == phi_v
True
sage: phi_k.rational_maps()
((x^3 + x + 1)/(x^2 + 1), (x^3*y + x^2*y + x*y + x + y)/(x^3 + x^2 + x + 1))
sage: phi_v.rational_maps()
((x^3 + x + 1)/(x^2 + 1), (x^3*y + x^2*y + x*y + x + y)/(x^3 + x^2 + x + 1))
sage: phi_k.degree() == phi_v.degree()
True
sage: phi_k.degree()
3
sage: phi_k.is_separable()
True
sage: phi_v(E(0))
(0 : 1 : 0)
sage: alpha = E.base_field().gen()
sage: Q = E((0, alpha*(alpha + 1)))
sage: phi_v(Q)
(1 : alpha^2 + alpha : 1)
sage: phi_v(P) == phi_k(P)
True
sage: phi_k(P) == phi_v.codomain()(0)
True

We can create an isogeny that has kernel equal to the full 2 torsion:

sage: E = EllipticCurve(GF(3), [0,0,0,1,1])
sage: ker_list = E.division_polynomial(2).list()
sage: phi = EllipticCurveIsogeny(E, ker_list); phi
Isogeny of degree 4 from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 3 to Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 3
sage: phi(E(0))
(0 : 1 : 0)
sage: phi(E((0,1)))
(1 : 0 : 1)
sage: phi(E((0,2)))
(1 : 0 : 1)
sage: phi(E((1,0)))
(0 : 1 : 0)
sage: phi.degree()
4

We can also create trivial isogenies with the trivial kernel:

sage: E = EllipticCurve(GF(17), [11, 11, 4, 12, 10])
sage: phi_v = EllipticCurveIsogeny(E, E(0))
sage: phi_v.degree()
1
sage: phi_v.rational_maps()
(x, y)
sage: E == phi_v.codomain()
True
sage: P = E.random_point()
sage: phi_v(P) == P
True

sage: E = EllipticCurve(GF(31), [23, 1, 22, 7, 18])
sage: phi_k = EllipticCurveIsogeny(E, [1])
sage: phi_k
Isogeny of degree 1 from Elliptic Curve defined by y^2 + 23*x*y + 22*y = x^3 + x^2 + 7*x + 18 over Finite Field of size 31 to Elliptic Curve defined by y^2 + 23*x*y + 22*y = x^3 + x^2 + 7*x + 18 over Finite Field of size 31
sage: phi_k.degree()
1
sage: phi_k.rational_maps()
(x, y)
sage: phi_k.codomain() == E
True
sage: phi_k.kernel_polynomial()
1
sage: P = E.random_point(); P == phi_k(P)
True

Velu and Kohel also work in characteristic 0:

sage: E = EllipticCurve(QQ, [0,0,0,3,4])
sage: P_list = E.torsion_points()
sage: phi = EllipticCurveIsogeny(E, P_list)
sage: phi
Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 3*x + 4 over Rational Field to Elliptic Curve defined by y^2 = x^3 - 27*x + 46 over Rational Field
sage: P = E((0,2))
sage: phi(P)
(6 : -10 : 1)
sage: phi_ker_poly = phi.kernel_polynomial()
sage: phi_ker_poly
x + 1
sage: ker_poly_list = phi_ker_poly.list()
sage: phi_k = EllipticCurveIsogeny(E, ker_poly_list); phi_k
Isogeny of degree 2 from Elliptic Curve defined by y^2 = x^3 + 3*x + 4 over Rational Field to Elliptic Curve defined by y^2 = x^3 - 27*x + 46 over Rational Field
sage: phi_k(P) == phi(P)
True
sage: phi_k == phi
True
sage: phi_k.degree()
2
sage: phi_k.is_separable()
True

A more complicated example over the rationals (of odd degree):

sage: E = EllipticCurve('11a1')
sage: P_list = E.torsion_points()
sage: phi_v = EllipticCurveIsogeny(E, P_list); phi_v
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
sage: P = E((16,-61))
sage: phi_v(P)
(0 : 1 : 0)
sage: ker_poly = phi_v.kernel_polynomial(); ker_poly
x^2 - 21*x + 80
sage: ker_poly_list = ker_poly.list()
sage: phi_k = EllipticCurveIsogeny(E, ker_poly_list); phi_k
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
sage: phi_k == phi_v
True
sage: phi_v(P) == phi_k(P)
True
sage: phi_k.is_separable()
True

We can also do this same example over the number field defined by the irreducible two torsion polynomial of E:

sage: E = EllipticCurve('11a1')
sage: P_list = E.torsion_points()
sage: K.<alpha> = NumberField(x^3 - 2* x^2 - 40*x - 158)
sage: EK = E.change_ring(K)
sage: P_list = [EK(P) for P in P_list]
sage: phi_v = EllipticCurveIsogeny(EK, P_list); phi_v
Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field in alpha with defining polynomial x^3 - 2*x^2 - 40*x - 158 to Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-7820)*x + (-263580) over Number Field in alpha with defining polynomial x^3 - 2*x^2 - 40*x - 158
sage: P = EK((alpha/2,-1/2))
sage: phi_v(P)
(122/121*alpha^2 + 1633/242*alpha - 3920/121 : -1/2 : 1)
sage: ker_poly = phi_v.kernel_polynomial()
sage: ker_poly
x^2 - 21*x + 80
sage: ker_poly_list = ker_poly.list()
sage: phi_k = EllipticCurveIsogeny(EK, ker_poly_list)
sage: phi_k
Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-10)*x + (-20) over Number Field in alpha with defining polynomial x^3 - 2*x^2 - 40*x - 158 to Elliptic Curve defined by y^2 + y = x^3 + (-1)*x^2 + (-7820)*x + (-263580) over Number Field in alpha with defining polynomial x^3 - 2*x^2 - 40*x - 158
sage: phi_v == phi_k
True
sage: phi_k(P) == phi_v(P)
True
sage: phi_k == phi_v
True
sage: phi_k.degree()
5
sage: phi_v.is_separable()
True

The following example shows how to specify an isogeny from domain and codomain:

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^2 - 21*x + 80
sage: phi = E.isogeny(f)
sage: E2 = phi.codomain()
sage: phi_s = EllipticCurveIsogeny(E, None, E2, 5)
sage: phi_s
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
sage: phi_s == phi
True
sage: phi_s.rational_maps() == phi.rational_maps()
True

However only cyclic normalized isogenies can be constructed this way. So it won’t find the isogeny [3]:

sage: E.isogeny(None, codomain=E,degree=9)
...
ValueError: The two curves are not linked by a cyclic normalized isogeny of degree 9

Also the presumed isogeny between the domain and codomain must be normalized:

sage: E2.isogeny(None,codomain=E,degree=5)
...
ValueError: The two curves are not linked by a cyclic normalized isogeny of degree 5
sage: phi.dual()
Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
sage: phi.dual().is_normalized()
False

Here an example of a construction of a endomorphisms with cyclic kernel on a CM-curve:

sage: K.<i> = NumberField(x^2+1)
sage: E = EllipticCurve(K, [1,0])
sage: RK.<X> = K[]
sage: f = X^2 - 2/5*i + 1/5
sage: phi= E.isogeny(f)
sage: isom = phi.codomain().isomorphism_to(E)
sage: phi.set_post_isomorphism(isom)
sage: phi.codomain() == phi.domain()
True
sage: phi.rational_maps()
(((-4/25*i - 3/25)*x^5 + (-4/5*i + 2/5)*x^3 + x)/(x^4 + (-4/5*i + 2/5)*x^2 + (-4/25*i - 3/25)),
((2/125*i - 11/125)*x^6*y + (64/125*i + 23/125)*x^4*y + (162/125*i - 141/125)*x^2*y + (-4/25*i - 3/25)*y)/(x^6 + (-6/5*i + 3/5)*x^4 + (-12/25*i - 9/25)*x^2 + (2/125*i - 11/125)))
codomain()

Returns the codomain (range) curve of this isogeny.

EXAMPLES:

sage: E = EllipticCurve(QQ, [0,0,0,1,0])
sage: phi = EllipticCurveIsogeny(E,  E((0,0)))
sage: phi.codomain()
Elliptic Curve defined by y^2 = x^3 - 4*x over Rational Field

sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
sage: phi = EllipticCurveIsogeny(E, [17, 1])
sage: phi.codomain()
Elliptic Curve defined by y^2 + x*y = x^3 + 24*x + 6 over Finite Field of size 31
degree()

Returns the degree of this isogeny.

EXAMPLES:

sage: E = EllipticCurve(QQ, [0,0,0,1,0])
sage: phi = EllipticCurveIsogeny(E,  E((0,0)))
sage: phi.degree()
2
sage: phi = EllipticCurveIsogeny(E, [0,1,0,1])
sage: phi.degree()
4

sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
sage: phi = EllipticCurveIsogeny(E, [17, 1])
sage: phi.degree()
3
domain()

Returns the domain curve of this isogeny.

EXAMPLES:

sage: E = EllipticCurve(QQ, [0,0,0,1,0])
sage: phi = EllipticCurveIsogeny(E,  E(0,0))
sage: phi.domain() == E
True

sage: E = EllipticCurve(GF(31), [1,0,0,1,2])
sage: phi = EllipticCurveIsogeny(E, [17, 1])
sage: phi.domain()
Elliptic Curve defined by y^2 + x*y = x^3 + x + 2 over Finite Field of size 31
dual()

Computes and returns the dual isogeny of this isogeny. If \varphi\colon E \to E_2 is the given isogeny, then the dual is by definition the unique isogeny \hat\varphi\colon E_2\to
E such that the compositions \hat\varphi\circ\varphi and \varphi\circ\hat\varphi are the multiplication [n] by the degree of \varphi on E and E_2 respectively.

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^2 - 21*x + 80
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi_hat = phi.dual()
sage: phi_hat.domain() == phi.codomain()
True
sage: phi_hat.codomain() == phi.domain()
True
sage: (X, Y) = phi.rational_maps()
sage: (Xhat, Yhat) = phi_hat.rational_maps()
sage: Xm = Xhat.subs(x=X, y=Y)
sage: Ym = Yhat.subs(x=X, y=Y)
sage: (Xm, Ym) == E.multiplication_by_m(5)
True

sage: E = EllipticCurve(GF(37), [0,0,0,1,8])
sage: R.<x> = GF(37)[]
sage: f = x^3 + x^2 + 28*x + 33
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi_hat = phi.dual()
sage: phi_hat.codomain() == phi.domain()
True
sage: phi_hat.domain() == phi.codomain()
True
sage: (X, Y) = phi.rational_maps()
sage: (Xhat, Yhat) = phi_hat.rational_maps()
sage: Xm = Xhat.subs(x=X, y=Y)
sage: Ym = Yhat.subs(x=X, y=Y)
sage: (Xm, Ym) == E.multiplication_by_m(7)
True

sage: E = EllipticCurve(GF(31), [0,0,0,1,8])
sage: R.<x> = GF(31)[]
sage: f = x^2 + 17*x + 29
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi_hat = phi.dual()
sage: phi_hat.codomain() == phi.domain()
True
sage: phi_hat.domain() == phi.codomain()
True
sage: (X, Y) = phi.rational_maps()
sage: (Xhat, Yhat) = phi_hat.rational_maps()
sage: Xm = Xhat.subs(x=X, y=Y)
sage: Ym = Yhat.subs(x=X, y=Y)
sage: (Xm, Ym) == E.multiplication_by_m(5)
True

Test (for trac ticket 7096):

sage: E = EllipticCurve('11a1')
sage: phi = E.isogeny(E(5,5))
sage: phi.dual().dual() == phi
True

sage: k = GF(103)
sage: E = EllipticCurve(k,[11,11])
sage: phi = E.isogeny(E(4,4))
sage: phi
Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 11*x + 11 over Finite Field of size 103 to Elliptic Curve defined by y^2 = x^3 + 25*x + 80 over Finite Field of size 103
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: phi.set_post_isomorphism(WeierstrassIsomorphism(phi.codomain(),(5,0,1,2)))
sage: phi.dual().dual() == phi
True

sage: E = EllipticCurve(GF(103),[1,0,0,1,-1])
sage: phi = E.isogeny(E(60,85))
sage: phi.dual()
Isogeny of degree 7 from Elliptic Curve defined by y^2 + x*y = x^3 + 84*x + 34 over Finite Field of size 103 to Elliptic Curve defined by y^2 + x*y = x^3 + x + 102 over Finite Field of size 103
formal(prec=20)

Computes the formal isogeny as a power series in the variable t=-x/y on the domain curve.

INPUT:

  • prec - (default = 20), the precision with which the computations

    in the formal group are carried out.

EXAMPLES:

sage: E = EllipticCurve(GF(13),[1,7])
sage: phi = E.isogeny(E(10,4))
sage: phi.formal()
t + 12*t^13 + 2*t^17 + 8*t^19 + 2*t^21 + O(t^23)

sage: E = EllipticCurve([0,1])
sage: phi = E.isogeny(E(2,3))
sage: phi.formal(prec=10)
t + 54*t^5 + 255*t^7 + 2430*t^9 + 19278*t^11 + O(t^13)

sage: E = EllipticCurve('11a2')
sage: R.<x> = QQ[]
sage: phi = E.isogeny(x^2 + 101*x + 12751/5)
sage: phi.formal(prec=7)
t - 2724/5*t^5 + 209046/5*t^7 - 4767/5*t^8 + 29200946/5*t^9 + O(t^10)
get_post_isomorphism()

Returns the post-isomorphism of this isogeny. If there has been no post-isomorphism set, this returns None.

EXAMPLES:

sage: E = EllipticCurve(j=GF(31)(0))
sage: R.<x> = GF(31)[]
sage: phi = EllipticCurveIsogeny(E, x+18)
sage: phi.get_post_isomorphism()
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: isom = WeierstrassIsomorphism(phi.codomain(), (6,8,10,12))
sage: phi.set_post_isomorphism(isom)
sage: isom == phi.get_post_isomorphism()
True

sage: E = EllipticCurve(GF(83), [1,0,1,1,0])
sage: R.<x> = GF(83)[]; f = x+24
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: phi2 = EllipticCurveIsogeny(E, None, E2, 2)
sage: phi2.get_post_isomorphism()
Generic morphism:
From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 65*x + 69 over Finite Field of size 83
To:   Abelian group of points on Elliptic Curve defined by y^2 + x*y + 77*y = x^3 + 49*x + 28 over Finite Field of size 83
Via:  (u,r,s,t) = (1, 7, 42, 80)
get_pre_isomorphism()

Returns the pre-isomorphism of this isogeny. If there has been no pre-isomorphism set, this returns None.

EXAMPLES:

sage: E = EllipticCurve(GF(31), [1,1,0,1,-1])
sage: R.<x> = GF(31)[]
sage: f = x^3 + 9*x^2 + x + 30
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi.get_post_isomorphism()
sage: Epr = E.short_weierstrass_model()
sage: isom = Epr.isomorphism_to(E)
sage: phi.set_pre_isomorphism(isom)
sage: isom == phi.get_pre_isomorphism()
True

sage: E = EllipticCurve(GF(83), [1,0,1,1,0])
sage: R.<x> = GF(83)[]; f = x+24
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: phi2 = EllipticCurveIsogeny(E, None, E2, 2)
sage: phi2.get_pre_isomorphism()
Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 83
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 62*x + 74 over Finite Field of size 83
  Via:  (u,r,s,t) = (1, 76, 41, 3)
is_injective()

Method inherited from the morphism class. Returns True if and only if this isogeny has trivial kernel.

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^2 + x - 29/5
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi.is_injective()
False
sage: phi = EllipticCurveIsogeny(E, R(1))
sage: phi.is_injective()
True

sage: F = GF(7)
sage: E = EllipticCurve(j=F(0))
sage: phi = EllipticCurveIsogeny(E, [ E((0,-1)), E((0,1))])
sage: phi.is_injective()
False
sage: phi = EllipticCurveIsogeny(E, E(0))
sage: phi.is_injective()
True
is_normalized(via_formal=True, check_by_pullback=True)

Returns True if this isogeny is normalized. An isogeny \varphi\colon E\to E_2 between two given Weierstrass equations is said to be normalized if the constant c is 1 in \varphi*(\omega_2) = c\cdot\omega, where \omega and omega_2 are the invariant differentials on E and E_2 corresponding to the given equation.

INPUT:

  • via_formal - (default: True) If True it simply checks if

    the leading term of the formal series is 1. Otherwise it uses a deprecated algorithm involving the second optional argument.

  • check_by_pullback - (default:True) Deprecated.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: E = EllipticCurve(GF(7), [0,0,0,1,0])
sage: R.<x> = GF(7)[]
sage: phi = EllipticCurveIsogeny(E, x)
sage: phi.is_normalized()
True
sage: isom = WeierstrassIsomorphism(phi.codomain(), (3, 0, 0, 0))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
False
sage: isom = WeierstrassIsomorphism(phi.codomain(), (5, 0, 0, 0))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
True
sage: isom = WeierstrassIsomorphism(phi.codomain(), (1, 1, 1, 1))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
True

sage: F = GF(2^5, 'alpha'); alpha = F.gen()
sage: E = EllipticCurve(F, [1,0,1,1,1])
sage: R.<x> = F[]
sage: phi = EllipticCurveIsogeny(E, x+1)
sage: isom = WeierstrassIsomorphism(phi.codomain(), (alpha, 0, 0, 0))
sage: phi.is_normalized()
True
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
False
sage: isom = WeierstrassIsomorphism(phi.codomain(), (1/alpha, 0, 0, 0))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
True
sage: isom = WeierstrassIsomorphism(phi.codomain(), (1, 1, 1, 1))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
True

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^3 - x^2 - 10*x - 79/4
sage: phi = EllipticCurveIsogeny(E, f)
sage: isom = WeierstrassIsomorphism(phi.codomain(), (2, 0, 0, 0))
sage: phi.is_normalized()
True
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
False
sage: isom = WeierstrassIsomorphism(phi.codomain(), (1/2, 0, 0, 0))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
True
sage: isom = WeierstrassIsomorphism(phi.codomain(), (1, 1, 1, 1))
sage: phi.set_post_isomorphism(isom)
sage: phi.is_normalized()
True
is_separable()

This function returns a bool indicating whether or not this isogeny is separable.

This function always returns True as currently this class only implements separable isogenies.

EXAMPLES:

sage: E = EllipticCurve(GF(17), [0,0,0,3,0])
sage: phi = EllipticCurveIsogeny(E,  E((0,0)))
sage: phi.is_separable()
True

sage: E = EllipticCurve('11a1')
sage: phi = EllipticCurveIsogeny(E, E.torsion_points())
sage: phi.is_separable()
True
is_surjective()

For elliptic curve isogenies, always returns True (as a non-constant map of algebraic curves must be surjective).

EXAMPLES:

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^2 + x - 29/5
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi.is_surjective()
True

sage: E = EllipticCurve(GF(7), [0,0,0,1,0])
sage: phi = EllipticCurveIsogeny(E,  E((0,0)))
sage: phi.is_surjective()
True

sage: F = GF(2^5, 'omega')
sage: E = EllipticCurve(j=F(0))
sage: R.<x> = F[]
sage: phi = EllipticCurveIsogeny(E, x)
sage: phi.is_surjective()
True
is_zero()

Member function inherited from morphism class.

EXAMPLES:

sage: E = EllipticCurve(j=GF(7)(0))
sage: phi = EllipticCurveIsogeny(E, [ E((0,1)), E((0,-1))])
sage: phi.is_zero()
...
NotImplementedError                      
kernel_polynomial()

Returns the kernel polynomial of this isogeny.

EXAMPLES:

sage: E = EllipticCurve(QQ, [0,0,0,2,0])
sage: phi = EllipticCurveIsogeny(E,  E((0,0)))
sage: phi.kernel_polynomial()
x

sage: E = EllipticCurve('11a1')
sage: phi = EllipticCurveIsogeny(E, E.torsion_points())
sage: phi.kernel_polynomial()
x^2 - 21*x + 80

sage: E = EllipticCurve(GF(17), [1,-1,1,-1,1])
sage: phi = EllipticCurveIsogeny(E, [1])
sage: phi.kernel_polynomial()
1

sage: E = EllipticCurve(GF(31), [0,0,0,3,0])
sage: phi = EllipticCurveIsogeny(E, [0,3,0,1])
sage: phi.kernel_polynomial()
x^3 + 3*x
n()

Numerical Approximation inherited from Map (through morphism), nonsensical for isogenies.

EXAMPLES:

sage: E = EllipticCurve(j=GF(7)(0))
sage: phi = EllipticCurveIsogeny(E, [ E((0,1)), E((0,-1))])
sage: phi.n()
...
NotImplementedError: Numerical approximations do not make sense for Elliptic Curve Isogenies
post_compose(left)

Member function inherited from morphism class.

EXAMPLES:

sage: E = EllipticCurve(j=GF(7)(0))
sage: phi = EllipticCurveIsogeny(E, [ E((0,1)), E((0,-1))])
sage: phi.post_compose(phi)
...
NotImplementedError                      
pre_compose(right)

Member function inherited from morphism class.

EXAMPLES:

sage: E = EllipticCurve(j=GF(7)(0))
sage: phi = EllipticCurveIsogeny(E, [ E((0,1)), E((0,-1))])
sage: phi.pre_compose(phi)
...
NotImplementedError                      
rational_maps()

This function returns this isogeny as a pair of rational maps.

EXAMPLES:

sage: E = EllipticCurve(QQ, [0,2,0,1,-1])
sage: phi = EllipticCurveIsogeny(E, [1])
sage: phi.rational_maps()
(x, y)

sage: E = EllipticCurve(GF(17), [0,0,0,3,0])
sage: phi = EllipticCurveIsogeny(E,  E((0,0)))
sage: phi.rational_maps()
((x^2 + 3)/x, (x^2*y - 3*y)/x^2)
set_post_isomorphism(postWI)

Modifies this isogeny object to post compose with the given Weierstrass isomorphism.

EXAMPLES:

sage: E = EllipticCurve(j=GF(31)(0))
sage: R.<x> = GF(31)[]
sage: phi = EllipticCurveIsogeny(E, x+18)
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: phi.set_post_isomorphism(WeierstrassIsomorphism(phi.codomain(), (6,8,10,12)))
sage: phi
Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 31 to Elliptic Curve defined by y^2 + 24*x*y + 7*y = x^3 + 22*x^2 + 16*x + 20 over Finite Field of size 31

sage: E = EllipticCurve(j=GF(47)(0))
sage: f = E.torsion_polynomial(3)/3
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: post_isom = E2.isomorphism_to(E)
sage: phi.set_post_isomorphism(post_isom)
sage: phi.rational_maps() == E.multiplication_by_m(3)
False
sage: phi.switch_sign()
sage: phi.rational_maps() == E.multiplication_by_m(3)
True

Example over a number field:

sage: R.<x> = QQ[]
sage: K.<a> = NumberField(x^2 + 2)
sage: E = EllipticCurve(j=K(1728))
sage: ker_list = E.torsion_points()
sage: phi = EllipticCurveIsogeny(E, ker_list)
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: post_isom = WeierstrassIsomorphism(phi.codomain(), (a,2,3,5))
sage: phi
Isogeny of degree 4 from Elliptic Curve defined by y^2 = x^3 + x over Number Field in a with defining polynomial x^2 + 2 to Elliptic Curve defined by y^2 = x^3 + (-44)*x + 112 over Number Field in a with defining polynomial x^2 + 2
set_pre_isomorphism(preWI)

Modifies this isogeny object to pre compose with the given Weierstrass isomorphism.

EXAMPLES:

sage: E = EllipticCurve(GF(31), [1,1,0,1,-1])
sage: R.<x> = GF(31)[]
sage: f = x^3 + 9*x^2 + x + 30
sage: phi = EllipticCurveIsogeny(E, f)
sage: Epr = E.short_weierstrass_model()
sage: isom = Epr.isomorphism_to(E)
sage: phi.set_pre_isomorphism(isom)
sage: phi.rational_maps()
((-6*x^4 - 3*x^3 + 12*x^2 + 10*x - 1)/(x^3 + x - 12),
 (3*x^7 + x^6*y - 14*x^6 - 3*x^5 + 5*x^4*y + 7*x^4 + 8*x^3*y - 8*x^3 - 5*x^2*y + 5*x^2 - 14*x*y + 14*x - 6*y - 6)/(x^6 + 2*x^4 + 7*x^3 + x^2 + 7*x - 11))
sage: phi(Epr((0,22)))
(13 : 21 : 1)
sage: phi(Epr((3,7)))
(14 : 17 : 1)

sage: E = EllipticCurve(GF(29), [0,0,0,1,0])
sage: R.<x> = GF(29)[]
sage: f = x^2 + 5
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi
Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 29 to Elliptic Curve defined by y^2 = x^3 + 20*x over Finite Field of size 29
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: inv_isom = WeierstrassIsomorphism(E, (1,-2,5,10))
sage: Epr = inv_isom.codomain().codomain()
sage: isom = Epr.isomorphism_to(E)
sage: phi.set_pre_isomorphism(isom); phi
Isogeny of degree 5 from Elliptic Curve defined by y^2 + 10*x*y + 20*y = x^3 + 27*x^2 + 6 over Finite Field of size 29 to Elliptic Curve defined by y^2 = x^3 + 20*x over Finite Field of size 29
sage: phi(Epr((12,1)))
(26 : 0 : 1)
sage: phi(Epr((2,9)))
(0 : 0 : 1)
sage: phi(Epr((21,12)))
(3 : 0 : 1)
sage: phi.rational_maps()[0]
(x^5 - 10*x^4 - 6*x^3 - 7*x^2 - x + 3)/(x^4 - 8*x^3 + 5*x^2 - 14*x - 6)

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^2 - 21*x + 80
sage: phi = EllipticCurveIsogeny(E, f); phi
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
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism
sage: Epr = E.short_weierstrass_model()
sage: isom = Epr.isomorphism_to(E)
sage: phi.set_pre_isomorphism(isom)
sage: phi
Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 - 13392*x - 1080432 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field
sage: phi(Epr((168,1188)))
(0 : 1 : 0)
switch_sign()

This function composes the isogeny with [-1] (flipping the coefficient between +/-1 on the y coordinate rational map).

EXAMPLES:

sage: E = EllipticCurve(GF(23), [0,0,0,1,0])
sage: f = E.torsion_polynomial(3)/3
sage: phi = EllipticCurveIsogeny(E, f, E)
sage: phi.rational_maps() == E.multiplication_by_m(3)
False
sage: phi.switch_sign()
sage: phi.rational_maps() == E.multiplication_by_m(3)
True

sage: E = EllipticCurve(GF(17), [-2, 3, -5, 7, -11])
sage: R.<x> = GF(17)[]
sage: f = x+6
sage: phi = EllipticCurveIsogeny(E, f)
sage: phi
Isogeny of degree 2 from Elliptic Curve defined by y^2 + 15*x*y + 12*y = x^3 + 3*x^2 + 7*x + 6 over Finite Field of size 17 to Elliptic Curve defined by y^2 + 15*x*y + 12*y = x^3 + 3*x^2 + 4*x + 8 over Finite Field of size 17
sage: phi.rational_maps()
((x^2 + 6*x + 4)/(x + 6), (x^2*y - 5*x*y + 8*x - 2*y)/(x^2 - 5*x + 2))
sage: phi.switch_sign()
sage: phi
Isogeny of degree 2 from Elliptic Curve defined by y^2 + 15*x*y + 12*y = x^3 + 3*x^2 + 7*x + 6 over Finite Field of size 17 to Elliptic Curve defined by y^2 + 15*x*y + 12*y = x^3 + 3*x^2 + 4*x + 8 over Finite Field of size 17
sage: phi.rational_maps()
((x^2 + 6*x + 4)/(x + 6),
 (2*x^3 - x^2*y - 5*x^2 + 5*x*y - 4*x + 2*y + 7)/(x^2 - 5*x + 2))

sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]
sage: f = x^2 - 21*x + 80
sage: phi = EllipticCurveIsogeny(E, f)
sage: (xmap1, ymap1) = phi.rational_maps()
sage: phi.switch_sign()
sage: (xmap2, ymap2) = phi.rational_maps()
sage: xmap1 == xmap2
True
sage: ymap1 == -ymap2 - E.a1()*xmap2 - E.a3()
True

sage: K.<a> = NumberField(x^2 + 1)
sage: E = EllipticCurve(K, [0,0,0,1,0])
sage: R.<x> = K[]
sage: phi = EllipticCurveIsogeny(E, x-a)
sage: phi.rational_maps()
((x^2 + (-a)*x - 2)/(x + (-a)), (x^2*y + (-2*a)*x*y + y)/(x^2 + (-2*a)*x - 1))
sage: phi.switch_sign()
sage: phi.rational_maps()
((x^2 + (-a)*x - 2)/(x + (-a)), (-x^2*y + (2*a)*x*y - y)/(x^2 + (-2*a)*x - 1))
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_codomain_formula(E, v, w)

Given parameters v and w (as in Velu / Kohel / etc formulas) computes the codomain curve.

EXAMPLES:

This formula is used by every Isogeny Instantiation:

sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: phi = EllipticCurveIsogeny(E, E((1,2)) )
sage: phi.codomain()
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 9*x + 13 over Finite Field of size 19
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_codomain_formula
sage: v = phi._EllipticCurveIsogeny__v
sage: w = phi._EllipticCurveIsogeny__w
sage: compute_codomain_formula(E, v, w)
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 9*x + 13 over Finite Field of size 19
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_codomain_kohel(E, kernel, degree)

This function computes the codomain from the kernel polynomial as per Kohel’s formulas.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_codomain_kohel
sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: phi = EllipticCurveIsogeny(E, [9,1])
sage: phi.codomain() == isogeny_codomain_from_kernel(E, [9,1])
True
sage: compute_codomain_kohel(E, [9,1], 2)
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 9*x + 8 over Finite Field of size 19
sage: R.<x> = GF(19)[]
sage: E = EllipticCurve(GF(19), [18,17,16,15,14])
sage: phi = EllipticCurveIsogeny(E, x^3 + 14*x^2 + 3*x + 11)
sage: phi.codomain() == isogeny_codomain_from_kernel(E, x^3 + 14*x^2 + 3*x + 11)
True
sage: compute_codomain_kohel(E, x^3 + 14*x^2 + 3*x + 11, 7)
Elliptic Curve defined by y^2 + 18*x*y + 16*y = x^3 + 17*x^2 + 18*x + 18 over Finite Field of size 19
sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: phi = EllipticCurveIsogeny(E, x^3 + 7*x^2 + 15*x + 12)
sage: isogeny_codomain_from_kernel(E, x^3 + 7*x^2 + 15*x + 12) == phi.codomain()
True
sage: compute_codomain_kohel(E, x^3 + 7*x^2 + 15*x + 12,4)
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 3*x + 15 over Finite Field of size 19

NOTES:

This function uses the formulas of Section 2.4 of [K96].

REFERENCES:

  • [K96] Kohel, “Endomorphism Rings of Elliptic Curves over Finite Fields”
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_intermediate_curves(E1, E2)

Computes isomorphism from E1 to an intermediate domain and an isomorphism from an intermediate codomain to E2.

Intermediate domain and intermediate codomain, are in short Weierstrass form.

This is used so we can compute \wp functions from the short Weierstrass model more easily.

The underlying field must be of characteristic not equal to 2,3.

INPUT:

  • E1 - an elliptic curve
  • E2 - an elliptic curve

OUTPUT:

tuple – (pre_isomorphism, post_isomorphism, intermediate_domain,
intermediate_codomain):
  • intermediate_domain: a short Weierstrass model isomorphic to E1
  • intermediate_codomain: a short Weierstrass model isomorphic to E2
  • pre_isomorphism: normalized isomorphism from E1 to intermediate_domain
  • post_isomorphism: normalized isomorphism from intermediate_codomain to E2

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_intermediate_curves
sage: E = EllipticCurve(GF(83), [1,0,1,1,0])
sage: R.<x> = GF(83)[]; f = x+24
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: compute_intermediate_curves(E, E2)
(Elliptic Curve defined by y^2 = x^3 + 62*x + 74 over Finite Field of size 83,
 Elliptic Curve defined by y^2 = x^3 + 65*x + 69 over Finite Field of size 83,
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 83
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 62*x + 74 over Finite Field of size 83
  Via:  (u,r,s,t) = (1, 76, 41, 3),
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 65*x + 69 over Finite Field of size 83
  To:   Abelian group of points on Elliptic Curve defined by y^2 + x*y + 77*y = x^3 + 49*x + 28 over Finite Field of size 83
  Via:  (u,r,s,t) = (1, 7, 42, 80))

sage: R.<x> = QQ[]
sage: K.<i> = NumberField(x^2 + 1)
sage: E = EllipticCurve(K, [0,0,0,1,0])
sage: E2 = EllipticCurve(K, [0,0,0,16,0])
sage: compute_intermediate_curves(E, E2)
(Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1,
 Elliptic Curve defined by y^2 = x^3 + 16*x over Number Field in i with defining polynomial x^2 + 1,
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1
  Via:  (u,r,s,t) = (1, 0, 0, 0),
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 16*x over Number Field in i with defining polynomial x^2 + 1
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 16*x over Number Field in i with defining polynomial x^2 + 1
  Via:  (u,r,s,t) = (1, 0, 0, 0))
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm='starks')

Computes the kernel polynomial of the degree ell isogeny between E1 and E2. There must be a degree ell, cyclic, separable, normalized isogeny from E1 to E2.

INPUT:

  • E1 - an elliptic curve in short Weierstrass form.
  • E2 - an elliptic curve in short Weierstrass form.
  • ell - the degree of the isogeny from E1 to E2.
  • algorithm - currently only starks (default) is implemented.

OUTPUT:

polynomial – over the field of definition of E1, E2, that is the
kernel polynomial of the isogeny from E1 to E2.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_kernel_polynomial

sage: E = EllipticCurve(GF(37), [0,0,0,1,8])
sage: R.<x> = GF(37)[]
sage: f = (x + 14) * (x + 30)
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: compute_isogeny_kernel_polynomial(E, E2, 5)
x^2 + 7*x + 13
sage: f
x^2 + 7*x + 13

sage: R.<x> = QQ[]
sage: K.<i> = NumberField(x^2 + 1)
sage: E = EllipticCurve(K, [0,0,0,1,0])
sage: E2 = EllipticCurve(K, [0,0,0,16,0])
sage: compute_isogeny_kernel_polynomial(E, E2, 4)
x^3 + x
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_isogeny_starks(E1, E2, ell)

Computes the degree ell isogeny between E1 and E2 via Stark’s algorithm. There must be a degree ell, separable, normalized cyclic isogeny from E1 to E2.

INPUT:

  • E1 - an elliptic curve in short Weierstrass form.
  • E2 - an elliptic curve in short Weierstrass form.
  • ell - the degree of the isogeny from E1 to E2.

OUTPUT:

polynomial – over the field of definition of E1, E2, that is the
kernel polynomial of the isogeny from E1 to E2.

ALGORITHM:

This function uses Starks Algorithm as presented in section 6.2 of [BMSS].

Note

As published there, the algorithm is incorrect, and a correct version (with slightly different notation) can be found in [M09]. The algorithm originates in [S72]

REFERENCES:

  • [BMSS] Boston, Morain, Salvy, Schost, “Fast Algorithms for Isogenies.”
  • [M09] Moody, “The Diffie-Hellman Problem and Generalization of Verheul’s Theorem”
  • [S72] Stark, “Class-numbers of complex quadratic fields.”

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_starks, compute_sequence_of_maps

sage: E = EllipticCurve(GF(97), [1,0,1,1,0])
sage: R.<x> = GF(97)[]; f = x^5 + 27*x^4 + 61*x^3 + 58*x^2 + 28*x + 21
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: (isom1, isom2, E1pr, E2pr, ker_poly) = compute_sequence_of_maps(E, E2, 11)
sage: compute_isogeny_starks(E1pr, E2pr, 11)
x^10 + 37*x^9 + 53*x^8 + 66*x^7 + 66*x^6 + 17*x^5 + 57*x^4 + 6*x^3 + 89*x^2 + 53*x + 8

sage: E = EllipticCurve(GF(37), [0,0,0,1,8])
sage: R.<x> = GF(37)[]
sage: f = (x + 14) * (x + 30)
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: compute_isogeny_starks(E, E2, 5)
x^4 + 14*x^3 + x^2 + 34*x + 21
sage: f**2
x^4 + 14*x^3 + x^2 + 34*x + 21

sage: E = EllipticCurve(QQ, [0,0,0,1,0])
sage: R.<x> = QQ[]
sage: f = x
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: compute_isogeny_starks(E, E2, 2)
x
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_sequence_of_maps(E1, E2, ell)

Given domain E1 and codomain E2 such that there is a degree ell separable normalized isogeny from E1 to E2, returns pre/post isomorphism, as well as intermediate domain and codomain, and kernel polynomial.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_sequence_of_maps
sage: E = EllipticCurve('11a1')
sage: R.<x> = QQ[]; f = x^2 - 21*x + 80
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: compute_sequence_of_maps(E, E2, 5)
(Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 - 31/3*x - 2501/108 over Rational Field
  Via:  (u,r,s,t) = (1, 1/3, 0, -1/2),
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 - 23461/3*x - 28748141/108 over Rational Field
  To:   Abelian group of points on Elliptic Curve defined by y^2 + y = x^3 - x^2 - 7820*x - 263580 over Rational Field
  Via:  (u,r,s,t) = (1, -1/3, 0, 1/2),
 Elliptic Curve defined by y^2 = x^3 - 31/3*x - 2501/108 over Rational Field,
 Elliptic Curve defined by y^2 = x^3 - 23461/3*x - 28748141/108 over Rational Field,
 x^2 - 61/3*x + 658/9)

sage: K.<i> = NumberField(x^2 + 1)
sage: E = EllipticCurve(K, [0,0,0,1,0])
sage: E2 = EllipticCurve(K, [0,0,0,16,0])
sage: compute_sequence_of_maps(E, E2, 4)
(Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1
  Via:  (u,r,s,t) = (1, 0, 0, 0),
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 16*x over Number Field in i with defining polynomial x^2 + 1
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 16*x over Number Field in i with defining polynomial x^2 + 1
  Via:  (u,r,s,t) = (1, 0, 0, 0),
 Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1,
 Elliptic Curve defined by y^2 = x^3 + 16*x over Number Field in i with defining polynomial x^2 + 1,
 x^3 + x)

sage: E = EllipticCurve(GF(97), [1,0,1,1,0])
sage: R.<x> = GF(97)[]; f = x^5 + 27*x^4 + 61*x^3 + 58*x^2 + 28*x + 21
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: compute_sequence_of_maps(E, E2, 11)
(Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 97
  To:   Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 52*x + 31 over Finite Field of size 97
  Via:  (u,r,s,t) = (1, 8, 48, 44),
 Generic morphism:
  From: Abelian group of points on Elliptic Curve defined by y^2 = x^3 + 41*x + 66 over Finite Field of size 97
  To:   Abelian group of points on Elliptic Curve defined by y^2 + x*y + 9*y = x^3 + 83*x + 6 over Finite Field of size 97
  Via:  (u,r,s,t) = (1, 89, 49, 53),
 Elliptic Curve defined by y^2 = x^3 + 52*x + 31 over Finite Field of size 97,
 Elliptic Curve defined by y^2 = x^3 + 41*x + 66 over Finite Field of size 97,
 x^5 + 67*x^4 + 13*x^3 + 35*x^2 + 77*x + 69)
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_vw_kohel_even_deg1(x0, y0, a1, a2, a4)

The formula for computing v and w using Kohel’s formulas for isogenies of degree 2.

EXAMPLES:

This function will be implicitly called by the following example:

sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: phi = EllipticCurveIsogeny(E, [9,1])
sage: phi
Isogeny of degree 2 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 19 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 9*x + 8 over Finite Field of size 19
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_vw_kohel_even_deg1
sage: a1,a2,a3,a4,a6 = E.ainvs()
sage: x0 = -9
sage: y0 = -(a1*x0 + a3)/2
sage: compute_vw_kohel_even_deg1(x0, y0, a1, a2, a4)
(18, 9)
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_vw_kohel_even_deg3(b2, b4, s1, s2, s3)

The formula for computing v and w using Kohel’s formulas for isogenies of degree 3.

EXAMPLES:

This function will be implicitly called by the following example:

sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: R.<x> = GF(19)[]
sage: phi = EllipticCurveIsogeny(E, x^3 + 7*x^2 + 15*x + 12)
sage: phi
Isogeny of degree 4 from Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Finite Field of size 19 to Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 3*x + 15 over Finite Field of size 19
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_vw_kohel_even_deg3
sage: (b2,b4) = (E.b2(), E.b4())
sage: (s1, s2, s3) = (-7, 15, -12)
sage: compute_vw_kohel_even_deg3(b2, b4, s1, s2, s3)
(4, 7)
sage.schemes.elliptic_curves.ell_curve_isogeny.compute_vw_kohel_odd(b2, b4, b6, s1, s2, s3, n)

This function computes the v and w according to Kohel’s formulas.

EXAMPLES:

This function will be implicitly called by the following example:

sage: E = EllipticCurve(GF(19), [18,17,16,15,14])
sage: R.<x> = GF(19)[]
sage: phi = EllipticCurveIsogeny(E, x^3 + 14*x^2 + 3*x + 11)
sage: phi
Isogeny of degree 7 from Elliptic Curve defined by y^2 + 18*x*y + 16*y = x^3 + 17*x^2 + 15*x + 14 over Finite Field of size 19 to Elliptic Curve defined by y^2 + 18*x*y + 16*y = x^3 + 17*x^2 + 18*x + 18 over Finite Field of size 19
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_vw_kohel_odd
sage: (b2,b4,b6) = (E.b2(), E.b4(), E.b6())
sage: (s1,s2,s3) = (-14,3,-11)
sage: compute_vw_kohel_odd(b2,b4,b6,s1,s2,s3,3)
(7, 1)
sage.schemes.elliptic_curves.ell_curve_isogeny.fill_isogeny_matrix(M)

Returns a filled isogeny matrix giving all degrees from one giving only prime degrees.

INPUT:

  • M – a square symmetric matrix whose off-diagonal i, j entry is either a prime l (if the i‘th and j‘th curves have an l-isogeny between them), otherwise is 0.

OUTPUT:

(matrix) a square matrix with entries 1 on the diagonal, and in general the i, j entry is d>0 if d is the minimal degree of an isogeny from the i‘th to the j‘th curve,

EXAMPLES:

sage: M = Matrix([[0, 2, 3, 3, 0, 0], [2, 0, 0, 0, 3, 3], [3, 0, 0, 0, 2, 0], [3, 0, 0, 0, 0, 2], [0, 3, 2, 0, 0, 0], [0, 3, 0, 2, 0, 0]]); M
[0 2 3 3 0 0]
[2 0 0 0 3 3]
[3 0 0 0 2 0]
[3 0 0 0 0 2]
[0 3 2 0 0 0]
[0 3 0 2 0 0]
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix
sage: fill_isogeny_matrix(M)
[ 1  2  3  3  6  6]
[ 2  1  6  6  3  3]
[ 3  6  1  9  2 18]
[ 3  6  9  1 18  2]
[ 6  3  2 18  1  9]
[ 6  3 18  2  9  1]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_13_0(E)

Returns list of all 13-isogenies from E when the j-invariant is 0.

OUTPUT:

(list) 13-isogenies with codomain E. In general these are normalised; but if -3 is a square then there are two endomorphisms of degree 13, for which the codomain is the same as the domain.

Note

This implementation requires that the characteristic is not 2, 3 or 13.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(13).

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_13_0  

Endomorphisms of degree 13 will exist when -3 is a square:

sage: K.<r> = QuadraticField(-3)
sage: E = EllipticCurve(K, [0, r]); E
Elliptic Curve defined by y^2 = x^3 + r over Number Field in r with defining polynomial x^2 + 3
sage: isogenies_13_0(E)
[Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + r over Number Field in r with defining polynomial x^2 + 3 to Elliptic Curve defined by y^2 = x^3 + r over Number Field in r with defining polynomial x^2 + 3,
Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + r over Number Field in r with defining polynomial x^2 + 3 to Elliptic Curve defined by y^2 = x^3 + r over Number Field in r with defining polynomial x^2 + 3]
sage: isogenies_13_0(E)[0].rational_maps()
(((-4/169*r - 11/169)*x^13 + (-128/13*r - 456/13)*x^10 + (-1224/13*r - 2664/13)*x^7 + (-2208/13*r + 5472/13)*x^4 + (1152/13*r - 8064/13)*x)/(x^12 + (4*r - 36)*x^9 + (-1080/13*r + 3816/13)*x^6 + (2112/13*r + 5184/13)*x^3 + (17280/169*r - 1152/169)), ((18/2197*r - 35/2197)*x^18*y + (-23142/2197*r + 35478/2197)*x^15*y + (-1127520/2197*r + 1559664/2197)*x^12*y + (87744/2197*r + 5992704/2197)*x^9*y + (-6625152/2197*r + 9085824/2197)*x^6*y + (28919808/2197*r - 2239488/2197)*x^3*y + (-1990656/2197*r + 3870720/2197)*y)/(x^18 + (6*r - 54)*x^15 + (-3024/13*r + 11808/13)*x^12 + (31296/13*r - 51840/13)*x^9 + (-487296/169*r - 2070144/169)*x^6 + (-940032/169*r - 248832/169)*x^3 + (-1990656/2197*r + 3870720/2197)))

An example of endomorphisms over a finite field:

sage: K = GF(19^2,'a')
sage: E = EllipticCurve(j=K(0)); E
Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in a of size 19^2
sage: isogenies_13_0(E)                   
[Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in a of size 19^2 to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in a of size 19^2,
Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in a of size 19^2 to Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in a of size 19^2]
sage: isogenies_13_0(E)[0].rational_maps()
((6*x^13 - 6*x^10 - 3*x^7 + 6*x^4 + x)/(x^12 - 5*x^9 - 9*x^6 - 7*x^3 + 5), (-8*x^18*y - 9*x^15*y + 9*x^12*y - 5*x^9*y + 5*x^6*y - 7*x^3*y + 7*y)/(x^18 + 2*x^15 + 3*x^12 - x^9 + 8*x^6 - 9*x^3 + 7))

A previous implementation did not work in some characteristics:

sage: K = GF(29)
sage: E = EllipticCurve(j=K(0))
sage: isogenies_13_0(E)
[Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 29 to Elliptic Curve defined by y^2 = x^3 + 26*x + 12 over Finite Field of size 29, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 29 to Elliptic Curve defined by y^2 = x^3 + 16*x + 28 over Finite Field of size 29]
sage: K = GF(101)                                          
sage: E = EllipticCurve(j=K(0)); E.ainvs()                 
(0, 0, 0, 0, 1)
sage: [phi.codomain().ainvs() for phi in isogenies_13_0(E)]
[(0, 0, 0, 64, 36), (0, 0, 0, 42, 66)]
sage: x = polygen(QQ)
sage: f = x^12 + 78624*x^9 - 130308048*x^6 + 2270840832*x^3 - 54500179968
sage: K.<a> = NumberField(f)      
sage: E = EllipticCurve(j=K(0)); E.ainvs()
(0, 0, 0, 0, 1)
sage: [phi.codomain().ainvs() for phi in isogenies_13_0(E)]
[(0, 0, 0, -739946459/23857162861049856*a^11 - 2591641747/1062017577504*a^8 + 16583647773233/4248070310016*a^5 - 14310911337/378211388*a^2, 26146225/4248070310016*a^9 + 7327668845/14750244132*a^6 + 174618431365/756422776*a^3 - 378332499709/94552847), (0, 0, 0, 3501275/5964290715262464*a^11 + 24721025/531008788752*a^8 - 47974903745/1062017577504*a^5 - 6773483100/94552847*a^2, 6699581/4248070310016*a^9 + 1826193509/14750244132*a^6 - 182763866047/756422776*a^3 - 321460597/94552847)]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_13_1728(E)

Returns list of all 13-isogenies from E when the j-invariant is 1728.

OUTPUT:

(list) 13-isogenies with codomain E. In general these are normalised; but if -1 is a square then there are two endomorphisms of degree 13, for which the codomain is the same as the domain; and over \QQ, the codomain is a minimal model.

Note

This implementation requires that the characteristic is not 2, 3 or 13.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(13).

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_13_1728

sage: K.<i> = QuadraticField(-1)
sage: E = EllipticCurve([0,0,0,i,0]); E.ainvs()
(0, 0, 0, i, 0)
sage: isogenies_13_1728(E)
[Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + i*x over Number Field in i with defining polynomial x^2 + 1 to Elliptic Curve defined by y^2 = x^3 + i*x over Number Field in i with defining polynomial x^2 + 1,
Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + i*x over Number Field in i with defining polynomial x^2 + 1 to Elliptic Curve defined by y^2 = x^3 + i*x over Number Field in i with defining polynomial x^2 + 1]
sage: K = GF(83)
sage: E = EllipticCurve(K, [0,0,0,5,0]); E.ainvs()
(0, 0, 0, 5, 0)
sage: isogenies_13_1728(E)                        
[]
sage: K = GF(89)                                  
sage: E = EllipticCurve(K, [0,0,0,5,0]); E.ainvs()
(0, 0, 0, 5, 0)
sage: isogenies_13_1728(E)                        
[Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 89 to Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 89,
Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 89 to Elliptic Curve defined by y^2 = x^3 + 5*x over Finite Field of size 89]
sage: K = GF(23)                                      
sage: E = EllipticCurve(K, [1,0])                     
sage: isogenies_13_1728(E)                            
[Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 23 to Elliptic Curve defined by y^2 = x^3 + 16 over Finite Field of size 23, Isogeny of degree 13 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 23 to Elliptic Curve defined by y^2 = x^3 + 7 over Finite Field of size 23]
sage: x = polygen(QQ)
sage: f = x^12 + 1092*x^10 - 432432*x^8 + 6641024*x^6 - 282896640*x^4 - 149879808*x^2 - 349360128
sage: K.<a> = NumberField(f)
sage: E = EllipticCurve(K, [1,0])
sage: [phi.codomain().ainvs() for phi in isogenies_13_1728(E)]
[(0,
0,
0,
11090413835/20943727039698624*a^10 + 32280103535965/55849938772529664*a^8 - 355655987835845/1551387188125824*a^6 + 19216954517530195/5235931759924656*a^4 - 1079766118721735/5936430566808*a^2 + 156413528482727/8080141604822,
214217013065/82065216155553792*a^11 + 1217882637605/427423000810176*a^9 - 214645003230565/189965778137856*a^7 + 22973355421236025/1282269002430528*a^5 - 2059145797340695/2544184528632*a^3 - 23198483147321/989405094468*a),
(0,
0,
0,
11090413835/20943727039698624*a^10 + 32280103535965/55849938772529664*a^8 - 355655987835845/1551387188125824*a^6 + 19216954517530195/5235931759924656*a^4 - 1079766118721735/5936430566808*a^2 + 156413528482727/8080141604822,
-214217013065/82065216155553792*a^11 - 1217882637605/427423000810176*a^9 + 214645003230565/189965778137856*a^7 - 22973355421236025/1282269002430528*a^5 + 2059145797340695/2544184528632*a^3 + 23198483147321/989405094468*a)]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_2(E)

Returns a list of all 2-isogenies with domain E.

INPUT:

  • E – an elliptic curve.

OUTPUT:

(list) 2-isogenies with domain E. In general these are normalised, but over \QQ the codomain is a minimal model.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_2   
sage: E = EllipticCurve('14a1'); E
Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field
sage: [phi.codomain().ainvs() for phi in isogenies_2(E)]
[(1, 0, 1, -36, -70)]

sage: E = EllipticCurve([1,2,3,4,5]); E
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 5 over Rational Field
sage: [phi.codomain().ainvs() for phi in isogenies_2(E)]
[]
sage: E = EllipticCurve(QQbar, [9,8]); E  
Elliptic Curve defined by y^2 = x^3 + 9*x + 8 over Algebraic Field
sage: isogenies_2(E) # not implemented
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_3(E)

Returns a list of all 3-isogenies with domain E.

INPUT:

  • E – an elliptic curve.

OUTPUT:

(list) 3-isogenies with domain E. In general these are normalised, but over \QQ the codomain is a minimal model.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_3
sage: E = EllipticCurve(GF(17), [1,1])
sage: [phi.codomain().ainvs() for phi in isogenies_3(E)]
[(0, 0, 0, 9, 7), (0, 0, 0, 0, 1)]

sage: E = EllipticCurve(GF(17^2,'a'), [1,1])
sage: [phi.codomain().ainvs() for phi in isogenies_3(E)]
[(0, 0, 0, 9, 7), (0, 0, 0, 0, 1), (0, 0, 0, 5*a + 1, a + 13), (0, 0, 0, 12*a + 6, 16*a + 14)]

sage: E = EllipticCurve('19a1')   
sage: [phi.codomain().ainvs() for phi in isogenies_3(E)]
[(0, 1, 1, 1, 0), (0, 1, 1, -769, -8470)]

sage: E = EllipticCurve([1,1]) 
sage: [phi.codomain().ainvs() for phi in isogenies_3(E)]
[]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_5_0(E)

Returns a list of all the 5-isogenies with domain E when the j-invariant is 0.

OUTPUT:

(list) 5-isogenies with codomain E. In general these are normalised, but over \QQ the codomain is a minimal model.

Note

This implementation requires that the characteristic is not 2, 3 or 5.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(5).

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_5_0
sage: E = EllipticCurve([0,12])
sage: isogenies_5_0(E)                              
[]

sage: E = EllipticCurve(GF(13^2,'a'),[0,-3])
sage: isogenies_5_0(E)
[Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + (4*a+6)*x + (2*a+10) over Finite Field in a of size 13^2, Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + (12*a+5)*x + (2*a+10) over Finite Field in a of size 13^2, Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + (10*a+2)*x + (2*a+10) over Finite Field in a of size 13^2, Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + (3*a+12)*x + (11*a+12) over Finite Field in a of size 13^2, Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + (a+4)*x + (11*a+12) over Finite Field in a of size 13^2, Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + (9*a+10)*x + (11*a+12) over Finite Field in a of size 13^2]

sage: K.<a> = NumberField(x**6-320*x**3-320)
sage: E = EllipticCurve(K,[0,0,1,0,0])
sage: isogenies_5_0(E)                      
[Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^6 - 320*x^3 - 320 to Elliptic Curve defined by y^2 = x^3 + (a^5-400*a^2)*x + (280*a^3-3120) over Number Field in a with defining polynomial x^6 - 320*x^3 - 320,
Isogeny of degree 5 from Elliptic Curve defined by y^2 + y = x^3 over Number Field in a with defining polynomial x^6 - 320*x^3 - 320 to Elliptic Curve defined by y^2 = x^3 + (23/2*a^5-3700*a^2)*x + (-280*a^3+86480) over Number Field in a with defining polynomial x^6 - 320*x^3 - 320]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_5_1728(E)

Returns a list of 5-isogenies with domain E when the j-invariant is 1728.

OUTPUT:

(list) 5-isogenies with codomain E. In general these are normalised; but if -1 is a square then there are two endomorphisms of degree 5, for which the codomain is the same as the domain curve; and over \QQ, the codomain is a minimal model.

Note

This implementation requires that the characteristic is not 2, 3 or 5.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(5).

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_5_1728 
sage: E = EllipticCurve([7,0])    
sage: isogenies_5_1728(E)
[]

sage: E = EllipticCurve(GF(13),[11,0])
sage: isogenies_5_1728(E)        
[Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 11*x over Finite Field of size 13 to Elliptic Curve defined by y^2 = x^3 + 11*x over Finite Field of size 13,
Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + 11*x over Finite Field of size 13 to Elliptic Curve defined by y^2 = x^3 + 11*x over Finite Field of size 13]

An example of endomorphisms of degree 5:

sage: K.<i> = QuadraticField(-1)                    
sage: E = EllipticCurve(K,[0,0,0,1,0])
sage: isogenies_5_1728(E)             
[Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1 to Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1,
Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1 to Elliptic Curve defined by y^2 = x^3 + x over Number Field in i with defining polynomial x^2 + 1]
sage: _[0].rational_maps()
(((-4/25*i - 3/25)*x^5 + (-4/5*i + 2/5)*x^3 + x)/(x^4 + (-4/5*i + 2/5)*x^2 + (-4/25*i - 3/25)),
((2/125*i - 11/125)*x^6*y + (64/125*i + 23/125)*x^4*y + (162/125*i - 141/125)*x^2*y + (-4/25*i - 3/25)*y)/(x^6 + (-6/5*i + 3/5)*x^4 + (-12/25*i - 9/25)*x^2 + (2/125*i - 11/125)))

An example of 5-isogenies over a number field:

sage: K.<a> = NumberField(x**4+20*x**2-80)
sage: K(5).is_square() #necessary but not sufficient!                   
True
sage: E = EllipticCurve(K,[0,0,0,1,0])    
sage: isogenies_5_1728(E)                 
[Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + x over Number Field in a with defining polynomial x^4 + 20*x^2 - 80 to Elliptic Curve defined by y^2 = x^3 + (-20*a^2-39)*x + (35*a^3+112*a) over Number Field in a with defining polynomial x^4 + 20*x^2 - 80,
Isogeny of degree 5 from Elliptic Curve defined by y^2 = x^3 + x over Number Field in a with defining polynomial x^4 + 20*x^2 - 80 to Elliptic Curve defined by y^2 = x^3 + (-20*a^2-39)*x + (-35*a^3-112*a) over Number Field in a with defining polynomial x^4 + 20*x^2 - 80]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_7_0(E)

Returns list of all 7-isogenies from E when the j-invariant is 0.

OUTPUT:

(list) 7-isogenies with codomain E. In general these are normalised; but if -3 is a square then there are two endomorphisms of degree 7, for which the codomain is the same as the domain; and over \QQ, the codomain is a minimal model.

Note

This implementation requires that the characteristic is not 2, 3 or 7.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(7).

EXAMPLES:

First some examples of endomorphisms:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_7_0   
sage: K.<r> = QuadraticField(-3)
sage: E = EllipticCurve(K, [0,1])  
sage: isogenies_7_0(E)
[Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 1 over Number Field in r with defining polynomial x^2 + 3 to Elliptic Curve defined by y^2 = x^3 + 1 over Number Field in r with defining polynomial x^2 + 3,
Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 1 over Number Field in r with defining polynomial x^2 + 3 to Elliptic Curve defined by y^2 = x^3 + 1 over Number Field in r with defining polynomial x^2 + 3]

sage: E = EllipticCurve(GF(13^2,'a'),[0,-3])
sage: isogenies_7_0(E)        
[Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2 to Elliptic Curve defined by y^2 = x^3 + 10 over Finite Field in a of size 13^2]

Now some examples of 7-isogenies which are not endomorphisms:

sage: K = GF(101)                
sage: E = EllipticCurve(K, [0,1])
sage: isogenies_7_0(E)           
[Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 55*x + 100 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 83*x + 26 over Finite Field of size 101]

Examples over a number field:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_7_0
sage: E = EllipticCurve('27a1').change_ring(QuadraticField(-3,'r'))
sage: isogenies_7_0(E)
[Isogeny of degree 7 from Elliptic Curve defined by y^2 + y = x^3 + (-7) over Number Field in r with defining polynomial x^2 + 3 to Elliptic Curve defined by y^2 + y = x^3 + (-7) over Number Field in r with defining polynomial x^2 + 3,
Isogeny of degree 7 from Elliptic Curve defined by y^2 + y = x^3 + (-7) over Number Field in r with defining polynomial x^2 + 3 to Elliptic Curve defined by y^2 + y = x^3 + (-7) over Number Field in r with defining polynomial x^2 + 3]

sage: K.<a> = NumberField(x^6 + 1512*x^3 - 21168)
sage: E = EllipticCurve(K, [0,1])
sage: isogs = isogenies_7_0(E)
sage: [phi.codomain().a_invariants() for phi in isogs]
[(0, 0, 0, -5/294*a^5 - 300/7*a^2, -55/2*a^3 - 1133),
(0, 0, 0, -295/1176*a^5 - 5385/14*a^2, 55/2*a^3 + 40447)]
sage: [phi.codomain().j_invariant() for phi in isogs] 
[158428486656000/7*a^3 - 313976217600000,
-158428486656000/7*a^3 - 34534529335296000]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_7_1728(E)

Returns list of all 7-isogenies from E when the j-invariant is 1728.

OUTPUT:

(list) 7-isogenies with codomain E. In general these are normalised; but over \QQ the codomain is a minimal model.

Note

This implementation requires that the characteristic is not 2, 3, or 7.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(7).

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_7_1728                                                                           
sage: E = EllipticCurve(GF(47), [1, 0])
sage: isogenies_7_1728(E)              
[Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 47 to Elliptic Curve defined by y^2 = x^3 + 26 over Finite Field of size 47,
Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 47 to Elliptic Curve defined by y^2 = x^3 + 21 over Finite Field of size 47]

An example in characteristic 53 (for which an earlier implementation did not work):

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_7_1728
sage: E = EllipticCurve(GF(53), [1, 0])
sage: isogenies_7_1728(E)
[]
sage: E = EllipticCurve(GF(53^2,'a'), [1, 0])
sage: [iso.codomain().ainvs() for iso in isogenies_7_1728(E)]
[(0, 0, 0, 36, 19*a + 15), (0, 0, 0, 36, 34*a + 38), (0, 0, 0, 33, 39*a + 28), (0, 0, 0, 33, 14*a + 25), (0, 0, 0, 19, 45*a + 16), (0, 0, 0, 19, 8*a + 37), (0, 0, 0, 3, 45*a + 16), (0, 0, 0, 3, 8*a + 37)]
sage: K.<a> = NumberField(x^8 + 84*x^6 - 1890*x^4 + 644*x^2 - 567)
sage: E = EllipticCurve(K, [1, 0])                                
sage: isogs = isogenies_7_1728(E)
sage: [phi.codomain().a_invariants() for phi in isogs]
[(0,
0,
0,
35/636*a^6 + 55/12*a^4 - 79135/636*a^2 + 1127/212,
155/636*a^7 + 245/12*a^5 - 313355/636*a^3 - 3577/636*a),
(0,
0,
0,
35/636*a^6 + 55/12*a^4 - 79135/636*a^2 + 1127/212,
-155/636*a^7 - 245/12*a^5 + 313355/636*a^3 + 3577/636*a)]
sage: [phi.codomain().j_invariant() for phi in isogs] 
[-526110256146528/53*a^6 + 183649373229024*a^4 - 3333881559996576/53*a^2 + 2910267397643616/53,
-526110256146528/53*a^6 + 183649373229024*a^4 - 3333881559996576/53*a^2 + 2910267397643616/53]
sage: E1 = isogs[0].codomain()
sage: E2 = isogs[1].codomain()
sage: E1.is_isomorphic(E2)
False
sage: E1.is_quadratic_twist(E2)
-1
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_prime_degree_genus_0(E, l=None)

Returns list of l -isogenies with domain E.

INPUT:

  • E – an elliptic curve.
  • l – either None or 2, 3, 5, 7, or 13.

OUTPUT:

(list) When l is None a list of all isogenies of degree 2, 3, 5, 7 and 13, otherwise a list of isogenies of the given degree.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(l), which automatically calls the appropriate function.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_prime_degree_genus_0
sage: E = EllipticCurve([0,12])
sage: isogenies_prime_degree_genus_0(E, 5)
[]

sage: E = EllipticCurve('1450c1')   
sage: isogenies_prime_degree_genus_0(E)   
[Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 300*x - 1000 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 5950*x - 182250 over Rational Field]

sage: E = EllipticCurve('50a1')   
sage: isogenies_prime_degree_genus_0(E)  
[Isogeny of degree 3 from Elliptic Curve defined by y^2 + x*y + y = x^3 - x - 2 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 - 126*x - 552 over Rational Field,
Isogeny of degree 5 from Elliptic Curve defined by y^2 + x*y + y = x^3 - x - 2 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 - 76*x + 298 over Rational Field]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogenies_sporadic_Q(E, l=None)

Returns list of l -isogenies with domain E (defined over \QQ).

Returns a list of sporadic l-isogenies from E (l = 11, 17, 19, 37, 43, 67 or 163). Only for elliptic curves over \QQ.

INPUT:

  • E – an elliptic curve defined over \QQ.
  • l – either None or a prime number.

OUTPUT:

(list) If l is None, a list of all isogenies with domain E and of degree 11, 17, 19, 37, 43, 67 or 163; otherwise a list of isogenies of the given degree.

Note

This function would normally be invoked indirectly via E.isogenies_prime_degree(l), which automatically calls the appropriate function.

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogenies_sporadic_Q                                                                       
sage: E = EllipticCurve('121a1')   
sage: isogenies_sporadic_Q(E, 11)
[Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 30*x - 76 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 305*x + 7888 over Rational Field]
sage: isogenies_sporadic_Q(E, 13)
[]
sage: isogenies_sporadic_Q(E, 17)
[]
sage: isogenies_sporadic_Q(E)    
[Isogeny of degree 11 from Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 30*x - 76 over Rational Field to Elliptic Curve defined by y^2 + x*y + y = x^3 + x^2 - 305*x + 7888 over Rational Field]
 
sage: E = EllipticCurve([1, 1, 0, -660, -7600])    
sage: isogenies_sporadic_Q(E, 17)
[Isogeny of degree 17 from Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 660*x - 7600 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 878710*x + 316677750 over Rational Field]
sage: isogenies_sporadic_Q(E)    
[Isogeny of degree 17 from Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 660*x - 7600 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 878710*x + 316677750 over Rational Field]
sage: isogenies_sporadic_Q(E, 11)
[]

sage: E = EllipticCurve([0, 0, 1, -1862, -30956])   
sage: isogenies_sporadic_Q(E, 11)
[]
sage: isogenies_sporadic_Q(E, 19)
[Isogeny of degree 19 from Elliptic Curve defined by y^2 + y = x^3 - 1862*x - 30956 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - 672182*x + 212325489 over Rational Field]
sage: isogenies_sporadic_Q(E)    
[Isogeny of degree 19 from Elliptic Curve defined by y^2 + y = x^3 - 1862*x - 30956 over Rational Field to Elliptic Curve defined by y^2 + y = x^3 - 672182*x + 212325489 over Rational Field]

sage: E = EllipticCurve([0, -1, 0, -6288, 211072])
sage: E.conductor()
19600
sage: isogenies_sporadic_Q(E,37)
[Isogeny of degree 37 from Elliptic Curve defined by y^2 = x^3 - x^2 - 6288*x + 211072 over Rational Field to Elliptic Curve defined by y^2 = x^3 - x^2 - 163137088*x - 801950801728 over Rational Field]

sage: E = EllipticCurve([1, 1, 0, -25178045, 48616918750])
sage: E.conductor()                                       
148225
sage: isogenies_sporadic_Q(E,37)
[Isogeny of degree 37 from Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 25178045*x + 48616918750 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 970*x - 13075 over Rational Field]

sage: E = EllipticCurve([-3440, 77658])         
sage: E.conductor()                    
118336
sage: isogenies_sporadic_Q(E,43)       
[Isogeny of degree 43 from Elliptic Curve defined by y^2 = x^3 - 3440*x + 77658 over Rational Field to Elliptic Curve defined by y^2 = x^3 - 6360560*x - 6174354606 over Rational Field]

sage: E = EllipticCurve([-29480, -1948226])     
sage: E.conductor()
287296
sage: isogenies_sporadic_Q(E,67)
[Isogeny of degree 67 from Elliptic Curve defined by y^2 = x^3 - 29480*x - 1948226 over Rational Field to Elliptic Curve defined by y^2 = x^3 - 132335720*x + 585954296438 over Rational Field]

sage: E = EllipticCurve([-34790720, -78984748304])
sage: E.conductor()
425104
sage: isogenies_sporadic_Q(E,163)
[Isogeny of degree 163 from Elliptic Curve defined by y^2 = x^3 - 34790720*x - 78984748304 over Rational Field to Elliptic Curve defined by y^2 = x^3 - 924354639680*x + 342062961763303088 over Rational Field]
sage.schemes.elliptic_curves.ell_curve_isogeny.isogeny_codomain_from_kernel(E, kernel, degree=None)

This function computes the isogeny codomain given a kernel.

INPUT:

  • E - The domain elliptic curve.

  • kernel - Either a list of points in the kernel of the isogeny, or a

    kernel polynomial (specified as a either a univariate polynomial or a coefficient list.)

  • degree - an integer, (default:None) optionally specified degree

    of the kernel.

OUTPUT:

(elliptic curve) the codomain of the separable normalized isogeny from this kernel

EXAMPLES:

sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogeny_codomain_from_kernel
sage: E = EllipticCurve(GF(7), [1,0,1,0,1])
sage: R.<x> = GF(7)[]
sage: isogeny_codomain_from_kernel(E, [4,1], degree=3)
Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + 6 over Finite Field of size 7
sage: EllipticCurveIsogeny(E, [4,1]).codomain() == isogeny_codomain_from_kernel(E, [4,1], degree=3)
True
sage: isogeny_codomain_from_kernel(E, x^3 + x^2 + 4*x + 3)
Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + 6 over Finite Field of size 7
sage: isogeny_codomain_from_kernel(E, x^3 + 2*x^2 + 4*x + 3)
Elliptic Curve defined by y^2 + x*y + y = x^3 + 5*x + 2 over Finite Field of size 7

sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: kernel_list = [E((15,10)), E((10,3)),E((6,5))] 
sage: isogeny_codomain_from_kernel(E, kernel_list)
Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 3*x + 15 over Finite Field of size 19
sage.schemes.elliptic_curves.ell_curve_isogeny.isogeny_determine_algorithm(E, kernel, codomain, degree, model)

Helper function that allows the various isogeny functions to infer the algorithm type from the parameters passed in.

If kernel is a list of points on the EllipticCurve E, then we assume the algorithm to use is Velu.

If kernel is a list of coefficients or a univariate polynomial we try to use the Kohel’s algorithms.

EXAMPLES:

This helper function will be implicitly called by the following examples:

sage: R.<x> = GF(5)[]
sage: E = EllipticCurve(GF(5), [0,0,0,1,0])
sage: phi = EllipticCurveIsogeny(E, x+3)
sage: phi2 = EllipticCurveIsogeny(E, [GF(5)(3),GF(5)(1)])
sage: phi == phi2
True
sage: phi3 = EllipticCurveIsogeny(E,  E((2,0)) )
sage: phi3 == phi2
True
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import isogeny_determine_algorithm
sage: isogeny_determine_algorithm(E, x+3, None, None, None)
'kohel'
sage: isogeny_determine_algorithm(E, [3, 1], None, None, None)
'kohel'
sage: isogeny_determine_algorithm(E, E((2,0)), None, None, None)
'velu'
sage.schemes.elliptic_curves.ell_curve_isogeny.split_kernel_polynomial(E1, ker_poly, ell)

Internal helper function for compute_isogeny_kernel_polynomial.

Given a full kernel polynomial (where two torsion x-coordinates are roots of multiplicity 1, and all other roots have multiplicity 2.) of degree \ell-1, returns the maximum separable divisor. (i.e. the kernel polynomial with roots of multiplicity at most 1).

EXAMPLES:

The following example implicitly exercises this function:

sage: E = EllipticCurve(GF(37), [0,0,0,1,8])
sage: R.<x> = GF(37)[]
sage: f = (x + 10) * (x + 12) * (x + 16)
sage: phi = EllipticCurveIsogeny(E, f)
sage: E2 = phi.codomain()
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_starks
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import split_kernel_polynomial
sage: ker_poly = compute_isogeny_starks(E, E2, 7); ker_poly
x^6 + 2*x^5 + 20*x^4 + 11*x^3 + 36*x^2 + 35*x + 16
sage: split_kernel_polynomial(E, ker_poly, 7)
x^3 + x^2 + 28*x + 33
sage.schemes.elliptic_curves.ell_curve_isogeny.two_torsion_part(E, poly_ring, psi, degree)

Returns the greatest common divisor of psi and the 2 torsion polynomial of E.

EXAMPLES:

Every function that computes the kernel polynomial via Kohel’s formulas will call this function:

sage: E = EllipticCurve(GF(19), [1,2,3,4,5])
sage: R.<x> = GF(19)[]
sage: phi = EllipticCurveIsogeny(E, x + 13)
sage: isogeny_codomain_from_kernel(E, x + 13) == phi.codomain()
True
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import two_torsion_part
sage: two_torsion_part(E, R, x+13, 2)
x + 13
sage.schemes.elliptic_curves.ell_curve_isogeny.unfill_isogeny_matrix(M)

Reverses the action of fill_isogeny_matrix.

INPUT:

  • M – a square symmetric matrix of integers.

OUTPUT:

(matrix) a square symmetric matrix obtained from M by replacing non-prime entries with 0.

EXAMPLES:

sage: M = Matrix([[0, 2, 3, 3, 0, 0], [2, 0, 0, 0, 3, 3], [3, 0, 0, 0, 2, 0], [3, 0, 0, 0, 0, 2], [0, 3, 2, 0, 0, 0], [0, 3, 0, 2, 0, 0]]); M
[0 2 3 3 0 0]
[2 0 0 0 3 3]
[3 0 0 0 2 0]
[3 0 0 0 0 2]
[0 3 2 0 0 0]
[0 3 0 2 0 0]
sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix, unfill_isogeny_matrix
sage: M1 = fill_isogeny_matrix(M); M1
[ 1  2  3  3  6  6]
[ 2  1  6  6  3  3]
[ 3  6  1  9  2 18]
[ 3  6  9  1 18  2]
[ 6  3  2 18  1  9]
[ 6  3 18  2  9  1]
sage: unfill_isogeny_matrix(M1)
[0 2 3 3 0 0]
[2 0 0 0 3 3]
[3 0 0 0 2 0]
[3 0 0 0 0 2]
[0 3 2 0 0 0]
[0 3 0 2 0 0]
sage: unfill_isogeny_matrix(M1) == M
True

Previous topic

Isomorphisms between Weierstrass models of elliptic curves

Next topic

Weierstrass \wp function for elliptic curves.

This Page