make Hecke operators into methods of Siegel modular forms default tip
authorAlexandru Ghitza <aghitza@alum.mit.edu>
Mon Apr 05 12:39:12 2010 +1000 (2010-04-05)
changeset 36a3aeb946b189
parent 35 493f24b8a281
make Hecke operators into methods of Siegel modular forms
nils/siegelmodforms/siegel_modular_form.py
     1.1 --- a/nils/siegelmodforms/siegel_modular_form.py	Sun Apr 04 17:27:01 2010 +1000
     1.2 +++ b/nils/siegelmodforms/siegel_modular_form.py	Mon Apr 05 12:39:12 2010 +1000
     1.3 @@ -472,6 +472,7 @@
     1.4          self.__Precision = SiegelModularFormPrecision( prec)
     1.5          self.__Prec = _normalized_prec(prec)
     1.6          self.__Name = name
     1.7 +        self.__rep_lists = dict()
     1.8          AlgebraElement.__init__( self, parent)
     1.9  
    1.10      def base_ring(self):
    1.11 @@ -1024,6 +1025,146 @@
    1.12                                                 d_right_coeffs, right.prec())
    1.13          return d_left*right/left.weight() - d_right*left/right.weight()
    1.14  
    1.15 +    #################
    1.16 +    # Hecke operators
    1.17 +    #################
    1.18 +
    1.19 +    def hecke_image(self, ell):
    1.20 +        r"""
    1.21 +        Return the Siegel modular form which is the image of self under
    1.22 +        the Hecke operator T(ell).
    1.23 +
    1.24 +        EXAMPLES::
    1.25 +
    1.26 +            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
    1.27 +            sage: A,B,C,D = siegel_modular_forms_generators()
    1.28 +            sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
    1.29 +            sage: TUps20 = Ups20.hecke_image(2)
    1.30 +            sage: TUps20[(1,1,1)]/Ups20[(1,1,1)]
    1.31 +            -840960
    1.32 +            sage: TUps20
    1.33 +            Siegel modular form on Sp(2,Z) of weight 20
    1.34 +            sage: A.hecke_image(5)
    1.35 +            T(5)(Igusa_4)
    1.36 +        """
    1.37 +        # TODO: compute precision for T(ell)F
    1.38 +        from sage.functions.all import ceil
    1.39 +        try:
    1.40 +            # TODO: I am not sure whether this sets the right prec
    1.41 +            a,b,c = self.prec()
    1.42 +            prec = (ceil(a/ell),ceil(b/ell),ceil(c/ell))
    1.43 +        except TypeError:
    1.44 +            prec = ceil(self.prec()/ell/ell)
    1.45 +            prec = _normalized_prec( prec)
    1.46 +        d = dict((f, self.hecke_coefficient(ell, f)) for f in self.keys() if _is_bounded(f, prec) )
    1.47 +        if self.name():
    1.48 +            name = 'T(' + str(ell) + ')(' + self.name() + ')'
    1.49 +        else:
    1.50 +            name = None
    1.51 +        return SiegelModularForm(self.group(), self.weight(), d, prec, name)
    1.52 +
    1.53 +    def hecke_coefficient(self, ell, (a,b,c)):
    1.54 +        r"""
    1.55 +        Return the `(a,b,c)`-indexed coefficient of the image of self
    1.56 +        under the Hecke operator T(ell).
    1.57 +        
    1.58 +        EXAMPLES::
    1.59 +
    1.60 +            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
    1.61 +            sage: A,B,C,D = siegel_modular_forms_generators()
    1.62 +            sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
    1.63 +            sage: Ups20.hecke_coefficient(5, (1,1,1))
    1.64 +            5813608045/992
    1.65 +            sage: Ups20.hecke_coefficient(5, (1,0,1))
    1.66 +            5813608045/248             
    1.67 +            sage: Ups20.hecke_coefficient(5, (1,0,1))/Ups20[(1,0,1)]
    1.68 +            -5232247240500
    1.69 +        """
    1.70 +        k = self.weight()
    1.71 +        coeff = 0
    1.72 +        from sage.rings.all import divisors
    1.73 +        for t1 in divisors(ell):
    1.74 +            for t2 in divisors(t1):
    1.75 +                cosets = self._get_representatives(ell, t1/t2)
    1.76 +                for V in cosets:                       
    1.77 +                    aprime, bprime, cprime = self._change_variables(V,(a,b,c))
    1.78 +                    if aprime % t1 == 0 and bprime % t2 == 0 and cprime % t2 == 0:
    1.79 +                        try:
    1.80 +                            coeff = coeff + t1**(k-2)*t2**(k-1)*self[(ell*aprime/t1**2,ell*bprime/t1/t2,ell*cprime/t2**2)]
    1.81 +                        except KeyError, msg:
    1.82 +                            raise ValueError, '%s' %(self,msg)
    1.83 +        return coeff
    1.84 +
    1.85 +    def _get_representatives(self, ell, t):
    1.86 +        r"""
    1.87 +        A helper function used in hecke_coefficient that computes the right
    1.88 +        coset representatives of `\Gamma^0(t)\SL(2,Z)` where
    1.89 +        `\Gamma^0(t)` is the subgroup of `SL(2,Z)` where the upper lh
    1.90 +        corner is divisible by `t`.
    1.91 + 
    1.92 +        EXAMPLES::
    1.93 +
    1.94 +            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
    1.95 +            sage: A, B, C, D = siegel_modular_forms_generators()
    1.96 +            sage: A._get_representatives(5, 3)
    1.97 +            [
    1.98 +            [ 0  1]  [1 0]  [1 1]  [1 2]
    1.99 +            [-1  0], [0 1], [0 1], [0 1]
   1.100 +            ]
   1.101 +
   1.102 +        NOTE
   1.103 +            We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$
   1.104 +            given by $A \mapsto [1:0]A$.
   1.105 +         """
   1.106 +        try:
   1.107 +            return self.__rep_lists[(ell,t)]
   1.108 +        except KeyError:
   1.109 +            from sage.matrix.all import MatrixSpace
   1.110 +            M = MatrixSpace(ZZ, 2,2)
   1.111 +        if t == 1:
   1.112 +            return [M([1,0,0,1])]
   1.113 +        from sage.modular.all import P1List
   1.114 +        P = list(P1List(t))
   1.115 +        from sage.rings.all import IntegerModRing, xgcd
   1.116 +        ZZt = IntegerModRing(t)
   1.117 +        rep_list = []
   1.118 +        for x,y in P1List(t):
   1.119 +            e, d,c = xgcd(x,y)
   1.120 +            rep = M([x,y,-c,d])
   1.121 +            rep_list.append(rep)
   1.122 +        self.__rep_lists[(ell,t)] = rep_list
   1.123 +        return rep_list
   1.124 +
   1.125 +    @staticmethod
   1.126 +    def _change_variables(V, (n,r,m)):
   1.127 +        r"""
   1.128 +        A helper function used in hecke_coefficient that computes the
   1.129 +        quadratic form [nprime,rprime,mprime] given by $Q((x,y) V)$
   1.130 +        where $Q=[n,r,m]$ and $V$ is a 2 by 2 matrix
   1.131 +
   1.132 +        EXAMPLES::
   1.133 +
   1.134 +            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
   1.135 +            sage: A, B, C, D = siegel_modular_forms_generators()
   1.136 +            sage: A._change_variables(matrix([[1,2],[2,3]]),(2,1,3))
   1.137 +            (16, 51, 41)
   1.138 +
   1.139 +        TODO: This should eventually be a method of quadratic forms.
   1.140 +        """
   1.141 +        from sage.rings.all import PolynomialRing, ZZ
   1.142 +        R = PolynomialRing(ZZ,2,'x, y')
   1.143 +        x, y = R.gens()
   1.144 +        g = R(n*x**2+r*x*y+m*y**2)
   1.145 +        a = V[0][0]
   1.146 +        b = V[0][1]
   1.147 +        c = V[1][0]
   1.148 +        d = V[1][1]
   1.149 +        f = g(a*x+c*y,b*x+d*y)
   1.150 +        nprime = f.monomial_coefficient(x**2)
   1.151 +        rprime = f.monomial_coefficient(x*y)
   1.152 +        mprime = f.monomial_coefficient(y**2)
   1.153 +        return nprime, rprime, mprime
   1.154 +
   1.155  
   1.156  def SiegelModularForm( arg0, arg1 = None, arg2 = None, prec = 100, name = None, hint = None):
   1.157      r"""
   1.158 @@ -1856,187 +1997,3 @@
   1.159              raise ValueError, 'bla bla bla\n%s' %msg
   1.160          return sum( polys[i]*X[i] for i in range(j))
   1.161  
   1.162 -
   1.163 -
   1.164 -class HeckeOperator (SageObject):
   1.165 -    r"""
   1.166 -    Implements a Hecke operator acting on Siegel modular forms.
   1.167 -
   1.168 -    TODO
   1.169 -        Implement Hecke operators for more general groups.
   1.170 -        (Use that forms know about their groups.)
   1.171 -    """
   1.172 -
   1.173 -    def __init__(self, ell):
   1.174 -        r"""
   1.175 -
   1.176 -        EXAMPLES::
   1.177 -
   1.178 -            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
   1.179 -            sage: A,B,C,D = siegel_modular_forms_generators()
   1.180 -            sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
   1.181 -            sage: T = HeckeOperator(2)
   1.182 -            sage: TUps20 = T(Ups20)
   1.183 -            sage: TUps20[(1,1,1)]/Ups20[(1,1,1)]
   1.184 -            -840960
   1.185 -        """
   1.186 -        self.__l = ell
   1.187 -        self.__rep_lists = dict()
   1.188 -        
   1.189 -    def _repr_(self):
   1.190 -        r"""
   1.191 -        Returns repr of self
   1.192 -
   1.193 -        EXAMPLES::
   1.194 -
   1.195 -            sage: T = HeckeOperator(2)
   1.196 -            sage: T._repr_()
   1.197 -            '2-th Hecke operator for Siegel modular forms'
   1.198 -
   1.199 -        """
   1.200 -
   1.201 -        return '%s-th Hecke operator for Siegel modular forms' % self.__l
   1.202 -
   1.203 -    def _latex_(self):
   1.204 -        r"""
   1.205 -
   1.206 -        EXAMPLES::
   1.207 -
   1.208 -            sage: T = HeckeOperator(9)
   1.209 -            sage: T._latex_()
   1.210 -            '9-th Hecke operator for Siegel modular forms'
   1.211 -        """
   1.212 -        from sage.misc.all import latex
   1.213 -        return latex(self.__l) + '-th Hecke operator for Siegel modular forms'
   1.214 -
   1.215 -    def __call__(self, F):
   1.216 -        r"""
   1.217 -        Allows on to apply self to a Siegel modular forms `F`.
   1.218 -
   1.219 -        EXAMPLES::
   1.220 -
   1.221 -            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
   1.222 -            sage: A,B,C,D = siegel_modular_forms_generators()
   1.223 -            sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
   1.224 -            sage: T = HeckeOperator(2)
   1.225 -            sage: TUps20 = T(Ups20)
   1.226 -            sage: TUps20[(1,1,1)]/Ups20[(1,1,1)]
   1.227 -            -840960
   1.228 -        """
   1.229 -        # TODO: compute precision for T(l)F
   1.230 -        l = self.__l
   1.231 -        from sage.functions.all import ceil
   1.232 -        try:
   1.233 -            # TODO: I am not sure whether this sets the right prec
   1.234 -            a,b,c = F.prec()
   1.235 -            prec = (ceil(a/l),ceil(b/l),ceil(c/l))
   1.236 -        except TypeError:
   1.237 -            prec = ceil(F.prec()/l/l)
   1.238 -            prec = _normalized_prec( prec)
   1.239 -        d = dict( (f,self.hecke_coeff( F, f)) for f in F.keys() if _is_bounded(f, prec) )
   1.240 -        if F.name():
   1.241 -            name = 'T(' + str(l) + ')(' + F.name() + ')'
   1.242 -        else:
   1.243 -            name = None
   1.244 -        # TODO: replace following instantiation by call to factory function 
   1.245 -        return SiegelModularForm_class( F.parent(), F.group(), F.weight(), d, prec, name)
   1.246 -
   1.247 -    def hecke_coeff(self, F, (a,b,c)):
   1.248 -        r"""
   1.249 -        Computes the coefficient indexed by `(a,b,c)` of `T(\ell) (F)`
   1.250 -
   1.251 -        EXAMPLES::
   1.252 -
   1.253 -            sage: from sage.modular.siegel.siegel_modular_form import siegel_modular_forms_generators
   1.254 -            sage: A,B,C,D = siegel_modular_forms_generators()
   1.255 -            sage: T = HeckeOperator(5)
   1.256 -            sage: Ups20 = -1/1785600*A*B*C - 1/1785600*A^2*D + C^2
   1.257 -            sage: T.hecke_coeff(Ups20,(1,1,1))
   1.258 -            5813608045/992
   1.259 -            sage: T.hecke_coeff(Ups20,(1,0,1))
   1.260 -            5813608045/248
   1.261 -            sage: T.hecke_coeff(Ups20,(1,0,1))/Ups20[(1,0,1)]
   1.262 -            -5232247240500
   1.263 -
   1.264 -        """
   1.265 -        ell = self.__l
   1.266 -        k = F.weight()
   1.267 -        coeff = 0
   1.268 -        from sage.rings.all import divisors
   1.269 -        for t1 in divisors(ell):
   1.270 -            for t2 in divisors(t1):
   1.271 -                cosets = self._get_representatives(t1/t2)
   1.272 -                for V in cosets:
   1.273 -                    aprime, bprime, cprime = self._change_variables(V,(a,b,c))
   1.274 -                    if aprime % t1 == 0 and bprime % t2 == 0 and cprime % t2 == 0:
   1.275 -                        try:
   1.276 -                            coeff = coeff + t1**(k-2)*t2**(k-1)*F[(ell*aprime/t1**2,ell*bprime/t1/t2,ell*cprime/t2**2)]
   1.277 -                        except KeyError, msg:
   1.278 -                            raise ValueError, '%s' %(F,msg)
   1.279 -        return coeff
   1.280 -
   1.281 -    def _get_representatives( self, t):
   1.282 -        r"""
   1.283 -        A helper function used in hecke_coeff that computes the right
   1.284 -        coset representatives of `\Gamma^0(t)\SL(2,Z)` where
   1.285 -        `\Gamma^0(t)` is the subgroup of `SL(2,Z)` where the upper lh
   1.286 -        corner is divisible by `t`.
   1.287 - 
   1.288 -        EXAMPLES::
   1.289 -
   1.290 -            sage: T = HeckeOperator(5)
   1.291 -            sage: T._get_representatives(3)
   1.292 -            [
   1.293 -            [ 0  1]  [1 0]  [1 1]  [1 2]
   1.294 -            [-1  0], [0 1], [0 1], [0 1]
   1.295 -            ]
   1.296 -
   1.297 -        NOTE
   1.298 -            We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$
   1.299 -            given by $A \mapsto [1:0]A$.
   1.300 -         """
   1.301 -        try:
   1.302 -            return self.__rep_lists[t]
   1.303 -        except KeyError:
   1.304 -            from sage.matrix.all import MatrixSpace
   1.305 -            M = MatrixSpace(ZZ, 2,2)
   1.306 -        if t == 1:
   1.307 -            return [M([1,0,0,1])]
   1.308 -        from sage.modular.all import P1List
   1.309 -        P = list(P1List(t))
   1.310 -        from sage.rings.all import IntegerModRing, xgcd
   1.311 -        ZZt = IntegerModRing(t)
   1.312 -        rep_list = []
   1.313 -        for x,y in P1List(t):
   1.314 -            e, d,c = xgcd(x,y)
   1.315 -            rep = M([x,y,-c,d])
   1.316 -            rep_list.append(rep)
   1.317 -        self.__rep_lists[t] = rep_list
   1.318 -        return rep_list
   1.319 -
   1.320 -    @staticmethod
   1.321 -    def _change_variables(V, (n,r,m)):
   1.322 -        r"""
   1.323 -        A helper function used in hecke_coeff that computes the
   1.324 -        quadratic form [nprime,rprime,mprime] given by $Q((x,y) V)$
   1.325 -        where $Q=[n,r,m]$ and $V$ is a 2 by 2 matrix
   1.326 -
   1.327 -        EXAMPLES::
   1.328 -
   1.329 -            sage: T = HeckeOperator(5)
   1.330 -            sage: T._change_variables(matrix([[1,2],[2,3]]),(2,1,3))
   1.331 -            (16, 51, 41)
   1.332 -        """
   1.333 -        from sage.rings.all import PolynomialRing, ZZ
   1.334 -        R = PolynomialRing(ZZ,2,'x, y')
   1.335 -        x, y = R.gens()
   1.336 -        g = R(n*x**2+r*x*y+m*y**2)
   1.337 -        a = V[0][0]
   1.338 -        b = V[0][1]
   1.339 -        c = V[1][0]
   1.340 -        d = V[1][1]
   1.341 -        f = g(a*x+c*y,b*x+d*y)
   1.342 -        nprime = f.monomial_coefficient(x**2)
   1.343 -        rprime = f.monomial_coefficient(x*y)
   1.344 -        mprime = f.monomial_coefficient(y**2)
   1.345 -        return nprime, rprime, mprime