Path: blob/master/sage/modular/hecke/ambient_module.py
4059 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, level, 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:277278279- ``level`` - a Hecke module, which should be of the same type as280self, or a positive integer (in which case Sage will use281:meth:`~hecke_module_of_level` to find the "natural" module of the282corresponding level).283284- ``t`` - int, the parameter of the degeneracy map, i.e., the map is285related to `f(q)` - `f(q^t)`.286287288OUTPUT: A morphism from self to corresponding the Hecke module of289given level.290291EXAMPLES::292293sage: M = ModularSymbols(11,sign=1)294sage: d1 = M.degeneracy_map(33); d1295Hecke module morphism degeneracy map corresponding to f(q) |--> f(q) defined by the matrix296[ 1 0 0 0 -2 -1]297[ 0 0 -2 2 0 0]298Domain: Modular Symbols space of dimension 2 for Gamma_0(11) of weight ...299Codomain: Modular Symbols space of dimension 6 for Gamma_0(33) of weight ...300sage: M.degeneracy_map(33,3).matrix()301[ 3 2 2 0 -2 1]302[ 0 2 0 -2 0 0]303sage: M = ModularSymbols(33,sign=1)304sage: d2 = M.degeneracy_map(11); d2.matrix()305[ 1 0]306[ 0 1/2]307[ 0 -1]308[ 0 1]309[ -1 0]310[ -1 0]311sage: (d2*d1).matrix()312[4 0]313[0 4]314315::316317sage: M = ModularSymbols(3,12,sign=1)318sage: M.degeneracy_map(1)319Hecke module morphism degeneracy map corresponding to f(q) |--> f(q) defined by the matrix320[1 0]321[0 0]322[0 1]323[0 1]324[0 1]325Domain: Modular Symbols space of dimension 5 for Gamma_0(3) of weight ...326Codomain: Modular Symbols space of dimension 2 for Gamma_0(1) of weight ...327328::329330sage: S = M.cuspidal_submodule()331sage: S.degeneracy_map(1)332Hecke module morphism defined by the matrix333[1 0]334[0 0]335[0 0]336Domain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...337Codomain: Modular Symbols space of dimension 2 for Gamma_0(1) of weight ...338339::340341sage: D = ModularSymbols(10,4).cuspidal_submodule().decomposition()342sage: D343[344Modular 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,345Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 10 for Gamma_0(10) of weight 4 with sign 0 over Rational Field346]347sage: D[1].degeneracy_map(5)348Hecke module morphism defined by the matrix349[ 0 0 -1 1]350[ 0 1/2 3/2 -2]351[ 0 -1 1 0]352[ 0 -3/4 -1/4 1]353Domain: Modular Symbols subspace of dimension 4 of Modular Symbols space ...354Codomain: Modular Symbols space of dimension 4 for Gamma_0(5) of weight ...355356We check for a subtle caching bug that came up in work on trac #10453::357358sage: loads(dumps(J0(33).decomposition()[0].modular_symbols()))359Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field360"""361if is_AmbientHeckeModule(level):362M = level363level = int(M.level())364else:365level = int(level)366M = None367368t = int(t)369370err = False371if self.level() % level == 0:372quo = self.level() // level373if quo % t != 0:374err = True375elif level % self.level() == 0:376quo = level // self.level()377if quo % t != 0:378err = True379else:380err = True381if err:382raise ValueError, ("The level of self (=%s) must be a divisor or multiple of " + \383"level (=%s), and t (=%s) must be a divisor of the quotient.")%\384(self.level(), level, t)385386eps = self.character()387if not (eps is None) and level % eps.conductor() != 0:388raise ArithmeticError, "The conductor of the character of this space " + \389"(=%s) must be divisible by the level (=%s)."%\390(eps.conductor(), level)391392if M is None:393M = self.hecke_module_of_level(level)394395key = (M.group(), t)396# bad idea to use (M, t) as the key, because using complicated objects397# like modular forms spaces as dictionary keys causes weird behaviour;398# on the other hand, (M.level(), t) isn't enough information.399try:400self._degeneracy_maps401except AttributeError:402self._degeneracy_maps = {}403404if self._degeneracy_maps.has_key(key):405return self._degeneracy_maps[key]406407if M.rank() == 0:408409A = matrix_space.MatrixSpace(self.base_ring(), self.rank(),0)(0)410411elif self.level() % level == 0: # lower the level412413A = self._degeneracy_lowering_matrix(M, t)414415elif level % self.level() == 0: # raise the level416417A = self._degeneracy_raising_matrix(M, t)418419d = degenmap.DegeneracyMap(A, self, M, t)420self._degeneracy_maps[key] = d421return d422423def dual_free_module(self):424r"""425The free module dual to self, as a submodule of the dual426module of the ambient space. As this space is ambient anyway,427this just returns self.free_module().428429EXAMPLE::430431sage: M = ModularForms(2,8); M.dual_free_module()432Vector space of dimension 3 over Rational Field433sage: M.dual_free_module() is M.free_module()434True435"""436return self.free_module()437438def fcp(self, n, var='x'):439"""440Returns the factorization of the characteristic polynomial of441the Hecke operator `T_n` of index `n` acting on this space.442443INPUT:444445446- ``self`` - Hecke module invariant under the Hecke operator of index447n.448449- ``int n`` - a positive integer.450451- ``var`` - variable of polynomial (default `x`)452453454OUTPUT:455456- ``list`` - list of the pairs (g,e), where g is an457irreducible factor of the characteristic polynomial of T_n, and e458is its multiplicity.459460EXAMPLES::461462sage: m = ModularSymbols(23, 2, sign=1)463sage: m.fcp(2)464(x - 3) * (x^2 + x - 1)465sage: m.hecke_operator(2).charpoly('x').factor()466(x - 3) * (x^2 + x - 1)467"""468n = int(n)469if n <= 0:470raise ArithmeticError, "n (=%s) must be positive"%n471return self.hecke_operator(n).fcp(var)472473def free_module(self):474"""475Return the free module underlying this ambient Hecke module (the476forgetful functor from Hecke modules to modules over the base ring)477478EXAMPLE::479480sage: ModularForms(59, 2).free_module()481Vector space of dimension 6 over Rational Field482"""483try:484return self.__free_module485except AttributeError:486M = sage.modules.all.FreeModule(self.base_ring(), self.rank())487self.__free_module = M488return M489490def hecke_bound(self):491r"""492Return an integer B such that the Hecke operators `T_n`, for `n\leq B`,493generate the full Hecke algebra as a module over the base ring. Note494that we include the `n` with `n` not coprime to the level.495496At present this returns an unproven guess for non-cuspidal spaces which497appears to be valid for `M_k(\Gamma_0(N))`, where k and N are the498weight and level of self. (It is clearly valid for *cuspidal* spaces499of any fixed character, as a consequence of the Sturm bound theorem.)500It returns a hopelessly wrong answer for spaces of full level501`\Gamma_1`.502503TODO: Get rid of this dreadful bit of code.504505EXAMPLE::506507sage: ModularSymbols(17, 4).hecke_bound()50815509sage: ModularSymbols(Gamma1(17), 4).hecke_bound() # wrong!51015511"""512try:513if self.is_cuspidal():514return Gamma0(self.level()).sturm_bound(self.weight())515except AttributeError:516pass517misc.verbose("WARNING: ambient.py -- hecke_bound; returning unproven guess.")518return Gamma0(self.level()).sturm_bound(self.weight()) + 2*Gamma0(self.level()).dimension_eis(self.weight()) + 5519520def hecke_module_of_level(self, level):521r"""522Return the Hecke module corresponding to self at the given level, which523should be either a divisor or a multiple of the level of self. This524raises NotImplementedError, and should be overridden in derived525classes.526527EXAMPLE::528529sage: sage.modular.hecke.ambient_module.AmbientHeckeModule.hecke_module_of_level(ModularForms(2, 8),6)530Traceback (most recent call last):531...532NotImplementedError533"""534raise NotImplementedError535536def hecke_images(self, i, v):537"""538Return images of the `i`-th standard basis vector under the539Hecke operators `T_p` for all integers in `v`.540541INPUT:542543544- ``i`` - nonnegative integer545546- ``v`` - a list of positive integer547548549OUTPUT:550551552- ``matrix`` - whose rows are the Hecke images553554555EXAMPLES::556557sage: M = ModularSymbols(DirichletGroup(13).0, 3)558sage: M.T(2)(M.0).element()559(zeta12 + 4, 0, -1, 1)560sage: M.hecke_images(0, [1,2])561[ 1 0 0 0]562[zeta12 + 4 0 -1 1]563"""564try:565return self._hecke_images(i, v)566except (AttributeError, NotImplementedError):567pass568# Use slow generic algorithm569x = self.gen(i)570X = [self.hecke_operator(n).apply_sparse(x).element() for n in v]571return matrix(self.base_ring(), X)572573def intersection(self, other):574"""575Returns the intersection of self and other, which must both lie in576a common ambient space of modular symbols.577578EXAMPLES::579580sage: M = ModularSymbols(43, sign=1)581sage: A = M[0] + M[1]582sage: B = M[1] + M[2]583sage: A.rank(), B.rank()584(2, 3)585sage: C = A.intersection(B); C.rank() # TODO5861587"""588if not isinstance(other, module.HeckeModule_free_module):589raise TypeError, "other (=%s) must be a Hecke module."%other590if self.ambient_hecke_module() != other.ambient_hecke_module():591raise ArithmeticError, "Intersection only defined for subspaces of a common ambient Hecke module."592return other # since self is ambient, so the intersection must equal other.593594def is_ambient(self):595r"""596Returns True if and only if self is an ambient Hecke module.597598.. warning::599600self can only be ambient by being of type601AmbientHeckeModule.602603For example, decomposing a simple ambient space yields a604single factor, and that factor is *not* considered an605ambient space.606607EXAMPLES::608609sage: m = ModularSymbols(10)610sage: m.is_ambient()611True612613::614615sage: a = m[0] # the unique simple factor616sage: a == m617True618sage: a.is_ambient()619False620"""621return True622623def is_full_hecke_module(self, compute=True):624"""625Returns True if this space is invariant under the action of626all Hecke operators, even those that divide the level. This is627always true for ambient Hecke modules, so return True.628629EXAMPLE::630631sage: ModularSymbols(11, 4).is_full_hecke_module()632True633"""634return True635636def is_new(self, p=None):637r"""638Return True if this module is entirely new.639640EXAMPLE::641642sage: ModularSymbols(11, 4).is_new()643False644sage: ModularSymbols(1, 12).is_new()645True646"""647try:648if self.__is_new.has_key(p):649return self.__is_new[p]650except AttributeError:651pass652AmbientHeckeModule.new_submodule(self,p)653return self.__is_new[p]654655def is_old(self, p=None):656r"""657Return True if this module is entirely old.658659EXAMPLE::660661sage: ModularSymbols(22).is_old()662True663sage: ModularSymbols(3, 12).is_old()664False665"""666try:667if self.__is_old.has_key(p):668return self.__is_old[p]669except AttributeError:670pass671self.old_submodule(p)672return self.__is_old[p]673674def is_submodule(self, V):675"""676Returns True if and only if self is a submodule of V. Since this is an677ambient space, this returns True if and only if V is equal to self.678679EXAMPLE::680681sage: ModularSymbols(1, 4).is_submodule(ModularSymbols(11,4))682False683sage: ModularSymbols(11, 4).is_submodule(ModularSymbols(11,4))684True685"""686if not isinstance(V, module.HeckeModule_free_module):687raise TypeError, "V must be a Hecke module"688if not V.is_ambient():689return False690return V.ambient_hecke_module() == self691692def linear_combination_of_basis(self, v):693r"""694Given a list or vector of length equal to the dimension of self,695construct the appropriate linear combination of the basis vectors of696self.697698EXAMPLE::699700sage: ModularForms(3, 12).linear_combination_of_basis([1,0,0,0,1])7012*q + 2049*q^2 + 177147*q^3 + 4196177*q^4 + 48830556*q^5 + O(q^6)702703"""704return self(v)705706def new_submodule(self, p=None):707"""708Returns the new or p-new submodule of self.709710INPUT:711712- ``p`` - (default: None); if not None, return only713the p-new submodule.714715OUTPUT: the new or p-new submodule of self, i.e. the intersection of716the kernel of the degeneracy lowering maps to level `N/p` (for the717given prime `p`, or for all prime divisors of `N` if `p` is not given).718719If self is cuspidal this is a Hecke-invariant complement of the720corresponding old submodule, but this may break down on Eisenstein721subspaces (see the amusing example in William Stein's book of a form722which is new and old at the same time).723724EXAMPLES::725726sage: m = ModularSymbols(33); m.rank()7279728sage: m.new_submodule().rank()7293730sage: m.new_submodule(3).rank()7314732sage: m.new_submodule(11).rank()7338734"""735try:736if self.__is_new[p]:737return self738except AttributeError:739self.__is_new = {}740except KeyError:741pass742743if self.rank() == 0:744self.__is_new[p] = True745return self746try:747return self.__new_submodule[p]748except AttributeError:749self.__new_submodule = {}750except KeyError:751pass752753# Construct the degeneracy map d.754N = self.level()755d = None756eps = self.character()757if eps == None:758f = 1759else:760f = eps.conductor()761if p == None:762D = arith.prime_divisors(N)763else:764if N % p != 0:765raise ValueError, "p must divide the level."766D = [p]767for q in D:768# Here we are only using degeneracy *lowering* maps, so it is fine769# to be careless and pass an integer for the level. One needs to be770# a bit more careful with degeneracy *raising* maps for the Gamma1771# and GammaH cases.772if ((N//q) % f) == 0:773NN = N//q774d1 = self.degeneracy_map(NN,1).matrix()775if d is None:776d = d1777else:778d = d.augment(d1)779d = d.augment(self.degeneracy_map(NN,q).matrix())780#end if781#end for782if d is None or d == 0:783self.__is_new[p] = True784return self785else:786self.__is_new[p] = False787ns = self.submodule(d.kernel(), check=False)788ns.__is_new = {p:True}789ns._is_full_hecke_module = True790self.__new_submodule[p] = ns791return ns792793def nonembedded_free_module(self):794r"""795Return the free module corresponding to self as an abstract free module796(rather than as a submodule of an ambient free module). As this module797is ambient anyway, this just returns ``self.free_module()``.798799EXAMPLES::800801sage: M = ModularSymbols(11, 2)802sage: M.nonembedded_free_module() is M.free_module()803True804"""805return self.free_module()806807def old_submodule(self, p=None):808"""809Returns the old or p-old submodule of self, i.e. the sum of the images810of the degeneracy maps from level `N/p` (for the given prime `p`, or811for all primes `p` dividing `N` if `p` is not given).812813INPUT:814815- ``p`` - (default: None); if not None, return only the p-old816submodule.817818OUTPUT: the old or p-old submodule of self819820EXAMPLES::821822sage: m = ModularSymbols(33); m.rank()8239824sage: m.old_submodule().rank()8257826sage: m.old_submodule(3).rank()8276828sage: m.new_submodule(11).rank()8298830831::832833sage: e = DirichletGroup(16)([-1, 1])834sage: M = ModularSymbols(e, 3, sign=1); M835Modular Symbols space of dimension 4 and level 16, weight 3, character [-1, 1], sign 1, over Rational Field836sage: M.old_submodule()837Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 4 and level 16, weight 3, character [-1, 1], sign 1, over Rational Field838839Illustrate that trac 10664 is fixed::840841sage: ModularSymbols(DirichletGroup(42)[7], 6, sign=1).old_subspace(3)842Modular Symbols subspace of dimension 0 of Modular Symbols space of dimension 40 and level 42, weight 6, character [-1, -1], sign 1, over Rational Field843844"""845try:846if self.__is_old[p]:847return self848except AttributeError:849self.__is_old = {}850except KeyError:851pass852853if self.rank() == 0:854self.__is_old[p] = True855return self856try:857return self.__old_submodule[p]858except AttributeError:859self.__old_submodule = {}860except KeyError:861pass862863# Construct the degeneracy map d.864N = self.level()865d = None866867eps = self.character()868if eps is None:869f = 1870else:871f = eps.conductor()872873if p is None:874D = arith.prime_divisors(N)875else:876if N % p != 0:877raise ValueError, "p must divide the level."878D = [p]879880for q in D:881NN = N//q882if NN % f == 0:883M = self.hecke_module_of_level(NN)884885# Here it is vital to pass self as an argument to886# degeneracy_map, because M and the level N don't uniquely887# determine self (e.g. the degeneracy map from level 1 to level888# N could go to Gamma0(N), Gamma1(N) or anything in between)889d1 = M.degeneracy_map(self, 1).matrix()890891if d is None:892d = d1893else:894d = d.stack(d1)895d = d.stack(M.degeneracy_map(self, q).matrix())896#end if897#end for898if d is None:899os = self.zero_submodule()900else:901os = self.submodule(d.image(), check=False)902903self.__is_old[p] = (os == self)904905os.__is_old = {p:True}906os._is_full_hecke_module = True907self.__old_submodule[p] = os908return os909910def submodule(self, M, Mdual=None, check=True):911"""912Return the Hecke submodule of self generated by M, which may be a913submodule of the free module of self, or a list of elements of self.914915EXAMPLE::916917sage: M = ModularForms(37, 2)918sage: A = M.submodule([M.newforms()[0].element(), M.newforms()[1].element()]); A919Modular Forms subspace of dimension 2 of Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(37) of weight 2 over Rational Field920"""921if check:922if not sage.modules.all.is_FreeModule(M):923V = self.free_module()924if isinstance(M, (list,tuple)):925M = V.span([V(x.element()) for x in M])926else:927M = V.span(M)928if not M.is_submodule(self.free_module()):929raise TypeError, "M must be a submodule of the free module associated to this module."930if M == self.free_module():931return self932return self._submodule_class()(self, M, Mdual, check=check)933934def _submodule_class(self):935r"""936The class of submodules of this module. This is a separate method so it937can be overridden in derived classes.938939EXAMPLE::940941sage: sage.modular.hecke.ambient_module.AmbientHeckeModule._submodule_class(ModularForms(1, 24))942<class 'sage.modular.hecke.submodule.HeckeSubmodule'>943sage: ModularForms(1, 24)._submodule_class()944<class 'sage.modular.modform.submodule.ModularFormsSubmodule'>945"""946return submodule.HeckeSubmodule947948def submodule_from_nonembedded_module(self, V, Vdual=None, check=True):949"""950Create a submodule of this module, from a submodule of an ambient free951module of the same rank as the rank of self.952953INPUT:954955- ``V`` - submodule of ambient free module of the same rank as the956rank of self.957958- ``Vdual`` - used to pass in dual submodule (may be None)959960- ``check`` - whether to check that submodule is Hecke equivariant961962OUTPUT: Hecke submodule of self963964EXAMPLE::965966sage: V = QQ^8967sage: ModularForms(24, 2).submodule_from_nonembedded_module(V.submodule([0]))968Modular Forms subspace of dimension 0 of Modular Forms space of dimension 8 for Congruence Subgroup Gamma0(24) of weight 2 over Rational Field969"""970return self.submodule(V, Vdual, check=check)971972def submodule_generated_by_images(self, M):973"""974Return the submodule of this ambient modular symbols space975generated by the images under all degeneracy maps of M. The space M976must have the same weight, sign, and group or character as this977ambient space.978979EXAMPLES::980981sage: ModularSymbols(6, 12).submodule_generated_by_images(ModularSymbols(1,12))982Modular Symbols subspace of dimension 12 of Modular Symbols space of dimension 22 for Gamma_0(6) of weight 12 with sign 0 over Rational Field983"""984S = self.zero_submodule()985if self.level() % M.level() == 0:986D = arith.divisors(self.level() // M.level())987elif M.level() % self.level() == 0:988D = arith.divisors(M.level() // self.level())989else:990D = []991for t in D:992d = M.degeneracy_map(self, t)993if d.codomain() != self:994raise ArithmeticError, "incompatible spaces of modular symbols"995S += d.image()996997if self.is_full_hecke_module(compute=False):998S._is_full_hecke_module = True9991000return S10011002100310041005