Path: blob/master/src/sage/modular/hecke/ambient_module.py
8820 views
"""1Ambient Hecke modules2"""34#*****************************************************************************5# Sage: System for Algebra and Geometry Experimentation6#7# Copyright (C) 2005 William Stein <[email protected]>8#9# Distributed under the terms of the GNU General Public License (GPL)10#11# This code is distributed in the hope that it will be useful,12# but WITHOUT ANY WARRANTY; without even the implied warranty of13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU14# General Public License for more details.15#16# The full text of the GPL is available at:17#18# http://www.gnu.org/licenses/19#*****************************************************************************2021import degenmap22import module23import submodule2425import sage.modules.all2627import sage.rings.all2829import sage.misc.misc as misc3031import sage.rings.arith as arith3233import sage.matrix.matrix_space as matrix_space34from sage.matrix.constructor import matrix3536from sage.modular.arithgroup.all import Gamma0 # for Sturm bound3738def is_AmbientHeckeModule(x):39r"""40Return True if x is of type AmbientHeckeModule.4142EXAMPLES::4344sage: from sage.modular.hecke.ambient_module import is_AmbientHeckeModule45sage: is_AmbientHeckeModule(ModularSymbols(6))46True47sage: is_AmbientHeckeModule(ModularSymbols(6).cuspidal_subspace())48False49sage: is_AmbientHeckeModule(ModularForms(11))50True51sage: is_AmbientHeckeModule(BrandtModule(2, 3))52True53"""54return isinstance(x, AmbientHeckeModule)5556class AmbientHeckeModule(module.HeckeModule_free_module):57"""58An ambient Hecke module, i.e. a Hecke module that is isomorphic as a module59over its base ring `R` to the standard free module `R^k` for some `k`. This60is the base class for ambient spaces of modular forms and modular symbols,61and for Brandt modules.62"""63def __init__(self, base_ring, rank, level, weight):64r"""65Create an ambient Hecke module.6667EXAMPLES::6869sage: ModularSymbols(6) # indirect doctest70Modular Symbols space of dimension 3 for Gamma_0(6) of weight 2 with sign 0 over Rational Field71sage: sage.modular.hecke.ambient_module.AmbientHeckeModule(QQ, 3, 2, 4)72Generic ambient Hecke module of rank 3, level 2 and weight 4 over Rational Field73"""74rank = sage.rings.all.Integer(rank)75if rank < 0:76raise ValueError, "rank (=%s) must be nonnegative"%rank77self.__rank = rank78module.HeckeModule_free_module.__init__(self, base_ring, level, weight)7980def rank(self):81"""82Return the rank of this ambient Hecke module.8384OUTPUT:8586Integer8788EXAMPLES::8990sage: M = sage.modular.hecke.ambient_module.AmbientHeckeModule(QQ, 3, 11, 2); M91Generic ambient Hecke module of rank 3, level 11 and weight 2 over Rational Field92sage: M.rank()93394"""95return self.__rank9697def __add__(self, other):98r"""99Sum of self and other. As self is an ambient space, this will only make100sense if other is a subspace of self, in which case the answer is self.101102EXAMPLES::103104sage: M = ModularSymbols(23)105sage: M + M is M106True107sage: M + 3108Traceback (most recent call last):109...110TypeError: other (=3) must be a Hecke module.111"""112if not isinstance(other, module.HeckeModule_free_module):113raise TypeError, "other (=%s) must be a Hecke module."%other114if other.ambient_hecke_module() == self:115return self116raise ArithmeticError, "Sum only defined for subspaces of a common ambient Hecke module."117118def _repr_(self):119r"""120String representation of self. Should be overridden by derived classes.121122EXAMPLE::123124sage: sage.modular.hecke.ambient_module.AmbientHeckeModule(QQ, 3, 2, 4)._repr_()125'Generic ambient Hecke module of rank 3, level 2 and weight 4 over Rational Field'126"""127return "Generic ambient Hecke module of rank %s, level %s and weight %s over %s"%(self.rank(), self.level(), self.weight(), self.base_ring())128129130def _degeneracy_raising_matrix(self, codomain):131"""132Matrix of the degeneracy map (with t = 1) from self to codomain, whose133level should be a multiple of the level of self.134135EXAMPLE::136137sage: sage.modular.hecke.ambient_module.AmbientHeckeModule(QQ, 3, 2, 4)._degeneracy_raising_matrix(4)138Traceback (most recent call last):139...140NotImplementedError141"""142raise NotImplementedError143144def _degeneracy_lowering_matrix(self, codomain, t):145"""146Matrix of the degeneracy map of index t from self to codomain, whose level should be a divisor of the level of self.147148EXAMPLE::149150sage: sage.modular.hecke.ambient_module.AmbientHeckeModule(QQ, 3, 2, 4)._degeneracy_lowering_matrix(2, 2)151Traceback (most recent call last):152...153NotImplementedError154"""155raise NotImplementedError156157def _hecke_image_of_ith_basis_element(self, n, i):158"""159Return the image under the Hecke operator T_n of the i-th basis160element.161162EXAMPLE::163164sage: sage.modular.hecke.ambient_module.AmbientHeckeModule(QQ, 3, 2, 4)._hecke_image_of_ith_basis_element(4, 2)165Traceback (most recent call last):166...167NotImplementedError168169"""170return self.hecke_operator(n)(self.gen(i))171172173def _set_dual_free_module(self, V):174r"""175Store the embedded dual module of this module. Since this module is an176ambient module, this is not necessary.177178EXAMPLE::179180sage: ModularForms(11, 2)._set_dual_free_module(None)181"""182pass # setting dual free module of ambient space is not necessary183184185def ambient_hecke_module(self):186r"""187Return the ambient space that contains this ambient space. This is,188of course, just this space again.189190EXAMPLE::191192sage: M = ModularForms(11, 4); M.ambient_hecke_module() is M193True194"""195return self196197def complement(self):198"""199Return the largest Hecke-stable complement of this space.200201EXAMPLES::202203sage: M=ModularSymbols(11,2,1)204sage: M205Modular Symbols space of dimension 2 for Gamma_0(11) of weight 2 with sign 1 over Rational Field206sage: M.complement()207Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 2 for Gamma_0(11) of weight 2 with sign 1 over Rational Field208sage: C=M.cuspidal_subspace()209sage: C210Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(11) of weight 2 with sign 1 over Rational Field211sage: C.complement()212Modular Symbols subspace of dimension 1 of Modular Symbols space of dimension 2 for Gamma_0(11) of weight 2 with sign 1 over Rational Field213"""214return self.zero_submodule()215216def decomposition_matrix(self):217r"""218Returns the matrix whose columns form a basis for the canonical219sorted decomposition of self coming from the Hecke operators.220221If the simple factors are `D_0, \ldots, D_n`, then the222first few columns are an echelonized basis for `D_0`, the223next an echelonized basis for `D_1`, the next for224`D_2`, etc.225226EXAMPLE::227228sage: S = ModularSymbols(37, 2)229sage: S.decomposition_matrix()230[ 1 0 0 0 -1/3]231[ 0 1 -1 0 1/2]232[ 0 0 0 1 -1/2]233[ 0 1 1 1 0]234[ 0 0 0 0 1]235"""236try:237return self.__decomposition_matrix_cache238except AttributeError:239rows = []240for A in self.decomposition():241for x in A.basis():242rows.append(x.list())243A = matrix_space.MatrixSpace(self.base_ring(),self.rank())(rows)244self.__decomposition_matrix_cache = A245return self.__decomposition_matrix_cache246247def decomposition_matrix_inverse(self):248"""249Returns the inverse of the matrix returned by250decomposition_matrix().251252EXAMPLE::253254sage: S = ModularSymbols(37, 2)255sage: t = S.decomposition_matrix_inverse(); t256[ 1 0 0 0 1/3]257[ 0 1/2 -1/2 1/2 -1/2]258[ 0 -1/2 -1/2 1/2 0]259[ 0 0 1 0 1/2]260[ 0 0 0 0 1]261sage: t * S.decomposition_matrix() == 1262True263"""264try:265return self.__decomposition_matrix_inverse_cache266except AttributeError:267self.__decomposition_matrix_inverse_cache = ~self.decomposition_matrix()268return self.__decomposition_matrix_inverse_cache269270def degeneracy_map(self, codomain, t=1):271"""272The `t`-th degeneracy map from self to the module ``codomain``. The273level of the codomain must be a divisor or multiple of level, and t274must be a divisor of the quotient.275276INPUT:277278- ``codomain`` - a Hecke module, which should be of the same type as279self, or a positive integer (in which case Sage will use280:meth:`~hecke_module_of_level` to find the "natural" module of the281corresponding level).282- ``t`` - int, the parameter of the degeneracy map, i.e., the map is283related to `f(q)` - `f(q^t)`.284285286OUTPUT: A morphism from self to codomain.287288EXAMPLES::289290sage: M = ModularSymbols(11,sign=1)291sage: d1 = M.degeneracy_map(33); d1292Hecke module morphism degeneracy map corresponding to f(q) |--> f(q) defined by the matrix293[ 1 0 0 0 -2 -1]294[ 0 0 -2 2 0 0]295Domain: Modular Symbols space of dimension 2 for Gamma_0(11) of weight ...296Codomain: Modular Symbols space of dimension 6 for Gamma_0(33) of weight ...297sage: M.degeneracy_map(33,3).matrix()298[ 3 2 2 0 -2 1]299[ 0 2 0 -2 0 0]300sage: M = ModularSymbols(33,sign=1)301sage: d2 = M.degeneracy_map(11); d2.matrix()302[ 1 0]303[ 0 1/2]304[ 0 -1]305[ 0 1]306[ -1 0]307[ -1 0]308sage: (d2*d1).matrix()309[4 0]310[0 4]311312::313314sage: M = ModularSymbols(3,12,sign=1)315sage: M.degeneracy_map(1)316Hecke module morphism degeneracy map corresponding to f(q) |--> f(q) defined by the matrix317[1 0]318[0 0]319[0 1]320[0 1]321[0 1]322Domain: Modular Symbols space of dimension 5 for Gamma_0(3) of weight ...323Codomain: Modular Symbols space of dimension 2 for Gamma_0(1) of weight ...324325::326327sage: S = M.cuspidal_submodule()328sage: S.degeneracy_map(1)329Hecke module morphism defined by the matrix330[1 0]331[0 0]332[0 0]333Domain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...334Codomain: Modular Symbols space of dimension 2 for Gamma_0(1) of weight ...335336::337338sage: D = ModularSymbols(10,4).cuspidal_submodule().decomposition()339sage: D340[341Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 10 for Gamma_0(10) of weight 4 with sign 0 over Rational Field,342Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 10 for Gamma_0(10) of weight 4 with sign 0 over Rational Field343]344sage: D[1].degeneracy_map(5)345Hecke module morphism defined by the matrix346[ 0 0 -1 1]347[ 0 1/2 3/2 -2]348[ 0 -1 1 0]349[ 0 -3/4 -1/4 1]350Domain: Modular Symbols subspace of dimension 4 of Modular Symbols space ...351Codomain: Modular Symbols space of dimension 4 for Gamma_0(5) of weight ...352353We check for a subtle caching bug that came up in work on trac #10453::354355sage: loads(dumps(J0(33).decomposition()[0].modular_symbols()))356Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field357358We check that certain absurd inputs are correctly caught::359360sage: chi = kronecker_character(7)361sage: ModularSymbols(Gamma0(7), 4).degeneracy_map(ModularSymbols(chi, 4))362Traceback (most recent call last):363...364ValueError: The characters of the domain and codomain must match365"""366if is_AmbientHeckeModule(codomain):367M = codomain368level = int(M.level())369else:370level = int(codomain)371M = None372373t = int(t)374375err = False376if self.level() % level == 0:377quo = self.level() // level378if quo % t != 0:379err = True380elif level % self.level() == 0:381quo = level // self.level()382if quo % t != 0:383err = True384else:385err = True386if err:387raise ValueError, ("The level of self (=%s) must be a divisor or multiple of " + \388"level (=%s), and t (=%s) must be a divisor of the quotient.")%\389(self.level(), level, t)390391eps = self.character()392if not (eps is None) and level % eps.conductor() != 0:393raise ArithmeticError, "The conductor of the character of this space " + \394"(=%s) must be divisible by the level (=%s)."%\395(eps.conductor(), level)396397if M is None:398M = self.hecke_module_of_level(level)399400if eps is not None and M.character() is not None:401if eps.primitive_character() != M.character().primitive_character():402raise ValueError("The characters of the domain and codomain must match")403404key = (M.group(), t)405# bad idea to use (M, t) as the key, because using complicated objects406# like modular forms spaces as dictionary keys causes weird behaviour;407# on the other hand, (M.level(), t) isn't enough information.408try:409self._degeneracy_maps410except AttributeError:411self._degeneracy_maps = {}412413if self._degeneracy_maps.has_key(key):414return self._degeneracy_maps[key]415416if M.rank() == 0:417418A = matrix_space.MatrixSpace(self.base_ring(), self.rank(),0)(0)419420elif self.level() % level == 0: # lower the level421422A = self._degeneracy_lowering_matrix(M, t)423424elif level % self.level() == 0: # raise the level425426A = self._degeneracy_raising_matrix(M, t)427428d = degenmap.DegeneracyMap(A, self, M, t)429self._degeneracy_maps[key] = d430return d431432def dual_free_module(self):433r"""434The free module dual to self, as a submodule of the dual435module of the ambient space. As this space is ambient anyway,436this just returns self.free_module().437438EXAMPLE::439440sage: M = ModularForms(2,8); M.dual_free_module()441Vector space of dimension 3 over Rational Field442sage: M.dual_free_module() is M.free_module()443True444"""445return self.free_module()446447def fcp(self, n, var='x'):448"""449Returns the factorization of the characteristic polynomial of450the Hecke operator `T_n` of index `n` acting on this space.451452INPUT:453454455- ``self`` - Hecke module invariant under the Hecke operator of index456n.457458- ``int n`` - a positive integer.459460- ``var`` - variable of polynomial (default `x`)461462463OUTPUT:464465- ``list`` - list of the pairs (g,e), where g is an466irreducible factor of the characteristic polynomial of T_n, and e467is its multiplicity.468469EXAMPLES::470471sage: m = ModularSymbols(23, 2, sign=1)472sage: m.fcp(2)473(x - 3) * (x^2 + x - 1)474sage: m.hecke_operator(2).charpoly('x').factor()475(x - 3) * (x^2 + x - 1)476"""477n = int(n)478if n <= 0:479raise ArithmeticError, "n (=%s) must be positive"%n480return self.hecke_operator(n).fcp(var)481482def free_module(self):483"""484Return the free module underlying this ambient Hecke module (the485forgetful functor from Hecke modules to modules over the base ring)486487EXAMPLE::488489sage: ModularForms(59, 2).free_module()490Vector space of dimension 6 over Rational Field491"""492try:493return self.__free_module494except AttributeError:495M = sage.modules.all.FreeModule(self.base_ring(), self.rank())496self.__free_module = M497return M498499def hecke_bound(self):500r"""501Return an integer B such that the Hecke operators `T_n`, for `n\leq B`,502generate the full Hecke algebra as a module over the base ring. Note503that we include the `n` with `n` not coprime to the level.504505At present this returns an unproven guess for non-cuspidal spaces which506appears to be valid for `M_k(\Gamma_0(N))`, where k and N are the507weight and level of self. (It is clearly valid for *cuspidal* spaces508of any fixed character, as a consequence of the Sturm bound theorem.)509It returns a hopelessly wrong answer for spaces of full level510`\Gamma_1`.511512TODO: Get rid of this dreadful bit of code.513514EXAMPLE::515516sage: ModularSymbols(17, 4).hecke_bound()51715518sage: ModularSymbols(Gamma1(17), 4).hecke_bound() # wrong!51915520"""521try:522if self.is_cuspidal():523return Gamma0(self.level()).sturm_bound(self.weight())524except AttributeError:525pass526misc.verbose("WARNING: ambient.py -- hecke_bound; returning unproven guess.")527return Gamma0(self.level()).sturm_bound(self.weight()) + 2*Gamma0(self.level()).dimension_eis(self.weight()) + 5528529def hecke_module_of_level(self, level):530r"""531Return the Hecke module corresponding to self at the given level, which532should be either a divisor or a multiple of the level of self. This533raises NotImplementedError, and should be overridden in derived534classes.535536EXAMPLE::537538sage: sage.modular.hecke.ambient_module.AmbientHeckeModule.hecke_module_of_level(ModularForms(2, 8),6)539Traceback (most recent call last):540...541NotImplementedError542"""543raise NotImplementedError544545def hecke_images(self, i, v):546"""547Return images of the `i`-th standard basis vector under the548Hecke operators `T_p` for all integers in `v`.549550INPUT:551552553- ``i`` - nonnegative integer554555- ``v`` - a list of positive integer556557558OUTPUT:559560561- ``matrix`` - whose rows are the Hecke images562563564EXAMPLES::565566sage: M = ModularSymbols(DirichletGroup(13).0, 3)567sage: M.T(2)(M.0).element()568(zeta12 + 4, 0, -1, 1)569sage: M.hecke_images(0, [1,2])570[ 1 0 0 0]571[zeta12 + 4 0 -1 1]572"""573try:574return self._hecke_images(i, v)575except (AttributeError, NotImplementedError):576pass577# Use slow generic algorithm578x = self.gen(i)579X = [self.hecke_operator(n).apply_sparse(x).element() for n in v]580return matrix(self.base_ring(), X)581582def intersection(self, other):583"""584Returns the intersection of self and other, which must both lie in585a common ambient space of modular symbols.586587EXAMPLES::588589sage: M = ModularSymbols(43, sign=1)590sage: A = M[0] + M[1]591sage: B = M[1] + M[2]592sage: A.rank(), B.rank()593(2, 3)594sage: C = A.intersection(B); C.rank() # TODO5951596"""597if not isinstance(other, module.HeckeModule_free_module):598raise TypeError, "other (=%s) must be a Hecke module."%other599if self.ambient_hecke_module() != other.ambient_hecke_module():600raise ArithmeticError, "Intersection only defined for subspaces of a common ambient Hecke module."601return other # since self is ambient, so the intersection must equal other.602603def is_ambient(self):604r"""605Returns True if and only if self is an ambient Hecke module.606607.. warning::608609self can only be ambient by being of type610AmbientHeckeModule.611612For example, decomposing a simple ambient space yields a613single factor, and that factor is *not* considered an614ambient space.615616EXAMPLES::617618sage: m = ModularSymbols(10)619sage: m.is_ambient()620True621622::623624sage: a = m[0] # the unique simple factor625sage: a == m626True627sage: a.is_ambient()628False629"""630return True631632def is_full_hecke_module(self, compute=True):633"""634Returns True if this space is invariant under the action of635all Hecke operators, even those that divide the level. This is636always true for ambient Hecke modules, so return True.637638EXAMPLE::639640sage: ModularSymbols(11, 4).is_full_hecke_module()641True642"""643return True644645def is_new(self, p=None):646r"""647Return True if this module is entirely new.648649EXAMPLE::650651sage: ModularSymbols(11, 4).is_new()652False653sage: ModularSymbols(1, 12).is_new()654True655"""656try:657if self.__is_new.has_key(p):658return self.__is_new[p]659except AttributeError:660pass661AmbientHeckeModule.new_submodule(self,p)662return self.__is_new[p]663664def is_old(self, p=None):665r"""666Return True if this module is entirely old.667668EXAMPLE::669670sage: ModularSymbols(22).is_old()671True672sage: ModularSymbols(3, 12).is_old()673False674"""675try:676if self.__is_old.has_key(p):677return self.__is_old[p]678except AttributeError:679pass680self.old_submodule(p)681return self.__is_old[p]682683def is_submodule(self, V):684"""685Returns True if and only if self is a submodule of V. Since this is an686ambient space, this returns True if and only if V is equal to self.687688EXAMPLE::689690sage: ModularSymbols(1, 4).is_submodule(ModularSymbols(11,4))691False692sage: ModularSymbols(11, 4).is_submodule(ModularSymbols(11,4))693True694"""695if not isinstance(V, module.HeckeModule_free_module):696raise TypeError, "V must be a Hecke module"697if not V.is_ambient():698return False699return V.ambient_hecke_module() == self700701def linear_combination_of_basis(self, v):702r"""703Given a list or vector of length equal to the dimension of self,704construct the appropriate linear combination of the basis vectors of705self.706707EXAMPLE::708709sage: ModularForms(3, 12).linear_combination_of_basis([1,0,0,0,1])7102*q + 2049*q^2 + 177147*q^3 + 4196177*q^4 + 48830556*q^5 + O(q^6)711712"""713return self(v)714715def new_submodule(self, p=None):716"""717Returns the new or p-new submodule of self.718719INPUT:720721- ``p`` - (default: None); if not None, return only722the p-new submodule.723724OUTPUT: the new or p-new submodule of self, i.e. the intersection of725the kernel of the degeneracy lowering maps to level `N/p` (for the726given prime `p`, or for all prime divisors of `N` if `p` is not given).727728If self is cuspidal this is a Hecke-invariant complement of the729corresponding old submodule, but this may break down on Eisenstein730subspaces (see the amusing example in William Stein's book of a form731which is new and old at the same time).732733EXAMPLES::734735sage: m = ModularSymbols(33); m.rank()7369737sage: m.new_submodule().rank()7383739sage: m.new_submodule(3).rank()7404741sage: m.new_submodule(11).rank()7428743"""744try:745if self.__is_new[p]:746return self747except AttributeError:748self.__is_new = {}749except KeyError:750pass751752if self.rank() == 0:753self.__is_new[p] = True754return self755try:756return self.__new_submodule[p]757except AttributeError:758self.__new_submodule = {}759except KeyError:760pass761762# Construct the degeneracy map d.763N = self.level()764d = None765eps = self.character()766if eps == None:767f = 1768else:769f = eps.conductor()770if p == None:771D = arith.prime_divisors(N)772else:773if N % p != 0:774raise ValueError, "p must divide the level."775D = [p]776for q in D:777# Here we are only using degeneracy *lowering* maps, so it is fine778# to be careless and pass an integer for the level. One needs to be779# a bit more careful with degeneracy *raising* maps for the Gamma1780# and GammaH cases.781if ((N//q) % f) == 0:782NN = N//q783d1 = self.degeneracy_map(NN,1).matrix()784if d is None:785d = d1786else:787d = d.augment(d1)788d = d.augment(self.degeneracy_map(NN,q).matrix())789#end if790#end for791if d is None or d == 0:792self.__is_new[p] = True793return self794else:795self.__is_new[p] = False796ns = self.submodule(d.kernel(), check=False)797ns.__is_new = {p:True}798ns._is_full_hecke_module = True799self.__new_submodule[p] = ns800return ns801802def nonembedded_free_module(self):803r"""804Return the free module corresponding to self as an abstract free module805(rather than as a submodule of an ambient free module). As this module806is ambient anyway, this just returns ``self.free_module()``.807808EXAMPLES::809810sage: M = ModularSymbols(11, 2)811sage: M.nonembedded_free_module() is M.free_module()812True813"""814return self.free_module()815816def old_submodule(self, p=None):817"""818Returns the old or p-old submodule of self, i.e. the sum of the images819of the degeneracy maps from level `N/p` (for the given prime `p`, or820for all primes `p` dividing `N` if `p` is not given).821822INPUT:823824- ``p`` - (default: None); if not None, return only the p-old825submodule.826827OUTPUT: the old or p-old submodule of self828829EXAMPLES::830831sage: m = ModularSymbols(33); m.rank()8329833sage: m.old_submodule().rank()8347835sage: m.old_submodule(3).rank()8366837sage: m.new_submodule(11).rank()8388839840::841842sage: e = DirichletGroup(16)([-1, 1])843sage: M = ModularSymbols(e, 3, sign=1); M844Modular Symbols space of dimension 4 and level 16, weight 3, character [-1, 1], sign 1, over Rational Field845sage: M.old_submodule()846Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 4 and level 16, weight 3, character [-1, 1], sign 1, over Rational Field847848Illustrate that trac 10664 is fixed::849850sage: ModularSymbols(DirichletGroup(42)[7], 6, sign=1).old_subspace(3)851Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 40 and level 42, weight 6, character [-1, -1], sign 1, over Rational Field852853"""854try:855if self.__is_old[p]:856return self857except AttributeError:858self.__is_old = {}859except KeyError:860pass861862if self.rank() == 0:863self.__is_old[p] = True864return self865try:866return self.__old_submodule[p]867except AttributeError:868self.__old_submodule = {}869except KeyError:870pass871872# Construct the degeneracy map d.873N = self.level()874d = None875876eps = self.character()877if eps is None:878f = 1879else:880f = eps.conductor()881882if p is None:883D = arith.prime_divisors(N)884else:885if N % p != 0:886raise ValueError, "p must divide the level."887D = [p]888889for q in D:890NN = N//q891if NN % f == 0:892M = self.hecke_module_of_level(NN)893894# Here it is vital to pass self as an argument to895# degeneracy_map, because M and the level N don't uniquely896# determine self (e.g. the degeneracy map from level 1 to level897# N could go to Gamma0(N), Gamma1(N) or anything in between)898d1 = M.degeneracy_map(self, 1).matrix()899900if d is None:901d = d1902else:903d = d.stack(d1)904d = d.stack(M.degeneracy_map(self, q).matrix())905#end if906#end for907if d is None:908os = self.zero_submodule()909else:910os = self.submodule(d.image(), check=False)911912self.__is_old[p] = (os == self)913914os.__is_old = {p:True}915os._is_full_hecke_module = True916self.__old_submodule[p] = os917return os918919def submodule(self, M, Mdual=None, check=True):920"""921Return the Hecke submodule of self generated by M, which may be a922submodule of the free module of self, or a list of elements of self.923924EXAMPLE::925926sage: M = ModularForms(37, 2)927sage: A = M.submodule([M.newforms()[0].element(), M.newforms()[1].element()]); A928Modular Forms subspace of dimension 2 of Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(37) of weight 2 over Rational Field929"""930if check:931if not sage.modules.all.is_FreeModule(M):932V = self.free_module()933if isinstance(M, (list,tuple)):934M = V.span([V(x.element()) for x in M])935else:936M = V.span(M)937if not M.is_submodule(self.free_module()):938raise TypeError, "M must be a submodule of the free module associated to this module."939if M == self.free_module():940return self941return self._submodule_class()(self, M, Mdual, check=check)942943def _submodule_class(self):944r"""945The class of submodules of this module. This is a separate method so it946can be overridden in derived classes.947948EXAMPLE::949950sage: sage.modular.hecke.ambient_module.AmbientHeckeModule._submodule_class(ModularForms(1, 24))951<class 'sage.modular.hecke.submodule.HeckeSubmodule'>952sage: ModularForms(1, 24)._submodule_class()953<class 'sage.modular.modform.submodule.ModularFormsSubmodule'>954"""955return submodule.HeckeSubmodule956957def submodule_from_nonembedded_module(self, V, Vdual=None, check=True):958"""959Create a submodule of this module, from a submodule of an ambient free960module of the same rank as the rank of self.961962INPUT:963964- ``V`` - submodule of ambient free module of the same rank as the965rank of self.966967- ``Vdual`` - used to pass in dual submodule (may be None)968969- ``check`` - whether to check that submodule is Hecke equivariant970971OUTPUT: Hecke submodule of self972973EXAMPLE::974975sage: V = QQ^8976sage: ModularForms(24, 2).submodule_from_nonembedded_module(V.submodule([0]))977Modular Forms subspace of dimension 0 of Modular Forms space of dimension 8 for Congruence Subgroup Gamma0(24) of weight 2 over Rational Field978"""979return self.submodule(V, Vdual, check=check)980981def submodule_generated_by_images(self, M):982"""983Return the submodule of this ambient modular symbols space984generated by the images under all degeneracy maps of M. The space M985must have the same weight, sign, and group or character as this986ambient space.987988EXAMPLES::989990sage: ModularSymbols(6, 12).submodule_generated_by_images(ModularSymbols(1,12))991Modular Symbols subspace of dimension 12 of Modular Symbols space of dimension 22 for Gamma_0(6) of weight 12 with sign 0 over Rational Field992"""993S = self.zero_submodule()994if self.level() % M.level() == 0:995D = arith.divisors(self.level() // M.level())996elif M.level() % self.level() == 0:997D = arith.divisors(M.level() // self.level())998else:999D = []1000for t in D:1001d = M.degeneracy_map(self, t)1002if d.codomain() != self:1003raise ArithmeticError, "incompatible spaces of modular symbols"1004S += d.image()10051006if self.is_full_hecke_module(compute=False):1007S._is_full_hecke_module = True10081009return S10101011101210131014