Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/hecke/module.py
4048 views
1
"""
2
Hecke modules
3
"""
4
5
##########################################################################################
6
# Copyright (C) 2004,2005,2006 William Stein <[email protected]>
7
#
8
# Distributed under the terms of the GNU General Public License (GPL)
9
#
10
# This code is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
# General Public License for more details.
14
#
15
# The full text of the GPL is available at:
16
#
17
# http://www.gnu.org/licenses/
18
##########################################################################################
19
20
import sage.rings.all
21
import sage.rings.arith as arith
22
import sage.misc.misc as misc
23
import sage.modules.module
24
from sage.structure.all import Sequence
25
import sage.matrix.matrix_space as matrix_space
26
from sage.structure.parent_gens import ParentWithGens
27
from sage.structure.parent import Parent
28
29
import sage.misc.prandom as random
30
31
import algebra
32
import element
33
import hecke_operator
34
35
from sage.modules.all import FreeModule
36
37
def is_HeckeModule(x):
38
r"""
39
Return True if x is a Hecke module.
40
41
EXAMPLES::
42
43
sage: from sage.modular.hecke.module import is_HeckeModule
44
sage: is_HeckeModule(ModularForms(Gamma0(7), 4))
45
True
46
sage: is_HeckeModule(QQ^3)
47
False
48
sage: is_HeckeModule(J0(37).homology())
49
True
50
"""
51
return isinstance(x, HeckeModule_generic)
52
53
class HeckeModule_generic(sage.modules.module.Module_old):
54
r"""
55
A very general base class for Hecke modules.
56
57
We define a Hecke module of weight `k` to be a module over a commutative
58
ring equipped with an action of operators `T_m` for all positive integers `m`
59
coprime to some integer `n`(the level), which satisfy `T_r T_s = T_{rs}` for
60
`r,s` coprime, and for powers of a prime `p`, `T_{p^r} = T_{p} T_{p^{r-1}} -
61
\varepsilon(p) p^{k-1} T_{p^{r-2}}`, where `\varepsilon(p)` is some
62
endomorphism of the module which commutes with the `T_m`.
63
64
We distinguish between *full* Hecke modules, which also have an action of
65
operators `T_m` for `m` not assumed to be coprime to the level, and
66
*anemic* Hecke modules, for which this does not hold.
67
"""
68
def __init__(self, base_ring, level, category = None):
69
r"""
70
Create a Hecke module. Not intended to be called directly.
71
72
EXAMPLE::
73
74
sage: CuspForms(Gamma0(17),2) # indirect doctest
75
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(17) of weight 2 over Rational Field
76
sage: ModularForms(3, 3).category()
77
Category of Hecke modules over Rational Field
78
"""
79
if not sage.rings.all.is_CommutativeRing(base_ring):
80
raise TypeError, "base_ring must be commutative ring"
81
82
from sage.categories.hecke_modules import HeckeModules
83
default_category = HeckeModules(base_ring)
84
if category is None:
85
category = default_category
86
else:
87
assert category.is_subcategory(default_category), "%s is not a subcategory of %s"%(category, default_category)
88
89
ParentWithGens.__init__(self, base_ring, category = category)
90
91
level = sage.rings.all.ZZ(level)
92
if level <= 0:
93
raise ValueError, "level (=%s) must be positive"%level
94
self.__level = level
95
self._hecke_matrices = {}
96
self._diamond_matrices = {}
97
98
def __setstate__(self, state):
99
r"""
100
Ensure that the category is initialized correctly on unpickling.
101
102
EXAMPLE::
103
104
sage: loads(dumps(ModularSymbols(11))).category() # indirect doctest
105
Category of Hecke modules over Rational Field
106
"""
107
if not self._is_category_initialized():
108
from sage.categories.hecke_modules import HeckeModules
109
self._init_category_(HeckeModules(state['_base']))
110
sage.modules.module.Module_old.__setstate__(self, state)
111
112
def __hash__(self):
113
r"""
114
Return a hash value for self.
115
116
EXAMPLE::
117
118
sage: CuspForms(Gamma0(17),2).__hash__()
119
-1797992588 # 32-bit
120
-3789716081060032652 # 64-bit
121
"""
122
return hash((self.base_ring(), self.__level))
123
124
def __cmp__(self, other):
125
r"""
126
Compare self to other. This must be overridden in all subclasses.
127
128
EXAMPLE::
129
130
sage: M = ModularForms(Gamma0(3))
131
sage: sage.modular.hecke.module.HeckeModule_generic.__cmp__(M, M)
132
Traceback (most recent call last):
133
...
134
NotImplementedError: ...
135
"""
136
raise NotImplementedError, "Derived class %s should implement __cmp__" % type(self)
137
138
def _compute_hecke_matrix_prime_power(self, p, r, **kwds):
139
r"""
140
Compute the Hecke matrix T_{p^r}, where `p` is prime and `r \ge 2`, assuming that
141
`T_p` is known. This is carried out by recursion.
142
143
All derived classes must override either this function or ``self.character()``.
144
145
EXAMPLE::
146
147
sage: M = ModularForms(SL2Z, 24)
148
sage: M._compute_hecke_matrix_prime_power(3, 3)
149
[ 834385168339943471891603972970040 462582247568491031177169792000 3880421605193373124143717311013888000]
150
[ 0 -4112503986561480 53074162446443642880]
151
[ 0 2592937954080 -1312130996155080]
152
"""
153
# convert input arguments to int's.
154
(p,r) = (int(p), int(r))
155
if not arith.is_prime(p):
156
raise ArithmeticError, "p must be a prime"
157
# T_{p^r} := T_p * T_{p^{r-1}} - eps(p)p^{k-1} T_{p^{r-2}}.
158
pow = p**(r-1)
159
if not self._hecke_matrices.has_key(pow):
160
# The following will force computation of T_{p^s}
161
# for all s<=r-1, except possibly s=0.
162
self._hecke_matrices[pow] = self._compute_hecke_matrix(pow)
163
if not self._hecke_matrices.has_key(1):
164
self._hecke_matrices[1] = self._compute_hecke_matrix(1)
165
Tp = self._hecke_matrices[p]
166
Tpr1 = self._hecke_matrices[pow]
167
eps = self.character()
168
if eps is None:
169
raise NotImplementedError, "either character or _compute_hecke_matrix_prime_power must be overloaded in a derived class"
170
k = self.weight()
171
Tpr2 = self._hecke_matrices[pow/p]
172
return Tp*Tpr1 - eps(p)*(p**(k-1)) * Tpr2
173
174
def _compute_hecke_matrix_general_product(self, F, **kwds):
175
r"""
176
Compute the matrix of a general Hecke operator acting on this space, by
177
factorising n into prime powers and multiplying together the Hecke
178
operators for each of these.
179
180
EXAMPLE::
181
182
sage: M = ModularSymbols(Gamma0(3), 4)
183
sage: M._compute_hecke_matrix_general_product(factor(10))
184
[1134 0]
185
[ 0 1134]
186
"""
187
prod = None
188
for p, r in F:
189
pow = int(p**r)
190
if not self._hecke_matrices.has_key(pow):
191
self._hecke_matrices[pow] = self._compute_hecke_matrix(pow)
192
if prod is None:
193
prod = self._hecke_matrices[pow]
194
else:
195
prod *= self._hecke_matrices[pow]
196
return prod
197
198
def _compute_dual_hecke_matrix(self, n):
199
r"""
200
Compute the matrix of the Hecke operator `T_n` acting on the dual of self.
201
202
EXAMPLE::
203
204
sage: M = ModularSymbols(Gamma0(3), 4)
205
sage: M._compute_dual_hecke_matrix(10)
206
[1134 0]
207
[ 0 1134]
208
"""
209
return self.hecke_matrix(n).transpose()
210
211
def _compute_hecke_matrix(self, n, **kwds):
212
r"""
213
Compute the matrix of the Hecke operator `T_n` acting on self.
214
215
EXAMPLE::
216
217
sage: M = EisensteinForms(DirichletGroup(3).0, 3)
218
sage: M._compute_hecke_matrix(16)
219
[205 0]
220
[ 0 205]
221
"""
222
n = int(n)
223
if n<1:
224
raise ValueError, "Hecke operator T_%s is not defined."%n
225
if n==1:
226
Mat = matrix_space.MatrixSpace(self.base_ring(),self.rank())
227
return Mat(1)
228
229
if arith.is_prime(n):
230
return self._compute_hecke_matrix_prime(n, **kwds)
231
232
F = arith.factor(n)
233
if len(F) == 1: # nontrivial prime power case
234
return self._compute_hecke_matrix_prime_power(F[0][0],F[0][1], **kwds)
235
236
else:
237
return self._compute_hecke_matrix_general_product(F, **kwds)
238
239
def _compute_hecke_matrix_prime(self, p, **kwds):
240
"""
241
Compute and return the matrix of the p-th Hecke operator for p prime.
242
Derived classes should overload this function, and they will inherit
243
the machinery for calculating general Hecke operators.
244
245
EXAMPLE::
246
247
sage: M = EisensteinForms(DirichletGroup(3).0, 3)
248
sage: sage.modular.hecke.module.HeckeModule_generic._compute_hecke_matrix_prime(M, 3)
249
Traceback (most recent call last):
250
...
251
NotImplementedError: All subclasses must implement _compute_hecke_matrix_prime
252
"""
253
raise NotImplementedError, "All subclasses must implement _compute_hecke_matrix_prime"
254
255
def _compute_diamond_matrix(self, d):
256
r"""
257
Compute the matrix of the diamond bracket operator `\langle d \rangle` on this space,
258
in cases where this isn't self-evident (i.e. when this is not a space
259
with fixed character).
260
261
EXAMPLE::
262
263
sage: M = EisensteinForms(Gamma1(5), 3)
264
sage: sage.modular.hecke.module.HeckeModule_generic._compute_diamond_matrix(M, 2)
265
Traceback (most recent call last):
266
...
267
NotImplementedError: All subclasses without fixed character must implement _compute_diamond_matrix
268
"""
269
raise NotImplementedError, "All subclasses without fixed character must implement _compute_diamond_matrix"
270
271
def _hecke_operator_class(self):
272
"""
273
Return the class to be used for instantiating Hecke operators
274
acting on self.
275
276
EXAMPLES::
277
278
sage: sage.modular.hecke.module.HeckeModule_generic(QQ,1)._hecke_operator_class()
279
<class 'sage.modular.hecke.hecke_operator.HeckeOperator'>
280
sage: ModularSymbols(1,12)._hecke_operator_class()
281
<class 'sage.modular.modsym.hecke_operator.HeckeOperator'>
282
"""
283
return hecke_operator.HeckeOperator
284
285
def _diamond_operator_class(self):
286
r"""
287
Return the class to be used for instantiating diamond bracket operators
288
acting on self.
289
290
EXAMPLES::
291
292
sage: sage.modular.hecke.module.HeckeModule_generic(QQ,1)._diamond_operator_class()
293
<class 'sage.modular.hecke.hecke_operator.DiamondBracketOperator'>
294
sage: ModularSymbols(1,12)._diamond_operator_class()
295
<class 'sage.modular.hecke.hecke_operator.DiamondBracketOperator'>
296
"""
297
return hecke_operator.DiamondBracketOperator
298
299
def anemic_hecke_algebra(self):
300
"""
301
Return the Hecke algebra associated to this Hecke module.
302
303
EXAMPLES::
304
305
sage: T = ModularSymbols(1,12).hecke_algebra()
306
sage: A = ModularSymbols(1,12).anemic_hecke_algebra()
307
sage: T == A
308
False
309
sage: A
310
Anemic Hecke algebra acting on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
311
sage: A.is_anemic()
312
True
313
"""
314
try:
315
return self.__anemic_hecke_algebra
316
except AttributeError:
317
self.__anemic_hecke_algebra = algebra.AnemicHeckeAlgebra(self)
318
return self.__anemic_hecke_algebra
319
320
def character(self):
321
r"""
322
The character of this space. As this is an abstract base class, return None.
323
324
EXAMPLE::
325
326
sage: sage.modular.hecke.module.HeckeModule_generic(QQ, 10).character() is None
327
True
328
"""
329
return None
330
331
def dimension(self):
332
r"""
333
Synonym for rank.
334
335
EXAMPLE::
336
337
sage: M = sage.modular.hecke.module.HeckeModule_generic(QQ, 10).dimension()
338
Traceback (most recent call last):
339
...
340
NotImplementedError: Derived subclasses must implement rank
341
"""
342
return self.rank()
343
344
def hecke_algebra(self):
345
"""
346
Return the Hecke algebra associated to this Hecke module.
347
348
EXAMPLES::
349
350
sage: T = ModularSymbols(Gamma1(5),3).hecke_algebra()
351
sage: T
352
Full Hecke algebra acting on Modular Symbols space of dimension 4 for Gamma_1(5) of weight 3 with sign 0 and over Rational Field
353
sage: T.is_anemic()
354
False
355
356
::
357
358
sage: M = ModularSymbols(37,sign=1)
359
sage: E, A, B = M.decomposition()
360
sage: A.hecke_algebra() == B.hecke_algebra()
361
False
362
"""
363
try:
364
return self.__hecke_algebra
365
except AttributeError:
366
self.__hecke_algebra = algebra.HeckeAlgebra(self)
367
return self.__hecke_algebra
368
369
def is_zero(self):
370
"""
371
Return True if this Hecke module has dimension 0.
372
373
EXAMPLES::
374
375
sage: ModularSymbols(11).is_zero()
376
False
377
sage: ModularSymbols(11).old_submodule().is_zero()
378
True
379
sage: CuspForms(10).is_zero()
380
True
381
sage: CuspForms(1,12).is_zero()
382
False
383
"""
384
return self.dimension() == 0
385
386
def is_full_hecke_module(self):
387
"""
388
Return True if this space is invariant under all Hecke operators.
389
390
Since self is guaranteed to be an anemic Hecke module, the significance
391
of this function is that it also ensures invariance under Hecke
392
operators of index that divide the level.
393
394
EXAMPLES::
395
396
sage: M = ModularSymbols(22); M.is_full_hecke_module()
397
True
398
sage: M.submodule(M.free_module().span([M.0.list()]), check=False).is_full_hecke_module()
399
False
400
"""
401
try:
402
return self._is_full_hecke_module
403
except AttributeError:
404
pass
405
406
# now compute whether invariant under Hecke operators of index
407
# dividing the level
408
misc.verbose("Determining if Hecke module is full.")
409
N = self.level()
410
for p in arith.prime_divisors(N):
411
if not self.is_hecke_invariant(p):
412
self._is_full_hecke_module = False
413
return False
414
self._is_full_hecke_module = True
415
return True
416
417
def is_hecke_invariant(self, n):
418
"""
419
Return True if self is invariant under the Hecke operator
420
`T_n`.
421
422
Since self is guaranteed to be an anemic Hecke module it is only
423
interesting to call this function when `n` is not coprime
424
to the level.
425
426
EXAMPLES::
427
428
sage: M = ModularSymbols(22).cuspidal_subspace()
429
sage: M.is_hecke_invariant(2)
430
True
431
432
We use check=False to create a nasty "module" that is not invariant
433
under `T_2`::
434
435
sage: S = M.submodule(M.free_module().span([M.0.list()]), check=False); S
436
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
437
sage: S.is_hecke_invariant(2)
438
False
439
sage: [n for n in range(1,12) if S.is_hecke_invariant(n)]
440
[1, 3, 5, 7, 9, 11]
441
"""
442
if arith.gcd(n, self.level()) == 1:
443
return True
444
if self.is_ambient():
445
return True
446
try:
447
self.hecke_operator(n).matrix()
448
except ArithmeticError:
449
return False
450
return True
451
452
def level(self):
453
"""
454
Returns the level of this modular symbols space.
455
456
INPUT:
457
458
459
- ``ModularSymbols self`` - an arbitrary space of
460
modular symbols
461
462
463
OUTPUT:
464
465
466
- ``int`` - the level
467
468
469
EXAMPLES::
470
471
sage: m = ModularSymbols(20)
472
sage: m.level()
473
20
474
"""
475
return self.__level
476
477
def rank(self):
478
r"""
479
Return the rank of this module over its base ring. Returns
480
NotImplementedError, since this is an abstract base class.
481
482
EXAMPLES::
483
484
sage: sage.modular.hecke.module.HeckeModule_generic(QQ, 10).rank()
485
Traceback (most recent call last):
486
...
487
NotImplementedError: Derived subclasses must implement rank
488
"""
489
raise NotImplementedError, "Derived subclasses must implement rank"
490
491
def submodule(self, X):
492
r"""
493
Return the submodule of self corresponding to X. As this is an abstract
494
base class, this raises a NotImplementedError.
495
496
EXAMPLES::
497
498
sage: sage.modular.hecke.module.HeckeModule_generic(QQ, 10).submodule(0)
499
Traceback (most recent call last):
500
...
501
NotImplementedError: Derived subclasses should implement submodule
502
"""
503
raise NotImplementedError, "Derived subclasses should implement submodule"
504
505
506
class HeckeModule_free_module(HeckeModule_generic):
507
"""
508
A Hecke module modeled on a free module over a commutative ring.
509
"""
510
def __init__(self, base_ring, level, weight):
511
r"""
512
Initialise a module.
513
514
EXAMPLES::
515
516
sage: M = sage.modular.hecke.module.HeckeModule_free_module(QQ, 12, -4); M
517
<class 'sage.modular.hecke.module.HeckeModule_free_module_with_category'>
518
sage: TestSuite(M).run(skip = ["_test_additive_associativity", "_test_an_element", "_test_elements", "_test_elements_eq", "_test_pickling", "_test_some_elements", "_test_zero", "_test_eq"]) # is this supposed to be an abstract parent without elements?
519
"""
520
HeckeModule_generic.__init__(self, base_ring, level)
521
self.__weight = weight
522
523
# def __cmp__(self, other):
524
# if not isinstance(other, HeckeModule_free_module):
525
# return -1
526
# c = HeckeModule_generic.__cmp__(self, other)
527
# if c: return c
528
# return cmp(self.__weight, other.__weight)
529
530
# def __contains__(self, x):
531
# r"""
532
# Return True if x is an element of self.
533
#
534
# This shouldn't be getting called, ever (?)
535
# """
536
# if not element.is_HeckeModuleElement(x):
537
# return False
538
# if x.parent() == self: # easy case
539
# return True
540
# return x.element() in self.free_module()
541
542
def __getitem__(self, n):
543
r"""
544
Return the nth term in the decomposition of self. See the docstring for
545
``decomposition`` for further information.
546
547
EXAMPLES::
548
549
sage: ModularSymbols(22)[0]
550
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 7 for Gamma_0(22) of weight 2 with sign 0 over Rational Field
551
"""
552
n = int(n)
553
D = self.decomposition()
554
if n < 0 or n >= len(D):
555
raise IndexError, "index (=%s) must be between 0 and %s"%(n, len(D)-1)
556
return D[n]
557
558
def __hash__(self):
559
r"""
560
Return a hash of self.
561
562
EXAMPLES::
563
564
sage: ModularSymbols(22).__hash__()
565
1471905187 # 32-bit
566
-3789725500948382301 # 64-bit
567
"""
568
return hash((self.__weight, self.level(), self.base_ring()))
569
570
def __len__(self):
571
r"""
572
The number of factors in the decomposition of self.
573
574
EXAMPLES::
575
576
sage: len(ModularSymbols(22))
577
2
578
"""
579
return len(self.decomposition())
580
581
def _eigen_nonzero(self):
582
"""
583
Return smallest integer i such that the i-th entries of the entries
584
of a basis for the dual vector space are not all 0.
585
586
EXAMPLES::
587
588
sage: M = ModularSymbols(31,2)
589
sage: M._eigen_nonzero()
590
0
591
sage: M.dual_free_module().basis()
592
[
593
(1, 0, 0, 0, 0),
594
(0, 1, 0, 0, 0),
595
(0, 0, 1, 0, 0),
596
(0, 0, 0, 1, 0),
597
(0, 0, 0, 0, 1)
598
]
599
sage: M.cuspidal_submodule().minus_submodule()._eigen_nonzero()
600
1
601
sage: M.cuspidal_submodule().minus_submodule().dual_free_module().basis()
602
[
603
(0, 1, 0, 0, 0),
604
(0, 0, 1, 0, 0)
605
]
606
"""
607
try:
608
return self.__eigen_nonzero
609
except AttributeError:
610
pass
611
A = self.ambient_hecke_module()
612
V = self.dual_free_module()
613
B = V.basis()
614
for i in range(V.degree()):
615
for b in B:
616
if b[i] != 0:
617
self.__eigen_nonzero = i
618
return i
619
assert False, 'bug in _eigen_nonzero'
620
621
def _eigen_nonzero_element(self, n=1):
622
r"""
623
Return `T_n(x)` where `x` is a sparse modular
624
symbol such that the image of `x` is nonzero under the dual
625
projection map associated to this space, and `T_n` is the
626
`n^{th}` Hecke operator.
627
628
Used in the dual_eigenvector and eigenvalue methods.
629
630
EXAMPLES::
631
632
sage: ModularSymbols(22)._eigen_nonzero_element(3)
633
4*(1,0) + (2,21) - (11,1) + (11,2)
634
"""
635
if self.rank() == 0:
636
raise ArithmeticError, "the rank of self must be positive"
637
A = self.ambient_hecke_module()
638
i = self._eigen_nonzero()
639
return A._hecke_image_of_ith_basis_vector(n, i)
640
641
def _hecke_image_of_ith_basis_vector(self, n, i):
642
r"""
643
Return `T_n(e_i)`, where `e_i` is the
644
`i`th basis vector of the ambient space.
645
646
EXAMPLE::
647
648
sage: ModularSymbols(Gamma0(3))._hecke_image_of_ith_basis_vector(4, 0)
649
7*(1,0)
650
sage: ModularForms(Gamma0(3))._hecke_image_of_ith_basis_vector(4, 0)
651
7 + 84*q + 252*q^2 + 84*q^3 + 588*q^4 + 504*q^5 + O(q^6)
652
"""
653
T = self.hecke_operator(n)
654
return T.apply_sparse(self.gen(i))
655
656
def _element_eigenvalue(self, x, name='alpha'):
657
r"""
658
Return the dot product of self with the eigenvector returned by dual_eigenvector.
659
660
EXAMPLE::
661
662
sage: M = ModularSymbols(11)[0]
663
sage: M._element_eigenvalue(M.0)
664
1
665
"""
666
if not element.is_HeckeModuleElement(x):
667
raise TypeError, "x must be a Hecke module element."
668
if not x in self.ambient_hecke_module():
669
raise ArithmeticError, "x must be in the ambient Hecke module."
670
v = self.dual_eigenvector(names=name)
671
return v.dot_product(x.element())
672
673
def _is_hecke_equivariant_free_module(self, submodule):
674
"""
675
Returns True if the given free submodule of the ambient free module
676
is invariant under all Hecke operators.
677
678
EXAMPLES::
679
680
sage: M = ModularSymbols(11); V = M.free_module()
681
sage: M._is_hecke_equivariant_free_module(V.span([V.0]))
682
False
683
sage: M._is_hecke_equivariant_free_module(V)
684
True
685
sage: M._is_hecke_equivariant_free_module(M.cuspidal_submodule().free_module())
686
True
687
688
We do the same as above, but with a modular forms space::
689
690
sage: M = ModularForms(11); V = M.free_module()
691
sage: M._is_hecke_equivariant_free_module(V.span([V.0 + V.1]))
692
False
693
sage: M._is_hecke_equivariant_free_module(V)
694
True
695
sage: M._is_hecke_equivariant_free_module(M.cuspidal_submodule().free_module())
696
True
697
"""
698
misc.verbose("Determining if free module is Hecke equivariant.")
699
bound = self.hecke_bound()
700
for p in arith.primes(bound+1):
701
try:
702
self.T(p).matrix().restrict(submodule, check=True)
703
except ArithmeticError:
704
return False
705
return True
706
707
def _set_factor_number(self, i):
708
r"""
709
For internal use. If this Hecke module was computed via a decomposition of another
710
Hecke module, this method stores the index of this space in that decomposition.
711
712
EXAMPLE::
713
714
sage: ModularSymbols(Gamma0(3))[0].factor_number() # indirect doctest
715
0
716
"""
717
self.__factor_number = i
718
719
def ambient(self):
720
r"""
721
Synonym for ambient_hecke_module. Return the ambient module associated to this module.
722
723
EXAMPLE::
724
725
sage: CuspForms(1, 12).ambient()
726
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
727
"""
728
return self.ambient_hecke_module()
729
730
def ambient_module(self):
731
r"""
732
Synonym for ambient_hecke_module. Return the ambient module associated to this module.
733
734
EXAMPLE::
735
736
sage: CuspForms(1, 12).ambient_module()
737
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
738
sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 10, 3).ambient_module()
739
Traceback (most recent call last):
740
...
741
NotImplementedError
742
"""
743
return self.ambient_hecke_module()
744
745
def ambient_hecke_module(self):
746
r"""
747
Return the ambient module associated to this module. As this is an
748
abstract base class, return NotImplementedError.
749
750
EXAMPLE::
751
752
sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 10, 3).ambient_hecke_module()
753
Traceback (most recent call last):
754
...
755
NotImplementedError
756
"""
757
raise NotImplementedError
758
759
def atkin_lehner_operator(self, d=None):
760
"""
761
Return the Atkin-Lehner operator `W_d` on this space, if
762
defined, where `d` is a divisor of the level `N`
763
such that `N/d` and `d` are coprime.
764
765
EXAMPLES::
766
767
sage: M = ModularSymbols(11)
768
sage: w = M.atkin_lehner_operator()
769
sage: w
770
Hecke module morphism Atkin-Lehner operator W_11 defined by the matrix
771
[-1 0 0]
772
[ 0 -1 0]
773
[ 0 0 -1]
774
Domain: Modular Symbols space of dimension 3 for Gamma_0(11) of weight ...
775
Codomain: Modular Symbols space of dimension 3 for Gamma_0(11) of weight ...
776
sage: M = ModularSymbols(Gamma1(13))
777
sage: w = M.atkin_lehner_operator()
778
sage: w.fcp('x')
779
(x - 1)^7 * (x + 1)^8
780
781
::
782
783
sage: M = ModularSymbols(33)
784
sage: S = M.cuspidal_submodule()
785
sage: S.atkin_lehner_operator()
786
Hecke module morphism Atkin-Lehner operator W_33 defined by the matrix
787
[ 0 -1 0 1 -1 0]
788
[ 0 -1 0 0 0 0]
789
[ 0 -1 0 0 -1 1]
790
[ 1 -1 0 0 -1 0]
791
[ 0 0 0 0 -1 0]
792
[ 0 -1 1 0 -1 0]
793
Domain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
794
Codomain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
795
796
::
797
798
sage: S.atkin_lehner_operator(3)
799
Hecke module morphism Atkin-Lehner operator W_3 defined by the matrix
800
[ 0 1 0 -1 1 0]
801
[ 0 1 0 0 0 0]
802
[ 0 1 0 0 1 -1]
803
[-1 1 0 0 1 0]
804
[ 0 0 0 0 1 0]
805
[ 0 1 -1 0 1 0]
806
Domain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
807
Codomain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
808
809
::
810
811
sage: N = M.new_submodule()
812
sage: N.atkin_lehner_operator()
813
Hecke module morphism Atkin-Lehner operator W_33 defined by the matrix
814
[ 1 2/5 4/5]
815
[ 0 -1 0]
816
[ 0 0 -1]
817
Domain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
818
Codomain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
819
"""
820
if d is None:
821
d = self.level()
822
d = int(d)
823
if self.level() % d != 0:
824
raise ArithmeticError, "d (=%s) must be a divisor of the level (=%s)"%(d,self.level())
825
826
N = self.level()
827
for p, e in arith.factor(d):
828
v = arith.valuation(N, p)
829
if e < v:
830
d *= p**(v-e)
831
d = int(d)
832
try:
833
return self.__atkin_lehner_operator[d]
834
except AttributeError:
835
self.__atkin_lehner_operator = {}
836
except KeyError:
837
pass
838
Wmat = self._compute_atkin_lehner_matrix(d)
839
H = self.endomorphism_ring()
840
W = H(Wmat, "Atkin-Lehner operator W_%s"%d)
841
self.__atkin_lehner_operator[d] = W
842
return W
843
844
def basis(self):
845
"""
846
Returns a basis for self.
847
848
EXAMPLES::
849
850
sage: m = ModularSymbols(43)
851
sage: m.basis()
852
((1,0), (1,31), (1,32), (1,38), (1,39), (1,40), (1,41))
853
"""
854
try:
855
return self.__basis
856
except AttributeError:
857
self.__basis = self.gens()
858
return self.__basis
859
860
def basis_matrix(self):
861
r"""
862
Return the matrix of the basis vectors of self (as vectors in some
863
ambient module)
864
865
EXAMPLE::
866
867
sage: CuspForms(1, 12).basis_matrix()
868
[1 0]
869
"""
870
return self.free_module().basis_matrix()
871
872
def coordinate_vector(self, x):
873
"""
874
Write x as a vector with respect to the basis given by
875
self.basis().
876
877
EXAMPLES::
878
879
sage: S = ModularSymbols(11,2).cuspidal_submodule()
880
sage: S.0
881
(1,8)
882
sage: S.basis()
883
((1,8), (1,9))
884
sage: S.coordinate_vector(S.0)
885
(1, 0)
886
"""
887
return self.free_module().coordinate_vector(x.element())
888
889
def decomposition(self, bound=None, anemic=True, height_guess=1, sort_by_basis = False,
890
proof=None):
891
"""
892
Returns the maximal decomposition of this Hecke module under the
893
action of Hecke operators of index coprime to the level. This is
894
the finest decomposition of self that we can obtain using factors
895
obtained by taking kernels of Hecke operators.
896
897
Each factor in the decomposition is a Hecke submodule obtained as
898
the kernel of `f(T_n)^r` acting on self, where n is
899
coprime to the level and `r=1`. If anemic is False, instead
900
choose `r` so that `f(X)^r` exactly divides the
901
characteristic polynomial.
902
903
INPUT:
904
905
906
- ``anemic`` - bool (default: True), if True, use only
907
Hecke operators of index coprime to the level.
908
909
- ``bound`` - int or None, (default: None). If None,
910
use all Hecke operators up to the Sturm bound, and hence obtain the
911
same result as one would obtain by using every element of the Hecke
912
ring. If a fixed integer, decompose using only Hecke operators
913
`T_p`, with `p` prime, up to bound.
914
- ``sort_by_basis`` - bool (default: ``False``); If True the resulting
915
decomposition will be sorted as if it was free modules, ignoring the
916
Hecke module structure. This will save a lot of time.
917
918
919
OUTPUT:
920
921
922
- ``list`` - a list of subspaces of self.
923
924
925
EXAMPLES::
926
927
sage: ModularSymbols(17,2).decomposition()
928
[
929
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 3 for Gamma_0(17) of weight 2 with sign 0 over Rational Field,
930
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(17) of weight 2 with sign 0 over Rational Field
931
]
932
sage: ModularSymbols(Gamma1(10),4).decomposition()
933
[
934
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 18 for Gamma_1(10) of weight 4 with sign 0 and over Rational Field,
935
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 18 for Gamma_1(10) of weight 4 with sign 0 and over Rational Field,
936
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 18 for Gamma_1(10) of weight 4 with sign 0 and over Rational Field,
937
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 18 for Gamma_1(10) of weight 4 with sign 0 and over Rational Field,
938
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 18 for Gamma_1(10) of weight 4 with sign 0 and over Rational Field,
939
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 18 for Gamma_1(10) of weight 4 with sign 0 and over Rational Field
940
]
941
sage: ModularSymbols(GammaH(12, [11])).decomposition()
942
[
943
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(12) with H generated by [11] of weight 2 with sign 0 and over Rational Field,
944
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(12) with H generated by [11] of weight 2 with sign 0 and over Rational Field,
945
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(12) with H generated by [11] of weight 2 with sign 0 and over Rational Field,
946
Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(12) with H generated by [11] of weight 2 with sign 0 and over Rational Field,
947
Modular Symbols subspace of dimension 5 of Modular Symbols space of dimension 9 for Congruence Subgroup Gamma_H(12) with H generated by [11] of weight 2 with sign 0 and over Rational Field
948
]
949
950
TESTS::
951
sage: M = ModularSymbols(1000,2,sign=1).new_subspace().cuspidal_subspace()
952
sage: M.decomposition(3, sort_by_basis = True)
953
[
954
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 154 for Gamma_0(1000) of weight 2 with sign 1 over Rational Field,
955
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 154 for Gamma_0(1000) of weight 2 with sign 1 over Rational Field,
956
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 154 for Gamma_0(1000) of weight 2 with sign 1 over Rational Field,
957
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 154 for Gamma_0(1000) of weight 2 with sign 1 over Rational Field,
958
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 154 for Gamma_0(1000) of weight 2 with sign 1 over Rational Field,
959
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 154 for Gamma_0(1000) of weight 2 with sign 1 over Rational Field
960
]
961
"""
962
if not isinstance(anemic, bool):
963
raise TypeError, "anemic must be of type bool."
964
965
key = (bound, anemic)
966
967
try:
968
if self.__decomposition[key] != None:
969
return self.__decomposition[key]
970
except AttributeError:
971
self.__decomposition = {}
972
except KeyError:
973
pass
974
if self.rank() == 0:
975
self.__decomposition[key] = Sequence([], immutable=True, cr=True)
976
return self.__decomposition[key]
977
978
is_rational = self.base_ring() == sage.rings.all.QQ
979
980
time = misc.verbose("Decomposing %s"%self)
981
T = self.ambient_hecke_module().hecke_algebra()
982
if bound is None:
983
bound = self.ambient_hecke_module().hecke_bound()
984
D = Sequence([], cr=True)
985
U = [self.free_module()]
986
p = 2
987
while len(U) > 0 and p <= bound:
988
misc.verbose(mesg="p=%s"%p,t=time)
989
if anemic:
990
while arith.GCD(p, self.level()) != 1:
991
p = arith.next_prime(p)
992
misc.verbose("Decomposition using p=%s"%p)
993
t = T.hecke_operator(p).matrix()
994
Uprime = []
995
for i in range(len(U)):
996
if self.base_ring().characteristic() == 0 and self.level()%p != 0:
997
is_diagonalizable = True
998
else:
999
is_diagonalizable = False
1000
if is_rational:
1001
X = t.decomposition_of_subspace(U[i], check_restrict = False,
1002
algorithm='multimodular',
1003
height_guess=height_guess, proof=proof)
1004
else:
1005
X = t.decomposition_of_subspace(U[i], check_restrict = False,
1006
is_diagonalizable=is_diagonalizable)
1007
for i in range(len(X)):
1008
W, is_irred = X[i]
1009
if is_irred:
1010
A = self.submodule(W, check=False)
1011
D.append(A)
1012
else:
1013
Uprime.append(W)
1014
# end for
1015
p = arith.next_prime(p)
1016
U = Uprime
1017
#end while
1018
for i in range(len(U)):
1019
A = self.submodule(U[i], check=False)
1020
D.append(A)
1021
for A in D:
1022
if anemic:
1023
A.__is_splittable_anemic = False
1024
A.__is_splittable = False
1025
else:
1026
A.__is_splittable = False
1027
self.__is_splittable = len(D) > 1
1028
if anemic:
1029
self.__is_splittable_anemic = len(D) > 1
1030
1031
D.sort(key = None if not sort_by_basis else lambda ss: ss.free_module())
1032
D.set_immutable()
1033
self.__decomposition[key] = D
1034
for i in range(len(D)):
1035
self.__decomposition[key][i]._set_factor_number(i)
1036
return self.__decomposition[key]
1037
1038
def degree(self):
1039
r"""
1040
The degree of this Hecke module (i.e. the rank of the ambient free
1041
module)
1042
1043
EXAMPLE::
1044
1045
sage: CuspForms(1, 12).degree()
1046
2
1047
"""
1048
return self.free_module().degree()
1049
1050
def dual_eigenvector(self, names='alpha', lift=True, nz=None):
1051
"""
1052
Return an eigenvector for the Hecke operators acting on the linear
1053
dual of this space. This eigenvector will have entries in an
1054
extension of the base ring of degree equal to the dimension of this
1055
space.
1056
1057
.. warning:
1058
1059
The input space must be simple.
1060
1061
INPUT:
1062
1063
1064
- ``name`` - print name of generator for eigenvalue
1065
field.
1066
1067
- ``lift`` - bool (default: True)
1068
1069
- ``nz`` - if not None, then normalize vector so dot
1070
product with this basis vector of ambient space is 1.
1071
1072
1073
OUTPUT: A vector with entries possibly in an extension of the base
1074
ring. This vector is an eigenvector for all Hecke operators acting
1075
via their transpose.
1076
1077
If lift = False, instead return an eigenvector in the subspace for
1078
the Hecke operators on the dual space. I.e., this is an eigenvector
1079
for the restrictions of Hecke operators to the dual space.
1080
1081
.. note::
1082
1083
#. The answer is cached so subsequent calls always return
1084
the same vector. However, the algorithm is randomized,
1085
so calls during another session may yield a different
1086
eigenvector. This function is used mainly for computing
1087
systems of Hecke eigenvalues.
1088
1089
#. One can also view a dual eigenvector as defining (via
1090
dot product) a functional phi from the ambient space of
1091
modular symbols to a field. This functional phi is an
1092
eigenvector for the dual action of Hecke operators on
1093
functionals.
1094
1095
EXAMPLE::
1096
1097
sage: ModularSymbols(14).cuspidal_subspace().simple_factors()[1].dual_eigenvector()
1098
(0, 1, 0, 0, 0)
1099
"""
1100
# TODO -- optimize by computing the answer for i not None in terms
1101
# of the answer for a given i if known !!
1102
try:
1103
w, w_lift = self.__dual_eigenvector[(names,nz)]
1104
if lift:
1105
return w_lift
1106
else:
1107
return w
1108
except KeyError:
1109
pass
1110
except AttributeError:
1111
self.__dual_eigenvector = {}
1112
1113
if not self.is_simple():
1114
raise ArithmeticError, "self must be simple"
1115
1116
# Find a Hecke operator that acts irreducibly on this space:
1117
p = 2
1118
t = self.dual_hecke_matrix(p)
1119
while True:
1120
f = t.charpoly('x')
1121
if f.is_irreducible():
1122
break
1123
p = arith.next_prime(p)
1124
t += random.choice([-2,-1,1,2]) * self.dual_hecke_matrix(p)
1125
1126
# Write down the eigenvector.
1127
# Write f(x) = (x-alpha)*g(x), where alpha is a root
1128
# of f(x).
1129
n = f.degree()
1130
if n > 1:
1131
R = f.parent()
1132
K = R.base_ring().extension(f, names=names)
1133
alpha = K.gen()
1134
beta = ~alpha # multiplicative inverse of alpha
1135
c = [-f[0]*beta]
1136
for i in range(1,n-1):
1137
c.append((c[i-1] - f[i])*beta)
1138
c.append( K(1) )
1139
else:
1140
K = self.base_ring()
1141
c = [1]
1142
1143
# The entries of c are the coefficients of g (as stated in
1144
# William Stein's Ph.D. thesis, Section 3.5.3). We compute
1145
# g(t)v for a some vector v, and get an eigenvector.
1146
V = FreeModule(K, n)
1147
t = t.change_ring(K) # coerce t to be over K.
1148
for j in range(n):
1149
v = V.gen(j)
1150
I = t.iterates(v, n) # iterates v, v*t, v*t^2, ...
1151
w = V(0)
1152
for i in range(n):
1153
w += c[i]*V(I.row(i).list())
1154
if w != 0:
1155
break
1156
1157
# Now w is an eigenvector for the action of the Hecke
1158
# operators on the subspace. We need an eigenvector
1159
# in the original space, so we take the linear combination
1160
# of the basis for the embedded dual vector space given
1161
# by the entries of w.
1162
Vdual = self.dual_free_module().change_ring(K)
1163
w_lift = Vdual.linear_combination_of_basis(w)
1164
1165
# Finally rescale so the dot product of this vector and
1166
# the _eigen_nonzero_element is 1.
1167
if nz is not None:
1168
x = self.ambient().gen(nz)
1169
else:
1170
x = self._eigen_nonzero_element()
1171
alpha = w_lift.dot_product(x.element())
1172
beta = ~alpha
1173
w_lift = w_lift * beta
1174
w = w * beta
1175
1176
self.__dual_eigenvector[(names,nz)] = (w, w_lift)
1177
if lift:
1178
return w_lift
1179
else:
1180
return w
1181
1182
def dual_hecke_matrix(self, n):
1183
"""
1184
The matrix of the `n^{th}` Hecke operator acting on the dual
1185
embedded representation of self.
1186
1187
EXAMPLE::
1188
1189
sage: CuspForms(1, 24).dual_hecke_matrix(5)
1190
[ 79345647584250/2796203 50530996976060416/763363419]
1191
[ 195556757760000/2796203 124970165346810/2796203]
1192
"""
1193
n = int(n)
1194
try:
1195
self._dual_hecke_matrices
1196
except AttributeError:
1197
self._dual_hecke_matrices = {}
1198
if not self._dual_hecke_matrices.has_key(n):
1199
T = self._compute_dual_hecke_matrix(n)
1200
self._dual_hecke_matrices[n] = T
1201
return self._dual_hecke_matrices[n]
1202
1203
def eigenvalue(self, n, name='alpha'):
1204
"""
1205
Assuming that self is a simple space, return the eigenvalue of the
1206
`n^{th}` Hecke operator on self.
1207
1208
INPUT:
1209
1210
1211
- ``n`` - index of Hecke operator
1212
1213
- ``name`` - print representation of generator of
1214
eigenvalue field
1215
1216
1217
EXAMPLES::
1218
1219
sage: A = ModularSymbols(125,sign=1).new_subspace()[0]
1220
sage: A.eigenvalue(7)
1221
-3
1222
sage: A.eigenvalue(3)
1223
-alpha - 2
1224
sage: A.eigenvalue(3,'w')
1225
-w - 2
1226
sage: A.eigenvalue(3,'z').charpoly('x')
1227
x^2 + 3*x + 1
1228
sage: A.hecke_polynomial(3)
1229
x^2 + 3*x + 1
1230
1231
::
1232
1233
sage: M = ModularSymbols(Gamma1(17)).decomposition()[8].plus_submodule()
1234
sage: M.eigenvalue(2,'a')
1235
a
1236
sage: M.eigenvalue(4,'a')
1237
4/3*a^3 + 17/3*a^2 + 28/3*a + 8/3
1238
1239
.. note::
1240
1241
#. In fact there are `d` systems of eigenvalues
1242
associated to self, where `d` is the rank of
1243
self. Each of the systems of eigenvalues is conjugate
1244
over the base field. This function chooses one of the
1245
systems and consistently returns eigenvalues from that
1246
system. Thus these are the coefficients `a_n` for
1247
`n\geq 1` of a modular eigenform attached to self.
1248
1249
#. This function works even for Eisenstein subspaces,
1250
though it will not give the constant coefficient of one
1251
of the corresponding Eisenstein series (i.e., the
1252
generalized Bernoulli number).
1253
"""
1254
if not self.is_simple():
1255
raise ArithmeticError, "self must be simple"
1256
n = int(n)
1257
try:
1258
return self.__eigenvalues[n][name]
1259
except AttributeError:
1260
self.__eigenvalues = {}
1261
except KeyError:
1262
pass
1263
if n <= 0:
1264
raise IndexError, "n must be a positive integer"
1265
1266
ev = self.__eigenvalues
1267
1268
if (arith.is_prime(n) or n==1):
1269
Tn_e = self._eigen_nonzero_element(n)
1270
an = self._element_eigenvalue(Tn_e, name=name)
1271
_dict_set(ev, n, name, an)
1272
return an
1273
1274
# Now use the Hecke eigenvalue recurrence, since arithmetic in
1275
# a field is faster than computing Heilbronn matrices for
1276
# non-prime n and doing some big sum (i.e., computing T_n(e)).
1277
# Also by computing using the recurrence on eigenvalues
1278
# we use information about divisors.
1279
F = arith.factor(n)
1280
prod = None
1281
for p, r in F:
1282
(p, r) = (int(p), int(r))
1283
pow = p**r
1284
if not (ev.has_key(pow) and ev[pow].has_key(name)):
1285
# TODO: Optimization -- do something much more
1286
# intelligent in case character is not defined. For
1287
# example, compute it using the diamond operators <d>
1288
eps = self.character()
1289
if eps is None:
1290
Tn_e = self._eigen_nonzero_element(pow)
1291
_dict_set(ev, pow, name, self._element_eigenvalue(Tn_e, name=name))
1292
else:
1293
# a_{p^r} := a_p * a_{p^{r-1}} - eps(p)p^{k-1} a_{p^{r-2}}
1294
apr1 = self.eigenvalue(pow//p, name=name)
1295
ap = self.eigenvalue(p, name=name)
1296
k = self.weight()
1297
apr2 = self.eigenvalue(pow//(p*p), name=name)
1298
apow = ap*apr1 - eps(p)*(p**(k-1)) * apr2
1299
_dict_set(ev, pow, name, apow)
1300
if prod is None:
1301
prod = ev[pow][name]
1302
else:
1303
prod *= ev[pow][name]
1304
_dict_set(ev, n, name, prod)
1305
return prod
1306
1307
def factor_number(self):
1308
"""
1309
If this Hecke module was computed via a decomposition of another
1310
Hecke module, this is the corresponding number. Otherwise return
1311
-1.
1312
1313
EXAMPLES::
1314
1315
sage: ModularSymbols(23)[0].factor_number()
1316
0
1317
sage: ModularSymbols(23).factor_number()
1318
-1
1319
"""
1320
try:
1321
return self.__factor_number
1322
except AttributeError:
1323
return -1
1324
1325
def gen(self, n):
1326
r"""
1327
Return the nth basis vector of the space.
1328
1329
EXAMPLE::
1330
1331
sage: ModularSymbols(23).gen(1)
1332
(1,17)
1333
"""
1334
return self(self.free_module().gen(n))
1335
1336
def hecke_matrix(self, n):
1337
"""
1338
The matrix of the `n^{th}` Hecke operator acting on given
1339
basis.
1340
1341
EXAMPLE::
1342
1343
sage: C = CuspForms(1, 16)
1344
sage: C.hecke_matrix(3)
1345
[-3348]
1346
"""
1347
n = int(n)
1348
if n <= 0:
1349
raise IndexError, "n must be positive."
1350
if not self._hecke_matrices.has_key(n):
1351
T = self._compute_hecke_matrix(n)
1352
T.set_immutable()
1353
self._hecke_matrices[n] = T
1354
return self._hecke_matrices[n]
1355
1356
def hecke_operator(self, n):
1357
"""
1358
Returns the `n`-th Hecke operator `T_n`.
1359
1360
INPUT:
1361
1362
1363
- ``ModularSymbols self`` - Hecke equivariant space of
1364
modular symbols
1365
1366
- ``int n`` - an integer at least 1.
1367
1368
1369
EXAMPLES::
1370
1371
sage: M = ModularSymbols(11,2)
1372
sage: T = M.hecke_operator(3) ; T
1373
Hecke operator T_3 on Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
1374
sage: T.matrix()
1375
[ 4 0 -1]
1376
[ 0 -1 0]
1377
[ 0 0 -1]
1378
sage: T(M.0)
1379
4*(1,0) - (1,9)
1380
sage: S = M.cuspidal_submodule()
1381
sage: T = S.hecke_operator(3) ; T
1382
Hecke operator T_3 on Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
1383
sage: T.matrix()
1384
[-1 0]
1385
[ 0 -1]
1386
sage: T(S.0)
1387
-(1,8)
1388
"""
1389
return self.hecke_algebra().hecke_operator(n)
1390
1391
def diamond_bracket_matrix(self, d):
1392
r"""
1393
Return the matrix of the diamond bracket operator `\langle d \rangle` on self.
1394
1395
EXAMPLES::
1396
1397
sage: M = ModularSymbols(DirichletGroup(5).0, 3)
1398
sage: M.diamond_bracket_matrix(3)
1399
[-zeta4 0]
1400
[ 0 -zeta4]
1401
sage: ModularSymbols(Gamma1(5), 3).diamond_bracket_matrix(3)
1402
[ 0 -1 0 0]
1403
[ 1 0 0 0]
1404
[ 0 0 0 1]
1405
[ 0 0 -1 0]
1406
"""
1407
d = int(d) % self.level()
1408
if not self._diamond_matrices.has_key(d):
1409
if self.character() is not None:
1410
D = matrix_space.MatrixSpace(self.base_ring(),self.rank())(self.character()(d))
1411
else:
1412
D = self._compute_diamond_matrix(d)
1413
D.set_immutable()
1414
self._diamond_matrices[d] = D
1415
return self._diamond_matrices[d]
1416
1417
def diamond_bracket_operator(self, d):
1418
r"""
1419
Return the diamond bracket operator `\langle d \rangle` on self.
1420
1421
EXAMPLES::
1422
1423
sage: M = ModularSymbols(DirichletGroup(5).0, 3)
1424
sage: M.diamond_bracket_operator(3)
1425
Diamond bracket operator <3> on Modular Symbols space of dimension 2 and level 5, weight 3, character [zeta4], sign 0, over Cyclotomic Field of order 4 and degree 2
1426
"""
1427
return self.hecke_algebra().diamond_bracket_operator(d)
1428
1429
def T(self, n):
1430
r"""
1431
Returns the `n^{th}` Hecke operator `T_n`. This
1432
function is a synonym for :meth:`.hecke_operator`.
1433
1434
EXAMPLE::
1435
1436
sage: M = ModularSymbols(11,2)
1437
sage: M.T(3)
1438
Hecke operator T_3 on Modular Symbols ...
1439
"""
1440
return self.hecke_operator(n)
1441
1442
def hecke_polynomial(self, n, var='x'):
1443
"""
1444
Return the characteristic polynomial of the `n^{th}` Hecke operator
1445
acting on this space.
1446
1447
INPUT:
1448
1449
1450
- ``n`` - integer
1451
1452
1453
OUTPUT: a polynomial
1454
1455
EXAMPLE::
1456
1457
sage: ModularSymbols(11,2).hecke_polynomial(3)
1458
x^3 - 2*x^2 - 7*x - 4
1459
"""
1460
return self.hecke_operator(n).charpoly(var)
1461
1462
def is_simple(self):
1463
r"""
1464
Return True if this space is simple as a module for the corresponding
1465
Hecke algebra. Raises NotImplementedError, as this is an abstract base
1466
class.
1467
1468
EXAMPLE::
1469
1470
sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 10, 3).is_simple()
1471
Traceback (most recent call last):
1472
...
1473
NotImplementedError
1474
"""
1475
raise NotImplementedError
1476
1477
def is_splittable(self):
1478
"""
1479
Returns True if and only if only it is possible to split off a
1480
nontrivial generalized eigenspace of self as the kernel of some Hecke
1481
operator (not necessarily prime to the level). Note that the direct sum
1482
of several copies of the same simple module is not splittable in this
1483
sense.
1484
1485
EXAMPLE::
1486
1487
sage: M = ModularSymbols(Gamma0(64)).cuspidal_subspace()
1488
sage: M.is_splittable()
1489
True
1490
sage: M.simple_factors()[0].is_splittable()
1491
False
1492
"""
1493
if not hasattr(self, "__is_splittable"):
1494
self.decomposition(anemic=False)
1495
return self.__is_splittable
1496
1497
def is_submodule(self, other):
1498
r"""
1499
Return True if self is a submodule of other.
1500
1501
EXAMPLES::
1502
1503
sage: M = ModularSymbols(Gamma0(64))
1504
sage: M[0].is_submodule(M)
1505
True
1506
sage: CuspForms(1, 24).is_submodule(ModularForms(1, 24))
1507
True
1508
sage: CuspForms(1, 12).is_submodule(CuspForms(3, 12))
1509
False
1510
"""
1511
if not isinstance(other, HeckeModule_free_module):
1512
return False
1513
return self.ambient_free_module() == other.ambient_free_module() and \
1514
self.free_module().is_submodule(other.free_module())
1515
1516
def is_splittable_anemic(self):
1517
"""
1518
Returns true if and only if only it is possible to split off a
1519
nontrivial generalized eigenspace of self as the kernel of some
1520
Hecke operator of index coprime to the level. Note that the direct sum
1521
of several copies of the same simple module is not splittable in this
1522
sense.
1523
1524
EXAMPLE::
1525
1526
sage: M = ModularSymbols(Gamma0(64)).cuspidal_subspace()
1527
sage: M.is_splittable_anemic()
1528
True
1529
sage: M.simple_factors()[0].is_splittable_anemic()
1530
False
1531
"""
1532
if not hasattr(self,"__is_splittable_anemic"):
1533
self.decomposition(anemic=True)
1534
return self.__is_splittable_anemic
1535
1536
def ngens(self):
1537
r"""
1538
Number of generators of self (equal to the rank).
1539
1540
EXAMPLE::
1541
1542
sage: ModularForms(1, 12).ngens()
1543
2
1544
"""
1545
return self.rank()
1546
1547
def projection(self):
1548
r"""
1549
Return the projection map from the ambient space to self.
1550
1551
ALGORITHM: Let `B` be the matrix whose columns are obtained
1552
by concatenating together a basis for the factors of the ambient
1553
space. Then the projection matrix onto self is the submatrix of
1554
`B^{-1}` obtained from the rows corresponding to self,
1555
i.e., if the basis vectors for self appear as columns `n`
1556
through `m` of `B`, then the projection matrix is
1557
got from rows `n` through `m` of `B^{-1}`.
1558
This is because projection with respect to the B basis is just
1559
given by an `m-n+1` row slice `P` of a diagonal
1560
matrix D with 1's in the `n` through `m` positions,
1561
so projection with respect to the standard basis is given by
1562
`P\cdot B^{-1}`, which is just rows `n`
1563
through `m` of `B^{-1}`.
1564
1565
EXAMPLES::
1566
1567
sage: e = EllipticCurve('34a')
1568
sage: m = ModularSymbols(34); s = m.cuspidal_submodule()
1569
sage: d = s.decomposition(7)
1570
sage: d
1571
[
1572
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(34) of weight 2 with sign 0 over Rational Field,
1573
Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 9 for Gamma_0(34) of weight 2 with sign 0 over Rational Field
1574
]
1575
sage: a = d[0]; a
1576
Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(34) of weight 2 with sign 0 over Rational Field
1577
sage: pi = a.projection()
1578
sage: pi(m([0,oo]))
1579
-1/6*(2,7) + 1/6*(2,13) - 1/6*(2,31) + 1/6*(2,33)
1580
sage: M = ModularSymbols(53,sign=1)
1581
sage: S = M.cuspidal_subspace()[1] ; S
1582
Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 5 for Gamma_0(53) of weight 2 with sign 1 over Rational Field
1583
sage: p = S.projection()
1584
sage: S.basis()
1585
((1,33) - (1,37), (1,35), (1,49))
1586
sage: [ p(x) for x in S.basis() ]
1587
[(1,33) - (1,37), (1,35), (1,49)]
1588
"""
1589
1590
# Compute the Hecke-stable projection map pi from the ambient
1591
# space of M to M. Computing the projection map is the same
1592
# as writing the ambient space as a direct sum of M and its
1593
# Hecke-stable complement, which is the old subspace plus the
1594
# other new factors, then *inverting*. With the projection
1595
# map in hand, we can compute Hecke operators directly on M
1596
# fairly quickly without having to compute them on the whole
1597
# ambient space. Of course, computing this inverse is way too
1598
# much work to be useful in general (!). (I sort of learned
1599
# this trick from Joe Wetherell, or at least he was aware of
1600
# it when I mentioned it to him in an airport once. It's also
1601
# sort of like a trick Cremona uses in his book for elliptic
1602
# curves.) It's not a very good trick though.
1603
1604
try:
1605
return self.__projection
1606
except AttributeError:
1607
i = self.factor_number()
1608
if i == -1:
1609
raise NotImplementedError,\
1610
"Computation of projection only implemented "+\
1611
"for decomposition factors."
1612
A = self.ambient_hecke_module()
1613
B = A.decomposition_matrix_inverse()
1614
i = (A.decomposition()).index(self)
1615
n = sum([A[j].rank() for j in range(i)])
1616
C = B.matrix_from_columns(range(n,n+self.rank()))
1617
H = A.Hom(self)
1618
pi = H(C, "Projection"%self)
1619
self.__projection = pi
1620
return self.__projection
1621
1622
1623
1624
def system_of_eigenvalues(self, n, name='alpha'):
1625
r"""
1626
Assuming that self is a simple space of modular symbols, return the
1627
eigenvalues `[a_1, \ldots, a_nmax]` of the Hecke
1628
operators on self. See ``self.eigenvalue(n)`` for more
1629
details.
1630
1631
INPUT:
1632
1633
1634
- ``n`` - number of eigenvalues
1635
1636
- ``alpha`` - name of generate for eigenvalue field
1637
1638
1639
EXAMPLES: These computations use pseudo-random numbers, so we set
1640
the seed for reproducible testing.
1641
1642
::
1643
1644
sage: set_random_seed(0)
1645
1646
The computations also use cached results from other computations,
1647
so we clear the caches for reproducible testing.
1648
1649
::
1650
1651
sage: ModularSymbols_clear_cache()
1652
1653
We compute eigenvalues for newforms of level 62.
1654
1655
::
1656
1657
sage: M = ModularSymbols(62,2,sign=-1)
1658
sage: S = M.cuspidal_submodule().new_submodule()
1659
sage: [A.system_of_eigenvalues(3) for A in S.decomposition()]
1660
[[1, 1, 0], [1, -1, 1/2*alpha + 1/2]]
1661
1662
Next we define a function that does the above::
1663
1664
sage: def b(N,k=2):
1665
... t=cputime()
1666
... S = ModularSymbols(N,k,sign=-1).cuspidal_submodule().new_submodule()
1667
... for A in S.decomposition():
1668
... print N, A.system_of_eigenvalues(5)
1669
1670
::
1671
1672
sage: b(63)
1673
63 [1, 1, 0, -1, 2]
1674
63 [1, alpha, 0, 1, -2*alpha]
1675
1676
This example illustrates finding field over which the eigenvalues
1677
are defined::
1678
1679
sage: M = ModularSymbols(23,2,sign=1).cuspidal_submodule().new_submodule()
1680
sage: v = M.system_of_eigenvalues(10); v
1681
[1, alpha, -2*alpha - 1, -alpha - 1, 2*alpha, alpha - 2, 2*alpha + 2, -2*alpha - 1, 2, -2*alpha + 2]
1682
sage: v[0].parent()
1683
Number Field in alpha with defining polynomial x^2 + x - 1
1684
1685
This example illustrates setting the print name of the eigenvalue
1686
field.
1687
1688
::
1689
1690
sage: A = ModularSymbols(125,sign=1).new_subspace()[0]
1691
sage: A.system_of_eigenvalues(10)
1692
[1, alpha, -alpha - 2, -alpha - 1, 0, -alpha - 1, -3, -2*alpha - 1, 3*alpha + 2, 0]
1693
sage: A.system_of_eigenvalues(10,'x')
1694
[1, x, -x - 2, -x - 1, 0, -x - 1, -3, -2*x - 1, 3*x + 2, 0]
1695
"""
1696
return [self.eigenvalue(m, name=name) for m in range(1,n+1)]
1697
1698
def weight(self):
1699
"""
1700
Returns the weight of this Hecke module.
1701
1702
INPUT:
1703
1704
1705
- ``self`` - an arbitrary Hecke module
1706
1707
1708
OUTPUT:
1709
1710
1711
- ``int`` - the weight
1712
1713
1714
EXAMPLES::
1715
1716
sage: m = ModularSymbols(20, weight=2)
1717
sage: m.weight()
1718
2
1719
"""
1720
return self.__weight
1721
1722
def zero_submodule(self):
1723
"""
1724
Return the zero submodule of self.
1725
1726
EXAMPLES::
1727
1728
sage: ModularSymbols(11,4).zero_submodule()
1729
Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 6 for Gamma_0(11) of weight 4 with sign 0 over Rational Field
1730
sage: CuspForms(11,4).zero_submodule()
1731
Modular Forms subspace of dimension 0 of Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field
1732
"""
1733
return self.submodule(self.free_module().zero_submodule(), check=False)
1734
1735
def _dict_set(v, n, key, val):
1736
r"""
1737
Rough-and-ready implementation of a two-layer-deep dictionary.
1738
1739
EXAMPLE::
1740
1741
sage: from sage.modular.hecke.module import _dict_set
1742
sage: v = {}
1743
sage: _dict_set(v, 1, 2, 3)
1744
sage: v
1745
{1: {2: 3}}
1746
sage: _dict_set(v, 1, 3, 4); v
1747
{1: {2: 3, 3: 4}}
1748
"""
1749
if v.has_key(n):
1750
v[n][key] = val
1751
else:
1752
v[n] = {key:val}
1753
1754
1755