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))
>>> from sage.all import *
>>> k = GF(Integer(11))
>>> E = EllipticCurve(k, [Integer(1),Integer(1)])
>>> Q = E(Integer(6),Integer(5))
>>> phi = E.isogeny(Q)
>>> 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
>>> P = E(Integer(4),Integer(5))
>>> phi(P)
(10 : 0 : 1)
>>> phi.codomain()
Elliptic Curve defined by y^2 = x^3 + 7*x + 8 over Finite Field of size 11
>>> 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 methods directly accessible from an elliptic curve E over a
field are
isogeny()
and
isogeny_codomain().
The most useful methods that apply to isogenies are:
- .domain()
- .codomain()
Warning
This class only implements separable isogenies. When using Kohel’s algorithm, only cyclic isogenies can be computed (except for \([2]\)).
Working with other kinds of isogenies may be possible using other
child classes of EllipticCurveHom.
Some algorithms may need the isogeny to be normalized.
AUTHORS:
- Daniel Shumow <shumow@gmail.com>: 2009-04-19: initial version 
- Chris Wuthrich: 7/09: add check of input, not the full list is needed. 10/09: eliminating some bugs. 
- John Cremona 2014-08-08: tidying of code and docstrings, systematic use of univariate vs. bivariate polynomials and rational functions. 
- Lorenz Panny (2022-04): major cleanup of code and documentation 
- Lorenz Panny (2022): inseparable duals 
- Rémy Oudompheng (2023): implementation of the BMSS algorithm 
- class sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny(E, kernel, codomain=None, degree=None, model=None, check=True)[source]¶
- Bases: - EllipticCurveHom- This class implements separable isogenies of elliptic curves. - Several different algorithms for computing isogenies are available. These include: - Vélu’s Formulas: Vélu’s original formulas for computing isogenies. This algorithm is selected by giving as the - kernelparameter 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 - kernelparameter a monic polynomial (or a coefficient list) which will define the kernel of the isogeny. Kohel’s algorithm is currently only implemented for cyclic isogenies, with the exception of \([2]\).
 - INPUT: - E– an elliptic curve; the domain of the isogeny to initialize
- kernel– a kernel; either a point on- E, a list of points on- E, a monic kernel polynomial, or- None. If initializing from a domain/codomain, this must be- None.
- codomain– an elliptic curve (default:- None)- If - kernelis- None, then- degreemust be given as well and the given- codomainmust be the codomain of a cyclic, separable, normalized isogeny of the given degree.
- If - kernelis 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– integer (default:- None)- If - kernelis- None, then this is the degree of the isogeny from- Eto- codomain.
- If - kernelis 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- E.
 
- model– string (default:- None); supported values (cf.- compute_model()):- 'minimal'– if- Eis 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– boolean (default:- True); check whether the input is valid. Setting this to- Falsecan lead to significant speedups.
 - 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)) # known bug True - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(7)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)]) >>> phi = EllipticCurveIsogeny(E, E((Integer(0),Integer(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 >>> phi.degree() == Integer(2) True >>> phi.kernel_polynomial() x >>> phi.rational_maps() ((x^2 + 1)/x, (x^2*y - y)/x^2) >>> phi == loads(dumps(phi)) # known bug True - A more complicated example of a characteristic-2 field: - sage: # needs sage.rings.finite_rings 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: phi_k = EllipticCurveIsogeny(E, phi_ker_poly) 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() == 3 True 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 - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> E = EllipticCurve(GF(Integer(2)**Integer(4),'alpha'), [Integer(0),Integer(0),Integer(1),Integer(0),Integer(1)]) >>> P = E((Integer(1),Integer(1))) >>> 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 >>> phi_ker_poly = phi_v.kernel_polynomial() >>> phi_ker_poly x + 1 >>> phi_k = EllipticCurveIsogeny(E, phi_ker_poly) >>> phi_k == phi_v True >>> 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)) >>> 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)) >>> phi_k.degree() == phi_v.degree() == Integer(3) True >>> phi_k.is_separable() True >>> phi_v(E(Integer(0))) (0 : 1 : 0) >>> alpha = E.base_field().gen() >>> Q = E((Integer(0), alpha*(alpha + Integer(1)))) >>> phi_v(Q) (1 : alpha^2 + alpha : 1) >>> phi_v(P) == phi_k(P) True >>> phi_k(P) == phi_v.codomain()(Integer(0)) True - We can create an isogeny whose kernel equals the full 2-torsion: - sage: # needs sage.rings.finite_rings sage: E = EllipticCurve(GF((3,2)), [0,0,0,1,1]) sage: ker_poly = E.division_polynomial(2) sage: phi = EllipticCurveIsogeny(E, ker_poly); phi Isogeny of degree 4 from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in z2 of size 3^2 to Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in z2 of size 3^2 sage: P1,P2,P3 = filter(bool, E(0).division_points(2)) sage: phi(P1) (0 : 1 : 0) sage: phi(P2) (0 : 1 : 0) sage: phi(P3) (0 : 1 : 0) sage: phi.degree() 4 - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> E = EllipticCurve(GF((Integer(3),Integer(2))), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(1)]) >>> ker_poly = E.division_polynomial(Integer(2)) >>> phi = EllipticCurveIsogeny(E, ker_poly); phi Isogeny of degree 4 from Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in z2 of size 3^2 to Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field in z2 of size 3^2 >>> P1,P2,P3 = filter(bool, E(Integer(0)).division_points(Integer(2))) >>> phi(P1) (0 : 1 : 0) >>> phi(P2) (0 : 1 : 0) >>> phi(P3) (0 : 1 : 0) >>> 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]); 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 - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(17)), [Integer(11), Integer(11), Integer(4), Integer(12), Integer(10)]) >>> phi_v = EllipticCurveIsogeny(E, E(Integer(0))) >>> phi_v.degree() 1 >>> phi_v.rational_maps() (x, y) >>> E == phi_v.codomain() True >>> P = E.random_point() >>> phi_v(P) == P True >>> E = EllipticCurve(GF(Integer(31)), [Integer(23), Integer(1), Integer(22), Integer(7), Integer(18)]) >>> phi_k = EllipticCurveIsogeny(E, [Integer(1)]); 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 >>> phi_k.degree() 1 >>> phi_k.rational_maps() (x, y) >>> phi_k.codomain() == E True >>> phi_k.kernel_polynomial() 1 >>> P = E.random_point(); P == phi_k(P) True - Vélu 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); 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: phi_k = EllipticCurveIsogeny(E, phi_ker_poly); 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 - >>> from sage.all import * >>> E = EllipticCurve(QQ, [Integer(0),Integer(0),Integer(0),Integer(3),Integer(4)]) >>> P_list = E.torsion_points() >>> phi = EllipticCurveIsogeny(E, P_list); 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 >>> P = E((Integer(0),Integer(2))) >>> phi(P) (6 : -10 : 1) >>> phi_ker_poly = phi.kernel_polynomial() >>> phi_ker_poly x + 1 >>> phi_k = EllipticCurveIsogeny(E, phi_ker_poly); 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 >>> phi_k(P) == phi(P) True >>> phi_k == phi True >>> phi_k.degree() 2 >>> 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: phi_k = EllipticCurveIsogeny(E, ker_poly); 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 - >>> from sage.all import * >>> E = EllipticCurve('11a1') >>> P_list = E.torsion_points() >>> 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 >>> P = E((Integer(16),-Integer(61))) >>> phi_v(P) (0 : 1 : 0) >>> ker_poly = phi_v.kernel_polynomial(); ker_poly x^2 - 21*x + 80 >>> phi_k = EllipticCurveIsogeny(E, ker_poly); 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 >>> phi_k == phi_v True >>> phi_v(P) == phi_k(P) True >>> 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: # needs sage.rings.number_field sage: E = EllipticCurve('11a1') sage: P_list = E.torsion_points() sage: x = polygen(ZZ, 'x') 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: phi_k = EllipticCurveIsogeny(EK, ker_poly); 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 - >>> from sage.all import * >>> # needs sage.rings.number_field >>> E = EllipticCurve('11a1') >>> P_list = E.torsion_points() >>> x = polygen(ZZ, 'x') >>> K = NumberField(x**Integer(3) - Integer(2)* x**Integer(2) - Integer(40)*x - Integer(158), names=('alpha',)); (alpha,) = K._first_ngens(1) >>> EK = E.change_ring(K) >>> P_list = [EK(P) for P in P_list] >>> 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 >>> P = EK((alpha/Integer(2),-Integer(1)/Integer(2))) >>> phi_v(P) (122/121*alpha^2 + 1633/242*alpha - 3920/121 : -1/2 : 1) >>> ker_poly = phi_v.kernel_polynomial() >>> ker_poly x^2 - 21*x + 80 >>> phi_k = EllipticCurveIsogeny(EK, ker_poly); 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 >>> phi_v == phi_k True >>> phi_k(P) == phi_v(P) True >>> phi_k == phi_v True >>> phi_k.degree() 5 >>> 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); 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 - >>> from sage.all import * >>> E = EllipticCurve('11a1') >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) - Integer(21)*x + Integer(80) >>> phi = E.isogeny(f) >>> E2 = phi.codomain() >>> phi_s = EllipticCurveIsogeny(E, None, E2, Integer(5)); 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 >>> phi_s == phi True >>> phi_s.rational_maps() == phi.rational_maps() True - However, only cyclic normalized isogenies can be constructed this way. The non-cyclic multiplication-by-\(3\) isogeny won’t be found: - sage: E.isogeny(None, codomain=E, degree=9) Traceback (most recent call last): ... ValueError: the two curves are not linked by a cyclic normalized isogeny of degree 9 - >>> from sage.all import * >>> E.isogeny(None, codomain=E, degree=Integer(9)) Traceback (most recent call last): ... ValueError: the two curves are not linked by a cyclic normalized isogeny of degree 9 - Non-normalized isogeny also won’t be found: - sage: E2.isogeny(None, codomain=E, degree=5) Traceback (most recent call last): ... ValueError: the two curves are not linked by a cyclic normalized isogeny of degree 5 sage: phihat = phi.dual(); phihat 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: phihat.is_normalized() False - >>> from sage.all import * >>> E2.isogeny(None, codomain=E, degree=Integer(5)) Traceback (most recent call last): ... ValueError: the two curves are not linked by a cyclic normalized isogeny of degree 5 >>> phihat = phi.dual(); phihat 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 >>> phihat.is_normalized() False - Here an example of a construction of a endomorphisms with cyclic kernel on a CM-curve: - sage: # needs sage.rings.number_field 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 = isom * phi 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)), ((11/125*i + 2/125)*x^6*y + (-23/125*i + 64/125)*x^4*y + (141/125*i + 162/125)*x^2*y + (3/25*i - 4/25)*y)/(x^6 + (-6/5*i + 3/5)*x^4 + (-12/25*i - 9/25)*x^2 + (2/125*i - 11/125))) - >>> from sage.all import * >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> E = EllipticCurve(K, [Integer(1),Integer(0)]) >>> RK = K['X']; (X,) = RK._first_ngens(1) >>> f = X**Integer(2) - Integer(2)/Integer(5)*i + Integer(1)/Integer(5) >>> phi= E.isogeny(f) >>> isom = phi.codomain().isomorphism_to(E) >>> phi = isom * phi >>> phi.codomain() == phi.domain() True >>> 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)), ((11/125*i + 2/125)*x^6*y + (-23/125*i + 64/125)*x^4*y + (141/125*i + 162/125)*x^2*y + (3/25*i - 4/25)*y)/(x^6 + (-6/5*i + 3/5)*x^4 + (-12/25*i - 9/25)*x^2 + (2/125*i - 11/125))) - dual()[source]¶
- Return the isogeny dual to this isogeny. - Note - If \(\varphi\colon E \to E'\) is the given isogeny and \(n\) is its degree, then the dual is by definition the unique isogeny \(\hat\varphi\colon E'\to E\) such that the compositions \(\hat\varphi\circ\varphi\) and \(\varphi\circ\hat\varphi\) are the multiplication-by-\(n\) maps on \(E\) and \(E'\), 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 - >>> from sage.all import * >>> E = EllipticCurve('11a1') >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) - Integer(21)*x + Integer(80) >>> phi = EllipticCurveIsogeny(E, f) >>> phi_hat = phi.dual() >>> phi_hat.domain() == phi.codomain() True >>> phi_hat.codomain() == phi.domain() True >>> (X, Y) = phi.rational_maps() >>> (Xhat, Yhat) = phi_hat.rational_maps() >>> Xm = Xhat.subs(x=X, y=Y) >>> Ym = Yhat.subs(x=X, y=Y) >>> (Xm, Ym) == E.multiplication_by_m(Integer(5)) True >>> E = EllipticCurve(GF(Integer(37)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(8)]) >>> R = GF(Integer(37))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(3) + x**Integer(2) + Integer(28)*x + Integer(33) >>> phi = EllipticCurveIsogeny(E, f) >>> phi_hat = phi.dual() >>> phi_hat.codomain() == phi.domain() True >>> phi_hat.domain() == phi.codomain() True >>> (X, Y) = phi.rational_maps() >>> (Xhat, Yhat) = phi_hat.rational_maps() >>> Xm = Xhat.subs(x=X, y=Y) >>> Ym = Yhat.subs(x=X, y=Y) >>> (Xm, Ym) == E.multiplication_by_m(Integer(7)) True >>> E = EllipticCurve(GF(Integer(31)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(8)]) >>> R = GF(Integer(31))['x']; (x,) = R._first_ngens(1) >>> f = x**Integer(2) + Integer(17)*x + Integer(29) >>> phi = EllipticCurveIsogeny(E, f) >>> phi_hat = phi.dual() >>> phi_hat.codomain() == phi.domain() True >>> phi_hat.domain() == phi.codomain() True >>> (X, Y) = phi.rational_maps() >>> (Xhat, Yhat) = phi_hat.rational_maps() >>> Xm = Xhat.subs(x=X, y=Y) >>> Ym = Yhat.subs(x=X, y=Y) >>> (Xm, Ym) == E.multiplication_by_m(Integer(5)) True - Inseparable duals should be computed correctly: - sage: # needs sage.rings.finite_rings sage: z2 = GF(71^2).gen() sage: E = EllipticCurve(j=57*z2+51) sage: E.isogeny(3*E.lift_x(0)).dual() Composite morphism of degree 71 = 71*1^2: From: Elliptic Curve defined by y^2 = x^3 + (32*z2+67)*x + (24*z2+37) over Finite Field in z2 of size 71^2 To: Elliptic Curve defined by y^2 = x^3 + (41*z2+56)*x + (18*z2+42) over Finite Field in z2 of size 71^2 sage: E.isogeny(E.lift_x(0)).dual() Composite morphism of degree 213 = 71*3: From: Elliptic Curve defined by y^2 = x^3 + (58*z2+31)*x + (34*z2+58) over Finite Field in z2 of size 71^2 To: Elliptic Curve defined by y^2 = x^3 + (41*z2+56)*x + (18*z2+42) over Finite Field in z2 of size 71^2 - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> z2 = GF(Integer(71)**Integer(2)).gen() >>> E = EllipticCurve(j=Integer(57)*z2+Integer(51)) >>> E.isogeny(Integer(3)*E.lift_x(Integer(0))).dual() Composite morphism of degree 71 = 71*1^2: From: Elliptic Curve defined by y^2 = x^3 + (32*z2+67)*x + (24*z2+37) over Finite Field in z2 of size 71^2 To: Elliptic Curve defined by y^2 = x^3 + (41*z2+56)*x + (18*z2+42) over Finite Field in z2 of size 71^2 >>> E.isogeny(E.lift_x(Integer(0))).dual() Composite morphism of degree 213 = 71*3: From: Elliptic Curve defined by y^2 = x^3 + (58*z2+31)*x + (34*z2+58) over Finite Field in z2 of size 71^2 To: Elliptic Curve defined by y^2 = x^3 + (41*z2+56)*x + (18*z2+42) over Finite Field in z2 of size 71^2 - …even if pre- or post-isomorphisms are present: - sage: # needs sage.rings.finite_rings sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism sage: phi = E.isogeny(E.lift_x(0)) sage: pre = ~WeierstrassIsomorphism(phi.domain(), (z2,2,3,4)) sage: post = WeierstrassIsomorphism(phi.codomain(), (5,6,7,8)) sage: phi = post * phi * pre sage: phi.dual() Composite morphism of degree 213 = 71*3: From: Elliptic Curve defined by y^2 + 17*x*y + 45*y = x^3 + 30*x^2 + (6*z2+64)*x + (48*z2+65) over Finite Field in z2 of size 71^2 To: Elliptic Curve defined by y^2 + (60*z2+22)*x*y + (69*z2+37)*y = x^3 + (32*z2+48)*x^2 + (19*z2+58)*x + (56*z2+22) over Finite Field in z2 of size 71^2 - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism >>> phi = E.isogeny(E.lift_x(Integer(0))) >>> pre = ~WeierstrassIsomorphism(phi.domain(), (z2,Integer(2),Integer(3),Integer(4))) >>> post = WeierstrassIsomorphism(phi.codomain(), (Integer(5),Integer(6),Integer(7),Integer(8))) >>> phi = post * phi * pre >>> phi.dual() Composite morphism of degree 213 = 71*3: From: Elliptic Curve defined by y^2 + 17*x*y + 45*y = x^3 + 30*x^2 + (6*z2+64)*x + (48*z2+65) over Finite Field in z2 of size 71^2 To: Elliptic Curve defined by y^2 + (60*z2+22)*x*y + (69*z2+37)*y = x^3 + (32*z2+48)*x^2 + (19*z2+58)*x + (56*z2+22) over Finite Field in z2 of size 71^2 
 - inseparable_degree()[source]¶
- Return the inseparable degree of this isogeny. - Since this class only implements separable isogenies, this method always returns one. 
 - kernel_polynomial()[source]¶
- Return 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 - >>> from sage.all import * >>> E = EllipticCurve(QQ, [Integer(0),Integer(0),Integer(0),Integer(2),Integer(0)]) >>> phi = EllipticCurveIsogeny(E, E((Integer(0),Integer(0)))) >>> phi.kernel_polynomial() x >>> E = EllipticCurve('11a1') >>> phi = EllipticCurveIsogeny(E, E.torsion_points()) >>> phi.kernel_polynomial() x^2 - 21*x + 80 >>> E = EllipticCurve(GF(Integer(17)), [Integer(1),-Integer(1),Integer(1),-Integer(1),Integer(1)]) >>> phi = EllipticCurveIsogeny(E, [Integer(1)]) >>> phi.kernel_polynomial() 1 >>> E = EllipticCurve(GF(Integer(31)), [Integer(0),Integer(0),Integer(0),Integer(3),Integer(0)]) >>> phi = EllipticCurveIsogeny(E, [Integer(0),Integer(3),Integer(0),Integer(1)]) >>> phi.kernel_polynomial() x^3 + 3*x 
 - rational_maps()[source]¶
- Return the pair of rational maps defining this isogeny. - Note - Both components are returned as elements of the function field \(F(x,y)\) in two variables over the base field \(F\), though the first only involves \(x\). To obtain the \(x\)-coordinate function as a rational function in \(F(x)\), use - x_rational_map().- 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) - >>> from sage.all import * >>> E = EllipticCurve(QQ, [Integer(0),Integer(2),Integer(0),Integer(1),-Integer(1)]) >>> phi = EllipticCurveIsogeny(E, [Integer(1)]) >>> phi.rational_maps() (x, y) >>> E = EllipticCurve(GF(Integer(17)), [Integer(0),Integer(0),Integer(0),Integer(3),Integer(0)]) >>> phi = EllipticCurveIsogeny(E, E((Integer(0),Integer(0)))) >>> phi.rational_maps() ((x^2 + 3)/x, (x^2*y - 3*y)/x^2) 
 - scaling_factor()[source]¶
- Return the Weierstrass scaling factor associated to this elliptic-curve isogeny. - The scaling factor is the constant \(u\) (in the base field) such that \(\varphi^* \omega_2 = u \omega_1\), where \(\varphi: E_1\to E_2\) is this isogeny and \(\omega_i\) are the standard Weierstrass differentials on \(E_i\) defined by \(\mathrm dx/(2y+a_1x+a_3)\). - EXAMPLES: - sage: # needs sage.rings.finite_rings sage: E = EllipticCurve(GF(257^2), [0,1]) sage: phi = E.isogeny(E.lift_x(240)) sage: phi.degree() 43 sage: phi.scaling_factor() 1 sage: phi.dual().scaling_factor() 43 - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> E = EllipticCurve(GF(Integer(257)**Integer(2)), [Integer(0),Integer(1)]) >>> phi = E.isogeny(E.lift_x(Integer(240))) >>> phi.degree() 43 >>> phi.scaling_factor() 1 >>> phi.dual().scaling_factor() 43 - ALGORITHM: The “inner” isogeny is normalized by construction, so we only need to account for the scaling factors of a pre- and post-isomorphism. 
 - x_rational_map()[source]¶
- Return the rational map giving the \(x\)-coordinate of this isogeny. - Note - This function returns the \(x\)-coordinate component of the isogeny as a rational function in \(F(x)\), where \(F\) is the base field. To obtain both coordinate functions as elements of the function field \(F(x,y)\) in two variables, use - rational_maps().- EXAMPLES: - sage: E = EllipticCurve(QQ, [0,2,0,1,-1]) sage: phi = EllipticCurveIsogeny(E, [1]) sage: phi.x_rational_map() x sage: E = EllipticCurve(GF(17), [0,0,0,3,0]) sage: phi = EllipticCurveIsogeny(E, E((0,0))) sage: phi.x_rational_map() (x^2 + 3)/x - >>> from sage.all import * >>> E = EllipticCurve(QQ, [Integer(0),Integer(2),Integer(0),Integer(1),-Integer(1)]) >>> phi = EllipticCurveIsogeny(E, [Integer(1)]) >>> phi.x_rational_map() x >>> E = EllipticCurve(GF(Integer(17)), [Integer(0),Integer(0),Integer(0),Integer(3),Integer(0)]) >>> phi = EllipticCurveIsogeny(E, E((Integer(0),Integer(0)))) >>> phi.x_rational_map() (x^2 + 3)/x 
 
- sage.schemes.elliptic_curves.ell_curve_isogeny.compute_codomain_formula(E, v, w)[source]¶
- Compute the codomain curve given parameters \(v\) and \(w\) (as in Vélu/Kohel/etc. formulas). - INPUT: - E– an elliptic curve
- v,- w– elements of the base field of- E
 - OUTPUT: - The elliptic curve with invariants \([a_1,a_2,a_3,a_4-5v,a_6-(a_1^2+4a_2)v-7w]\) where \(E = [a_1,a_2,a_3,a_4,a_6]\). - EXAMPLES: - This formula is used by every invocation of the - EllipticCurveIsogenyconstructor:- 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) == phi.codomain() True - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> phi = EllipticCurveIsogeny(E, E((Integer(1),Integer(2))) ) >>> 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 >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_codomain_formula >>> v = phi._EllipticCurveIsogeny__v >>> w = phi._EllipticCurveIsogeny__w >>> compute_codomain_formula(E, v, w) == phi.codomain() True 
- sage.schemes.elliptic_curves.ell_curve_isogeny.compute_codomain_kohel(E, kernel)[source]¶
- Compute the codomain from the kernel polynomial using Kohel’s formulas. - INPUT: - E– domain elliptic curve
- kernel– polynomial or list; the kernel polynomial, or a list of its coefficients
 - OUTPUT: elliptic curve; the codomain elliptic curve of the isogeny defined by - kernel- 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]) 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) 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) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 3*x + 15 over Finite Field of size 19 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_codomain_kohel >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> phi = EllipticCurveIsogeny(E, [Integer(9),Integer(1)]) >>> phi.codomain() == isogeny_codomain_from_kernel(E, [Integer(9),Integer(1)]) True >>> compute_codomain_kohel(E, [Integer(9),Integer(1)]) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 9*x + 8 over Finite Field of size 19 >>> R = GF(Integer(19))['x']; (x,) = R._first_ngens(1) >>> E = EllipticCurve(GF(Integer(19)), [Integer(18),Integer(17),Integer(16),Integer(15),Integer(14)]) >>> phi = EllipticCurveIsogeny(E, x**Integer(3) + Integer(14)*x**Integer(2) + Integer(3)*x + Integer(11)) >>> phi.codomain() == isogeny_codomain_from_kernel(E, x**Integer(3) + Integer(14)*x**Integer(2) + Integer(3)*x + Integer(11)) True >>> compute_codomain_kohel(E, x**Integer(3) + Integer(14)*x**Integer(2) + Integer(3)*x + Integer(11)) 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 >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> phi = EllipticCurveIsogeny(E, x**Integer(3) + Integer(7)*x**Integer(2) + Integer(15)*x + Integer(12)) >>> isogeny_codomain_from_kernel(E, x**Integer(3) + Integer(7)*x**Integer(2) + Integer(15)*x + Integer(12)) == phi.codomain() True >>> compute_codomain_kohel(E, x**Integer(3) + Integer(7)*x**Integer(2) + Integer(15)*x + Integer(12)) Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 3*x + 15 over Finite Field of size 19 - ALGORITHM: - This function uses the formulas of Section 2.4 of [Koh1996]. 
- sage.schemes.elliptic_curves.ell_curve_isogeny.compute_intermediate_curves(E1, E2)[source]¶
- Return intermediate curves and isomorphisms. - Note - This is used to compute \(\wp\) functions from the short Weierstrass model more easily. - Warning - The base field must be of characteristic not equal to \(2\) or \(3\). - INPUT: - E1,- E2– elliptic curves
 - OUTPUT: - A tuple ( - pre_isomorphism,- post_isomorphism,- intermediate_domain,- intermediate_codomain) where:- intermediate_domainis a short Weierstrass curve isomorphic to- E1;
- intermediate_codomainis a short Weierstrass curve isomorphic to- E2;
- pre_isomorphismis a normalized isomorphism from- E1to- intermediate_domain;
- post_isomorphismis a normalized isomorphism from- intermediate_codomainto- 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, Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 83 To: 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), Elliptic-curve morphism: From: Elliptic Curve defined by y^2 = x^3 + 65*x + 69 over Finite Field of size 83 To: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + 16 over Finite Field of size 83 Via: (u,r,s,t) = (1, 7, 42, 42)) sage: # needs sage.rings.number_field 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, Elliptic-curve endomorphism of 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), Elliptic-curve endomorphism of 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)) - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_intermediate_curves >>> E = EllipticCurve(GF(Integer(83)), [Integer(1),Integer(0),Integer(1),Integer(1),Integer(0)]) >>> R = GF(Integer(83))['x']; (x,) = R._first_ngens(1); f = x + Integer(24) >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> 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, Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 83 To: 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), Elliptic-curve morphism: From: Elliptic Curve defined by y^2 = x^3 + 65*x + 69 over Finite Field of size 83 To: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + 16 over Finite Field of size 83 Via: (u,r,s,t) = (1, 7, 42, 42)) >>> # needs sage.rings.number_field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> E = EllipticCurve(K, [Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)]) >>> E2 = EllipticCurve(K, [Integer(0),Integer(0),Integer(0),Integer(16),Integer(0)]) >>> 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, Elliptic-curve endomorphism of 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), Elliptic-curve endomorphism of 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_bmss(E1, E2, l)[source]¶
- Compute the kernel polynomial of the unique normalized isogeny of degree - lbetween- E1and- E2.- Both curves must be given in short Weierstrass form, and the characteristic must be either \(0\) or no smaller than \(4l+4\). - ALGORITHM: [BMSS2006], algorithm fastElkies’. - EXAMPLES: - sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_bmss sage: E1 = EllipticCurve(GF(167), [153, 112]) sage: E2 = EllipticCurve(GF(167), [56, 40]) sage: compute_isogeny_bmss(E1, E2, 13) x^6 + 139*x^5 + 73*x^4 + 139*x^3 + 120*x^2 + 88*x - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_bmss >>> E1 = EllipticCurve(GF(Integer(167)), [Integer(153), Integer(112)]) >>> E2 = EllipticCurve(GF(Integer(167)), [Integer(56), Integer(40)]) >>> compute_isogeny_bmss(E1, E2, Integer(13)) x^6 + 139*x^5 + 73*x^4 + 139*x^3 + 120*x^2 + 88*x 
- sage.schemes.elliptic_curves.ell_curve_isogeny.compute_isogeny_kernel_polynomial(E1, E2, ell, algorithm=None)[source]¶
- Return the kernel polynomial of a cyclic, separable, normalized isogeny of degree - ellfrom- E1to- E2.- INPUT: - E1– domain elliptic curve in short Weierstrass form
- E2– codomain elliptic curve in short Weierstrass form
- ell– the degree of an isogeny from- E1to- E2
- algorithm–- None(default, choose automatically) or- 'bmss'(- compute_isogeny_bmss()) or- 'stark'(- compute_isogeny_stark())
 - OUTPUT: the kernel polynomial of an isogeny from - E1to- E2- Note - If there is no degree- - ell, cyclic, separable, normalized isogeny from- E1to- E2, a- ValueErrorwill be raised.- 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: # needs sage.rings.number_field 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_kernel_polynomial >>> E = EllipticCurve(GF(Integer(37)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(8)]) >>> R = GF(Integer(37))['x']; (x,) = R._first_ngens(1) >>> f = (x + Integer(14)) * (x + Integer(30)) >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> compute_isogeny_kernel_polynomial(E, E2, Integer(5)) x^2 + 7*x + 13 >>> f x^2 + 7*x + 13 >>> # needs sage.rings.number_field >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> E = EllipticCurve(K, [Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)]) >>> E2 = EllipticCurve(K, [Integer(0),Integer(0),Integer(0),Integer(16),Integer(0)]) >>> compute_isogeny_kernel_polynomial(E, E2, Integer(4)) x^3 + x 
- sage.schemes.elliptic_curves.ell_curve_isogeny.compute_isogeny_stark(E1, E2, ell)[source]¶
- Return the kernel polynomial of an isogeny of degree - ellfrom- E1to- E2.- INPUT: - E1– domain elliptic curve in short Weierstrass form
- E2– codomain elliptic curve in short Weierstrass form
- ell– the degree of an isogeny from- E1to- E2
 - OUTPUT: the kernel polynomial of an isogeny from - E1to- E2- Note - If there is no degree- - ell, cyclic, separable, normalized isogeny from- E1to- E2, a- ValueErrorwill be raised.- ALGORITHM: - This function uses Stark’s algorithm as presented in Section 6.2 of [BMSS2006]. - Note - As published in [BMSS2006], the algorithm is incorrect, and a correct version (with slightly different notation) can be found in [Mo2009]. The algorithm originates in [Sta1973]. - EXAMPLES: - sage: from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_stark, 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_stark(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_stark(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_stark(E, E2, 2) x - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_isogeny_stark, compute_sequence_of_maps >>> E = EllipticCurve(GF(Integer(97)), [Integer(1),Integer(0),Integer(1),Integer(1),Integer(0)]) >>> R = GF(Integer(97))['x']; (x,) = R._first_ngens(1); f = x**Integer(5) + Integer(27)*x**Integer(4) + Integer(61)*x**Integer(3) + Integer(58)*x**Integer(2) + Integer(28)*x + Integer(21) >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> isom1, isom2, E1pr, E2pr, ker_poly = compute_sequence_of_maps(E, E2, Integer(11)) >>> compute_isogeny_stark(E1pr, E2pr, Integer(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 >>> E = EllipticCurve(GF(Integer(37)), [Integer(0),Integer(0),Integer(0),Integer(1),Integer(8)]) >>> R = GF(Integer(37))['x']; (x,) = R._first_ngens(1) >>> f = (x + Integer(14)) * (x + Integer(30)) >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> compute_isogeny_stark(E, E2, Integer(5)) x^4 + 14*x^3 + x^2 + 34*x + 21 >>> f**Integer(2) x^4 + 14*x^3 + x^2 + 34*x + 21 >>> E = EllipticCurve(QQ, [Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)]) >>> R = QQ['x']; (x,) = R._first_ngens(1) >>> f = x >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> compute_isogeny_stark(E, E2, Integer(2)) x 
- sage.schemes.elliptic_curves.ell_curve_isogeny.compute_sequence_of_maps(E1, E2, ell)[source]¶
- Return intermediate curves, isomorphisms and kernel polynomial. - INPUT: - E1,- E2– elliptic curves
- ell– a prime such that there is a degree-- ellseparable normalized isogeny from- E1to- E2
 - OUTPUT: - A tuple ( - pre_isom,- post_isom,- E1pr,- E2pr,- ker_poly) where:- E1pris an elliptic curve in short Weierstrass form isomorphic to- E1;
- E2pris an elliptic curve in short Weierstrass form isomorphic to- E2;
- pre_isomis a normalized isomorphism from- E1to- E1pr;
- post_isomis a normalized isomorphism from- E2prto- E2;
- ker_polyis the kernel polynomial of an- ell-isogeny from- E1prto- E2pr.
 - 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) (Elliptic-curve morphism: 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 = x^3 - 31/3*x - 2501/108 over Rational Field Via: (u,r,s,t) = (1, 1/3, 0, -1/2), Elliptic-curve morphism: From: Elliptic Curve defined by y^2 = x^3 - 23461/3*x - 28748141/108 over Rational Field To: 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: # needs sage.rings.number_field 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) (Elliptic-curve endomorphism of 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), Elliptic-curve endomorphism of 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) (Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 97 To: 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), Elliptic-curve morphism: From: Elliptic Curve defined by y^2 = x^3 + 41*x + 66 over Finite Field of size 97 To: Elliptic Curve defined by y^2 + x*y + y = x^3 + 87*x + 26 over Finite Field of size 97 Via: (u,r,s,t) = (1, 89, 49, 49), 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) - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_sequence_of_maps >>> E = EllipticCurve('11a1') >>> R = QQ['x']; (x,) = R._first_ngens(1); f = x**Integer(2) - Integer(21)*x + Integer(80) >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> compute_sequence_of_maps(E, E2, Integer(5)) (Elliptic-curve morphism: 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 = x^3 - 31/3*x - 2501/108 over Rational Field Via: (u,r,s,t) = (1, 1/3, 0, -1/2), Elliptic-curve morphism: From: Elliptic Curve defined by y^2 = x^3 - 23461/3*x - 28748141/108 over Rational Field To: 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) >>> # needs sage.rings.number_field >>> K = NumberField(x**Integer(2) + Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> E = EllipticCurve(K, [Integer(0),Integer(0),Integer(0),Integer(1),Integer(0)]) >>> E2 = EllipticCurve(K, [Integer(0),Integer(0),Integer(0),Integer(16),Integer(0)]) >>> compute_sequence_of_maps(E, E2, Integer(4)) (Elliptic-curve endomorphism of 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), Elliptic-curve endomorphism of 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) >>> E = EllipticCurve(GF(Integer(97)), [Integer(1),Integer(0),Integer(1),Integer(1),Integer(0)]) >>> R = GF(Integer(97))['x']; (x,) = R._first_ngens(1); f = x**Integer(5) + Integer(27)*x**Integer(4) + Integer(61)*x**Integer(3) + Integer(58)*x**Integer(2) + Integer(28)*x + Integer(21) >>> phi = EllipticCurveIsogeny(E, f) >>> E2 = phi.codomain() >>> compute_sequence_of_maps(E, E2, Integer(11)) (Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + x*y + y = x^3 + x over Finite Field of size 97 To: 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), Elliptic-curve morphism: From: Elliptic Curve defined by y^2 = x^3 + 41*x + 66 over Finite Field of size 97 To: Elliptic Curve defined by y^2 + x*y + y = x^3 + 87*x + 26 over Finite Field of size 97 Via: (u,r,s,t) = (1, 89, 49, 49), 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)[source]¶
- Compute Vélu’s \((v,w)\) using Kohel’s formulas for isogenies of degree exactly divisible by \(2\). - INPUT: - x0,- y0– coordinates of a 2-torsion point on an elliptic curve \(E\)
- a1,- a2,- a4– invariants of \(E\)
 - OUTPUT: Vélu’s isogeny parameters \((v,w)\). - 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]); 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.a_invariants() sage: x0 = -9 sage: y0 = -(a1*x0 + a3)/2 sage: compute_vw_kohel_even_deg1(x0, y0, a1, a2, a4) (18, 9) - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> phi = EllipticCurveIsogeny(E, [Integer(9),Integer(1)]); 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 >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_vw_kohel_even_deg1 >>> a1,a2,a3,a4,a6 = E.a_invariants() >>> x0 = -Integer(9) >>> y0 = -(a1*x0 + a3)/Integer(2) >>> 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)[source]¶
- Compute Vélu’s \((v,w)\) using Kohel’s formulas for isogenies of degree divisible by \(4\). - INPUT: - b2,- b4– invariants of an elliptic curve \(E\)
- s1,- s2,- s3– signed coefficients of the 2-division polynomial of \(E\)
 - OUTPUT: Vélu’s isogeny parameters \((v,w)\). - 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); 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) - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> R = GF(Integer(19))['x']; (x,) = R._first_ngens(1) >>> phi = EllipticCurveIsogeny(E, x**Integer(3) + Integer(7)*x**Integer(2) + Integer(15)*x + Integer(12)); 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 >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_vw_kohel_even_deg3 >>> b2,b4 = E.b2(), E.b4() >>> s1, s2, s3 = -Integer(7), Integer(15), -Integer(12) >>> 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)[source]¶
- Compute Vélu’s \((v,w)\) using Kohel’s formulas for isogenies of odd degree. - INPUT: - b2,- b4,- b6– invariants of an elliptic curve \(E\)
- s1,- s2,- s3– signed coefficients of lowest powers of \(x\) in the kernel polynomial
- n– integer; the degree
 - OUTPUT: Vélu’s isogeny parameters \((v,w)\) - 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); 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) - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(19)), [Integer(18),Integer(17),Integer(16),Integer(15),Integer(14)]) >>> R = GF(Integer(19))['x']; (x,) = R._first_ngens(1) >>> phi = EllipticCurveIsogeny(E, x**Integer(3) + Integer(14)*x**Integer(2) + Integer(3)*x + Integer(11)); 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 >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import compute_vw_kohel_odd >>> b2,b4,b6 = E.b2(), E.b4(), E.b6() >>> s1,s2,s3 = -Integer(14),Integer(3),-Integer(11) >>> compute_vw_kohel_odd(b2,b4,b6,s1,s2,s3,Integer(3)) (7, 1) 
- sage.schemes.elliptic_curves.ell_curve_isogeny.fill_isogeny_matrix(M)[source]¶
- Return 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 \(0\)
 - OUTPUT: - 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] - >>> from sage.all import * >>> M = Matrix([[Integer(0), Integer(2), Integer(3), Integer(3), Integer(0), Integer(0)], [Integer(2), Integer(0), Integer(0), Integer(0), Integer(3), Integer(3)], [Integer(3), Integer(0), Integer(0), Integer(0), Integer(2), Integer(0)], ... [Integer(3), Integer(0), Integer(0), Integer(0), Integer(0), Integer(2)], [Integer(0), Integer(3), Integer(2), Integer(0), Integer(0), Integer(0)], [Integer(0), Integer(3), Integer(0), Integer(2), Integer(0), Integer(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] >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix >>> 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.isogeny_codomain_from_kernel(E, kernel)[source]¶
- Compute the isogeny codomain given a kernel. - INPUT: - E– domain elliptic curve
- 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: elliptic curve) The codomain of the separable normalized isogeny defined by 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]) 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])) 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: # needs sage.rings.finite_rings 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 - >>> from sage.all import * >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import isogeny_codomain_from_kernel >>> E = EllipticCurve(GF(Integer(7)), [Integer(1),Integer(0),Integer(1),Integer(0),Integer(1)]) >>> R = GF(Integer(7))['x']; (x,) = R._first_ngens(1) >>> isogeny_codomain_from_kernel(E, [Integer(4),Integer(1)]) Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + 6 over Finite Field of size 7 >>> (EllipticCurveIsogeny(E, [Integer(4),Integer(1)]).codomain() ... == isogeny_codomain_from_kernel(E, [Integer(4),Integer(1)])) True >>> isogeny_codomain_from_kernel(E, x**Integer(3) + x**Integer(2) + Integer(4)*x + Integer(3)) Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x + 6 over Finite Field of size 7 >>> isogeny_codomain_from_kernel(E, x**Integer(3) + Integer(2)*x**Integer(2) + Integer(4)*x + Integer(3)) Elliptic Curve defined by y^2 + x*y + y = x^3 + 5*x + 2 over Finite Field of size 7 >>> # needs sage.rings.finite_rings >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> kernel_list = [E((Integer(15),Integer(10))), E((Integer(10),Integer(3))), E((Integer(6),Integer(5)))] >>> 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.two_torsion_part(E, psi)[source]¶
- Return the greatest common divisor of - psiand the 2-torsion polynomial of \(E\).- INPUT: - E– an elliptic curve
- psi– a univariate polynomial over the base field of- E
 - OUTPUT: polynomial; the \(\gcd\) of - psiand 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, x + 13) x + 13 - >>> from sage.all import * >>> E = EllipticCurve(GF(Integer(19)), [Integer(1),Integer(2),Integer(3),Integer(4),Integer(5)]) >>> R = GF(Integer(19))['x']; (x,) = R._first_ngens(1) >>> phi = EllipticCurveIsogeny(E, x + Integer(13)) >>> isogeny_codomain_from_kernel(E, x + Integer(13)) == phi.codomain() True >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import two_torsion_part >>> two_torsion_part(E, x + Integer(13)) x + 13 
- sage.schemes.elliptic_curves.ell_curve_isogeny.unfill_isogeny_matrix(M)[source]¶
- Reverses the action of - fill_isogeny_matrix.- INPUT: - M– a square symmetric matrix of integers
 - OUTPUT: - A square symmetric matrix obtained from - Mby 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 - >>> from sage.all import * >>> M = Matrix([[Integer(0), Integer(2), Integer(3), Integer(3), Integer(0), Integer(0)], [Integer(2), Integer(0), Integer(0), Integer(0), Integer(3), Integer(3)], [Integer(3), Integer(0), Integer(0), Integer(0), Integer(2), Integer(0)], ... [Integer(3), Integer(0), Integer(0), Integer(0), Integer(0), Integer(2)], [Integer(0), Integer(3), Integer(2), Integer(0), Integer(0), Integer(0)], [Integer(0), Integer(3), Integer(0), Integer(2), Integer(0), Integer(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] >>> from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix, unfill_isogeny_matrix >>> 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] >>> 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] >>> unfill_isogeny_matrix(M1) == M True