Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/modform/constructor.py
4045 views
1
# -*- coding: utf-8 -*-
2
"""
3
Creating Spaces of Modular Forms
4
5
EXAMPLES::
6
7
sage: m = ModularForms(Gamma1(4),11)
8
sage: m
9
Modular Forms space of dimension 6 for Congruence Subgroup Gamma1(4) of weight 11 over Rational Field
10
sage: m.basis()
11
[
12
q - 134*q^5 + O(q^6),
13
q^2 + 80*q^5 + O(q^6),
14
q^3 + 16*q^5 + O(q^6),
15
q^4 - 4*q^5 + O(q^6),
16
1 + 4092/50521*q^2 + 472384/50521*q^3 + 4194300/50521*q^4 + O(q^6),
17
q + 1024*q^2 + 59048*q^3 + 1048576*q^4 + 9765626*q^5 + O(q^6)
18
]
19
20
"""
21
22
#########################################################################
23
# Copyright (C) 2004--2006 William Stein <[email protected]>
24
#
25
# Distributed under the terms of the GNU General Public License (GPL)
26
#
27
# http://www.gnu.org/licenses/
28
#########################################################################
29
30
import weakref
31
import re
32
33
import sage.modular.arithgroup.all as arithgroup
34
import sage.modular.dirichlet as dirichlet
35
import sage.rings.all as rings
36
37
import ambient_eps
38
import ambient_g0
39
import ambient_g1
40
import ambient_R
41
import defaults
42
43
44
def canonical_parameters(group, level, weight, base_ring):
45
"""
46
Given a group, level, weight, and base_ring as input by the user,
47
return a canonicalized version of them, where level is a Sage
48
integer, group really is a group, weight is a Sage integer, and
49
base_ring a Sage ring. Note that we can't just get the level from
50
the group, because we have the convention that the character for
51
Gamma1(N) is None (which makes good sense).
52
53
INPUT:
54
55
56
- ``group`` - int, long, Sage integer, group,
57
dirichlet character, or
58
59
- ``level`` - int, long, Sage integer, or group
60
61
- ``weight`` - coercible to Sage integer
62
63
- ``base_ring`` - commutative Sage ring
64
65
66
OUTPUT:
67
68
69
- ``level`` - Sage integer
70
71
- ``group`` - congruence subgroup
72
73
- ``weight`` - Sage integer
74
75
- ``ring`` - commutative Sage ring
76
77
78
EXAMPLES::
79
80
sage: from sage.modular.modform.constructor import canonical_parameters
81
sage: v = canonical_parameters(5, 5, int(7), ZZ); v
82
(5, Congruence Subgroup Gamma0(5), 7, Integer Ring)
83
sage: type(v[0]), type(v[1]), type(v[2]), type(v[3])
84
(<type 'sage.rings.integer.Integer'>,
85
<class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class_with_category'>,
86
<type 'sage.rings.integer.Integer'>,
87
<type 'sage.rings.integer_ring.IntegerRing_class'>)
88
sage: canonical_parameters( 5, 7, 7, ZZ )
89
Traceback (most recent call last):
90
...
91
ValueError: group and level do not match.
92
"""
93
weight = rings.Integer(weight)
94
if weight <= 0:
95
raise NotImplementedError, "weight must be at least 1"
96
97
if isinstance(group, dirichlet.DirichletCharacter):
98
if ( group.level() != rings.Integer(level) ):
99
raise ValueError, "group.level() and level do not match."
100
group = group.minimize_base_ring()
101
level = rings.Integer(level)
102
103
elif arithgroup.is_CongruenceSubgroup(group):
104
if ( rings.Integer(level) != group.level() ):
105
raise ValueError, "group.level() and level do not match."
106
# normalize the case of SL2Z
107
if arithgroup.is_SL2Z(group) or \
108
arithgroup.is_Gamma1(group) and group.level() == rings.Integer(1):
109
group = arithgroup.Gamma0(rings.Integer(1))
110
111
elif group is None:
112
pass
113
114
else:
115
try:
116
m = rings.Integer(group)
117
except TypeError:
118
raise TypeError, "group of unknown type."
119
level = rings.Integer(level)
120
if ( m != level ):
121
raise ValueError, "group and level do not match."
122
group = arithgroup.Gamma0(m)
123
124
if not rings.is_CommutativeRing(base_ring):
125
raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring
126
127
# it is *very* important to include the level as part of the data
128
# that defines the key, since dirichlet characters of different
129
# levels can compare equal, but define much different modular
130
# forms spaces.
131
return level, group, weight, base_ring
132
133
_cache = {}
134
135
def ModularForms_clear_cache():
136
"""
137
Clear the cache of modular forms.
138
139
EXAMPLES::
140
141
sage: M = ModularForms(37,2)
142
sage: sage.modular.modform.constructor._cache == {}
143
False
144
145
::
146
147
sage: sage.modular.modform.constructor.ModularForms_clear_cache()
148
sage: sage.modular.modform.constructor._cache
149
{}
150
"""
151
global _cache
152
_cache = {}
153
154
def ModularForms(group = 1,
155
weight = 2,
156
base_ring = None,
157
use_cache = True,
158
prec = defaults.DEFAULT_PRECISION):
159
r"""
160
Create an ambient space of modular forms.
161
162
INPUT:
163
164
165
- ``group`` - A congruence subgroup or a Dirichlet
166
character eps.
167
168
- ``weight`` - int, the weight, which must be an
169
integer = 1.
170
171
- ``base_ring`` - the base ring (ignored if group is
172
a Dirichlet character)
173
174
175
Create using the command ModularForms(group, weight, base_ring)
176
where group could be either a congruence subgroup or a Dirichlet
177
character.
178
179
EXAMPLES: First we create some spaces with trivial character::
180
181
sage: ModularForms(Gamma0(11),2).dimension()
182
2
183
sage: ModularForms(Gamma0(1),12).dimension()
184
2
185
186
If we give an integer N for the congruence subgroup, it defaults to
187
`\Gamma_0(N)`::
188
189
sage: ModularForms(1,12).dimension()
190
2
191
sage: ModularForms(11,4)
192
Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field
193
194
We create some spaces for `\Gamma_1(N)`.
195
196
::
197
198
sage: ModularForms(Gamma1(13),2)
199
Modular Forms space of dimension 13 for Congruence Subgroup Gamma1(13) of weight 2 over Rational Field
200
sage: ModularForms(Gamma1(13),2).dimension()
201
13
202
sage: [ModularForms(Gamma1(7),k).dimension() for k in [2,3,4,5]]
203
[5, 7, 9, 11]
204
sage: ModularForms(Gamma1(5),11).dimension()
205
12
206
207
We create a space with character::
208
209
sage: e = (DirichletGroup(13).0)^2
210
sage: e.order()
211
6
212
sage: M = ModularForms(e, 2); M
213
Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
214
sage: f = M.T(2).charpoly('x'); f
215
x^3 + (-2*zeta6 - 2)*x^2 - 2*zeta6*x + 14*zeta6 - 7
216
sage: f.factor()
217
(x - 2*zeta6 - 1) * (x - zeta6 - 2) * (x + zeta6 + 1)
218
219
We can also create spaces corresponding to the groups `\Gamma_H(N)` intermediate
220
between `\Gamma_0(N)` and `\Gamma_1(N)`::
221
222
sage: G = GammaH(30, [11])
223
sage: M = ModularForms(G, 2); M
224
Modular Forms space of dimension 20 for Congruence Subgroup Gamma_H(30) with H generated by [11] of weight 2 over Rational Field
225
sage: M.T(7).charpoly().factor() # long time (7s on sage.math, 2011)
226
(x + 4) * x^2 * (x - 6)^4 * (x + 6)^4 * (x - 8)^7 * (x^2 + 4)
227
228
More examples of spaces with character::
229
230
sage: e = DirichletGroup(5, RationalField()).gen(); e
231
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1
232
233
sage: m = ModularForms(e, 2); m
234
Modular Forms space of dimension 2, character [-1] and weight 2 over Rational Field
235
sage: m == loads(dumps(m))
236
True
237
sage: m.T(2).charpoly('x')
238
x^2 - 1
239
sage: m = ModularForms(e, 6); m.dimension()
240
4
241
sage: m.T(2).charpoly('x')
242
x^4 - 917*x^2 - 42284
243
244
This came up in a subtle bug (trac #5923)::
245
246
sage: ModularForms(gp(1), gap(12))
247
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
248
249
This came up in another bug (related to trac #8630)::
250
251
sage: chi = DirichletGroup(109, CyclotomicField(3)).0
252
sage: ModularForms(chi, 2, base_ring = CyclotomicField(15))
253
Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 15 and degree 8
254
255
We create some weight 1 spaces. The first example works fine, since we can prove purely by Riemann surface theory that there are no weight 1 cusp forms::
256
257
sage: M = ModularForms(Gamma1(11), 1); M
258
Modular Forms space of dimension 5 for Congruence Subgroup Gamma1(11) of weight 1 over Rational Field
259
sage: M.basis()
260
[
261
1 + 22*q^5 + O(q^6),
262
q + 4*q^5 + O(q^6),
263
q^2 - 4*q^5 + O(q^6),
264
q^3 - 5*q^5 + O(q^6),
265
q^4 - 3*q^5 + O(q^6)
266
]
267
sage: M.cuspidal_subspace().basis()
268
[
269
]
270
sage: M == M.eisenstein_subspace()
271
True
272
273
This example doesn't work so well, because we can't calculate the cusp
274
forms; but we can still work with the Eisenstein series.
275
276
sage: M = ModularForms(Gamma1(57), 1); M
277
Modular Forms space of dimension (unknown) for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
278
sage: M.basis()
279
Traceback (most recent call last):
280
...
281
NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general
282
sage: M.cuspidal_subspace().basis()
283
Traceback (most recent call last):
284
...
285
NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general
286
287
sage: E = M.eisenstein_subspace(); E
288
Eisenstein subspace of dimension 36 of Modular Forms space of dimension (unknown) for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
289
sage: (E.0 + E.2).q_expansion(40)
290
1 + q^2 + 1473/2*q^36 - 1101/2*q^37 + q^38 - 373/2*q^39 + O(q^40)
291
292
"""
293
if isinstance(group, dirichlet.DirichletCharacter):
294
if base_ring is None:
295
base_ring = group.minimize_base_ring().base_ring()
296
if base_ring is None:
297
base_ring = rings.QQ
298
299
if isinstance(group, dirichlet.DirichletCharacter) \
300
or arithgroup.is_CongruenceSubgroup(group):
301
level = group.level()
302
else:
303
level = group
304
305
key = canonical_parameters(group, level, weight, base_ring)
306
307
if use_cache and _cache.has_key(key):
308
M = _cache[key]()
309
if not (M is None):
310
M.set_precision(prec)
311
return M
312
313
(level, group, weight, base_ring) = key
314
315
M = None
316
if arithgroup.is_Gamma0(group):
317
M = ambient_g0.ModularFormsAmbient_g0_Q(group.level(), weight)
318
if base_ring != rings.QQ:
319
M = ambient_R.ModularFormsAmbient_R(M, base_ring)
320
321
elif arithgroup.is_Gamma1(group):
322
M = ambient_g1.ModularFormsAmbient_g1_Q(group.level(), weight)
323
if base_ring != rings.QQ:
324
M = ambient_R.ModularFormsAmbient_R(M, base_ring)
325
326
elif arithgroup.is_GammaH(group):
327
M = ambient_g1.ModularFormsAmbient_gH_Q(group, weight)
328
if base_ring != rings.QQ:
329
M = ambient_R.ModularFormsAmbient_R(M, base_ring)
330
331
elif isinstance(group, dirichlet.DirichletCharacter):
332
eps = group
333
if eps.base_ring().characteristic() != 0:
334
# TODO -- implement this
335
# Need to add a lift_to_char_0 function for characters,
336
# and need to still remember eps.
337
raise NotImplementedError, "currently the character must be over a ring of characteristic 0."
338
eps = eps.minimize_base_ring()
339
if eps.is_trivial():
340
return ModularForms(eps.modulus(), weight, base_ring,
341
use_cache = use_cache,
342
prec = prec)
343
M = ambient_eps.ModularFormsAmbient_eps(eps, weight)
344
if base_ring != eps.base_ring():
345
M = M.base_extend(base_ring) # ambient_R.ModularFormsAmbient_R(M, base_ring)
346
347
if M is None:
348
raise NotImplementedError, \
349
"computation of requested space of modular forms not defined or implemented"
350
351
M.set_precision(prec)
352
_cache[key] = weakref.ref(M)
353
return M
354
355
356
def CuspForms(group = 1,
357
weight = 2,
358
base_ring = None,
359
use_cache = True,
360
prec = defaults.DEFAULT_PRECISION):
361
"""
362
Create a space of cuspidal modular forms.
363
364
See the documentation for the ModularForms command for a
365
description of the input parameters.
366
367
EXAMPLES::
368
369
sage: CuspForms(11,2)
370
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
371
"""
372
return ModularForms(group, weight, base_ring,
373
use_cache=use_cache, prec=prec).cuspidal_submodule()
374
375
376
def EisensteinForms(group = 1,
377
weight = 2,
378
base_ring = None,
379
use_cache = True,
380
prec = defaults.DEFAULT_PRECISION):
381
"""
382
Create a space of eisenstein modular forms.
383
384
See the documentation for the ModularForms command for a
385
description of the input parameters.
386
387
EXAMPLES::
388
389
sage: EisensteinForms(11,2)
390
Eisenstein subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(11) of weight 2 over Rational Field
391
"""
392
return ModularForms(group, weight, base_ring,
393
use_cache=use_cache, prec=prec).eisenstein_submodule()
394
395
396
397
def Newforms(group, weight=2, base_ring=None, names=None):
398
r"""
399
Returns a list of the newforms of the given weight and level (or weight,
400
level and character). These are calculated as
401
`\operatorname{Gal}(\overline{F} / F)`-orbits, where `F` is the given base
402
field.
403
404
INPUT:
405
406
407
- ``group`` - the congruence subgroup of the newform, or a Nebentypus
408
character
409
410
- ``weight`` - the weight of the newform (default 2)
411
412
- ``base_ring`` - the base ring (defaults to `\QQ` for spaces without
413
character, or the base ring of the character otherwise)
414
415
- ``names`` - if the newform has coefficients in a
416
number field, a generator name must be specified
417
418
419
EXAMPLES::
420
421
sage: Newforms(11, 2)
422
[q - 2*q^2 - q^3 + 2*q^4 + q^5 + O(q^6)]
423
sage: Newforms(65, names='a')
424
[q - q^2 - 2*q^3 - q^4 - q^5 + O(q^6),
425
q + a1*q^2 + (a1 + 1)*q^3 + (-2*a1 - 1)*q^4 + q^5 + O(q^6),
426
q + a2*q^2 + (-a2 + 1)*q^3 + q^4 - q^5 + O(q^6)]
427
428
A more complicated example involving both a nontrivial character, and a
429
base field that is not minimal for that character::
430
431
sage: K.<i> = QuadraticField(-1)
432
sage: chi = DirichletGroup(5, K).gen(0)
433
sage: len(Newforms(chi, 7, names='a'))
434
1
435
sage: x = polygen(K); L.<c> = K.extension(x^2 - 402*i)
436
sage: N = Newforms(chi, 7, base_ring = L); len(N)
437
2
438
sage: sorted([N[0][2], N[1][2]]) == sorted([1/2*c - 5/2*i - 5/2, -1/2*c - 5/2*i - 5/2])
439
True
440
441
We test that #8630 is fixed::
442
443
sage: chi = DirichletGroup(109, CyclotomicField(3)).0
444
sage: CuspForms(chi, 2, base_ring = CyclotomicField(9))
445
Cuspidal subspace of dimension 8 of Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 9 and degree 6
446
"""
447
return CuspForms(group, weight, base_ring).newforms(names)
448
449
450
def Newform(identifier, group=None, weight=2, base_ring=rings.QQ, names=None):
451
"""
452
INPUT:
453
454
455
- ``identifier`` - a canonical label, or the index of
456
the specific newform desired
457
458
- ``group`` - the congruence subgroup of the newform
459
460
- ``weight`` - the weight of the newform (default 2)
461
462
- ``base_ring`` - the base ring
463
464
- ``names`` - if the newform has coefficients in a
465
number field, a generator name must be specified
466
467
468
EXAMPLES::
469
470
sage: Newform('67a', names='a')
471
q + 2*q^2 - 2*q^3 + 2*q^4 + 2*q^5 + O(q^6)
472
sage: Newform('67b', names='a')
473
q + a1*q^2 + (-a1 - 3)*q^3 + (-3*a1 - 3)*q^4 - 3*q^5 + O(q^6)
474
"""
475
if isinstance(group, str) and names is None:
476
names = group
477
if isinstance(identifier, str):
478
group, identifier = parse_label(identifier)
479
if weight != 2:
480
raise ValueError, "Canonical label not implemented for higher weight forms."
481
elif base_ring != rings.QQ:
482
raise ValueError, "Canonical label not implemented except for over Q."
483
elif group is None:
484
raise ValueError, "Must specify a group or a label."
485
return Newforms(group, weight, base_ring, names=names)[identifier]
486
487
488
def parse_label(s):
489
"""
490
Given a string s corresponding to a newform label, return the
491
corresponding group and index.
492
493
EXAMPLES::
494
495
sage: sage.modular.modform.constructor.parse_label('11a')
496
(Congruence Subgroup Gamma0(11), 0)
497
sage: sage.modular.modform.constructor.parse_label('11aG1')
498
(Congruence Subgroup Gamma1(11), 0)
499
sage: sage.modular.modform.constructor.parse_label('11wG1')
500
(Congruence Subgroup Gamma1(11), 22)
501
"""
502
m = re.match(r'(\d+)([a-z]+)((?:G.*)?)$', s)
503
if not m:
504
raise ValueError, "Invalid label: %s" % s
505
N, order, G = m.groups()
506
N = int(N)
507
index = 0
508
for c in reversed(order):
509
index = 26*index + ord(c)-ord('a')
510
if G == '' or G == 'G0':
511
G = arithgroup.Gamma0(N)
512
elif G == 'G1':
513
G = arithgroup.Gamma1(N)
514
elif G[:2] == 'GH':
515
if G[2] != '[' or G[-1] != ']':
516
raise ValueError, "Invalid congruence subgroup label: %s" % G
517
gens = [int(g.strip()) for g in G[3:-1].split(',')]
518
return arithgroup.GammaH(N, gens)
519
else:
520
raise ValueError, "Invalid congruence subgroup label: %s" % G
521
return G, index
522
523
524
525