Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/schemes/elliptic_curves/modular_parametrization.py
4108 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Modular parametrization of elliptic curves over `\QQ`
4
5
By the work of Taylor--Wiles et al. it is known that there
6
is a surjective morphism
7
8
.. math::
9
10
\phi_E: X_0(N) \rightarrow E.
11
12
from the modular curve `X_0(N)`, where `N` is the conductor of `E`.
13
The map sends the cusp `\infty` to the origin of `E`.
14
15
EXMAPLES::
16
17
sage: phi = EllipticCurve('11a1').modular_parametrization()
18
sage: phi
19
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
20
sage: phi(0.5+CDF(I))
21
(285684.320516... + 7.0...e-11*I : 1.526964169...e8 + 5.6...e-8*I : 1.00000000000000)
22
sage: phi.power_series(prec = 7)
23
(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))
24
25
AUTHORS:
26
27
- chris wuthrich (02/10) - moved from ell_rational_field.py.
28
29
"""
30
31
######################################################################
32
# Copyright (C) 2010 William Stein <[email protected]>
33
#
34
# Distributed under the terms of the GNU General Public License (GPL)
35
#
36
# This code is distributed in the hope that it will be useful,
37
# but WITHOUT ANY WARRANTY; without even the implied warranty of
38
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39
# General Public License for more details.
40
#
41
# The full text of the GPL is available at:
42
#
43
# http://www.gnu.org/licenses/
44
######################################################################
45
46
import heegner
47
48
from sage.rings.all import (LaurentSeriesRing, RationalField, ComplexField, QQ)
49
import sage.misc.misc as misc
50
51
class ModularParameterization:
52
r"""
53
This class represents the modular parametrization of an elliptic curve
54
55
.. math::
56
57
\phi_E: X_0(N) \rightarrow E.
58
59
Evaluation is done by passing through the lattice representation of `E`.
60
61
EXAMPLES::
62
63
sage: phi = EllipticCurve('11a1').modular_parametrization()
64
sage: phi
65
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
66
67
"""
68
def __init__(self, E):
69
r"""
70
EXAMPLES::
71
s
72
sage: from sage.schemes.elliptic_curves.ell_rational_field import ModularParameterization
73
sage: phi = ModularParameterization(EllipticCurve('389a'))
74
sage: phi(CC.0/5)
75
(27.1965586309057 : -144.727322178982 : 1.00000000000000)
76
77
sage: phi == loads(dumps(phi))
78
True
79
80
"""
81
self._E = E
82
83
def curve(self):
84
"""
85
Returns the curve associated to this modular parametrization.
86
87
EXAMPLES::
88
89
sage: E = EllipticCurve('15a')
90
sage: phi = E.modular_parametrization()
91
sage: phi.curve() is E
92
True
93
"""
94
return self._E
95
96
def __repr__(self):
97
"""
98
TESTS::
99
100
sage: E = EllipticCurve('37a')
101
sage: phi = E.modular_parametrization()
102
sage: phi
103
Modular parameterization from the upper half plane to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field
104
sage: phi.__repr__()
105
'Modular parameterization from the upper half plane to Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field'
106
"""
107
return "Modular parameterization from the upper half plane to %s" % self._E
108
109
def __cmp__(self,other):
110
r"""
111
Compares two modular parametrizations by simply comparing the elliptic curves.
112
113
EXAMPLES::
114
115
sage: E = EllipticCurve('37a1')
116
sage: phi = E.modular_parametrization()
117
sage: phi == phi
118
True
119
"""
120
c = cmp(type(self), type(other))
121
if c:
122
return c
123
return cmp(self._E, other._E)
124
125
def __call__(self, z, prec=None):
126
r"""
127
Evaluate self at a point `z \in X_0(N)` where `z` is given by a
128
representative in the upper half plane. All computations done with ``prec``
129
bits of precision. If ``prec`` is not given, use the precision of `z`.
130
131
EXAMPLES::
132
133
sage: E = EllipticCurve('37a')
134
sage: phi = E.modular_parametrization()
135
sage: phi((sqrt(7)*I - 17)/74, 53)
136
(...e-16 - ...e-16*I : ...e-16 + ...e-16*I : 1.00000000000000)
137
138
Verify that the mapping is invariant under the action of `\Gamma_0(N)`
139
on the upper half plane::
140
141
sage: E = EllipticCurve('11a')
142
sage: phi = E.modular_parametrization()
143
sage: tau = CC((1+1j)/5)
144
sage: phi(tau)
145
(-3.92181329652811 - 12.2578555525366*I : 44.9649874434872 + 14.3257120944681*I : 1.00000000000000)
146
sage: phi(tau+1)
147
(-3.92181329652810 - 12.2578555525366*I : 44.9649874434872 + 14.3257120944681*I : 1.00000000000000)
148
sage: phi((6*tau+1) / (11*tau+2))
149
(-3.9218132965285... - 12.2578555525369*I : 44.964987443489... + 14.325712094467...*I : 1.00000000000000)
150
151
We can also apply the modular parametrization to a Heegner point on `X_0(N)`::
152
153
sage: H = heegner_points(389,-7,5); H
154
All Heegner points of conductor 5 on X_0(389) associated to QQ[sqrt(-7)]
155
sage: x = H[0]; x
156
Heegner point 5/778*sqrt(-7) - 147/778 of discriminant -7 and conductor 5 on X_0(389)
157
sage: E = EllipticCurve('389a'); phi = E.modular_parametrization()
158
sage: phi(x)
159
Heegner point of discriminant -7 and conductor 5 on elliptic curve of conductor 389
160
sage: phi(x).quadratic_form()
161
389*x^2 + 147*x*y + 14*y^2
162
163
164
ALGORITHM:
165
166
Integrate the modular form attached to this elliptic curve from
167
`z` to `\infty` to get a point on the lattice representation of
168
`E`, then use the Weierstrass `\wp` function to map it to the
169
curve itself.
170
"""
171
if isinstance(z, heegner.HeegnerPointOnX0N):
172
return z.map_to_curve(self.curve())
173
# Map to the CC of CC/PeriodLattice.
174
tm = misc.verbose("Evaluating modular parameterization to precision %s bits"%prec)
175
w = self.map_to_complex_numbers(z, prec=prec)
176
# Map to E via Weierstrass P
177
z = self._E.elliptic_exponential(w)
178
misc.verbose("Finished evaluating modular parameterization", tm)
179
return z
180
181
def map_to_complex_numbers(self, z, prec=None):
182
"""
183
Evaluate self at a point `z \in X_0(N)` where `z` is given by
184
a representative in the upper half plane, returning a point in
185
the complex numbers. All computations done with ``prec`` bits
186
of precision. If ``prec`` is not given, use the precision of `z`.
187
Use self(z) to compute the image of z on the Weierstrass equation
188
of the curve.
189
190
EXAMPLES::
191
192
sage: E = EllipticCurve('37a'); phi = E.modular_parametrization()
193
sage: tau = (sqrt(7)*I - 17)/74
194
sage: z = phi.map_to_complex_numbers(tau); z
195
0.929592715285395 - 1.22569469099340*I
196
sage: E.elliptic_exponential(z)
197
(...e-16 - ...e-16*I : ...e-16 + ...e-16*I : 1.00000000000000)
198
sage: phi(tau)
199
(...e-16 - ...e-16*I : ...e-16 + ...e-16*I : 1.00000000000000)
200
"""
201
if prec is None:
202
try:
203
prec = z.parent().prec()
204
except AttributeError:
205
prec = 53
206
CC = ComplexField(prec)
207
if z in QQ:
208
raise NotImplementedError
209
z = CC(z)
210
if z.imag() <= 0:
211
raise ValueError, "Point must be in the upper half plane"
212
# TODO: for very small imaginary part, maybe try to transform under
213
# \Gamma_0(N) to a better representative?
214
q = (2*CC.gen()*CC.pi()*z).exp()
215
# nterms'th term is less than 2**-(prec+10) (c.f. eclib code)
216
nterms = (-(prec+10)/q.abs().log2()).ceil()
217
# Use Horner's rule to sum the integral of the form
218
enumerated_an = list(enumerate(self._E.anlist(nterms)))[1:]
219
lattice_point = 0
220
for n, an in reversed(enumerated_an):
221
lattice_point += an/n
222
lattice_point *= q
223
return lattice_point
224
225
def power_series(self, prec=20):
226
r"""
227
Computes and returns the power series of this modular parametrization.
228
229
The curve must be a a minimal model. The prec parameter determines
230
the number of significant terms. This means that X will be given up
231
to O(q^(prec-2)) and Y will be given up to O(q^(prec-3)).
232
233
OUTPUT: A list of two Laurent series ``[X(x),Y(x)]`` of degrees -2, -3
234
respectively, which satisfy the equation of the elliptic curve.
235
There are modular functions on `\Gamma_0(N)` where `N` is the
236
conductor.
237
238
The series should satisfy the differential equation
239
240
.. math::
241
242
\frac{\mathrm{d}X}{2Y + a_1 X + a_3} = \frac{f(q)\, \mathrm{d}q}{q}
243
244
where `f` is ``self.curve().q_expansion()``.
245
246
EXAMPLES::
247
248
sage: E=EllipticCurve('389a1')
249
sage: phi = E.modular_parametrization()
250
sage: X,Y = phi.power_series(prec = 10)
251
sage: X
252
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)
253
sage: Y
254
-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)
255
sage: X,Y = phi.power_series()
256
sage: X
257
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)
258
sage: Y
259
-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)
260
261
The following should give 0, but only approximately::
262
263
sage: q = X.parent().gen()
264
sage: E.defining_polynomial()(X,Y,1) + O(q^11) == 0
265
True
266
267
Note that below we have to change variable from x to q::
268
269
sage: a1,_,a3,_,_=E.a_invariants()
270
sage: f=E.q_expansion(17)
271
sage: q=f.parent().gen()
272
sage: f/q == (X.derivative()/(2*Y+a1*X+a3))
273
True
274
"""
275
R = LaurentSeriesRing(RationalField(),'q')
276
if not self._E.is_minimal():
277
raise NotImplementedError, "Only implemented for minimal curves."
278
from sage.libs.all import pari
279
old_prec = pari.get_series_precision()
280
pari.set_series_precision(prec-1)
281
XY = self._E.pari_mincurve().elltaniyama()
282
pari.set_series_precision(old_prec)
283
return R(XY[0]),R(XY[1])
284
285
286