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