Modular parametrization of elliptic curves over \(\QQ\)#

By the work of Taylor–Wiles et al. it is known that there is a surjective morphism

\[\phi_E: X_0(N) \rightarrow E.\]

from the modular curve \(X_0(N)\), where \(N\) is the conductor of \(E\). The map sends the cusp \(\infty\) to the origin of \(E\).

EXAMPLES:

sage: phi = EllipticCurve('11a1').modular_parametrization()
sage: phi
Modular parameterization
 from the upper half plane
   to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
sage: phi(0.5+CDF(I))
(285684.320516... + 7.0...e-11*I : 1.526964169...e8 + 5.6...e-8*I : 1.00000000000000)
sage: phi.power_series(prec = 7)
(q^-2 + 2*q^-1 + 4 + 5*q + 8*q^2 + q^3 + 7*q^4 + O(q^5),
 -q^-3 - 3*q^-2 - 7*q^-1 - 13 - 17*q - 26*q^2 - 19*q^3 + O(q^4))

AUTHORS:

  • Chris Wuthrich (02/10): moved from ell_rational_field.py.

class sage.schemes.elliptic_curves.modular_parametrization.ModularParameterization(E)#

Bases: object

This class represents the modular parametrization of an elliptic curve

\[\phi_E: X_0(N) \rightarrow E.\]

Evaluation is done by passing through the lattice representation of \(E\).

EXAMPLES:

sage: phi = EllipticCurve('11a1').modular_parametrization()
sage: phi
Modular parameterization
 from the upper half plane
   to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20
      over Rational Field
curve()#

Return the curve associated to this modular parametrization.

EXAMPLES:

sage: E = EllipticCurve('15a')
sage: phi = E.modular_parametrization()
sage: phi.curve() is E
True
map_to_complex_numbers(z, prec=None)#

Evaluate self at a point \(z \in X_0(N)\) where \(z\) is given by a representative in the upper half plane, returning a point in the complex numbers.

All computations are done with prec bits of precision. If prec is not given, use the precision of \(z\). Use self(z) to compute the image of z on the Weierstrass equation of the curve.

EXAMPLES:

sage: # needs sage.symbolic
sage: E = EllipticCurve('37a'); phi = E.modular_parametrization()
sage: x = polygen(ZZ, 'x')
sage: tau = (sqrt(7)*I - 17)/74
sage: z = phi.map_to_complex_numbers(tau); z
0.929592715285395 - 1.22569469099340*I
sage: E.elliptic_exponential(z)
(...e-16 - ...e-16*I : ...e-16 + ...e-16*I : 1.00000000000000)
sage: phi(tau)
(...e-16 - ...e-16*I : ...e-16 + ...e-16*I : 1.00000000000000)
power_series(prec=20)#

Return the power series of this modular parametrization.

The curve must be a minimal model. The prec parameter determines the number of significant terms. This means that X will be given up to O(q^(prec-2)) and Y will be given up to O(q^(prec-3)).

OUTPUT: A list of two Laurent series [X(x),Y(x)] of degrees -2, -3 respectively, which satisfy the equation of the elliptic curve. There are modular functions on \(\Gamma_0(N)\) where \(N\) is the conductor.

The series should satisfy the differential equation

\[\frac{\mathrm{d}X}{2Y + a_1 X + a_3} = \frac{f(q)\, \mathrm{d}q}{q}\]

where \(f\) is self.curve().q_expansion().

EXAMPLES:

sage: E = EllipticCurve('389a1')
sage: phi = E.modular_parametrization()
sage: X, Y = phi.power_series(prec=10)
sage: X
q^-2 + 2*q^-1 + 4 + 7*q + 13*q^2 + 18*q^3 + 31*q^4 + 49*q^5 + 74*q^6 + 111*q^7 + O(q^8)
sage: Y
-q^-3 - 3*q^-2 - 8*q^-1 - 17 - 33*q - 61*q^2 - 110*q^3 - 186*q^4 - 320*q^5 - 528*q^6 + O(q^7)
sage: X,Y = phi.power_series()
sage: X
q^-2 + 2*q^-1 + 4 + 7*q + 13*q^2 + 18*q^3 + 31*q^4 + 49*q^5 + 74*q^6 + 111*q^7 + 173*q^8 + 251*q^9 + 379*q^10 + 560*q^11 + 824*q^12 + 1199*q^13 + 1773*q^14 + 2548*q^15 + 3722*q^16 + 5374*q^17 + O(q^18)
sage: Y
-q^-3 - 3*q^-2 - 8*q^-1 - 17 - 33*q - 61*q^2 - 110*q^3 - 186*q^4 - 320*q^5 - 528*q^6 - 861*q^7 - 1383*q^8 - 2218*q^9 - 3472*q^10 - 5451*q^11 - 8447*q^12 - 13020*q^13 - 19923*q^14 - 30403*q^15 - 46003*q^16 + O(q^17)

The following should give 0, but only approximately:

sage: q = X.parent().gen()
sage: E.defining_polynomial()(X,Y,1) + O(q^11) == 0
True

Note that below we have to change variable from \(x\) to \(q\):

sage: a1,_,a3,_,_ = E.a_invariants()
sage: f = E.q_expansion(17)
sage: q = f.parent().gen()
sage: f/q == (X.derivative()/(2*Y+a1*X+a3))
True