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 \((u,r,s,t)\), 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 \((u,r,s,t)\) maps a point \((x,y)\) to the point
\[((x-r) / u^2, \; (y - s(x-r) - t) / u^3) .\]If the domain \(E\) has Weierstrass coefficients \([a_1,a_2,a_3,a_4,a_6]\), the codomain \(F\) is given by
\[\begin{split}a_1' &= (a_1 + 2s) / u \\ a_2' &= (a_2 - a_1s + 3r - s^2) / u^2 \\ a_3' &= (a_3 + a_1r + 2t) / u^3 \\ a_4' &= (a_4 + 2a_2r - a_1(rs+t) - a_3s + 3r^2 - 2st) / u^4 \\ a_6' &= (a_6 - a_1rt + a_2r^2 - a_3t + a_4r + r^3 - t^2) / u^6 .\end{split}\]EXAMPLES:
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
- 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)
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
- 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
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
- kernel_polynomial()[source]¶
Return the kernel polynomial of this isomorphism.
Isomorphisms have trivial kernel by definition, hence this method always returns \(1\).
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
- 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
- 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
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
- scaling_factor()[source]¶
Return the Weierstrass scaling factor associated to this Weierstrass isomorphism.
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 isomorphism and \(\omega_i\) are the standard Weierstrass differentials on \(E_i\) defined by \(\mathrm dx/(2y+a_1x+a_3)\).
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
ALGORITHM: The scaling factor equals the \(u\) component of the tuple \((u,r,s,t)\) defining the isomorphism.
- x_rational_map()[source]¶
Return the \(x\)-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
- 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 \([u,r,s,t]\) (with \(u \neq 0\)) which specifies a transformation \((x,y) \mapsto (x',y')\) where
\((x,y) = (u^2x'+r , u^3y' + su^2x' + t).\)
INPUT:
u,r,s,t– (default: \(1\), \(0\), \(0\), \(0\)); 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)
- 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
- tuple()[source]¶
Return the parameters \(u,r,s,t\) 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)
- sage.schemes.elliptic_curves.weierstrass_morphism.identity_morphism(E)[source]¶
Given an elliptic curve \(E\), return the identity morphism on \(E\) as a
WeierstrassIsomorphism.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)
- sage.schemes.elliptic_curves.weierstrass_morphism.negation_morphism(E)[source]¶
Given an elliptic curve \(E\), return the negation endomorphism \([-1]\) of \(E\) as a
WeierstrassIsomorphism.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)