Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/schemes/elliptic_curves/ell_modular_symbols.py
8820 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Modular symbols
4
5
To an elliptic curves `E` over the rational numbers one can associate
6
a space - or better two spaces - of modular symbols of level `N`,
7
equal to the conductor of `E`; because `E` is known to be modular.
8
9
There are two implementations of modular symbols, one within ``sage``
10
and the other as part of Cremona's ``eclib``. One can choose here which
11
one is used.
12
13
The normalisation of our modular symbols attached to `E` can be chosen, too.
14
For instance one can make it depended on `E` rather than on its
15
isogeny class. This is useful for `p`-adic L-functions.
16
17
For more details on modular symbols consult the following
18
19
REFERENCES:
20
21
- [MTT] B. Mazur, J. Tate, and J. Teitelbaum,
22
On `p`-adic analogues of the conjectures of Birch and
23
Swinnerton-Dyer, Inventiones mathematicae 84, (1986), 1-48.
24
25
- [Cre] John Cremona, Algorithms for modular elliptic curves,
26
Cambridge University Press, 1997.
27
28
- [SW] William Stein and Christian Wuthrich, Computations About Tate-Shafarevich Groups
29
using Iwasawa theory, preprint 2009.
30
31
AUTHORS:
32
33
- William Stein (2007): first version
34
35
- Chris Wuthrich (2008): add scaling and reference to eclib
36
37
"""
38
39
#*****************************************************************************
40
# Copyright (C) 2007 William Stein <[email protected]>
41
#
42
# Distributed under the terms of the GNU General Public License (GPL)
43
#
44
# This code is distributed in the hope that it will be useful,
45
# but WITHOUT ANY WARRANTY; without even the implied warranty of
46
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47
# General Public License for more details.
48
#
49
# The full text of the GPL is available at:
50
#
51
# http://www.gnu.org/licenses/
52
#*****************************************************************************
53
54
from sage.structure.sage_object import SageObject
55
from sage.modular.modsym.all import ModularSymbols
56
from sage.libs.cremona.newforms import ECModularSymbol
57
from sage.databases.cremona import parse_cremona_label
58
59
from sage.rings.arith import next_prime, kronecker_symbol, prime_divisors, valuation
60
from sage.rings.infinity import unsigned_infinity as infinity
61
from sage.rings.integer import Integer
62
from sage.modular.cusps import Cusps
63
from sage.rings.integer_ring import ZZ
64
from sage.rings.rational_field import QQ
65
from sage.misc.all import verbose
66
67
from sage.schemes.elliptic_curves.constructor import EllipticCurve
68
69
oo = Cusps(infinity)
70
zero = Integer(0)
71
72
def modular_symbol_space(E, sign, base_ring, bound=None):
73
r"""
74
Creates the space of modular symbols of a given sign over a give base_ring,
75
attached to the isogeny class of elliptic curves.
76
77
INPUT:
78
79
- ``E`` - an elliptic curve over `\QQ`
80
- ``sign`` - integer, -1, 0, or 1
81
- ``base_ring`` - ring
82
- ``bound`` - (default: None) maximum number of Hecke operators to
83
use to cut out modular symbols factor. If None, use
84
enough to provably get the correct answer.
85
86
OUTPUT: a space of modular symbols
87
88
EXAMPLES::
89
90
sage: import sage.schemes.elliptic_curves.ell_modular_symbols
91
sage: E=EllipticCurve('11a1')
92
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.modular_symbol_space(E,-1,GF(37))
93
sage: M
94
Modular Symbols space of dimension 1 for Gamma_0(11) of weight 2 with sign -1 over Finite Field of size 37
95
96
"""
97
_sign = int(sign)
98
if _sign != sign:
99
raise TypeError, 'sign must be an integer'
100
if not (_sign in [-1,0,1]):
101
raise TypeError, 'sign must -1, 0, or 1'
102
N = E.conductor()
103
M = ModularSymbols(N, sign=sign, base_ring=base_ring)
104
if bound is None:
105
bound = M.hecke_bound() + 10
106
V = M
107
p = 2
108
while p <= bound and V.dimension() > 1:
109
t = V.T(p)
110
ap = E.ap(p)
111
V = (t - ap).kernel()
112
p = next_prime(p)
113
114
return V
115
116
class ModularSymbol(SageObject):
117
r"""
118
A modular symbol attached to an elliptic curve, which is the map
119
`\QQ\to \QQ` obtained by sending `r` to the normalized
120
symmetrized (or anti-symmetrized) integral from `r` to `\infty`.
121
122
This is as defined in [MTT], but normalized
123
to depend on the curve and not only its isogeny class as in [SW].
124
125
See the documentation of ``E.modular_symbol()`` in
126
Elliptic curves over the rational numbers
127
for help.
128
129
REFERENCES:
130
131
- [MTT] B. Mazur, J. Tate, and J. Teitelbaum,
132
On `p`-adic analogues of the conjectures of Birch and
133
Swinnerton-Dyer, Inventiones mathematicae 84, (1986), 1-48.
134
135
- [SW] William Stein and Christian Wuthrich, Computations About Tate-Shafarevich Groups
136
using Iwasawa theory, preprint 2009.
137
138
"""
139
140
def sign(self):
141
r"""
142
Return the sign of this elliptic curve modular symbol.
143
144
EXAMPLES::
145
146
sage: m = EllipticCurve('11a1').modular_symbol()
147
sage: m.sign()
148
1
149
sage: m = EllipticCurve('11a1').modular_symbol(sign=-1)
150
sage: m.sign()
151
-1
152
"""
153
154
return self._sign
155
156
def elliptic_curve(self):
157
r"""
158
Return the elliptic curve of this modular symbol.
159
160
EXAMPLES::
161
162
sage: m = EllipticCurve('11a1').modular_symbol()
163
sage: m.elliptic_curve()
164
Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
165
166
"""
167
return self._E
168
169
def base_ring(self):
170
r"""
171
Return the base ring for this modular symbol.
172
173
EXAMPLES::
174
175
sage: m = EllipticCurve('11a1').modular_symbol()
176
sage: m.base_ring()
177
Rational Field
178
"""
179
return self._base_ring
180
181
def _repr_(self):
182
r"""
183
String representation of modular symbols.
184
185
EXAMPLES::
186
187
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
188
sage: m
189
Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
190
sage: m = EllipticCurve('43a1').modular_symbol(sign=-1)
191
sage: m
192
Modular symbol with sign -1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 + x^2 over Rational Field
193
"""
194
return "Modular symbol with sign %s over %s attached to %s"%(
195
self._sign, self._base_ring, self._E)
196
197
def _find_scaling_L_ratio(self):
198
r"""
199
This function is use to set ``_scaling``, the factor used to adjust the
200
scalar multiple of the modular symbol.
201
If `[0]`, the modular symbol evaluated at 0, is non-zero, we can just scale
202
it with respect to the approximation of the L-value. It is known that
203
the quotient is a rational number with small denominator.
204
Otherwise we try to scale using quadratic twists.
205
206
``_scaling`` will be set to a rational non-zero multiple if we succeed and to 1 otherwise.
207
Even if we fail we scale at least to make up the difference between the periods
208
of the `X_0`-optimal curve and our given curve `E` in the isogeny class.
209
210
EXAMPLES::
211
212
sage : m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
213
sage : m._scaling
214
1
215
sage: m = EllipticCurve('11a2').modular_symbol(use_eclib=True)
216
sage: m._scaling
217
5/2
218
sage: m = EllipticCurve('11a3').modular_symbol(use_eclib=True)
219
sage: m._scaling
220
1/10
221
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=False)
222
sage: m._scaling
223
1/5
224
sage: m = EllipticCurve('11a2').modular_symbol(use_eclib=False)
225
sage: m._scaling
226
1
227
sage: m = EllipticCurve('11a3').modular_symbol(use_eclib=False)
228
sage: m._scaling
229
1/25
230
sage: m = EllipticCurve('37a1').modular_symbol(use_eclib=False)
231
sage: m._scaling
232
1
233
sage: m = EllipticCurve('37a1').modular_symbol(use_eclib=True)
234
sage: m._scaling
235
-1
236
sage: m = EllipticCurve('389a1').modular_symbol(use_eclib=True)
237
sage: m._scaling
238
-1/2
239
sage: m = EllipticCurve('389a1').modular_symbol(use_eclib=False)
240
sage: m._scaling
241
2
242
sage: m = EllipticCurve('196a1').modular_symbol(use_eclib=False)
243
sage: m._scaling
244
1/2
245
246
Some harder cases fail::
247
248
sage: m = EllipticCurve('121b1').modular_symbol(use_eclib=False)
249
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
250
sage: m._scaling
251
1
252
253
TESTS::
254
255
sage: rk0 = ['11a1', '11a2', '15a1', '27a1', '37b1']
256
sage: for la in rk0: # long time (3s on sage.math, 2011)
257
... E = EllipticCurve(la)
258
... me = E.modular_symbol(use_eclib = True)
259
... ms = E.modular_symbol(use_eclib = False)
260
... print E.lseries().L_ratio()*E.real_components(), me(0), ms(0)
261
1/5 1/5 1/5
262
1 1 1
263
1/4 1/4 1/4
264
1/3 1/3 1/3
265
2/3 2/3 2/3
266
267
sage: rk1 = ['37a1','43a1','53a1', '91b1','91b2','91b3']
268
sage: [EllipticCurve(la).modular_symbol(use_eclib=True)(0) for la in rk1] # long time (1s on sage.math, 2011)
269
[0, 0, 0, 0, 0, 0]
270
sage: for la in rk1: # long time (8s on sage.math, 2011)
271
... E = EllipticCurve(la)
272
... m = E.modular_symbol(use_eclib = True)
273
... lp = E.padic_lseries(5)
274
... for D in [5,17,12,8]:
275
... ED = E.quadratic_twist(D)
276
... md = sum([kronecker(D,u)*m(ZZ(u)/D) for u in range(D)])
277
... etaa = lp._quotient_of_periods_to_twist(D)
278
... assert ED.lseries().L_ratio()*ED.real_components()*etaa == md
279
280
"""
281
E = self._E
282
self._scaling = 1 # by now.
283
self._failed_to_scale = False
284
285
if self._sign == 1 :
286
at0 = self(0)
287
# print 'modular symbol evaluates to ',at0,' at 0'
288
if at0 != 0 :
289
l1 = self.__lalg__(1)
290
if at0 != l1:
291
verbose('scale modular symbols by %s'%(l1/at0))
292
self._scaling = l1/at0
293
else :
294
# if [0] = 0, we can still hope to scale it correctly by considering twists of E
295
Dlist = [5,8,12,13,17,21,24,28,29, 33, 37, 40, 41, 44, 53, 56, 57, 60, 61, 65, 69, 73, 76, 77, 85, 88, 89, 92, 93, 97] # a list of positive fundamental discriminants
296
j = 0
297
at0 = 0
298
# computes [0]+ for the twist of E by D until one value is non-zero
299
while j < 30 and at0 == 0 :
300
D = Dlist[j]
301
# the following line checks if the twist of the newform of E by D is a newform
302
# this is to avoid that we 'twist back'
303
if all( valuation(E.conductor(),ell)<= valuation(D,ell) for ell in prime_divisors(D) ) :
304
at0 = sum([kronecker_symbol(D,u) * self(ZZ(u)/D) for u in range(1,abs(D))])
305
j += 1
306
if j == 30 and at0 == 0: # curves like "121b1", "225a1", "225e1", "256a1", "256b1", "289a1", "361a1", "400a1", "400c1", "400h1", "441b1", "441c1", "441d1", "441f1 .. will arrive here
307
self._failed_to_scale = True
308
self.__scale_by_periods_only__()
309
else :
310
l1 = self.__lalg__(D)
311
if at0 != l1:
312
verbose('scale modular symbols by %s found at D=%s '%(l1/at0,D), level=2)
313
self._scaling = l1/at0
314
315
else : # that is when sign = -1
316
Dlist = [-3,-4,-7,-8,-11,-15,-19,-20,-23,-24, -31, -35, -39, -40, -43, -47, -51, -52, -55, -56, -59, -67, -68, -71, -79, -83, -84, -87, -88, -91] # a list of negative fundamental discriminants
317
j = 0
318
at0 = 0
319
while j < 30 and at0 == 0 :
320
# computes [0]+ for the twist of E by D until one value is non-zero
321
D = Dlist[j]
322
if all( valuation(E.conductor(),ell)<= valuation(D,ell) for ell in prime_divisors(D) ) :
323
at0 = - sum([kronecker_symbol(D,u) * self(ZZ(u)/D) for u in range(1,abs(D))])
324
j += 1
325
if j == 30 and at0 == 0: # no more hope for a normalization
326
# we do at least a scaling with the quotient of the periods
327
self._failed_to_scale = True
328
self.__scale_by_periods_only__()
329
else :
330
l1 = self.__lalg__(D)
331
if at0 != l1:
332
verbose('scale modular symbols by %s'%(l1/at0))
333
self._scaling = l1/at0
334
335
336
def __lalg__(self,D):
337
r"""
338
For positive `D`, this function evaluates the quotient
339
`L(E_D,1)\cdot \sqrt(D)/\Omega_E` where `E_D` is the twist of
340
`E` by `D`, `\Omega_E` is the least positive period of `E`.
341
For negative `E`, it is the quotient
342
`L(E_D,1)\cdot \sqrt(-D)/\Omega^{-}_E`
343
where `\Omega^{-}_E` is the least positive imaginary part of a
344
non-real period of `E`.
345
346
EXMAPLES::
347
348
sage: E = EllipticCurve('11a1')
349
sage: m = E.modular_symbol(sign=+1)
350
sage: m.__lalg__(1)
351
1/5
352
sage: m.__lalg__(3)
353
5/2
354
355
"""
356
from sage.functions.all import sqrt
357
# the computation of the L-value could take a lot of time,
358
# but then the conductor is so large
359
# that the computation of modular symbols for E took even longer
360
361
E = self._E
362
ED = E.quadratic_twist(D)
363
lv = ED.lseries().L_ratio() # this is L(ED,1) divided by the Neron period omD of ED
364
lv *= ED.real_components()
365
omD = ED.period_lattice().basis()[0]
366
if D > 0 :
367
om = E.period_lattice().basis()[0]
368
q = sqrt(D)*omD/om * 8
369
else :
370
om = E.period_lattice().basis()[1].imag()
371
q = sqrt(-D)*omD/om*8
372
373
# see padic_lseries.pAdicLeries._quotient_of_periods_to_twist
374
# for the explanation of the second factor
375
verbose('real approximation is %s'%q)
376
return lv/8 * QQ(int(round(q)))
377
378
def __scale_by_periods_only__(self):
379
r"""
380
If we fail to scale with ``_find_scaling_L_ratio``, we drop here
381
to try and find the scaling by the quotient of the
382
periods to the `X_0`-optimal curve. The resulting ``_scaling``
383
is not guaranteed to be correct, but could well be.
384
385
EXAMPLES::
386
387
sage: E = EllipticCurve('11a1')
388
sage: m = E.modular_symbol(sign=+1)
389
sage: m.__scale_by_periods_only__()
390
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
391
sage: m._scaling
392
1
393
394
sage: E = EllipticCurve('11a3')
395
sage: m = E.modular_symbol(sign=+1, use_eclib=True)
396
sage: m.__scale_by_periods_only__()
397
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
398
sage: m._scaling
399
1/5
400
401
"""
402
# we only do this inside the cremona-tables.
403
try :
404
crla = parse_cremona_label(self._E.label())
405
except RuntimeError: # raised when curve is outside of the table
406
print "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by a rational number."
407
self._scaling = 1
408
else :
409
print "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2."
410
cr0 = Integer(crla[0]).str() + crla[1] + '1'
411
E0 = EllipticCurve(cr0)
412
q = E0.period_lattice().basis()[0]/self._E.period_lattice().basis()[0]
413
q = QQ(int(round(q*200)))/200
414
verbose('scale modular symbols by %s'%q)
415
self._scaling = q
416
417
418
class ModularSymbolECLIB(ModularSymbol):
419
def __init__(self, E, sign, normalize="L_ratio"):
420
r"""
421
Modular symbols attached to `E` using ``eclib``.
422
423
INPUT:
424
425
- ``E`` - an elliptic curve
426
- ``sign`` - an integer, -1 or 1
427
- ``normalize`` - either 'L_ratio' (default) or 'none';
428
For 'L_ratio', the modular symbol is correctly normalized
429
by comparing it to the quotient of `L(E,1)` by the least
430
positive period for the curve and some small twists.
431
For 'none', the modular symbol is almost certainly
432
not correctly normalized, i.e. all values will be a
433
fixed scalar multiple of what they should be.
434
435
EXAMPLES::
436
437
sage: import sage.schemes.elliptic_curves.ell_modular_symbols
438
sage: E=EllipticCurve('11a1')
439
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolECLIB(E,+1)
440
sage: M
441
Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
442
sage: M(0)
443
1/5
444
sage: E=EllipticCurve('11a2')
445
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolECLIB(E,+1)
446
sage: M(0)
447
1
448
449
This is a rank 1 case with vanishing positive twists.
450
The modular symbol can not be adjusted::
451
452
sage: E=EllipticCurve('121b1')
453
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolECLIB(E,+1)
454
Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by -1, 2 or -2.
455
sage: M(0)
456
0
457
sage: M(1/7)
458
-2
459
460
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=True)
461
sage: M(0)
462
2
463
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=True,normalize='none')
464
sage: M(0)
465
8
466
467
sage: E = EllipticCurve('15a1')
468
sage: [C.modular_symbol(use_eclib=True,normalize='L_ratio')(0) for C in E.isogeny_class()]
469
[1/4, 1/8, 1/4, 1/2, 1/8, 1/16, 1/2, 1]
470
sage: [C.modular_symbol(use_eclib=True,normalize='none')(0) for C in E.isogeny_class()]
471
[1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4, 1/4]
472
473
Currently, the interface for negative modular symbols in eclib is not yet written::
474
475
sage: E.modular_symbol(use_eclib=True,sign=-1)
476
Traceback (most recent call last):
477
...
478
NotImplementedError: Despite that eclib has now -1 modular symbols the interface to them is not yet written.
479
480
TESTS (for trac 10236)::
481
482
sage: E = EllipticCurve('11a1')
483
sage: m = E.modular_symbol(use_eclib=True)
484
sage: m(1/7)
485
7/10
486
sage: m(0)
487
1/5
488
"""
489
self._sign = ZZ(sign)
490
if self._sign != sign:
491
raise TypeError, 'sign must be an integer'
492
if self._sign != -1 and self._sign != 1:
493
raise TypeError, 'sign must -1 or 1'
494
if self._sign == -1:
495
raise NotImplementedError, "Despite that eclib has now -1 modular symbols the interface to them is not yet written."
496
self._E = E
497
self._use_eclib = True
498
self._base_ring = QQ
499
self._normalize = normalize
500
self._modsym = ECModularSymbol(E)
501
p = ZZ(2)
502
while not E.is_good(p):
503
p = p.next_prime()
504
# this computes {0,oo} using the Hecke-operator at p
505
self._atzero = sum([self._modsym(ZZ(a)/p) for a in range(p)])/E.Np(p)
506
507
if normalize == "L_ratio":
508
self._find_scaling_L_ratio()
509
elif normalize == "none":
510
self._scaling = ZZ(1)
511
else :
512
raise ValueError, "no normalization '%s' known for modular symbols using John Cremona's eclib"%normalize
513
514
515
def _call_with_caching(self, r):
516
r"""
517
Evaluates the modular symbol at `r`, caching the computed value.
518
519
EXAMPLES::
520
521
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
522
sage: m._call_with_caching(0)
523
1/5
524
"""
525
try:
526
return self.__cache[r]
527
except AttributeError:
528
self.__cache = {}
529
except KeyError:
530
pass
531
c = (self._atzero - self._modsym(r))*self._scaling
532
self.__cache[r] = c
533
return c
534
535
def __call__(self, r):
536
r"""
537
Evaluates the modular symbol at `r`.
538
539
EXAMPLES::
540
541
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=True)
542
sage: m(0)
543
1/5
544
545
"""
546
# this computes {0,oo} - {0,r} = {r,oo}
547
from sage.rings.rational import Rational
548
if r != oo:
549
r = Rational(r)
550
r = r.numer() % r.denom() / r.denom()
551
return (self._atzero - self._modsym(r))*self._scaling
552
553
554
class ModularSymbolSage(ModularSymbol):
555
def __init__(self, E, sign, normalize="L_ratio"):
556
"""
557
Modular symbols attached to `E` using ``sage``.
558
559
INPUT:
560
561
- ``E`` -- an elliptic curve
562
- ``sign`` -- an integer, -1 or 1
563
- ``normalize`` -- either 'L_ratio' (default), 'period', or 'none';
564
For 'L_ratio', the modular symbol is correctly normalized
565
by comparing it to the quotient of `L(E,1)` by the least
566
positive period for the curve and some small twists.
567
The normalization 'period' uses the integral_period_map
568
for modular symbols and is known to be equal to the above
569
normalization up to the sign and a possible power of 2.
570
For 'none', the modular symbol is almost certainly
571
not correctly normalized, i.e. all values will be a
572
fixed scalar multiple of what they should be. But
573
the initial computation of the modular symbol is
574
much faster, though evaluation of
575
it after computing it won't be any faster.
576
577
EXAMPLES::
578
579
sage: E=EllipticCurve('11a1')
580
sage: import sage.schemes.elliptic_curves.ell_modular_symbols
581
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1)
582
sage: M
583
Modular symbol with sign 1 over Rational Field attached to Elliptic Curve defined by y^2 + y = x^3 - x^2 - 10*x - 20 over Rational Field
584
sage: M(0)
585
1/5
586
sage: E=EllipticCurve('11a2')
587
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1)
588
sage: M(0)
589
1
590
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,-1)
591
sage: M(1/3)
592
1
593
594
This is a rank 1 case with vanishing positive twists.
595
The modular symbol is adjusted by -2::
596
597
sage: E=EllipticCurve('121b1')
598
sage: M=sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,-1,normalize='L_ratio')
599
sage: M(1/3)
600
2
601
sage: M._scaling
602
-2
603
604
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=False)
605
sage: M(0)
606
2
607
sage: M = EllipticCurve('121d1').modular_symbol(use_eclib=False,normalize='none')
608
sage: M(0)
609
1
610
611
sage: E = EllipticCurve('15a1')
612
sage: [C.modular_symbol(use_eclib=False, normalize='L_ratio')(0) for C in E.isogeny_class()]
613
[1/4, 1/8, 1/4, 1/2, 1/8, 1/16, 1/2, 1]
614
sage: [C.modular_symbol(use_eclib=False, normalize='period')(0) for C in E.isogeny_class()]
615
[1/8, 1/16, 1/8, 1/4, 1/16, 1/32, 1/4, 1/2]
616
sage: [C.modular_symbol(use_eclib=False, normalize='none')(0) for C in E.isogeny_class()]
617
[1, 1, 1, 1, 1, 1, 1, 1]
618
619
"""
620
self._sign = ZZ(sign)
621
if self._sign != sign:
622
raise TypeError, 'sign must be an integer'
623
if self._sign != -1 and self._sign != 1:
624
raise TypeError, 'sign must -1 or 1'
625
self._E = E
626
self._use_eclib = False
627
self._normalize = normalize
628
self._modsym = E.modular_symbol_space(sign=self._sign)
629
self._base_ring = self._modsym.base_ring()
630
self._ambient_modsym = self._modsym.ambient_module()
631
632
if normalize == "L_ratio":
633
self._e = self._modsym.dual_eigenvector()
634
self._find_scaling_L_ratio()
635
if self._failed_to_scale:
636
self._find_scaling_period() # will reset _e and _scaling
637
else:
638
self._e *= self._scaling
639
elif normalize == "period" :
640
self._find_scaling_period() # this will set _e and _scaling
641
elif normalize == "none":
642
self._scaling = 1
643
self._e = self._modsym.dual_eigenvector()
644
else :
645
raise ValueError, "no normalization %s known for modular symbols"%normalize
646
647
648
def _find_scaling_period(self):
649
r"""
650
Uses the integral period map of the modular symbol implementation in sage
651
in order to determine the scaling. The resulting modular symbol is correct
652
only for the `X_0`-optimal curve, at least up to a possible factor +-1 or +-2.
653
654
EXAMPLES::
655
656
sage: E = EllipticCurve('11a1')
657
sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
658
sage: m._e
659
(1/5, 1)
660
sage: E = EllipticCurve('11a2')
661
sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
662
sage: m._e
663
(1, 5)
664
sage: E = EllipticCurve('121b2')
665
sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
666
sage: m._e
667
(0, 11/2, 0, 11/2, 11/2, 0, 0, -3, 2, 1/2, -1, 3/2)
668
669
"""
670
671
P = self._modsym.integral_period_mapping()
672
self._e = P.matrix().transpose().row(0)
673
self._e /= 2
674
E = self._E
675
try :
676
crla = parse_cremona_label(E.label())
677
except RuntimeError: # raised when curve is outside of the table
678
self._scaling = 1
679
else :
680
cr0 = Integer(crla[0]).str() + crla[1] + '1'
681
E0 = EllipticCurve(cr0)
682
q = E0.period_lattice().basis()[0]/E.period_lattice().basis()[0]
683
q = QQ(int(round(q*200)))/200
684
verbose('scale modular symbols by %s'%q)
685
self._scaling = q
686
self._e *= self._scaling
687
688
def _call_with_caching(self, r):
689
r"""
690
Evaluates the modular symbol at `r`, caching the computed value.
691
692
EXAMPLES::
693
694
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=False)
695
sage: m._call_with_caching(0)
696
1/5
697
"""
698
try:
699
return self.__cache[r]
700
except AttributeError:
701
self.__cache = {}
702
except KeyError:
703
pass
704
w = self._ambient_modsym([oo,r]).element()
705
c = (self._e).dot_product(w)
706
self.__cache[r] = c
707
return c
708
709
def __call__(self, r):
710
r"""
711
Evaluates the modular symbol at `r`.
712
713
EXAMPLES::
714
715
sage: m = EllipticCurve('11a1').modular_symbol(use_eclib=False)
716
sage: m(0)
717
1/5
718
719
"""
720
# this next line takes most of the time
721
w = self._ambient_modsym.modular_symbol([zero, oo, Cusps(r)], check=False)
722
723
return (self._e).dot_product(w.element())
724
725