Isomorphisms between Weierstrass models of elliptic curves¶
AUTHORS:
Robert Bradshaw (2007): initial version
John Cremona (Jan 2008): isomorphisms, automorphisms and twists in all characteristics
Lorenz Panny (2021):
EllipticCurveHominterface
- class sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism(E=None, urst=None, F=None)[source]¶
Bases:
EllipticCurveHom,baseWIClass representing a Weierstrass isomorphism between two elliptic curves.
INPUT:
E– anEllipticCurve, orNone(see below)urst– a 4-tuple , abaseWIobject, orNone(see below)F– anEllipticCurve, orNone(see below)
Given two Elliptic Curves
EandF(represented by Weierstrass models as usual), and a transformationurstfromEtoF, construct an isomorphism fromEtoF. An exception is raised ifurst(E) != F. At most one ofE,F,urstcan beNone. In this case, the missing input is constructed from the others in such a way thaturst(E) == Fholds, and an exception is raised if this is impossible (typically becauseEandFare not isomorphic).Users will not usually need to use this class directly, but instead use methods such as
isomorphism_to()orisomorphisms().Explicitly, the isomorphism defined by
maps a point to the pointIf the domain
has Weierstrass coefficients , the codomain is given byEXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import * sage: WeierstrassIsomorphism(EllipticCurve([0,1,2,3,4]), (-1,2,3,4)) Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field To: Elliptic Curve defined by y^2 - 6*x*y - 10*y = x^3 - 2*x^2 - 11*x - 2 over Rational Field Via: (u,r,s,t) = (-1, 2, 3, 4) sage: E = EllipticCurve([0,1,2,3,4]) sage: F = EllipticCurve(E.cremona_label()) sage: WeierstrassIsomorphism(E, None, F) Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field To: Elliptic Curve defined by y^2 = x^3 + x^2 + 3*x + 5 over Rational Field Via: (u,r,s,t) = (1, 0, 0, -1) sage: w = WeierstrassIsomorphism(None, (1,0,0,-1), F) sage: w._domain == E True
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import * >>> WeierstrassIsomorphism(EllipticCurve([Integer(0),Integer(1),Integer(2),Integer(3),Integer(4)]), (-Integer(1),Integer(2),Integer(3),Integer(4))) Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field To: Elliptic Curve defined by y^2 - 6*x*y - 10*y = x^3 - 2*x^2 - 11*x - 2 over Rational Field Via: (u,r,s,t) = (-1, 2, 3, 4) >>> E = EllipticCurve([Integer(0),Integer(1),Integer(2),Integer(3),Integer(4)]) >>> F = EllipticCurve(E.cremona_label()) >>> WeierstrassIsomorphism(E, None, F) Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 2*y = x^3 + x^2 + 3*x + 4 over Rational Field To: Elliptic Curve defined by y^2 = x^3 + x^2 + 3*x + 5 over Rational Field Via: (u,r,s,t) = (1, 0, 0, -1) >>> w = WeierstrassIsomorphism(None, (Integer(1),Integer(0),Integer(0),-Integer(1)), F) >>> w._domain == E True
from sage.schemes.elliptic_curves.weierstrass_morphism import * WeierstrassIsomorphism(EllipticCurve([0,1,2,3,4]), (-1,2,3,4)) E = EllipticCurve([0,1,2,3,4]) F = EllipticCurve(E.cremona_label()) WeierstrassIsomorphism(E, None, F) w = WeierstrassIsomorphism(None, (1,0,0,-1), F) w._domain == E
- dual()[source]¶
Return the dual isogeny of this isomorphism.
For isomorphisms, the dual is just the inverse.
EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism sage: E = EllipticCurve(QuadraticField(-3), [0,1]) # needs sage.rings.number_field sage: w = WeierstrassIsomorphism(E, (CyclotomicField(3).gen(),0,0,0)) # needs sage.rings.number_field sage: (w.dual() * w).rational_maps() # needs sage.rings.number_field (x, y)
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism >>> E = EllipticCurve(QuadraticField(-Integer(3)), [Integer(0),Integer(1)]) # needs sage.rings.number_field >>> w = WeierstrassIsomorphism(E, (CyclotomicField(Integer(3)).gen(),Integer(0),Integer(0),Integer(0))) # needs sage.rings.number_field >>> (w.dual() * w).rational_maps() # needs sage.rings.number_field (x, y)
from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism E = EllipticCurve(QuadraticField(-3), [0,1]) # needs sage.rings.number_field w = WeierstrassIsomorphism(E, (CyclotomicField(3).gen(),0,0,0)) # needs sage.rings.number_field (w.dual() * w).rational_maps() # needs sage.rings.number_field
sage: E1 = EllipticCurve([11,22,33,44,55]) sage: E2 = E1.short_weierstrass_model() sage: iso = E1.isomorphism_to(E2) sage: iso.dual() == ~iso True
>>> from sage.all import * >>> E1 = EllipticCurve([Integer(11),Integer(22),Integer(33),Integer(44),Integer(55)]) >>> E2 = E1.short_weierstrass_model() >>> iso = E1.isomorphism_to(E2) >>> iso.dual() == ~iso True
E1 = EllipticCurve([11,22,33,44,55]) E2 = E1.short_weierstrass_model() iso = E1.isomorphism_to(E2) iso.dual() == ~iso
- inseparable_degree()[source]¶
Return the inseparable degree of this Weierstrass isomorphism.
For isomorphisms, this method always returns one.
- is_identity()[source]¶
Check if this Weierstrass isomorphism is the identity.
EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism sage: p = 97 sage: Fp = GF(p) sage: E = EllipticCurve(Fp, [1, 28]) sage: ws = WeierstrassIsomorphism(E, None, E) sage: ws.is_identity() False
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism >>> p = Integer(97) >>> Fp = GF(p) >>> E = EllipticCurve(Fp, [Integer(1), Integer(28)]) >>> ws = WeierstrassIsomorphism(E, None, E) >>> ws.is_identity() False
from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism p = 97 Fp = GF(p) E = EllipticCurve(Fp, [1, 28]) ws = WeierstrassIsomorphism(E, None, E) ws.is_identity()
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism sage: p = 97 sage: Fp = GF(p) sage: E = EllipticCurve(Fp, [1, 28]) sage: ws = WeierstrassIsomorphism(E, (1, 0, 0, 0), None) sage: ws.is_identity() True
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism >>> p = Integer(97) >>> Fp = GF(p) >>> E = EllipticCurve(Fp, [Integer(1), Integer(28)]) >>> ws = WeierstrassIsomorphism(E, (Integer(1), Integer(0), Integer(0), Integer(0)), None) >>> ws.is_identity() True
from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism p = 97 Fp = GF(p) E = EllipticCurve(Fp, [1, 28]) ws = WeierstrassIsomorphism(E, (1, 0, 0, 0), None) ws.is_identity()
- kernel_polynomial()[source]¶
Return the kernel polynomial of this isomorphism.
Isomorphisms have trivial kernel by definition, hence this method always returns
.EXAMPLES:
sage: E1 = EllipticCurve([11,22,33,44,55]) sage: E2 = EllipticCurve_from_j(E1.j_invariant()) sage: iso = E1.isomorphism_to(E2) sage: iso.kernel_polynomial() 1 sage: psi = E1.isogeny(iso.kernel_polynomial(), codomain=E2); psi Isogeny of degree 1 from Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681 over Rational Field sage: psi in {iso, -iso} True
>>> from sage.all import * >>> E1 = EllipticCurve([Integer(11),Integer(22),Integer(33),Integer(44),Integer(55)]) >>> E2 = EllipticCurve_from_j(E1.j_invariant()) >>> iso = E1.isomorphism_to(E2) >>> iso.kernel_polynomial() 1 >>> psi = E1.isogeny(iso.kernel_polynomial(), codomain=E2); psi Isogeny of degree 1 from Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field to Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681 over Rational Field >>> psi in {iso, -iso} True
E1 = EllipticCurve([11,22,33,44,55]) E2 = EllipticCurve_from_j(E1.j_invariant()) iso = E1.isomorphism_to(E2) iso.kernel_polynomial() psi = E1.isogeny(iso.kernel_polynomial(), codomain=E2); psi psi in {iso, -iso}
- order()[source]¶
Compute the order of this Weierstrass isomorphism if it is an automorphism.
A
ValueErroris raised if the domain is not equal to the codomain.A
NotImplementedErroris raised if the order of the automorphism is not 1, 2, 3, 4 or 6.EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import * sage: p = 97 sage: Fp = GF(p) sage: E = EllipticCurve(Fp, [1, 28]) sage: ws = WeierstrassIsomorphism(E, None, E) sage: ws.order() 2
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import * >>> p = Integer(97) >>> Fp = GF(p) >>> E = EllipticCurve(Fp, [Integer(1), Integer(28)]) >>> ws = WeierstrassIsomorphism(E, None, E) >>> ws.order() 2
from sage.schemes.elliptic_curves.weierstrass_morphism import * p = 97 Fp = GF(p) E = EllipticCurve(Fp, [1, 28]) ws = WeierstrassIsomorphism(E, None, E) ws.order()
- rational_maps()[source]¶
Return the pair of rational maps defining this isomorphism.
EXAMPLES:
sage: E1 = EllipticCurve([11,22,33,44,55]) sage: E2 = EllipticCurve_from_j(E1.j_invariant()) sage: iso = E1.isomorphism_to(E2); iso Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681 over Rational Field Via: (u,r,s,t) = (1, -17, -5, 77) sage: iso.rational_maps() (x + 17, 5*x + y + 8) sage: f = E2.defining_polynomial()(*iso.rational_maps(), 1) sage: I = E1.defining_ideal() sage: x,y,z = I.ring().gens() sage: f in I + Ideal(z-1) True
>>> from sage.all import * >>> E1 = EllipticCurve([Integer(11),Integer(22),Integer(33),Integer(44),Integer(55)]) >>> E2 = EllipticCurve_from_j(E1.j_invariant()) >>> iso = E1.isomorphism_to(E2); iso Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681 over Rational Field Via: (u,r,s,t) = (1, -17, -5, 77) >>> iso.rational_maps() (x + 17, 5*x + y + 8) >>> f = E2.defining_polynomial()(*iso.rational_maps(), Integer(1)) >>> I = E1.defining_ideal() >>> x,y,z = I.ring().gens() >>> f in I + Ideal(z-Integer(1)) True
E1 = EllipticCurve([11,22,33,44,55]) E2 = EllipticCurve_from_j(E1.j_invariant()) iso = E1.isomorphism_to(E2); iso iso.rational_maps() f = E2.defining_polynomial()(*iso.rational_maps(), 1) I = E1.defining_ideal() x,y,z = I.ring().gens() f in I + Ideal(z-1)
sage: # needs sage.rings.finite_rings sage: E = EllipticCurve(GF(65537), [1,1,1,1,1]) sage: w = E.isomorphism_to(E.short_weierstrass_model()) sage: f,g = w.rational_maps() sage: P = E.random_point() sage: w(P).xy() == (f(P.xy()), g(P.xy())) True
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> E = EllipticCurve(GF(Integer(65537)), [Integer(1),Integer(1),Integer(1),Integer(1),Integer(1)]) >>> w = E.isomorphism_to(E.short_weierstrass_model()) >>> f,g = w.rational_maps() >>> P = E.random_point() >>> w(P).xy() == (f(P.xy()), g(P.xy())) True
# needs sage.rings.finite_rings E = EllipticCurve(GF(65537), [1,1,1,1,1]) w = E.isomorphism_to(E.short_weierstrass_model()) f,g = w.rational_maps() P = E.random_point() w(P).xy() == (f(P.xy()), g(P.xy()))
- scaling_factor()[source]¶
Return the Weierstrass scaling factor associated to this Weierstrass isomorphism.
The scaling factor is the constant
(in the base field) such that , where is this isomorphism and are the standard Weierstrass differentials on defined by .EXAMPLES:
sage: E = EllipticCurve(QQbar, [0,1]) # needs sage.rings.number_field sage: all(f.scaling_factor() == f.formal()[1] for f in E.automorphisms()) # needs sage.rings.number_field True
>>> from sage.all import * >>> E = EllipticCurve(QQbar, [Integer(0),Integer(1)]) # needs sage.rings.number_field >>> all(f.scaling_factor() == f.formal()[Integer(1)] for f in E.automorphisms()) # needs sage.rings.number_field True
E = EllipticCurve(QQbar, [0,1]) # needs sage.rings.number_field all(f.scaling_factor() == f.formal()[1] for f in E.automorphisms()) # needs sage.rings.number_field
ALGORITHM: The scaling factor equals the
component of the tuple defining the isomorphism.
- x_rational_map()[source]¶
Return the
-coordinate rational map of this isomorphism.EXAMPLES:
sage: E1 = EllipticCurve([11,22,33,44,55]) sage: E2 = EllipticCurve_from_j(E1.j_invariant()) sage: iso = E1.isomorphism_to(E2); iso Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681 over Rational Field Via: (u,r,s,t) = (1, -17, -5, 77) sage: iso.x_rational_map() x + 17 sage: iso.x_rational_map() == iso.rational_maps()[0] True
>>> from sage.all import * >>> E1 = EllipticCurve([Integer(11),Integer(22),Integer(33),Integer(44),Integer(55)]) >>> E2 = EllipticCurve_from_j(E1.j_invariant()) >>> iso = E1.isomorphism_to(E2); iso Elliptic-curve morphism: From: Elliptic Curve defined by y^2 + 11*x*y + 33*y = x^3 + 22*x^2 + 44*x + 55 over Rational Field To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 - 684*x + 6681 over Rational Field Via: (u,r,s,t) = (1, -17, -5, 77) >>> iso.x_rational_map() x + 17 >>> iso.x_rational_map() == iso.rational_maps()[Integer(0)] True
E1 = EllipticCurve([11,22,33,44,55]) E2 = EllipticCurve_from_j(E1.j_invariant()) iso = E1.isomorphism_to(E2); iso iso.x_rational_map() iso.x_rational_map() == iso.rational_maps()[0]
- class sage.schemes.elliptic_curves.weierstrass_morphism.baseWI(u=1, r=0, s=0, t=0)[source]¶
Bases:
objectThis class implements the basic arithmetic of isomorphisms between Weierstrass models of elliptic curves.
These are specified by lists of the form
(with ) which specifies a transformation whereINPUT:
u,r,s,t– (default: , , , ); standard parameters of an isomorphism between Weierstrass models
EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import * sage: baseWI() (1, 0, 0, 0) sage: baseWI(2,3,4,5) (2, 3, 4, 5) sage: R.<u,r,s,t> = QQ[] sage: baseWI(u,r,s,t) (u, r, s, t)
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import * >>> baseWI() (1, 0, 0, 0) >>> baseWI(Integer(2),Integer(3),Integer(4),Integer(5)) (2, 3, 4, 5) >>> R = QQ['u, r, s, t']; (u, r, s, t,) = R._first_ngens(4) >>> baseWI(u,r,s,t) (u, r, s, t)
from sage.schemes.elliptic_curves.weierstrass_morphism import * baseWI() baseWI(2,3,4,5) R.<u,r,s,t> = QQ[] baseWI(u,r,s,t)
- is_identity()[source]¶
Return
Trueif this is the identity isomorphism.EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import * sage: w = baseWI(); w.is_identity() True sage: w = baseWI(2,3,4,5); w.is_identity() False
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import * >>> w = baseWI(); w.is_identity() True >>> w = baseWI(Integer(2),Integer(3),Integer(4),Integer(5)); w.is_identity() False
from sage.schemes.elliptic_curves.weierstrass_morphism import * w = baseWI(); w.is_identity() w = baseWI(2,3,4,5); w.is_identity()
- tuple()[source]¶
Return the parameters
as a tuple.EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import * sage: w = baseWI(2,3,4,5) sage: w.tuple() (2, 3, 4, 5)
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import * >>> w = baseWI(Integer(2),Integer(3),Integer(4),Integer(5)) >>> w.tuple() (2, 3, 4, 5)
from sage.schemes.elliptic_curves.weierstrass_morphism import * w = baseWI(2,3,4,5) w.tuple()
- sage.schemes.elliptic_curves.weierstrass_morphism.identity_morphism(E)[source]¶
Given an elliptic curve
, return the identity morphism on as aWeierstrassIsomorphism.EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import identity_morphism sage: E = EllipticCurve([5,6,7,8,9]) sage: id_ = identity_morphism(E) sage: id_.rational_maps() (x, y)
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import identity_morphism >>> E = EllipticCurve([Integer(5),Integer(6),Integer(7),Integer(8),Integer(9)]) >>> id_ = identity_morphism(E) >>> id_.rational_maps() (x, y)
from sage.schemes.elliptic_curves.weierstrass_morphism import identity_morphism E = EllipticCurve([5,6,7,8,9]) id_ = identity_morphism(E) id_.rational_maps()
- sage.schemes.elliptic_curves.weierstrass_morphism.negation_morphism(E)[source]¶
Given an elliptic curve
, return the negation endomorphism of as aWeierstrassIsomorphism.EXAMPLES:
sage: from sage.schemes.elliptic_curves.weierstrass_morphism import negation_morphism sage: E = EllipticCurve([5,6,7,8,9]) sage: neg = negation_morphism(E) sage: neg.rational_maps() (x, -5*x - y - 7)
>>> from sage.all import * >>> from sage.schemes.elliptic_curves.weierstrass_morphism import negation_morphism >>> E = EllipticCurve([Integer(5),Integer(6),Integer(7),Integer(8),Integer(9)]) >>> neg = negation_morphism(E) >>> neg.rational_maps() (x, -5*x - y - 7)
from sage.schemes.elliptic_curves.weierstrass_morphism import negation_morphism E = EllipticCurve([5,6,7,8,9]) neg = negation_morphism(E) neg.rational_maps()