"""
Hecke modules
"""
import sage.rings.all
import sage.rings.arith as arith
import sage.misc.misc as misc
import sage.modules.module
from sage.structure.all import Sequence
import sage.matrix.matrix_space as matrix_space
from sage.structure.parent_gens import ParentWithGens
from sage.structure.parent import Parent
import sage.misc.prandom as random
import algebra
import element
import hecke_operator
from sage.modules.all import FreeModule
def is_HeckeModule(x):
r"""
Return True if x is a Hecke module.
EXAMPLES::
sage: from sage.modular.hecke.module import is_HeckeModule
sage: is_HeckeModule(ModularForms(Gamma0(7), 4))
True
sage: is_HeckeModule(QQ^3)
False
sage: is_HeckeModule(J0(37).homology())
True
"""
return isinstance(x, HeckeModule_generic)
class HeckeModule_generic(sage.modules.module.Module_old):
r"""
A very general base class for Hecke modules.
We define a Hecke module of weight `k` to be a module over a commutative
ring equipped with an action of operators `T_m` for all positive integers `m`
coprime to some integer `n`(the level), which satisfy `T_r T_s = T_{rs}` for
`r,s` coprime, and for powers of a prime `p`, `T_{p^r} = T_{p} T_{p^{r-1}} -
\varepsilon(p) p^{k-1} T_{p^{r-2}}`, where `\varepsilon(p)` is some
endomorphism of the module which commutes with the `T_m`.
We distinguish between *full* Hecke modules, which also have an action of
operators `T_m` for `m` not assumed to be coprime to the level, and
*anemic* Hecke modules, for which this does not hold.
"""
def __init__(self, base_ring, level, category = None):
r"""
Create a Hecke module. Not intended to be called directly.
EXAMPLE::
sage: CuspForms(Gamma0(17),2) # indirect doctest
Cuspidal subspace of dimension 1 of Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(17) of weight 2 over Rational Field
sage: ModularForms(3, 3).category()
Category of Hecke modules over Rational Field
"""
if not sage.rings.all.is_CommutativeRing(base_ring):
raise TypeError, "base_ring must be commutative ring"
from sage.categories.hecke_modules import HeckeModules
default_category = HeckeModules(base_ring)
if category is None:
category = default_category
else:
assert category.is_subcategory(default_category), "%s is not a subcategory of %s"%(category, default_category)
ParentWithGens.__init__(self, base_ring, category = category)
level = sage.rings.all.ZZ(level)
if level <= 0:
raise ValueError, "level (=%s) must be positive"%level
self.__level = level
self._hecke_matrices = {}
self._diamond_matrices = {}
def __setstate__(self, state):
r"""
Ensure that the category is initialized correctly on unpickling.
EXAMPLE::
sage: loads(dumps(ModularSymbols(11))).category() # indirect doctest
Category of Hecke modules over Rational Field
"""
if not self._is_category_initialized():
from sage.categories.hecke_modules import HeckeModules
self._init_category_(HeckeModules(state['_base']))
sage.modules.module.Module_old.__setstate__(self, state)
def __hash__(self):
r"""
Return a hash value for self.
EXAMPLE::
sage: CuspForms(Gamma0(17),2).__hash__()
-1797992588 # 32-bit
-3789716081060032652 # 64-bit
"""
return hash((self.base_ring(), self.__level))
def __cmp__(self, other):
r"""
Compare self to other. This must be overridden in all subclasses.
EXAMPLE::
sage: M = ModularForms(Gamma0(3))
sage: sage.modular.hecke.module.HeckeModule_generic.__cmp__(M, M)
Traceback (most recent call last):
...
NotImplementedError: ...
"""
raise NotImplementedError, "Derived class %s should implement __cmp__" % type(self)
def _compute_hecke_matrix_prime_power(self, p, r, **kwds):
r"""
Compute the Hecke matrix T_{p^r}, where `p` is prime and `r \ge 2`, assuming that
`T_p` is known. This is carried out by recursion.
All derived classes must override either this function or ``self.character()``.
EXAMPLE::
sage: M = ModularForms(SL2Z, 24)
sage: M._compute_hecke_matrix_prime_power(3, 3)
[ 834385168339943471891603972970040 462582247568491031177169792000 3880421605193373124143717311013888000]
[ 0 -4112503986561480 53074162446443642880]
[ 0 2592937954080 -1312130996155080]
"""
(p,r) = (int(p), int(r))
if not arith.is_prime(p):
raise ArithmeticError, "p must be a prime"
pow = p**(r-1)
if not self._hecke_matrices.has_key(pow):
self._hecke_matrices[pow] = self._compute_hecke_matrix(pow)
if not self._hecke_matrices.has_key(1):
self._hecke_matrices[1] = self._compute_hecke_matrix(1)
Tp = self._hecke_matrices[p]
Tpr1 = self._hecke_matrices[pow]
eps = self.character()
if eps is None:
raise NotImplementedError, "either character or _compute_hecke_matrix_prime_power must be overloaded in a derived class"
k = self.weight()
Tpr2 = self._hecke_matrices[pow/p]
return Tp*Tpr1 - eps(p)*(p**(k-1)) * Tpr2
def _compute_hecke_matrix_general_product(self, F, **kwds):
r"""
Compute the matrix of a general Hecke operator acting on this space, by
factorising n into prime powers and multiplying together the Hecke
operators for each of these.
EXAMPLE::
sage: M = ModularSymbols(Gamma0(3), 4)
sage: M._compute_hecke_matrix_general_product(factor(10))
[1134 0]
[ 0 1134]
"""
prod = None
for p, r in F:
pow = int(p**r)
if not self._hecke_matrices.has_key(pow):
self._hecke_matrices[pow] = self._compute_hecke_matrix(pow)
if prod is None:
prod = self._hecke_matrices[pow]
else:
prod *= self._hecke_matrices[pow]
return prod
def _compute_dual_hecke_matrix(self, n):
r"""
Compute the matrix of the Hecke operator `T_n` acting on the dual of self.
EXAMPLE::
sage: M = ModularSymbols(Gamma0(3), 4)
sage: M._compute_dual_hecke_matrix(10)
[1134 0]
[ 0 1134]
"""
return self.hecke_matrix(n).transpose()
def _compute_hecke_matrix(self, n, **kwds):
r"""
Compute the matrix of the Hecke operator `T_n` acting on self.
EXAMPLE::
sage: M = EisensteinForms(DirichletGroup(3).0, 3)
sage: M._compute_hecke_matrix(16)
[205 0]
[ 0 205]
"""
n = int(n)
if n<1:
raise ValueError, "Hecke operator T_%s is not defined."%n
if n==1:
Mat = matrix_space.MatrixSpace(self.base_ring(),self.rank())
return Mat(1)
if arith.is_prime(n):
return self._compute_hecke_matrix_prime(n, **kwds)
F = arith.factor(n)
if len(F) == 1:
return self._compute_hecke_matrix_prime_power(F[0][0],F[0][1], **kwds)
else:
return self._compute_hecke_matrix_general_product(F, **kwds)
def _compute_hecke_matrix_prime(self, p, **kwds):
"""
Compute and return the matrix of the p-th Hecke operator for p prime.
Derived classes should overload this function, and they will inherit
the machinery for calculating general Hecke operators.
EXAMPLE::
sage: M = EisensteinForms(DirichletGroup(3).0, 3)
sage: sage.modular.hecke.module.HeckeModule_generic._compute_hecke_matrix_prime(M, 3)
Traceback (most recent call last):
...
NotImplementedError: All subclasses must implement _compute_hecke_matrix_prime
"""
raise NotImplementedError, "All subclasses must implement _compute_hecke_matrix_prime"
def _compute_diamond_matrix(self, d):
r"""
Compute the matrix of the diamond bracket operator `\langle d \rangle` on this space,
in cases where this isn't self-evident (i.e. when this is not a space
with fixed character).
EXAMPLE::
sage: M = EisensteinForms(Gamma1(5), 3)
sage: sage.modular.hecke.module.HeckeModule_generic._compute_diamond_matrix(M, 2)
Traceback (most recent call last):
...
NotImplementedError: All subclasses without fixed character must implement _compute_diamond_matrix
"""
raise NotImplementedError, "All subclasses without fixed character must implement _compute_diamond_matrix"
def _hecke_operator_class(self):
"""
Return the class to be used for instantiating Hecke operators
acting on self.
EXAMPLES::
sage: sage.modular.hecke.module.HeckeModule_generic(QQ,1)._hecke_operator_class()
<class 'sage.modular.hecke.hecke_operator.HeckeOperator'>
sage: ModularSymbols(1,12)._hecke_operator_class()
<class 'sage.modular.modsym.hecke_operator.HeckeOperator'>
"""
return hecke_operator.HeckeOperator
def _diamond_operator_class(self):
r"""
Return the class to be used for instantiating diamond bracket operators
acting on self.
EXAMPLES::
sage: sage.modular.hecke.module.HeckeModule_generic(QQ,1)._diamond_operator_class()
<class 'sage.modular.hecke.hecke_operator.DiamondBracketOperator'>
sage: ModularSymbols(1,12)._diamond_operator_class()
<class 'sage.modular.hecke.hecke_operator.DiamondBracketOperator'>
"""
return hecke_operator.DiamondBracketOperator
def anemic_hecke_algebra(self):
"""
Return the Hecke algebra associated to this Hecke module.
EXAMPLES::
sage: T = ModularSymbols(1,12).hecke_algebra()
sage: A = ModularSymbols(1,12).anemic_hecke_algebra()
sage: T == A
False
sage: A
Anemic Hecke algebra acting on Modular Symbols space of dimension 3 for Gamma_0(1) of weight 12 with sign 0 over Rational Field
sage: A.is_anemic()
True
"""
try:
return self.__anemic_hecke_algebra
except AttributeError:
self.__anemic_hecke_algebra = algebra.AnemicHeckeAlgebra(self)
return self.__anemic_hecke_algebra
def character(self):
r"""
The character of this space. As this is an abstract base class, return None.
EXAMPLE::
sage: sage.modular.hecke.module.HeckeModule_generic(QQ, 10).character() is None
True
"""
return None
def dimension(self):
r"""
Synonym for rank.
EXAMPLE::
sage: M = sage.modular.hecke.module.HeckeModule_generic(QQ, 10).dimension()
Traceback (most recent call last):
...
NotImplementedError: Derived subclasses must implement rank
"""
return self.rank()
def hecke_algebra(self):
"""
Return the Hecke algebra associated to this Hecke module.
EXAMPLES::
sage: T = ModularSymbols(Gamma1(5),3).hecke_algebra()
sage: T
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
sage: T.is_anemic()
False
::
sage: M = ModularSymbols(37,sign=1)
sage: E, A, B = M.decomposition()
sage: A.hecke_algebra() == B.hecke_algebra()
False
"""
try:
return self.__hecke_algebra
except AttributeError:
self.__hecke_algebra = algebra.HeckeAlgebra(self)
return self.__hecke_algebra
def is_zero(self):
"""
Return True if this Hecke module has dimension 0.
EXAMPLES::
sage: ModularSymbols(11).is_zero()
False
sage: ModularSymbols(11).old_submodule().is_zero()
True
sage: CuspForms(10).is_zero()
True
sage: CuspForms(1,12).is_zero()
False
"""
return self.dimension() == 0
def is_full_hecke_module(self):
"""
Return True if this space is invariant under all Hecke operators.
Since self is guaranteed to be an anemic Hecke module, the significance
of this function is that it also ensures invariance under Hecke
operators of index that divide the level.
EXAMPLES::
sage: M = ModularSymbols(22); M.is_full_hecke_module()
True
sage: M.submodule(M.free_module().span([M.0.list()]), check=False).is_full_hecke_module()
False
"""
try:
return self._is_full_hecke_module
except AttributeError:
pass
misc.verbose("Determining if Hecke module is full.")
N = self.level()
for p in arith.prime_divisors(N):
if not self.is_hecke_invariant(p):
self._is_full_hecke_module = False
return False
self._is_full_hecke_module = True
return True
def is_hecke_invariant(self, n):
"""
Return True if self is invariant under the Hecke operator
`T_n`.
Since self is guaranteed to be an anemic Hecke module it is only
interesting to call this function when `n` is not coprime
to the level.
EXAMPLES::
sage: M = ModularSymbols(22).cuspidal_subspace()
sage: M.is_hecke_invariant(2)
True
We use check=False to create a nasty "module" that is not invariant
under `T_2`::
sage: S = M.submodule(M.free_module().span([M.0.list()]), check=False); S
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
sage: S.is_hecke_invariant(2)
False
sage: [n for n in range(1,12) if S.is_hecke_invariant(n)]
[1, 3, 5, 7, 9, 11]
"""
if arith.gcd(n, self.level()) == 1:
return True
if self.is_ambient():
return True
try:
self.hecke_operator(n).matrix()
except ArithmeticError:
return False
return True
def level(self):
"""
Returns the level of this modular symbols space.
INPUT:
- ``ModularSymbols self`` - an arbitrary space of
modular symbols
OUTPUT:
- ``int`` - the level
EXAMPLES::
sage: m = ModularSymbols(20)
sage: m.level()
20
"""
return self.__level
def rank(self):
r"""
Return the rank of this module over its base ring. Returns
NotImplementedError, since this is an abstract base class.
EXAMPLES::
sage: sage.modular.hecke.module.HeckeModule_generic(QQ, 10).rank()
Traceback (most recent call last):
...
NotImplementedError: Derived subclasses must implement rank
"""
raise NotImplementedError, "Derived subclasses must implement rank"
def submodule(self, X):
r"""
Return the submodule of self corresponding to X. As this is an abstract
base class, this raises a NotImplementedError.
EXAMPLES::
sage: sage.modular.hecke.module.HeckeModule_generic(QQ, 10).submodule(0)
Traceback (most recent call last):
...
NotImplementedError: Derived subclasses should implement submodule
"""
raise NotImplementedError, "Derived subclasses should implement submodule"
class HeckeModule_free_module(HeckeModule_generic):
"""
A Hecke module modeled on a free module over a commutative ring.
"""
def __init__(self, base_ring, level, weight):
r"""
Initialise a module.
EXAMPLES::
sage: M = sage.modular.hecke.module.HeckeModule_free_module(QQ, 12, -4); M
<class 'sage.modular.hecke.module.HeckeModule_free_module_with_category'>
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?
"""
HeckeModule_generic.__init__(self, base_ring, level)
self.__weight = weight
def __getitem__(self, n):
r"""
Return the nth term in the decomposition of self. See the docstring for
``decomposition`` for further information.
EXAMPLES::
sage: ModularSymbols(22)[0]
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
"""
n = int(n)
D = self.decomposition()
if n < 0 or n >= len(D):
raise IndexError, "index (=%s) must be between 0 and %s"%(n, len(D)-1)
return D[n]
def __hash__(self):
r"""
Return a hash of self.
EXAMPLES::
sage: ModularSymbols(22).__hash__()
1471905187 # 32-bit
-3789725500948382301 # 64-bit
"""
return hash((self.__weight, self.level(), self.base_ring()))
def __len__(self):
r"""
The number of factors in the decomposition of self.
EXAMPLES::
sage: len(ModularSymbols(22))
2
"""
return len(self.decomposition())
def _eigen_nonzero(self):
"""
Return smallest integer i such that the i-th entries of the entries
of a basis for the dual vector space are not all 0.
EXAMPLES::
sage: M = ModularSymbols(31,2)
sage: M._eigen_nonzero()
0
sage: M.dual_free_module().basis()
[
(1, 0, 0, 0, 0),
(0, 1, 0, 0, 0),
(0, 0, 1, 0, 0),
(0, 0, 0, 1, 0),
(0, 0, 0, 0, 1)
]
sage: M.cuspidal_submodule().minus_submodule()._eigen_nonzero()
1
sage: M.cuspidal_submodule().minus_submodule().dual_free_module().basis()
[
(0, 1, 0, 0, 0),
(0, 0, 1, 0, 0)
]
"""
try:
return self.__eigen_nonzero
except AttributeError:
pass
A = self.ambient_hecke_module()
V = self.dual_free_module()
B = V.basis()
for i in range(V.degree()):
for b in B:
if b[i] != 0:
self.__eigen_nonzero = i
return i
assert False, 'bug in _eigen_nonzero'
def _eigen_nonzero_element(self, n=1):
r"""
Return `T_n(x)` where `x` is a sparse modular
symbol such that the image of `x` is nonzero under the dual
projection map associated to this space, and `T_n` is the
`n^{th}` Hecke operator.
Used in the dual_eigenvector and eigenvalue methods.
EXAMPLES::
sage: ModularSymbols(22)._eigen_nonzero_element(3)
4*(1,0) + (2,21) - (11,1) + (11,2)
"""
if self.rank() == 0:
raise ArithmeticError, "the rank of self must be positive"
A = self.ambient_hecke_module()
i = self._eigen_nonzero()
return A._hecke_image_of_ith_basis_vector(n, i)
def _hecke_image_of_ith_basis_vector(self, n, i):
r"""
Return `T_n(e_i)`, where `e_i` is the
`i`th basis vector of the ambient space.
EXAMPLE::
sage: ModularSymbols(Gamma0(3))._hecke_image_of_ith_basis_vector(4, 0)
7*(1,0)
sage: ModularForms(Gamma0(3))._hecke_image_of_ith_basis_vector(4, 0)
7 + 84*q + 252*q^2 + 84*q^3 + 588*q^4 + 504*q^5 + O(q^6)
"""
T = self.hecke_operator(n)
return T.apply_sparse(self.gen(i))
def _element_eigenvalue(self, x, name='alpha'):
r"""
Return the dot product of self with the eigenvector returned by dual_eigenvector.
EXAMPLE::
sage: M = ModularSymbols(11)[0]
sage: M._element_eigenvalue(M.0)
1
"""
if not element.is_HeckeModuleElement(x):
raise TypeError, "x must be a Hecke module element."
if not x in self.ambient_hecke_module():
raise ArithmeticError, "x must be in the ambient Hecke module."
v = self.dual_eigenvector(names=name)
return v.dot_product(x.element())
def _is_hecke_equivariant_free_module(self, submodule):
"""
Returns True if the given free submodule of the ambient free module
is invariant under all Hecke operators.
EXAMPLES::
sage: M = ModularSymbols(11); V = M.free_module()
sage: M._is_hecke_equivariant_free_module(V.span([V.0]))
False
sage: M._is_hecke_equivariant_free_module(V)
True
sage: M._is_hecke_equivariant_free_module(M.cuspidal_submodule().free_module())
True
We do the same as above, but with a modular forms space::
sage: M = ModularForms(11); V = M.free_module()
sage: M._is_hecke_equivariant_free_module(V.span([V.0 + V.1]))
False
sage: M._is_hecke_equivariant_free_module(V)
True
sage: M._is_hecke_equivariant_free_module(M.cuspidal_submodule().free_module())
True
"""
misc.verbose("Determining if free module is Hecke equivariant.")
bound = self.hecke_bound()
for p in arith.primes(bound+1):
try:
self.T(p).matrix().restrict(submodule, check=True)
except ArithmeticError:
return False
return True
def _set_factor_number(self, i):
r"""
For internal use. If this Hecke module was computed via a decomposition of another
Hecke module, this method stores the index of this space in that decomposition.
EXAMPLE::
sage: ModularSymbols(Gamma0(3))[0].factor_number() # indirect doctest
0
"""
self.__factor_number = i
def ambient(self):
r"""
Synonym for ambient_hecke_module. Return the ambient module associated to this module.
EXAMPLE::
sage: CuspForms(1, 12).ambient()
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
"""
return self.ambient_hecke_module()
def ambient_module(self):
r"""
Synonym for ambient_hecke_module. Return the ambient module associated to this module.
EXAMPLE::
sage: CuspForms(1, 12).ambient_module()
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 10, 3).ambient_module()
Traceback (most recent call last):
...
NotImplementedError
"""
return self.ambient_hecke_module()
def ambient_hecke_module(self):
r"""
Return the ambient module associated to this module. As this is an
abstract base class, return NotImplementedError.
EXAMPLE::
sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 10, 3).ambient_hecke_module()
Traceback (most recent call last):
...
NotImplementedError
"""
raise NotImplementedError
def atkin_lehner_operator(self, d=None):
"""
Return the Atkin-Lehner operator `W_d` on this space, if
defined, where `d` is a divisor of the level `N`
such that `N/d` and `d` are coprime.
EXAMPLES::
sage: M = ModularSymbols(11)
sage: w = M.atkin_lehner_operator()
sage: w
Hecke module morphism Atkin-Lehner operator W_11 defined by the matrix
[-1 0 0]
[ 0 -1 0]
[ 0 0 -1]
Domain: Modular Symbols space of dimension 3 for Gamma_0(11) of weight ...
Codomain: Modular Symbols space of dimension 3 for Gamma_0(11) of weight ...
sage: M = ModularSymbols(Gamma1(13))
sage: w = M.atkin_lehner_operator()
sage: w.fcp('x')
(x - 1)^7 * (x + 1)^8
::
sage: M = ModularSymbols(33)
sage: S = M.cuspidal_submodule()
sage: S.atkin_lehner_operator()
Hecke module morphism Atkin-Lehner operator W_33 defined by the matrix
[ 0 -1 0 1 -1 0]
[ 0 -1 0 0 0 0]
[ 0 -1 0 0 -1 1]
[ 1 -1 0 0 -1 0]
[ 0 0 0 0 -1 0]
[ 0 -1 1 0 -1 0]
Domain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
Codomain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
::
sage: S.atkin_lehner_operator(3)
Hecke module morphism Atkin-Lehner operator W_3 defined by the matrix
[ 0 1 0 -1 1 0]
[ 0 1 0 0 0 0]
[ 0 1 0 0 1 -1]
[-1 1 0 0 1 0]
[ 0 0 0 0 1 0]
[ 0 1 -1 0 1 0]
Domain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
Codomain: Modular Symbols subspace of dimension 6 of Modular Symbols space ...
::
sage: N = M.new_submodule()
sage: N.atkin_lehner_operator()
Hecke module morphism Atkin-Lehner operator W_33 defined by the matrix
[ 1 2/5 4/5]
[ 0 -1 0]
[ 0 0 -1]
Domain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
Codomain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
"""
if d is None:
d = self.level()
d = int(d)
if self.level() % d != 0:
raise ArithmeticError, "d (=%s) must be a divisor of the level (=%s)"%(d,self.level())
N = self.level()
for p, e in arith.factor(d):
v = arith.valuation(N, p)
if e < v:
d *= p**(v-e)
d = int(d)
try:
return self.__atkin_lehner_operator[d]
except AttributeError:
self.__atkin_lehner_operator = {}
except KeyError:
pass
Wmat = self._compute_atkin_lehner_matrix(d)
H = self.endomorphism_ring()
W = H(Wmat, "Atkin-Lehner operator W_%s"%d)
self.__atkin_lehner_operator[d] = W
return W
def basis(self):
"""
Returns a basis for self.
EXAMPLES::
sage: m = ModularSymbols(43)
sage: m.basis()
((1,0), (1,31), (1,32), (1,38), (1,39), (1,40), (1,41))
"""
try:
return self.__basis
except AttributeError:
self.__basis = self.gens()
return self.__basis
def basis_matrix(self):
r"""
Return the matrix of the basis vectors of self (as vectors in some
ambient module)
EXAMPLE::
sage: CuspForms(1, 12).basis_matrix()
[1 0]
"""
return self.free_module().basis_matrix()
def coordinate_vector(self, x):
"""
Write x as a vector with respect to the basis given by
self.basis().
EXAMPLES::
sage: S = ModularSymbols(11,2).cuspidal_submodule()
sage: S.0
(1,8)
sage: S.basis()
((1,8), (1,9))
sage: S.coordinate_vector(S.0)
(1, 0)
"""
return self.free_module().coordinate_vector(x.element())
def decomposition(self, bound=None, anemic=True, height_guess=1, sort_by_basis = False,
proof=None):
"""
Returns the maximal decomposition of this Hecke module under the
action of Hecke operators of index coprime to the level. This is
the finest decomposition of self that we can obtain using factors
obtained by taking kernels of Hecke operators.
Each factor in the decomposition is a Hecke submodule obtained as
the kernel of `f(T_n)^r` acting on self, where n is
coprime to the level and `r=1`. If anemic is False, instead
choose `r` so that `f(X)^r` exactly divides the
characteristic polynomial.
INPUT:
- ``anemic`` - bool (default: True), if True, use only
Hecke operators of index coprime to the level.
- ``bound`` - int or None, (default: None). If None,
use all Hecke operators up to the Sturm bound, and hence obtain the
same result as one would obtain by using every element of the Hecke
ring. If a fixed integer, decompose using only Hecke operators
`T_p`, with `p` prime, up to bound.
- ``sort_by_basis`` - bool (default: ``False``); If True the resulting
decomposition will be sorted as if it was free modules, ignoring the
Hecke module structure. This will save a lot of time.
OUTPUT:
- ``list`` - a list of subspaces of self.
EXAMPLES::
sage: ModularSymbols(17,2).decomposition()
[
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,
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
]
sage: ModularSymbols(Gamma1(10),4).decomposition()
[
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,
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,
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,
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,
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,
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
]
sage: ModularSymbols(GammaH(12, [11])).decomposition()
[
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,
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,
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,
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,
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
]
TESTS::
sage: M = ModularSymbols(1000,2,sign=1).new_subspace().cuspidal_subspace()
sage: M.decomposition(3, sort_by_basis = True)
[
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,
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,
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,
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,
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,
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
]
"""
if not isinstance(anemic, bool):
raise TypeError, "anemic must be of type bool."
key = (bound, anemic)
try:
if self.__decomposition[key] != None:
return self.__decomposition[key]
except AttributeError:
self.__decomposition = {}
except KeyError:
pass
if self.rank() == 0:
self.__decomposition[key] = Sequence([], immutable=True, cr=True)
return self.__decomposition[key]
is_rational = self.base_ring() == sage.rings.all.QQ
time = misc.verbose("Decomposing %s"%self)
T = self.ambient_hecke_module().hecke_algebra()
if bound is None:
bound = self.ambient_hecke_module().hecke_bound()
D = Sequence([], cr=True)
U = [self.free_module()]
p = 2
while len(U) > 0 and p <= bound:
misc.verbose(mesg="p=%s"%p,t=time)
if anemic:
while arith.GCD(p, self.level()) != 1:
p = arith.next_prime(p)
misc.verbose("Decomposition using p=%s"%p)
t = T.hecke_operator(p).matrix()
Uprime = []
for i in range(len(U)):
if self.base_ring().characteristic() == 0 and self.level()%p != 0:
is_diagonalizable = True
else:
is_diagonalizable = False
if is_rational:
X = t.decomposition_of_subspace(U[i], check_restrict = False,
algorithm='multimodular',
height_guess=height_guess, proof=proof)
else:
X = t.decomposition_of_subspace(U[i], check_restrict = False,
is_diagonalizable=is_diagonalizable)
for i in range(len(X)):
W, is_irred = X[i]
if is_irred:
A = self.submodule(W, check=False)
D.append(A)
else:
Uprime.append(W)
p = arith.next_prime(p)
U = Uprime
for i in range(len(U)):
A = self.submodule(U[i], check=False)
D.append(A)
for A in D:
if anemic:
A.__is_splittable_anemic = False
A.__is_splittable = False
else:
A.__is_splittable = False
self.__is_splittable = len(D) > 1
if anemic:
self.__is_splittable_anemic = len(D) > 1
D.sort(key = None if not sort_by_basis else lambda ss: ss.free_module())
D.set_immutable()
self.__decomposition[key] = D
for i in range(len(D)):
self.__decomposition[key][i]._set_factor_number(i)
return self.__decomposition[key]
def degree(self):
r"""
The degree of this Hecke module (i.e. the rank of the ambient free
module)
EXAMPLE::
sage: CuspForms(1, 12).degree()
2
"""
return self.free_module().degree()
def dual_eigenvector(self, names='alpha', lift=True, nz=None):
"""
Return an eigenvector for the Hecke operators acting on the linear
dual of this space. This eigenvector will have entries in an
extension of the base ring of degree equal to the dimension of this
space.
.. warning:
The input space must be simple.
INPUT:
- ``name`` - print name of generator for eigenvalue
field.
- ``lift`` - bool (default: True)
- ``nz`` - if not None, then normalize vector so dot
product with this basis vector of ambient space is 1.
OUTPUT: A vector with entries possibly in an extension of the base
ring. This vector is an eigenvector for all Hecke operators acting
via their transpose.
If lift = False, instead return an eigenvector in the subspace for
the Hecke operators on the dual space. I.e., this is an eigenvector
for the restrictions of Hecke operators to the dual space.
.. note::
#. The answer is cached so subsequent calls always return
the same vector. However, the algorithm is randomized,
so calls during another session may yield a different
eigenvector. This function is used mainly for computing
systems of Hecke eigenvalues.
#. One can also view a dual eigenvector as defining (via
dot product) a functional phi from the ambient space of
modular symbols to a field. This functional phi is an
eigenvector for the dual action of Hecke operators on
functionals.
EXAMPLE::
sage: ModularSymbols(14).cuspidal_subspace().simple_factors()[1].dual_eigenvector()
(0, 1, 0, 0, 0)
"""
try:
w, w_lift = self.__dual_eigenvector[(names,nz)]
if lift:
return w_lift
else:
return w
except KeyError:
pass
except AttributeError:
self.__dual_eigenvector = {}
if not self.is_simple():
raise ArithmeticError, "self must be simple"
p = 2
t = self.dual_hecke_matrix(p)
while True:
f = t.charpoly('x')
if f.is_irreducible():
break
p = arith.next_prime(p)
t += random.choice([-2,-1,1,2]) * self.dual_hecke_matrix(p)
n = f.degree()
if n > 1:
R = f.parent()
K = R.base_ring().extension(f, names=names)
alpha = K.gen()
beta = ~alpha
c = [-f[0]*beta]
for i in range(1,n-1):
c.append((c[i-1] - f[i])*beta)
c.append( K(1) )
else:
K = self.base_ring()
c = [1]
V = FreeModule(K, n)
t = t.change_ring(K)
for j in range(n):
v = V.gen(j)
I = t.iterates(v, n)
w = V(0)
for i in range(n):
w += c[i]*V(I.row(i).list())
if w != 0:
break
Vdual = self.dual_free_module().change_ring(K)
w_lift = Vdual.linear_combination_of_basis(w)
if nz is not None:
x = self.ambient().gen(nz)
else:
x = self._eigen_nonzero_element()
alpha = w_lift.dot_product(x.element())
beta = ~alpha
w_lift = w_lift * beta
w = w * beta
self.__dual_eigenvector[(names,nz)] = (w, w_lift)
if lift:
return w_lift
else:
return w
def dual_hecke_matrix(self, n):
"""
The matrix of the `n^{th}` Hecke operator acting on the dual
embedded representation of self.
EXAMPLE::
sage: CuspForms(1, 24).dual_hecke_matrix(5)
[ 79345647584250/2796203 50530996976060416/763363419]
[ 195556757760000/2796203 124970165346810/2796203]
"""
n = int(n)
try:
self._dual_hecke_matrices
except AttributeError:
self._dual_hecke_matrices = {}
if not self._dual_hecke_matrices.has_key(n):
T = self._compute_dual_hecke_matrix(n)
self._dual_hecke_matrices[n] = T
return self._dual_hecke_matrices[n]
def eigenvalue(self, n, name='alpha'):
"""
Assuming that self is a simple space, return the eigenvalue of the
`n^{th}` Hecke operator on self.
INPUT:
- ``n`` - index of Hecke operator
- ``name`` - print representation of generator of
eigenvalue field
EXAMPLES::
sage: A = ModularSymbols(125,sign=1).new_subspace()[0]
sage: A.eigenvalue(7)
-3
sage: A.eigenvalue(3)
-alpha - 2
sage: A.eigenvalue(3,'w')
-w - 2
sage: A.eigenvalue(3,'z').charpoly('x')
x^2 + 3*x + 1
sage: A.hecke_polynomial(3)
x^2 + 3*x + 1
::
sage: M = ModularSymbols(Gamma1(17)).decomposition()[8].plus_submodule()
sage: M.eigenvalue(2,'a')
a
sage: M.eigenvalue(4,'a')
4/3*a^3 + 17/3*a^2 + 28/3*a + 8/3
.. note::
#. In fact there are `d` systems of eigenvalues
associated to self, where `d` is the rank of
self. Each of the systems of eigenvalues is conjugate
over the base field. This function chooses one of the
systems and consistently returns eigenvalues from that
system. Thus these are the coefficients `a_n` for
`n\geq 1` of a modular eigenform attached to self.
#. This function works even for Eisenstein subspaces,
though it will not give the constant coefficient of one
of the corresponding Eisenstein series (i.e., the
generalized Bernoulli number).
"""
if not self.is_simple():
raise ArithmeticError, "self must be simple"
n = int(n)
try:
return self.__eigenvalues[n][name]
except AttributeError:
self.__eigenvalues = {}
except KeyError:
pass
if n <= 0:
raise IndexError, "n must be a positive integer"
ev = self.__eigenvalues
if (arith.is_prime(n) or n==1):
Tn_e = self._eigen_nonzero_element(n)
an = self._element_eigenvalue(Tn_e, name=name)
_dict_set(ev, n, name, an)
return an
F = arith.factor(n)
prod = None
for p, r in F:
(p, r) = (int(p), int(r))
pow = p**r
if not (ev.has_key(pow) and ev[pow].has_key(name)):
eps = self.character()
if eps is None:
Tn_e = self._eigen_nonzero_element(pow)
_dict_set(ev, pow, name, self._element_eigenvalue(Tn_e, name=name))
else:
apr1 = self.eigenvalue(pow//p, name=name)
ap = self.eigenvalue(p, name=name)
k = self.weight()
apr2 = self.eigenvalue(pow//(p*p), name=name)
apow = ap*apr1 - eps(p)*(p**(k-1)) * apr2
_dict_set(ev, pow, name, apow)
if prod is None:
prod = ev[pow][name]
else:
prod *= ev[pow][name]
_dict_set(ev, n, name, prod)
return prod
def factor_number(self):
"""
If this Hecke module was computed via a decomposition of another
Hecke module, this is the corresponding number. Otherwise return
-1.
EXAMPLES::
sage: ModularSymbols(23)[0].factor_number()
0
sage: ModularSymbols(23).factor_number()
-1
"""
try:
return self.__factor_number
except AttributeError:
return -1
def gen(self, n):
r"""
Return the nth basis vector of the space.
EXAMPLE::
sage: ModularSymbols(23).gen(1)
(1,17)
"""
return self(self.free_module().gen(n))
def hecke_matrix(self, n):
"""
The matrix of the `n^{th}` Hecke operator acting on given
basis.
EXAMPLE::
sage: C = CuspForms(1, 16)
sage: C.hecke_matrix(3)
[-3348]
"""
n = int(n)
if n <= 0:
raise IndexError, "n must be positive."
if not self._hecke_matrices.has_key(n):
T = self._compute_hecke_matrix(n)
T.set_immutable()
self._hecke_matrices[n] = T
return self._hecke_matrices[n]
def hecke_operator(self, n):
"""
Returns the `n`-th Hecke operator `T_n`.
INPUT:
- ``ModularSymbols self`` - Hecke equivariant space of
modular symbols
- ``int n`` - an integer at least 1.
EXAMPLES::
sage: M = ModularSymbols(11,2)
sage: T = M.hecke_operator(3) ; T
Hecke operator T_3 on Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
sage: T.matrix()
[ 4 0 -1]
[ 0 -1 0]
[ 0 0 -1]
sage: T(M.0)
4*(1,0) - (1,9)
sage: S = M.cuspidal_submodule()
sage: T = S.hecke_operator(3) ; T
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
sage: T.matrix()
[-1 0]
[ 0 -1]
sage: T(S.0)
-(1,8)
"""
return self.hecke_algebra().hecke_operator(n)
def diamond_bracket_matrix(self, d):
r"""
Return the matrix of the diamond bracket operator `\langle d \rangle` on self.
EXAMPLES::
sage: M = ModularSymbols(DirichletGroup(5).0, 3)
sage: M.diamond_bracket_matrix(3)
[-zeta4 0]
[ 0 -zeta4]
sage: ModularSymbols(Gamma1(5), 3).diamond_bracket_matrix(3)
[ 0 -1 0 0]
[ 1 0 0 0]
[ 0 0 0 1]
[ 0 0 -1 0]
"""
d = int(d) % self.level()
if not self._diamond_matrices.has_key(d):
if self.character() is not None:
D = matrix_space.MatrixSpace(self.base_ring(),self.rank())(self.character()(d))
else:
D = self._compute_diamond_matrix(d)
D.set_immutable()
self._diamond_matrices[d] = D
return self._diamond_matrices[d]
def diamond_bracket_operator(self, d):
r"""
Return the diamond bracket operator `\langle d \rangle` on self.
EXAMPLES::
sage: M = ModularSymbols(DirichletGroup(5).0, 3)
sage: M.diamond_bracket_operator(3)
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
"""
return self.hecke_algebra().diamond_bracket_operator(d)
def T(self, n):
r"""
Returns the `n^{th}` Hecke operator `T_n`. This
function is a synonym for :meth:`.hecke_operator`.
EXAMPLE::
sage: M = ModularSymbols(11,2)
sage: M.T(3)
Hecke operator T_3 on Modular Symbols ...
"""
return self.hecke_operator(n)
def hecke_polynomial(self, n, var='x'):
"""
Return the characteristic polynomial of the `n^{th}` Hecke operator
acting on this space.
INPUT:
- ``n`` - integer
OUTPUT: a polynomial
EXAMPLE::
sage: ModularSymbols(11,2).hecke_polynomial(3)
x^3 - 2*x^2 - 7*x - 4
"""
return self.hecke_operator(n).charpoly(var)
def is_simple(self):
r"""
Return True if this space is simple as a module for the corresponding
Hecke algebra. Raises NotImplementedError, as this is an abstract base
class.
EXAMPLE::
sage: sage.modular.hecke.module.HeckeModule_free_module(QQ, 10, 3).is_simple()
Traceback (most recent call last):
...
NotImplementedError
"""
raise NotImplementedError
def is_splittable(self):
"""
Returns True if and only if only it is possible to split off a
nontrivial generalized eigenspace of self as the kernel of some Hecke
operator (not necessarily prime to the level). Note that the direct sum
of several copies of the same simple module is not splittable in this
sense.
EXAMPLE::
sage: M = ModularSymbols(Gamma0(64)).cuspidal_subspace()
sage: M.is_splittable()
True
sage: M.simple_factors()[0].is_splittable()
False
"""
if not hasattr(self, "__is_splittable"):
self.decomposition(anemic=False)
return self.__is_splittable
def is_submodule(self, other):
r"""
Return True if self is a submodule of other.
EXAMPLES::
sage: M = ModularSymbols(Gamma0(64))
sage: M[0].is_submodule(M)
True
sage: CuspForms(1, 24).is_submodule(ModularForms(1, 24))
True
sage: CuspForms(1, 12).is_submodule(CuspForms(3, 12))
False
"""
if not isinstance(other, HeckeModule_free_module):
return False
return self.ambient_free_module() == other.ambient_free_module() and \
self.free_module().is_submodule(other.free_module())
def is_splittable_anemic(self):
"""
Returns true if and only if only it is possible to split off a
nontrivial generalized eigenspace of self as the kernel of some
Hecke operator of index coprime to the level. Note that the direct sum
of several copies of the same simple module is not splittable in this
sense.
EXAMPLE::
sage: M = ModularSymbols(Gamma0(64)).cuspidal_subspace()
sage: M.is_splittable_anemic()
True
sage: M.simple_factors()[0].is_splittable_anemic()
False
"""
if not hasattr(self,"__is_splittable_anemic"):
self.decomposition(anemic=True)
return self.__is_splittable_anemic
def ngens(self):
r"""
Number of generators of self (equal to the rank).
EXAMPLE::
sage: ModularForms(1, 12).ngens()
2
"""
return self.rank()
def projection(self):
r"""
Return the projection map from the ambient space to self.
ALGORITHM: Let `B` be the matrix whose columns are obtained
by concatenating together a basis for the factors of the ambient
space. Then the projection matrix onto self is the submatrix of
`B^{-1}` obtained from the rows corresponding to self,
i.e., if the basis vectors for self appear as columns `n`
through `m` of `B`, then the projection matrix is
got from rows `n` through `m` of `B^{-1}`.
This is because projection with respect to the B basis is just
given by an `m-n+1` row slice `P` of a diagonal
matrix D with 1's in the `n` through `m` positions,
so projection with respect to the standard basis is given by
`P\cdot B^{-1}`, which is just rows `n`
through `m` of `B^{-1}`.
EXAMPLES::
sage: e = EllipticCurve('34a')
sage: m = ModularSymbols(34); s = m.cuspidal_submodule()
sage: d = s.decomposition(7)
sage: d
[
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,
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
]
sage: a = d[0]; a
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
sage: pi = a.projection()
sage: pi(m([0,oo]))
-1/6*(2,7) + 1/6*(2,13) - 1/6*(2,31) + 1/6*(2,33)
sage: M = ModularSymbols(53,sign=1)
sage: S = M.cuspidal_subspace()[1] ; S
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
sage: p = S.projection()
sage: S.basis()
((1,33) - (1,37), (1,35), (1,49))
sage: [ p(x) for x in S.basis() ]
[(1,33) - (1,37), (1,35), (1,49)]
"""
try:
return self.__projection
except AttributeError:
i = self.factor_number()
if i == -1:
raise NotImplementedError,\
"Computation of projection only implemented "+\
"for decomposition factors."
A = self.ambient_hecke_module()
B = A.decomposition_matrix_inverse()
i = (A.decomposition()).index(self)
n = sum([A[j].rank() for j in range(i)])
C = B.matrix_from_columns(range(n,n+self.rank()))
H = A.Hom(self)
pi = H(C, "Projection"%self)
self.__projection = pi
return self.__projection
def system_of_eigenvalues(self, n, name='alpha'):
r"""
Assuming that self is a simple space of modular symbols, return the
eigenvalues `[a_1, \ldots, a_nmax]` of the Hecke
operators on self. See ``self.eigenvalue(n)`` for more
details.
INPUT:
- ``n`` - number of eigenvalues
- ``alpha`` - name of generate for eigenvalue field
EXAMPLES: These computations use pseudo-random numbers, so we set
the seed for reproducible testing.
::
sage: set_random_seed(0)
The computations also use cached results from other computations,
so we clear the caches for reproducible testing.
::
sage: ModularSymbols_clear_cache()
We compute eigenvalues for newforms of level 62.
::
sage: M = ModularSymbols(62,2,sign=-1)
sage: S = M.cuspidal_submodule().new_submodule()
sage: [A.system_of_eigenvalues(3) for A in S.decomposition()]
[[1, 1, 0], [1, -1, 1/2*alpha + 1/2]]
Next we define a function that does the above::
sage: def b(N,k=2):
... t=cputime()
... S = ModularSymbols(N,k,sign=-1).cuspidal_submodule().new_submodule()
... for A in S.decomposition():
... print N, A.system_of_eigenvalues(5)
::
sage: b(63)
63 [1, 1, 0, -1, 2]
63 [1, alpha, 0, 1, -2*alpha]
This example illustrates finding field over which the eigenvalues
are defined::
sage: M = ModularSymbols(23,2,sign=1).cuspidal_submodule().new_submodule()
sage: v = M.system_of_eigenvalues(10); v
[1, alpha, -2*alpha - 1, -alpha - 1, 2*alpha, alpha - 2, 2*alpha + 2, -2*alpha - 1, 2, -2*alpha + 2]
sage: v[0].parent()
Number Field in alpha with defining polynomial x^2 + x - 1
This example illustrates setting the print name of the eigenvalue
field.
::
sage: A = ModularSymbols(125,sign=1).new_subspace()[0]
sage: A.system_of_eigenvalues(10)
[1, alpha, -alpha - 2, -alpha - 1, 0, -alpha - 1, -3, -2*alpha - 1, 3*alpha + 2, 0]
sage: A.system_of_eigenvalues(10,'x')
[1, x, -x - 2, -x - 1, 0, -x - 1, -3, -2*x - 1, 3*x + 2, 0]
"""
return [self.eigenvalue(m, name=name) for m in range(1,n+1)]
def weight(self):
"""
Returns the weight of this Hecke module.
INPUT:
- ``self`` - an arbitrary Hecke module
OUTPUT:
- ``int`` - the weight
EXAMPLES::
sage: m = ModularSymbols(20, weight=2)
sage: m.weight()
2
"""
return self.__weight
def zero_submodule(self):
"""
Return the zero submodule of self.
EXAMPLES::
sage: ModularSymbols(11,4).zero_submodule()
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
sage: CuspForms(11,4).zero_submodule()
Modular Forms subspace of dimension 0 of Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field
"""
return self.submodule(self.free_module().zero_submodule(), check=False)
def _dict_set(v, n, key, val):
r"""
Rough-and-ready implementation of a two-layer-deep dictionary.
EXAMPLE::
sage: from sage.modular.hecke.module import _dict_set
sage: v = {}
sage: _dict_set(v, 1, 2, 3)
sage: v
{1: {2: 3}}
sage: _dict_set(v, 1, 3, 4); v
{1: {2: 3, 3: 4}}
"""
if v.has_key(n):
v[n][key] = val
else:
v[n] = {key:val}