Modular Forms and Hecke Operators
=================================
Congruence subgroups
--------------------
Definition
~~~~~~~~~~
A congruence subgroup is a subgroup of the group
:math:`\mathrm{SL}_2(\ZZ)` of determinant :math:`\pm 1` integer
matrices that contains
.. math::
\Gamma(N) = \mathrm{Ker}(\mathrm{SL}_2(\ZZ) \to \mathrm{SL}_2(\ZZ/N\ZZ))
for some positive integer :math:`N`. Since :math:`\Gamma(N)` has
finite index in :math:`\mathrm{SL}_2(\ZZ)`, all congruence subgroups
have finite index. The converse is not true, though in many other
settings it is true (see [paper of Serre]).
The inverse image :math:`\Gamma_0(N)` of the subgroup of upper
triangular matrices in :math:`\mathrm{SL}_2(\ZZ/N\ZZ)`
is a congruence subgroup, as is the inverse image :math:`\Gamma_1(N)`
of the subgroup of matrices of the form
:math:`\left(\begin{smallmatrix}1&*\\0&1\end{smallmatrix}\right)`. Also,
for any subgroup :math:`H\subset (\ZZ/N\ZZ)^*`, the
inverse image :math:`\Gamma_H(N)` of the subgroup of
:math:`\mathrm{SL}_2(\ZZ/N\ZZ)` of all elements of the
form :math:`\left(\begin{smallmatrix}a&*\\0&d\end{smallmatrix}\right)`
with :math:`d \in H` is a congruence subgroup.
We can create each of the above congruence subgroups in Sage, using
the Gamma0, Gamma1, and GammaH commands.
::
sage: Gamma0(8)
Congruence Subgroup Gamma0(8)
sage: Gamma1(13)
Congruence Subgroup Gamma1(13)
sage: GammaH(11,[4])
Congruence Subgroup Gamma_H(11) with H generated by [4]
The second argument to the GammaH command is a list of generators of
the subgroup :math:`H` of :math:`(\ZZ/N\ZZ)^*`.
Generators
~~~~~~~~~~
Sage can compute a list of generators for these subgroups. The
algorithm Sage uses is a straightforward generic procedure that uses
coset representatives for the congruence subgroup (which are easy to
enumerate) to obtain a list of generators [[ref my modular forms
book]].
The list of generators Sage computes is unfortunately large. Improving this
would be an excellent Sage development project, which would involve much
beautiful mathematics.
UPDATE (March 2012): The project referred to above has been carried out (by
several people, notably Hartmut Monien, building on earlier work of Chris
Kurth). Sage now uses a much more advanced algorithm based on Farey symbols
which calculates a *minimal* set of generators.
::
sage: Gamma0(2).gens()
(
[1 1] [ 1 -1]
[0 1], [ 2 -1]
)
sage: Gamma0(2).gens(algorithm="todd-coxeter") # the old implementation
(
[1 1] [-1 0] [ 1 -1] [ 1 -1] [-1 1]
[0 1], [ 0 -1], [ 0 1], [ 2 -1], [-2 1]
)
sage: len(Gamma1(13).gens())
15
Modular Forms
-------------
Definition
~~~~~~~~~~
A modular form on a congruence subgroup
:math:`\Gamma` of integer weight :math:`k` is a holomorphic
function :math:`f(z)` on the upper half plane
.. math::
\mathfrak{h}^* = \{z \in \CC : \Im(z) > 0\}\cup \QQ \cup\{i\infty\}
such that for every matrix
:math:`\left(\begin{smallmatrix}a&b\\c&d\end{smallmatrix}\right)\in\Gamma`,
we have
.. _modform:
.. math::
f\left(\frac{az+b}{cz+d}\right) = (cz+d)^{k} f(z).
A cusp form is a modular form that vanishes at all of the cusps
:math:`\QQ \cup \{i\infty\}`.
If :math:`\Gamma` contains :math:`\Gamma_1(N)` for some :math:`N`,
then
:math:`\left(\begin{smallmatrix}1&1\\0&1\end{smallmatrix}\right)\in\Gamma`,
so :ref:`the modular form condition ` implies that :math:`f(z) = f(z+1)`. This, coupled
with the holomorphicity condition, implies that :math:`f(z)` has a
Fourier expansion
.. math::
f(z) = \sum_{n=0}^{\infty} a_n e^{2\pi i n z}
with :math:`a_n\in\CC`. We let :math:`q = e^{2\pi i z}`, and
call :math:`f = \sum_{n=0}^{\infty} a_n q^n` the :math:`q`-expansion
of :math:`f`.
Creation in Sage
~~~~~~~~~~~~~~~~
Henceforth we assume that
:math:`\Gamma` is either :math:`\Gamma_1(N)`,
:math:`\Gamma_0(N)`, or :math:`\Gamma_H(N)` for some
:math:`H` and :math:`N`. The complex vector space
:math:`M_k(\Gamma)` of all modular forms of weight :math:`k`
on :math:`\Gamma` is a finite dimensional vector space.
We create the space :math:`M_k(\Gamma)` in Sage by typing
``ModularForms(G, k)`` where :math:`G` is the congruence subgroup
and :math:`k` is the weight.
::
sage: ModularForms(Gamma0(25), 4)
Modular Forms space of dimension 11 for ...
sage: S = CuspForms(Gamma0(25),4, prec=15); S
Cuspidal subspace of dimension 5 of Modular Forms space ...
sage: S.basis()
[
q + q^9 - 8*q^11 - 8*q^14 + O(q^15),
q^2 - q^7 - q^8 - 7*q^12 + 7*q^13 + O(q^15),
q^3 + q^7 - 2*q^8 - 6*q^12 - 5*q^13 + O(q^15),
q^4 - q^6 - 3*q^9 + 5*q^11 - 2*q^14 + O(q^15),
q^5 - 4*q^10 + O(q^15)
]
Dimension Formulas
~~~~~~~~~~~~~~~~~~
Sage computes the dimensions of all these spaces using simple
arithmetic formulas instead of actually computing bases for the spaces
in question. In fact, Sage has the most general collection of modular
forms dimension formulas of any software; type ``help(sage.modular.dims)``
to see a list of arithmetic functions that are used to implement these
dimension formulas.
::
sage: ModularForms(Gamma1(949284), 456).dimension()
11156973844800
sage: a = [dimension_cusp_forms(Gamma0(N),2) for N in [1..25]]; a
[0, 0, ..., 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 2, 2, 1, 0]
sage: oeis(a) # optional - internet
0: A001617: Genus of modular group GAMMA_0 (n). Or, genus of modular curve X_0(n).
Sage doesn't have simple formulas for dimensions of spaces of
modular forms of weight :math:`1`, since such formulas perhaps do
not exist.
Diamond Bracket Operators
~~~~~~~~~~~~~~~~~~~~~~~~~
The space
:math:`M_k(\Gamma_1(N))` is equipped with an action of
:math:`(\ZZ/N\ZZ)^*` by diamond bracket operators
:math:`\langle d \rangle`, and this induces a decomposition
.. math::
M_k(\Gamma_1(N)) = \bigoplus_{\varepsilon:(\ZZ/N\ZZ)^* \to \CC^*} M_k(N,\varepsilon),
where the sum is over all complex characters of the
finite abelian group :math:`(\ZZ/N\ZZ)^*`. These
characters are called Dirichlet characters, which are central in
number theory.
The factors :math:`M_k(N,\varepsilon)` then have bases whose
:math:`q`-expansions are elements of :math:`R[[q]]`, where
:math:`R = \ZZ[\varepsilon]` is the ring generated over
:math:`\ZZ` by the image of :math:`\varepsilon`. We illustrate
this with :math:`N=k=5` below, where DirichletGroup will be
described later.
::
sage: CuspForms(DirichletGroup(5).0, 5).basis()
[
q + (-zeta4 - 1)*q^2 + (6*zeta4 - 6)*q^3 - ... + O(q^6)
]
Dirichlet Characters
~~~~~~~~~~~~~~~~~~~~
Use the command DirichletGroup(N,R) to create the group of all
Dirichlet characters of modulus :math:`N` taking values in the
ring :math:`R`. If :math:`R` is omitted, it defaults to a
cyclotomic field.
::
sage: G = DirichletGroup(8); G
Group of Dirichlet characters of modulus 8 over Cyclotomic
Field of order 2 and degree 1
sage: v = G.list(); v
[Dirichlet character modulo 8 of conductor 1 mapping 7 |--> 1, 5 |--> 1,
Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1,
Dirichlet character modulo 8 of conductor 8 mapping 7 |--> 1, 5 |--> -1,
Dirichlet character modulo 8 of conductor 8 mapping 7 |--> -1, 5 |--> -1]
sage: eps = G.0; eps
Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1
sage: eps.values()
[0, 1, 0, -1, 0, 1, 0, -1]
Sage both represents Dirichlet characters by giving a "matrix",
i.e., the list of images of canonical generators of
:math:`(\ZZ/N\ZZ)^*`, and as vectors modulo and
integer :math:`n`. For years, I was torn between these two
representations, until J. Quer and I realized that the best
approach is to use both and make it easy to convert between them.
.. link
::
sage: parent(eps.element())
Vector space of dimension 2 over Ring of integers modulo 2
Given a Dirichlet character, Sage also lets you compute the
associated Jacobi and Gauss sums, generalized Bernoulli numbers,
the conductor, Galois orbit, etc.
Decomposing :math:`M_k(\Gamma_1(N))`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Recall that
Dirichlet characters give a decomposition
.. math::
M_k(\Gamma_1(N)) = \bigoplus_{\varepsilon:(\ZZ/N\ZZ)^* \to \CC^*} M_k(N,\varepsilon).
Given a Dirichlet character :math:`\varepsilon` we type
ModularForms(eps, weight) to create the space of modular forms with
that character and a given integer weight. For example, we create
the space of forms of weight :math:`5` with the character modulo
:math:`8` above that is :math:`-1` on :math:`3` and
:math:`1` on :math:`5` as follows.
.. link
::
sage: ModularForms(eps,5)
Modular Forms space of dimension 6, character [-1, 1] and
weight 5 over Rational Field
sage: sum([ModularForms(eps,5).dimension() for eps in v])
11
sage: ModularForms(Gamma1(8),5)
Modular Forms space of dimension 11 ...
.. note::
Exercise: Compute the dimensions of all spaces :math:`M_2(37,\varepsilon)`
for all Dirichlet characters :math:`\varepsilon`.
Hecke Operators
~~~~~~~~~~~~~~~
The space :math:`M_k(\Gamma)`
is equipped with an action of a commuting ring :math:`\mathbb{T}` of
Hecke operators :math:`T_n` for :math:`n\geq 1`. A standard
computational problem in the theory of modular forms is to compute
an explicit basis of :math:`q`-expansion for
:math:`M_k(\Gamma)` along with matrices for the action of any
Hecke operator :math:`T_n`, and to compute the subspace
:math:`S_k(\Gamma)` of cusp forms.
::
sage: M = ModularForms(Gamma0(11),4)
sage: M.basis()
[
q + 3*q^3 - 6*q^4 - 7*q^5 + O(q^6),
q^2 - 4*q^3 + 2*q^4 + 8*q^5 + O(q^6),
1 + O(q^6),
q + 9*q^2 + 28*q^3 + 73*q^4 + 126*q^5 + O(q^6)
]
sage: M.hecke_matrix(2)
[0 2 0 0]
[1 2 0 0]
[0 0 9 0]
[0 0 0 9]
We can also compute Hecke operators on the cuspidal subspace.
.. link
::
sage: S = M.cuspidal_subspace()
sage: S.hecke_matrix(2)
[0 2]
[1 2]
sage: S.hecke_matrix(3)
[ 3 -8]
[-4 -5]
Hecke Operator on :math:`M_k(\Gamma_1(N))`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At the time these lectures were first written, Sage didn't yet implement
computation of the Hecke operators on :math:`M_k(\Gamma_1(N))`, but these have
subsequently been added:
::
sage: M = ModularForms(Gamma1(5),2)
sage: M
Modular Forms space of dimension 3 for Congruence Subgroup
Gamma1(5) of weight 2 over Rational Field
sage: M.hecke_matrix(2)
[ -21 0 -240]
[ -2 0 -23]
[ 2 1 24]
These are calculated by first calculating Hecke operators on modular symbols
for :math:`\Gamma_1(N)`, which is a :math:`\mathbb{T}`-module that is
isomorphic to :math:`M_k(\Gamma_1(N))` (see :ref:`sec-modsym`).
::
sage: ModularSymbols(Gamma1(5),2,sign=1).hecke_matrix(2)
[ 2 1 1]
[ 1 2 -1]
[ 0 0 -1]