示例#1
0
文件: special.py 项目: merbst/psage
def eisenstein_basis(N, k, verbose=False):
    r"""
    Find spanning list of 'easy' generators for the subspace of
    `M_k(\Gamma_0(N))` generated by level 1 Eisenstein series and
    their images of even integer weights up to `k`.

    INPUT:
        - N -- positive integer
        - k -- positive integer
        - ``verbose`` -- bool (default: False)

    OUTPUT:
        - list of monomials in images of level 1 Eisenstein series
        - prec of q-expansions needed to determine element of
          `M_k(\Gamma_0(N))`.

    EXAMPLES::

        sage: from psage.modform.rational.special import eisenstein_basis
        sage: eisenstein_basis(5,4)
        ([E4(q^5)^1, E4(q^1)^1, E2^*(q^5)^2], 3)
        sage: eisenstein_basis(11,2,verbose=True)  # warning below because of verbose
        Warning -- not enough series.
        ([E2^*(q^11)^1], 2)
        sage: eisenstein_basis(11,2,verbose=False)
        ([E2^*(q^11)^1], 2)
    """
    assert N > 1
    if k % 2 != 0:
        return []
    # Make list E of Eisenstein series, to enough precision to
    # determine them, until we span space.
    M = ModularForms(N, k)
    prec = M.echelon_basis()[-1].valuation() + 1
    
    gens = eisenstein_gens(N, k, prec)
    R = PolynomialRing(ZZ, len(gens), ['E%sq%s'%(g[1],g[0]) for g in gens])
    z = [(R.gen(i), g[1]) for i, g in enumerate(gens)]
    m = monomials(z, k)
    
    A = QQ**prec
    V = A.zero_subspace()
    E = []
    for i, z in enumerate(m):
        d = z.degrees()
        f = prod(g[2]**d[i] for i, g in enumerate(gens) if d[i])
        v = A(f.padded_list(prec))
        if v not in V:
            V = V + A.span([v])
            w = [(gens[i][0],gens[i][1],d[i]) for i in range(len(d)) if d[i]]
            E.append(EisensteinMonomial(w))
            if V.dimension() == M.dimension():
                 return E, prec

    if verbose: print "Warning -- not enough series."
    return E, prec
示例#2
0
    def _rank(self, K):
        """
        Return the dimension of the level N space of given weight. 
        """
        if not K is QQ:
            raise NotImplementedError

        if not self.__level.is_prime():
            raise NotImplementedError

        if self.__weight % 2 != 0:
            raise NotImplementedError("Only even weights available")

        N = self.__level

        if N == 1:
            ## By Igusa's theorem on the generators of the graded ring
            P = PowerSeriesRing(ZZ, 't')
            t = P.gen(0)

            dims = 1 / ((1 - t**4) * (1 - t**6) * (1 - t**10) *
                        (1 - t**12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]
        if N == 2:
            ## As in Ibukiyama, Onodera - On the graded ring of modular forms of the Siegel
            ## paramodular group of level 2, Proposition 2
            P = PowerSeriesRing(ZZ, 't')
            t = P.gen(0)

            dims = ((1 + t**10) * (1 + t**12) * (1 + t**11))
            dims = dims / ((1 - t**4) * (1 - t**6) * (1 - t**8) *
                           (1 - t**12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]
        if N == 3:
            ## By Dern, Paramodular forms of degree 2 and level 3, Corollary 5.6
            P = PowerSeriesRing(ZZ, 't')
            t = P.gen(0)

            dims = ((1 + t**12) * (1 + t**8 + t**9 + t**10 + t**11 + t**19))
            dims = dims / ((1 - t**4) * (1 - t**6)**2 *
                           (1 - t**12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]
        if N == 5:
            ## By Marschner, Paramodular forms of degree 2 with particular emphasis on level t = 5,
            ## Corollary 7.3.4. PhD thesis electronically available via the library of
            ## RWTH University, Aachen, Germany
            P = PowerSeriesRing(ZZ, 't')
            t = P.gen(0)

            dims =   t**30 + t**24 + t**23 + 2*t**22 + t**21 + 2*t**20 + t**19 + 2*t**18 \
                   + 2*t**16 + 2*t**14 + 2*t**12 + t**11 + 2*t**10 + t**9 + 2*t**8 + t**7 + t**6 + 1
            dims = dims / ((1 - t**4) * (1 - t**5) * (1 - t**6) *
                           (1 - t**12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]

        if self.__weight == 2:
            ## There are only cuspforms, since there is no elliptic modular form
            ## of weight 2.
            if N < 277:
                ## Poor, Yuen - Paramodular cusp forms tells us that all forms are
                ## Gritsenko lifts
                return JacobiFormD1NN_Gamma(self.__level, 2)._rank(QQ)

            raise NotImplementedError
        elif self.__weight == 4:
            ## This is the formula cited by Poor and Yuen in Paramodular cusp forms
            cuspidal_dim = Integer((N**2 - 143) / Integer(576) +
                                   N / Integer(8) + kronecker_symbol(-1, N) *
                                   (N - 12) / Integer(96) +
                                   kronecker_symbol(2, N) / Integer(8) +
                                   kronecker_symbol(3, N) / Integer(12) +
                                   kronecker_symbol(-3, N) * N / Integer(36))
        else:
            ## This is the formula given by Ibukiyama in
            ## Relations of dimension of automorphic forms of Sp(2,R) and its compact twist Sp(2),
            ## Theorem 4
            p = N
            k = self.__weight

            ## This is the reversed Ibukiyama symbol [.., .., ..; ..]
            def ibukiyama_symbol(modulus, *args):
                return args[k % modulus]

            ## if p == 2 this formula is wrong. If the weight is even it differs by
            ## -3/16 from the true dimension and if the weight is odd it differs by
            ## -1/16 from the true dimension.
            H1 = (p**2 + 1) * (2 * k - 2) * (2 * k - 3) * (
                2 * k - 4) / Integer(2**9 * 3**3 * 5)
            H2 = (-1)**k * (2 * k - 2) * (2 * k - 4) / Integer(2**8 * 3**2) \
                 + ( (-1)**k * (2 * k - 2) * (2 * k - 4) / Integer(2**7 * 3)
                     if p !=2 else
                     (-1)**k * (2 * k - 2) * (2 * k - 4) / Integer(2**9) )
            H3 = (ibukiyama_symbol(4, k - 2, -k + 1, -k + 2, k - 1) /
                  Integer(2**4 * 3) if p != 3 else 5 *
                  ibukiyama_symbol(4, k - 2, -k + 1, -k + 2, k - 1) /
                  Integer(2**5 * 3))
            H4 = (ibukiyama_symbol(3, 2 * k - 3, -k + 1, -k + 2) /
                  Integer(2**2 * 3**3) if p != 2 else 5 *
                  ibukiyama_symbol(3, 2 * k - 3, -k + 1, -k + 2) /
                  Integer(2**2 * 3**3))
            H5 = ibukiyama_symbol(6, -1, -k + 1, -k + 2, 1, k - 1,
                                  k - 2) / Integer(2**2 * 3**2)
            if p % 4 == 1:
                H6 = 5 * (2 * k - 3) * (p + 1) / Integer(
                    2**7 * 3) + (-1)**k * (p + 1) / Integer(2**7)
            elif p % 4 == 3:
                H6 = (2 * k - 3) * (p - 1) / Integer(
                    2**7) + 5 * (-1)**k * (p - 1) / Integer(2**7 * 3)
            else:
                H6 = 3 * (2 * k - 3) / Integer(2**7) + 7 * (-1)**k / Integer(
                    2**7 * 3)
            if p % 3 == 1:
                H7 =   (2 * k - 3) * (p + 1) / Integer(2 * 3**3) \
                     + (p + 1) * ibukiyama_symbol(3, 0, -1, 1) / Integer(2**2 * 3**3)
            elif p % 3 == 2:
                H7 =   (2 * k - 3) * (p - 1) / Integer(2**2 * 3**3) \
                     + (p - 1) * ibukiyama_symbol(3, 0, -1, 1) / Integer(2 * 3**3)
            else:
                H7 =   5 * (2 * k - 3) / Integer(2**2 * 3**3) \
                     + ibukiyama_symbol(3, 0, -1, 1) / Integer(3**3)
            H8 = ibukiyama_symbol(12, 1, 0, 0, -1, -1, -1, -1, 0, 0, 1, 1,
                                  1) / Integer(2 * 3)
            H9 = (2 * ibukiyama_symbol(6, 1, 0, 0, -1, 0, 0) / Integer(3**2)
                  if p != 2 else ibukiyama_symbol(6, 1, 0, 0, -1, 0, 0) /
                  Integer(2 * 3**2))
            H10 = (1 + kronecker_symbol(5, p)) * ibukiyama_symbol(
                5, 1, 0, 0, -1, 0) / Integer(5)
            H11 = (1 + kronecker_symbol(2, p)) * ibukiyama_symbol(
                4, 1, 0, 0, -1) / Integer(2**3)
            if p % 12 == 1:
                H12 = ibukiyama_symbol(3, 0, 1, -1) / Integer(2 * 3)
            elif p % 12 == 11:
                H12 = (-1)**k / Integer(2 * 3)
            elif p == 2 or p == 3:
                H12 = (-1)**k / Integer(2**2 * 3)
            else:
                H12 = 0

            I1 = ibukiyama_symbol(6, 0, 1, 1, 0, -1, -1) / Integer(6)
            I2 = ibukiyama_symbol(3, -2, 1, 1) / Integer(2 * 3**2)
            if p == 3:
                I3 = ibukiyama_symbol(3, -2, 1, 1) / Integer(3**2)
            elif p % 3 == 1:
                I3 = 2 * ibukiyama_symbol(3, -1, 1, 0) / Integer(3**2)
            else:
                I3 = 2 * ibukiyama_symbol(3, -1, 0, 1) / Integer(3**2)
            I4 = ibukiyama_symbol(4, -1, 1, 1, -1) / Integer(2**2)
            I5 = (-1)**k / Integer(2**3)
            I6 = (-1)**k * (2 - kronecker_symbol(-1, p)) / Integer(2**4)
            I7 = -(-1)**k * (2 * k - 3) / Integer(2**3 * 3)
            I8 = -p * (2 * k - 3) / Integer(2**4 * 3**2)
            I9 = -1 / Integer(2**3 * 3)
            I10 = (p + 1) / Integer(2**3 * 3)
            I11 = -(1 + kronecker_symbol(-1, p)) / Integer(8)
            I12 = -(1 + kronecker_symbol(-3, p)) / Integer(6)

            cuspidal_dim =   H1 + H2 + H3 + H4 + H5 + H6 + H7 + H8 + H9 + H10 + H11 + H12 \
                           + I1 + I2 + I3 + I4 + I5 + I6 + I7 + I8 + I9 + I10 + I11 + I12

        mfs = ModularForms(1, self.__weight)

        return cuspidal_dim + mfs.dimension() + mfs.cuspidal_subspace(
        ).dimension()
示例#3
0
    def _rank(self, K):
        """
        Return the dimension of the level N space of given weight. 
        """
        if not K is QQ:
            raise NotImplementedError

        if not self.__level.is_prime():
            raise NotImplementedError

        if self.__weight % 2 != 0:
            raise NotImplementedError("Only even weights available")

        N = self.__level

        if N == 1:
            ## By Igusa's theorem on the generators of the graded ring
            P = PowerSeriesRing(ZZ, "t")
            t = P.gen(0)

            dims = 1 / ((1 - t ** 4) * (1 - t ** 6) * (1 - t ** 10) * (1 - t ** 12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]
        if N == 2:
            ## As in Ibukiyama, Onodera - On the graded ring of modular forms of the Siegel
            ## paramodular group of level 2, Proposition 2
            P = PowerSeriesRing(ZZ, "t")
            t = P.gen(0)

            dims = (1 + t ** 10) * (1 + t ** 12) * (1 + t ** 11)
            dims = dims / ((1 - t ** 4) * (1 - t ** 6) * (1 - t ** 8) * (1 - t ** 12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]
        if N == 3:
            ## By Dern, Paramodular forms of degree 2 and level 3, Corollary 5.6
            P = PowerSeriesRing(ZZ, "t")
            t = P.gen(0)

            dims = (1 + t ** 12) * (1 + t ** 8 + t ** 9 + t ** 10 + t ** 11 + t ** 19)
            dims = dims / ((1 - t ** 4) * (1 - t ** 6) ** 2 * (1 - t ** 12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]
        if N == 5:
            ## By Marschner, Paramodular forms of degree 2 with particular emphasis on level t = 5,
            ## Corollary 7.3.4. PhD thesis electronically available via the library of
            ## RWTH University, Aachen, Germany
            P = PowerSeriesRing(ZZ, "t")
            t = P.gen(0)

            dims = (
                t ** 30
                + t ** 24
                + t ** 23
                + 2 * t ** 22
                + t ** 21
                + 2 * t ** 20
                + t ** 19
                + 2 * t ** 18
                + 2 * t ** 16
                + 2 * t ** 14
                + 2 * t ** 12
                + t ** 11
                + 2 * t ** 10
                + t ** 9
                + 2 * t ** 8
                + t ** 7
                + t ** 6
                + 1
            )
            dims = dims / ((1 - t ** 4) * (1 - t ** 5) * (1 - t ** 6) * (1 - t ** 12)).add_bigoh(self.__weight + 1)

            return dims[self.__weight]

        if self.__weight == 2:
            ## There are only cuspforms, since there is no elliptic modular form
            ## of weight 2.
            if N < 277:
                ## Poor, Yuen - Paramodular cusp forms tells us that all forms are
                ## Gritsenko lifts
                return JacobiFormD1NN_Gamma(self.__level, 2)._rank(QQ)

            raise NotImplementedError
        elif self.__weight == 4:
            ## This is the formula cited by Poor and Yuen in Paramodular cusp forms
            cuspidal_dim = Integer(
                (N ** 2 - 143) / Integer(576)
                + N / Integer(8)
                + kronecker_symbol(-1, N) * (N - 12) / Integer(96)
                + kronecker_symbol(2, N) / Integer(8)
                + kronecker_symbol(3, N) / Integer(12)
                + kronecker_symbol(-3, N) * N / Integer(36)
            )
        else:
            ## This is the formula given by Ibukiyama in
            ## Relations of dimension of automorphic forms of Sp(2,R) and its compact twist Sp(2),
            ## Theorem 4
            p = N
            k = self.__weight

            ## This is the reversed Ibukiyama symbol [.., .., ..; ..]
            def ibukiyama_symbol(modulus, *args):
                return args[k % modulus]

            ## if p == 2 this formula is wrong. If the weight is even it differs by
            ## -3/16 from the true dimension and if the weight is odd it differs by
            ## -1/16 from the true dimension.
            H1 = (p ** 2 + 1) * (2 * k - 2) * (2 * k - 3) * (2 * k - 4) / Integer(2 ** 9 * 3 ** 3 * 5)
            H2 = (-1) ** k * (2 * k - 2) * (2 * k - 4) / Integer(2 ** 8 * 3 ** 2) + (
                (-1) ** k * (2 * k - 2) * (2 * k - 4) / Integer(2 ** 7 * 3)
                if p != 2
                else (-1) ** k * (2 * k - 2) * (2 * k - 4) / Integer(2 ** 9)
            )
            H3 = (
                ibukiyama_symbol(4, k - 2, -k + 1, -k + 2, k - 1) / Integer(2 ** 4 * 3)
                if p != 3
                else 5 * ibukiyama_symbol(4, k - 2, -k + 1, -k + 2, k - 1) / Integer(2 ** 5 * 3)
            )
            H4 = (
                ibukiyama_symbol(3, 2 * k - 3, -k + 1, -k + 2) / Integer(2 ** 2 * 3 ** 3)
                if p != 2
                else 5 * ibukiyama_symbol(3, 2 * k - 3, -k + 1, -k + 2) / Integer(2 ** 2 * 3 ** 3)
            )
            H5 = ibukiyama_symbol(6, -1, -k + 1, -k + 2, 1, k - 1, k - 2) / Integer(2 ** 2 * 3 ** 2)
            if p % 4 == 1:
                H6 = 5 * (2 * k - 3) * (p + 1) / Integer(2 ** 7 * 3) + (-1) ** k * (p + 1) / Integer(2 ** 7)
            elif p % 4 == 3:
                H6 = (2 * k - 3) * (p - 1) / Integer(2 ** 7) + 5 * (-1) ** k * (p - 1) / Integer(2 ** 7 * 3)
            else:
                H6 = 3 * (2 * k - 3) / Integer(2 ** 7) + 7 * (-1) ** k / Integer(2 ** 7 * 3)
            if p % 3 == 1:
                H7 = (2 * k - 3) * (p + 1) / Integer(2 * 3 ** 3) + (p + 1) * ibukiyama_symbol(3, 0, -1, 1) / Integer(
                    2 ** 2 * 3 ** 3
                )
            elif p % 3 == 2:
                H7 = (2 * k - 3) * (p - 1) / Integer(2 ** 2 * 3 ** 3) + (p - 1) * ibukiyama_symbol(
                    3, 0, -1, 1
                ) / Integer(2 * 3 ** 3)
            else:
                H7 = 5 * (2 * k - 3) / Integer(2 ** 2 * 3 ** 3) + ibukiyama_symbol(3, 0, -1, 1) / Integer(3 ** 3)
            H8 = ibukiyama_symbol(12, 1, 0, 0, -1, -1, -1, -1, 0, 0, 1, 1, 1) / Integer(2 * 3)
            H9 = (
                2 * ibukiyama_symbol(6, 1, 0, 0, -1, 0, 0) / Integer(3 ** 2)
                if p != 2
                else ibukiyama_symbol(6, 1, 0, 0, -1, 0, 0) / Integer(2 * 3 ** 2)
            )
            H10 = (1 + kronecker_symbol(5, p)) * ibukiyama_symbol(5, 1, 0, 0, -1, 0) / Integer(5)
            H11 = (1 + kronecker_symbol(2, p)) * ibukiyama_symbol(4, 1, 0, 0, -1) / Integer(2 ** 3)
            if p % 12 == 1:
                H12 = ibukiyama_symbol(3, 0, 1, -1) / Integer(2 * 3)
            elif p % 12 == 11:
                H12 = (-1) ** k / Integer(2 * 3)
            elif p == 2 or p == 3:
                H12 = (-1) ** k / Integer(2 ** 2 * 3)
            else:
                H12 = 0

            I1 = ibukiyama_symbol(6, 0, 1, 1, 0, -1, -1) / Integer(6)
            I2 = ibukiyama_symbol(3, -2, 1, 1) / Integer(2 * 3 ** 2)
            if p == 3:
                I3 = ibukiyama_symbol(3, -2, 1, 1) / Integer(3 ** 2)
            elif p % 3 == 1:
                I3 = 2 * ibukiyama_symbol(3, -1, 1, 0) / Integer(3 ** 2)
            else:
                I3 = 2 * ibukiyama_symbol(3, -1, 0, 1) / Integer(3 ** 2)
            I4 = ibukiyama_symbol(4, -1, 1, 1, -1) / Integer(2 ** 2)
            I5 = (-1) ** k / Integer(2 ** 3)
            I6 = (-1) ** k * (2 - kronecker_symbol(-1, p)) / Integer(2 ** 4)
            I7 = -(-1) ** k * (2 * k - 3) / Integer(2 ** 3 * 3)
            I8 = -p * (2 * k - 3) / Integer(2 ** 4 * 3 ** 2)
            I9 = -1 / Integer(2 ** 3 * 3)
            I10 = (p + 1) / Integer(2 ** 3 * 3)
            I11 = -(1 + kronecker_symbol(-1, p)) / Integer(8)
            I12 = -(1 + kronecker_symbol(-3, p)) / Integer(6)

            cuspidal_dim = (
                H1
                + H2
                + H3
                + H4
                + H5
                + H6
                + H7
                + H8
                + H9
                + H10
                + H11
                + H12
                + I1
                + I2
                + I3
                + I4
                + I5
                + I6
                + I7
                + I8
                + I9
                + I10
                + I11
                + I12
            )

        mfs = ModularForms(1, self.__weight)

        return cuspidal_dim + mfs.dimension() + mfs.cuspidal_subspace().dimension()
def _siegel_modular_forms_generators(parent, prec=None, degree=0):
    r"""
    Compute the four Igusa generators of the ring of Siegel modular forms 
    of degree 2 and level 1 and even weight (this happens if weights='even').  
    If weights = 'all' you get the Siegel modular forms of degree 2, level 1 
    and even and odd weight.

    EXAMPLES::

        sage: A, B, C, D = SiegelModularFormsAlgebra().gens()
        sage: C[(2, 0, 9)]
        -390420
        sage: D[(4, 2, 5)]
        17689760
        sage: A2, B2, C2, D2 = SiegelModularFormsAlgebra().gens(prec=50)
        sage: A[(1, 0, 1)] == A2[(1, 0, 1)]
        True
        sage: A3, B3, C3, D3 = SiegelModularFormsAlgebra().gens(prec=500)
        sage: B2[(2, 1, 3)] == B3[(2, 1, 3)]
        True

    TESTS::

        sage: from sage.modular.siegel.siegel_modular_forms_algebra import _siegel_modular_forms_generators
        sage: S = SiegelModularFormsAlgebra()
        sage: S.gens() == _siegel_modular_forms_generators(S)
        True
    """
    group = parent.group()
    weights = parent.weights()
    if prec is None:
        prec = parent.default_prec()
    if group == 'Sp(4,Z)' and 0 == degree:
        from sage.modular.all import ModularForms
        E4 = ModularForms(1, 4).gen(0)
        M6 = ModularForms(1, 6)
        E6 = ModularForms(1, 6).gen(0)
        M8 = ModularForms(1, 8)
        M10 = ModularForms(1, 10)
        Delta = ModularForms(1, 12).cuspidal_subspace().gen(0)
        M14 = ModularForms(1, 14)
        A = SiegelModularForm(60 * E4, M6(0), prec=prec, name='Igusa_4')
        B = SiegelModularForm(-84 * E6, M8(0), prec=prec, name='Igusa_6')
        C = SiegelModularForm(M10(0), -Delta, prec=prec, name='Igusa_10')
        D = SiegelModularForm(Delta, M14(0), prec=prec, name='Igusa_12')
        # TODO: the base_ring of A, B, ... should be ZZ
        # Here a hack for now:
        a = [A, B, C, D]
        b = []
        from sage.rings.all import ZZ
        for F in a:
            c = F.coeffs()
            for f in c.iterkeys():
                c[f] = ZZ(c[f])
            F = parent.element_class(parent=parent,
                                     weight=F.weight(),
                                     coeffs=c,
                                     prec=prec,
                                     name=F.name())
            b.append(F)
        if weights == 'even': return b
        if weights == 'all':
            from fastmult import chi35
            coeffs35 = chi35(prec, b[0], b[1], b[2], b[3])
            from sage.groups.all import KleinFourGroup
            G = KleinFourGroup()
            from sage.algebras.all import GroupAlgebra
            R = GroupAlgebra(G)
            det = R(G.gen(0))
            E = parent.element_class(parent=parent,
                                     weight=35,
                                     coeffs=coeffs35,
                                     prec=prec,
                                     name='Delta_35')
            E = E * det
            b.append(E)
            return b
        raise ValueError, "weights = '%s': should be 'all' or 'even'" % weights
    if group == 'Sp(4,Z)' and weights == 'even' and 2 == degree:
        b = _siegel_modular_forms_generators(parent=parent)
        c = []
        for F in b:
            i = b.index(F)
            for G in b[(i + 1):]:
                c.append(F.satoh_bracket(G))
        return c
    raise NotImplementedError, "Not yet implemented"