Ejemplo n.º 1
0
def AbelianVariety(X):
    """
    Create the abelian variety corresponding to the given defining
    data.

    INPUT:


    -  ``X`` - an integer, string, newform, modsym space,
       congruence subgroup or tuple of congruence subgroups


    OUTPUT: a modular abelian variety

    EXAMPLES::

        sage: AbelianVariety(Gamma0(37))
        Abelian variety J0(37) of dimension 2
        sage: AbelianVariety('37a')
        Newform abelian subvariety 37a of dimension 1 of J0(37)
        sage: AbelianVariety(Newform('37a'))
        Newform abelian subvariety 37a of dimension 1 of J0(37)
        sage: AbelianVariety(ModularSymbols(37).cuspidal_submodule())
        Abelian variety J0(37) of dimension 2
        sage: AbelianVariety((Gamma0(37), Gamma0(11)))
        Abelian variety J0(37) x J0(11) of dimension 3
        sage: AbelianVariety(37)
        Abelian variety J0(37) of dimension 2
        sage: AbelianVariety([1,2,3])
        Traceback (most recent call last):
        ...
        TypeError: X must be an integer, string, newform, modsym space, congruence subgroup or tuple of congruence subgroups
    """
    if isinstance(X, (int, long, Integer)):
        X = Gamma0(X)
    if is_CongruenceSubgroup(X):
        X = X.modular_symbols().cuspidal_submodule()
    elif isinstance(X, str):
        from sage.modular.modform.constructor import Newform
        f = Newform(X, names='a')
        return ModularAbelianVariety_newform(f, internal_name=True)
    elif isinstance(X, sage.modular.modform.element.Newform):
        return ModularAbelianVariety_newform(X)

    if is_ModularSymbolsSpace(X):
        return abvar.ModularAbelianVariety_modsym(X)

    if isinstance(X,
                  (tuple, list)) and all([is_CongruenceSubgroup(G)
                                          for G in X]):
        return abvar.ModularAbelianVariety(X)

    raise TypeError(
        "X must be an integer, string, newform, modsym space, congruence subgroup or tuple of congruence subgroups"
    )
Ejemplo n.º 2
0
def AbelianVariety(X):
    """
    Create the abelian variety corresponding to the given defining
    data.

    INPUT:


    -  ``X`` - an integer, string, newform, modsym space,
       congruence subgroup or tuple of congruence subgroups


    OUTPUT: a modular abelian variety

    EXAMPLES::

        sage: AbelianVariety(Gamma0(37))
        Abelian variety J0(37) of dimension 2
        sage: AbelianVariety('37a')
        Newform abelian subvariety 37a of dimension 1 of J0(37)
        sage: AbelianVariety(Newform('37a'))
        Newform abelian subvariety 37a of dimension 1 of J0(37)
        sage: AbelianVariety(ModularSymbols(37).cuspidal_submodule())
        Abelian variety J0(37) of dimension 2
        sage: AbelianVariety((Gamma0(37), Gamma0(11)))
        Abelian variety J0(37) x J0(11) of dimension 3
        sage: AbelianVariety(37)
        Abelian variety J0(37) of dimension 2
        sage: AbelianVariety([1,2,3])
        Traceback (most recent call last):
        ...
        TypeError: X must be an integer, string, newform, modsym space, congruence subgroup or tuple of congruence subgroups
    """
    if isinstance(X, (int, long, Integer)):
        X = Gamma0(X)
    if is_CongruenceSubgroup(X):
        X = X.modular_symbols().cuspidal_submodule()
    elif isinstance(X, str):
        from sage.modular.modform.constructor import Newform
        f = Newform(X, names='a')
        return ModularAbelianVariety_newform(f, internal_name=True)
    elif isinstance(X, sage.modular.modform.element.Newform):
        return ModularAbelianVariety_newform(X)

    if is_ModularSymbolsSpace(X):
        return abvar.ModularAbelianVariety_modsym(X)

    if isinstance(X, (tuple,list)) and all([is_CongruenceSubgroup(G) for G in X]):
        return abvar.ModularAbelianVariety(X)

    raise TypeError("X must be an integer, string, newform, modsym space, congruence subgroup or tuple of congruence subgroups")
Ejemplo n.º 3
0
    def __init__(self, group, weight, base_ring, character=None):
        """
        Create an ambient space of modular forms.
        
        EXAMPLES::
        
            sage: m = ModularForms(Gamma1(20),20); m
            Modular Forms space of dimension 238 for Congruence Subgroup Gamma1(20) of weight 20 over Rational Field
            sage: m.is_ambient()
            True
        """
        if not arithgroup.is_CongruenceSubgroup(group):
            raise TypeError, 'group (=%s) must be a congruence subgroup' % group
        weight = rings.Integer(weight)

        if character is None and arithgroup.is_Gamma0(group):
            character = dirichlet.TrivialCharacter(group.level(), base_ring)

        space.ModularFormsSpace.__init__(self, group, weight, character,
                                         base_ring)
        try:
            d = self.dimension()
        except NotImplementedError:
            d = None
        hecke.AmbientHeckeModule.__init__(self, base_ring, d, group.level(),
                                          weight)
Ejemplo n.º 4
0
    def __init__(self, group, weight, base_ring, character=None, eis_only=False):
        """
        Create an ambient space of modular forms.

        EXAMPLES::

            sage: m = ModularForms(Gamma1(20),20); m
            Modular Forms space of dimension 238 for Congruence Subgroup Gamma1(20) of weight 20 over Rational Field
            sage: m.is_ambient()
            True
        """
        if not arithgroup.is_CongruenceSubgroup(group):
            raise TypeError('group (=%s) must be a congruence subgroup'%group)
        weight = rings.Integer(weight)

        if character is None and arithgroup.is_Gamma0(group):
            character = dirichlet.TrivialCharacter(group.level(), base_ring)

        self._eis_only=eis_only
        space.ModularFormsSpace.__init__(self, group, weight, character, base_ring)
        if eis_only:
            d = self._dim_eisenstein()
        else:
            d = self.dimension()
        hecke.AmbientHeckeModule.__init__(self, base_ring, d, group.level(), weight)
Ejemplo n.º 5
0
    def __init__(self, group, base_ring=QQ):
        r"""
        The ring of modular forms (of weights 0 or at least 2) for a congruence
        subgroup of `{\rm SL}_2(\ZZ)`, with coefficients in a specified base ring.

        INPUT:

        - ``group`` -- a congruence subgroup of `{\rm SL}_2(\ZZ)`, or a
          positive integer `N` (interpreted as `\Gamma_0(N)`)

        - ``base_ring`` (ring, default: `\QQ`) -- a base ring, which should be
          `\QQ`, `\ZZ`, or the integers mod `p` for some prime `p`.

        EXAMPLES::

            sage: ModularFormsRing(Gamma1(13))
            Ring of modular forms for Congruence Subgroup Gamma1(13) with coefficients in Rational Field
            sage: m = ModularFormsRing(4); m
            Ring of modular forms for Congruence Subgroup Gamma0(4) with coefficients in Rational Field
            sage: m.modular_forms_of_weight(2)
            Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(4) of weight 2 over Rational Field
            sage: m.modular_forms_of_weight(10)
            Modular Forms space of dimension 6 for Congruence Subgroup Gamma0(4) of weight 10 over Rational Field
            sage: m == loads(dumps(m))
            True
            sage: m.generators()
            [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10)),
            (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10))]
            sage: m.q_expansion_basis(2,10)
            [1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10),
             q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)]
            sage: m.q_expansion_basis(3,10)
            []
            sage: m.q_expansion_basis(10,10)
            [1 + 10560*q^6 + 3960*q^8 + O(q^10),
             q - 8056*q^7 - 30855*q^9 + O(q^10),
             q^2 - 796*q^6 - 8192*q^8 + O(q^10),
             q^3 + 66*q^7 + 832*q^9 + O(q^10),
             q^4 + 40*q^6 + 528*q^8 + O(q^10),
             q^5 + 20*q^7 + 190*q^9 + O(q^10)]
        """
        if isinstance(group, (int, long, Integer)):
            group = Gamma0(group)
        elif not is_CongruenceSubgroup(group):
            raise ValueError("Group (=%s) should be a congruence subgroup")

        if base_ring != ZZ and not base_ring.is_prime_field():
            raise ValueError(
                "Base ring (=%s) should be QQ, ZZ or a finite prime field")

        self.__group = group
        self.__base_ring = base_ring
        self.__cached_maxweight = ZZ(-1)
        self.__cached_gens = []
        self.__cached_cusp_maxweight = ZZ(-1)
        self.__cached_cusp_gens = []
Ejemplo n.º 6
0
    def __init__(self, group, base_ring=QQ):
        r"""
        INPUT:

        - ``group`` -- a congruence subgroup of `{\rm SL}_2(\ZZ)`, or a
          positive integer `N` (interpreted as `\Gamma_0(N)`)

        - ``base_ring`` (ring, default: `\QQ`) -- a base ring, which should be
          `\QQ`, `\ZZ`, or the integers mod `p` for some prime `p`.

        TESTS::

        Check that :trac:`15037` is fixed::

            sage: ModularFormsRing(3.4)
            Traceback (most recent call last):
            ...
            ValueError: Group (=3.40000000000000) should be a congruence subgroup
            sage: ModularFormsRing(Gamma0(2), base_ring=PolynomialRing(ZZ,x))
            Traceback (most recent call last):
            ...
            ValueError: Base ring (=Univariate Polynomial Ring in x over Integer Ring) should be QQ, ZZ or a finite prime field

        ::

            sage: TestSuite(ModularFormsRing(1)).run()
            sage: TestSuite(ModularFormsRing(Gamma0(6))).run()
            sage: TestSuite(ModularFormsRing(Gamma1(4))).run()

        .. TODO::

            - Add graded modular forms over non-trivial Dirichlet character;
            - makes gen_forms returns modular forms over base rings other than `QQ`;
            - implement binary operations between two forms with different groups.
        """
        if isinstance(group, (int, Integer)):
            group = Gamma0(group)
        elif not is_CongruenceSubgroup(group):
            raise ValueError("Group (=%s) should be a congruence subgroup" %
                             group)

        if base_ring != ZZ and not base_ring.is_field(
        ) and not base_ring.is_finite():
            raise ValueError(
                "Base ring (=%s) should be QQ, ZZ or a finite prime field" %
                base_ring)

        self.__group = group
        self.__cached_maxweight = ZZ(-1)
        self.__cached_gens = []
        self.__cached_cusp_maxweight = ZZ(-1)
        self.__cached_cusp_gens = []
        Parent.__init__(self,
                        base=base_ring,
                        category=GradedAlgebras(base_ring))
Ejemplo n.º 7
0
    def __init__(self, group, base_ring=QQ):
        r"""
        The ring of modular forms (of weights 0 or at least 2) for a congruence
        subgroup of `{\rm SL}_2(\ZZ)`, with coefficients in a specified base ring.

        INPUT:

        - ``group`` -- a congruence subgroup of `{\rm SL}_2(\ZZ)`, or a
          positive integer `N` (interpreted as `\Gamma_0(N)`)

        - ``base_ring`` (ring, default: `\QQ`) -- a base ring, which should be
          `\QQ`, `\ZZ`, or the integers mod `p` for some prime `p`.

        EXAMPLES::

            sage: ModularFormsRing(Gamma1(13))
            Ring of modular forms for Congruence Subgroup Gamma1(13) with coefficients in Rational Field
            sage: m = ModularFormsRing(4); m
            Ring of modular forms for Congruence Subgroup Gamma0(4) with coefficients in Rational Field
            sage: m.modular_forms_of_weight(2)
            Modular Forms space of dimension 2 for Congruence Subgroup Gamma0(4) of weight 2 over Rational Field
            sage: m.modular_forms_of_weight(10)
            Modular Forms space of dimension 6 for Congruence Subgroup Gamma0(4) of weight 10 over Rational Field
            sage: m == loads(dumps(m))
            True
            sage: m.generators()
            [(2, 1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10)),
            (2, q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10))]
            sage: m.q_expansion_basis(2,10)
            [1 + 24*q^2 + 24*q^4 + 96*q^6 + 24*q^8 + O(q^10),
             q + 4*q^3 + 6*q^5 + 8*q^7 + 13*q^9 + O(q^10)]
            sage: m.q_expansion_basis(3,10)
            []
            sage: m.q_expansion_basis(10,10)
            [1 + 10560*q^6 + 3960*q^8 + O(q^10),
             q - 8056*q^7 - 30855*q^9 + O(q^10),
             q^2 - 796*q^6 - 8192*q^8 + O(q^10),
             q^3 + 66*q^7 + 832*q^9 + O(q^10),
             q^4 + 40*q^6 + 528*q^8 + O(q^10),
             q^5 + 20*q^7 + 190*q^9 + O(q^10)]
        """
        if isinstance(group, (int, long, Integer)):
            group = Gamma0(group)
        elif not is_CongruenceSubgroup(group):
            raise ValueError("Group (=%s) should be a congruence subgroup")

        if base_ring != ZZ and not base_ring.is_prime_field():
            raise ValueError("Base ring (=%s) should be QQ, ZZ or a finite prime field")

        self.__group = group
        self.__base_ring = base_ring
        self.__cached_maxweight = ZZ(-1)
        self.__cached_gens = []
        self.__cached_cusp_maxweight = ZZ(-1)
        self.__cached_cusp_gens = []
Ejemplo n.º 8
0
    def __init__(self, group=1, base_ring=QQ, name='E2'):
        r"""
        INPUT:

        - ``group`` (default: `{\rm SL}_2(\ZZ)`) -- a congruence subgroup of
          `{\rm SL}_2(\ZZ)`, or a positive integer `N` (interpreted as
          `\Gamma_0(N)`).

        - ``base_ring`` (ring, default: `\QQ`) -- a base ring, which should be
          `\QQ`, `\ZZ`, or the integers mod `p` for some prime `p`.

        - ``name`` (str, default: ``'E2'``) -- a variable name corresponding to
          the weight 2 Eisenstein series.

        TESTS:

            sage: M = QuasiModularForms(1)
            sage: M.group()
            Modular Group SL(2,Z)
            sage: M.base_ring()
            Rational Field
            sage: QuasiModularForms(Integers(5))
            Traceback (most recent call last):
            ...
            ValueError: Group (=Ring of integers modulo 5) should be a congruence subgroup

        ::

            sage: TestSuite(QuasiModularForms(1)).run()
            sage: TestSuite(QuasiModularForms(Gamma0(3))).run()
            sage: TestSuite(QuasiModularForms(Gamma1(3))).run()
        """
        if not isinstance(name, str):
            raise TypeError("`name` must be a string")
        #check if the group is SL2(Z)
        if isinstance(group, (int, Integer)):
            group = Gamma0(group)
        elif not is_CongruenceSubgroup(group):
            raise ValueError("Group (=%s) should be a congruence subgroup" %
                             group)

        #Check if the base ring is the rationnal field
        if base_ring != QQ:
            raise NotImplementedError(
                "base ring other than Q are not yet supported for quasimodular forms ring"
            )

        self.__group = group
        self.__modular_forms_subring = ModularFormsRing(group, base_ring)
        self.__polynomial_subring = self.__modular_forms_subring[name]
        Parent.__init__(self,
                        base=base_ring,
                        category=GradedAlgebras(base_ring))
Ejemplo n.º 9
0
    def __init__(self,
                 group = arithgroup.Gamma0(1),
                 weight = 2,
                 sign = 0,
                 base_ring = rings.QQ,
                 character = None):
        """
        Space of boundary symbols for a congruence subgroup of SL_2(Z).

        This class is an abstract base class, so only derived classes
        should be instantiated.

        INPUT:


        -  ``weight`` - int, the weight

        -  ``group`` - arithgroup.congroup_generic.CongruenceSubgroup, a congruence
           subgroup.

        -  ``sign`` - int, either -1, 0, or 1

        -  ``base_ring`` - rings.Ring (defaults to the
           rational numbers)


        EXAMPLES::

            sage: B = ModularSymbols(Gamma0(11),2).boundary_space()
            sage: isinstance(B, sage.modular.modsym.boundary.BoundarySpace)
            True
            sage: B == loads(dumps(B))
            True
        """
        weight = int(weight)
        if weight <= 1:
            raise ArithmeticError("weight must be at least 2")
        if not arithgroup.is_CongruenceSubgroup(group):
            raise TypeError("group must be a congruence subgroup")
        sign = int(sign)
        if not isinstance(base_ring, rings.Ring) and rings.is_CommutativeRing(base_ring):
            raise TypeError("base_ring must be a commutative ring")
        if character is None and arithgroup.is_Gamma0(group):
            character = dirichlet.TrivialCharacter(group.level(), base_ring)
        (self.__group, self.__weight, self.__character,
          self.__sign, self.__base_ring) = (group, weight,
                                             character, sign, base_ring)
        self._known_gens = []
        self._known_gens_repr = []
        self._is_zero = []
        hecke.HeckeModule_generic.__init__(self, base_ring, group.level())
Ejemplo n.º 10
0
 def __init__(self,
              group = arithgroup.Gamma0(1),
              weight = 2,
              sign = 0,
              base_ring = rings.QQ,
              character = None):
     """
     Space of boundary symbols for a congruence subgroup of SL_2(Z).
     
     This class is an abstract base class, so only derived classes
     should be instantiated.
     
     INPUT:
     
     
     -  ``weight`` - int, the weight
     
     -  ``group`` - arithgroup.congroup_generic.CongruenceSubgroup, a congruence
        subgroup.
     
     -  ``sign`` - int, either -1, 0, or 1
     
     -  ``base_ring`` - rings.Ring (defaults to the
        rational numbers)
     
     
     EXAMPLES::
     
         sage: B = ModularSymbols(Gamma0(11),2).boundary_space()
         sage: isinstance(B, sage.modular.modsym.boundary.BoundarySpace)
         True
         sage: B == loads(dumps(B))
         True
     """
     weight = int(weight)
     if weight <= 1:
         raise ArithmeticError, "weight must be at least 2"
     if not arithgroup.is_CongruenceSubgroup(group):
         raise TypeError, "group must be a congruence subgroup"
     sign = int(sign)
     if not isinstance(base_ring, rings.Ring) and rings.is_CommutativeRing(base_ring):
         raise TypeError, "base_ring must be a commutative ring"
     if character == None and arithgroup.is_Gamma0(group):
         character = dirichlet.TrivialCharacter(group.level(), base_ring)
     (self.__group, self.__weight, self.__character,
       self.__sign, self.__base_ring) = (group, weight,
                                          character, sign, base_ring)
     self._known_gens = []
     self._known_gens_repr = []
     self._is_zero = []
     hecke.HeckeModule_generic.__init__(self, base_ring, group.level())
Ejemplo n.º 11
0
def canonical_parameters(group, level, weight, base_ring):
    """
    Given a group, level, weight, and base_ring as input by the user,
    return a canonicalized version of them, where level is a Sage
    integer, group really is a group, weight is a Sage integer, and
    base_ring a Sage ring. Note that we can't just get the level from
    the group, because we have the convention that the character for
    Gamma1(N) is None (which makes good sense).

    INPUT:


    -  ``group`` - int, long, Sage integer, group,
       dirichlet character, or

    -  ``level`` - int, long, Sage integer, or group

    -  ``weight`` - coercible to Sage integer

    -  ``base_ring`` - commutative Sage ring


    OUTPUT:


    -  ``level`` - Sage integer

    -  ``group`` - congruence subgroup

    -  ``weight`` - Sage integer

    -  ``ring`` - commutative Sage ring


    EXAMPLES::

        sage: from sage.modular.modform.constructor import canonical_parameters
        sage: v = canonical_parameters(5, 5, int(7), ZZ); v
        (5, Congruence Subgroup Gamma0(5), 7, Integer Ring)
        sage: type(v[0]), type(v[1]), type(v[2]), type(v[3])
        (<type 'sage.rings.integer.Integer'>,
         <class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class_with_category'>,
         <type 'sage.rings.integer.Integer'>,
         <type 'sage.rings.integer_ring.IntegerRing_class'>)
        sage: canonical_parameters( 5, 7, 7, ZZ )
        Traceback (most recent call last):
        ...
        ValueError: group and level do not match.
    """
    weight = rings.Integer(weight)
    if weight <= 0:
        raise NotImplementedError, "weight must be at least 1"

    if isinstance(group, dirichlet.DirichletCharacter):
        if ( group.level() != rings.Integer(level) ):
            raise ValueError, "group.level() and level do not match."
        group = group.minimize_base_ring()
        level = rings.Integer(level)

    elif arithgroup.is_CongruenceSubgroup(group):
        if ( rings.Integer(level) != group.level() ):
            raise ValueError, "group.level() and level do not match."
        # normalize the case of SL2Z
        if arithgroup.is_SL2Z(group) or \
           arithgroup.is_Gamma1(group) and group.level() == rings.Integer(1):
            group = arithgroup.Gamma0(rings.Integer(1))

    elif group is None:
        pass

    else:
        try:
            m = rings.Integer(group)
        except TypeError:
            raise TypeError, "group of unknown type."
        level = rings.Integer(level)
        if ( m != level ):
            raise ValueError, "group and level do not match."
        group = arithgroup.Gamma0(m)

    if not is_CommutativeRing(base_ring):
        raise TypeError, "base_ring (=%s) must be a commutative ring"%base_ring

    # it is *very* important to include the level as part of the data
    # that defines the key, since dirichlet characters of different
    # levels can compare equal, but define much different modular
    # forms spaces.
    return level, group, weight, base_ring
Ejemplo n.º 12
0
def ModularForms(group  = 1,
                 weight = 2,
                 base_ring = None,
                 use_cache = True,
                 prec = defaults.DEFAULT_PRECISION):
    r"""
    Create an ambient space of modular forms.

    INPUT:


    -  ``group`` - A congruence subgroup or a Dirichlet
       character eps.

    -  ``weight`` - int, the weight, which must be an
       integer = 1.

    -  ``base_ring`` - the base ring (ignored if group is
       a Dirichlet character)


    Create using the command ModularForms(group, weight, base_ring)
    where group could be either a congruence subgroup or a Dirichlet
    character.

    EXAMPLES: First we create some spaces with trivial character::

        sage: ModularForms(Gamma0(11),2).dimension()
        2
        sage: ModularForms(Gamma0(1),12).dimension()
        2

    If we give an integer N for the congruence subgroup, it defaults to
    `\Gamma_0(N)`::

        sage: ModularForms(1,12).dimension()
        2
        sage: ModularForms(11,4)
        Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field

    We create some spaces for `\Gamma_1(N)`.

    ::

        sage: ModularForms(Gamma1(13),2)
        Modular Forms space of dimension 13 for Congruence Subgroup Gamma1(13) of weight 2 over Rational Field
        sage: ModularForms(Gamma1(13),2).dimension()
        13
        sage: [ModularForms(Gamma1(7),k).dimension() for k in [2,3,4,5]]
        [5, 7, 9, 11]
        sage: ModularForms(Gamma1(5),11).dimension()
        12

    We create a space with character::

        sage: e = (DirichletGroup(13).0)^2
        sage: e.order()
        6
        sage: M = ModularForms(e, 2); M
        Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
        sage: f = M.T(2).charpoly('x'); f
        x^3 + (-2*zeta6 - 2)*x^2 - 2*zeta6*x + 14*zeta6 - 7
        sage: f.factor()
        (x - zeta6 - 2) * (x - 2*zeta6 - 1) * (x + zeta6 + 1)

    We can also create spaces corresponding to the groups `\Gamma_H(N)` intermediate
    between `\Gamma_0(N)` and `\Gamma_1(N)`::

        sage: G = GammaH(30, [11])
        sage: M = ModularForms(G, 2); M
        Modular Forms space of dimension 20 for Congruence Subgroup Gamma_H(30) with H generated by [11] of weight 2 over Rational Field
        sage: M.T(7).charpoly().factor()  # long time (7s on sage.math, 2011)
        (x + 4) * x^2 * (x - 6)^4 * (x + 6)^4 * (x - 8)^7 * (x^2 + 4)

    More examples of spaces with character::

        sage: e = DirichletGroup(5, RationalField()).gen(); e
        Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1

        sage: m = ModularForms(e, 2); m
        Modular Forms space of dimension 2, character [-1] and weight 2 over Rational Field
        sage: m == loads(dumps(m))
        True
        sage: m.T(2).charpoly('x')
        x^2 - 1
        sage: m = ModularForms(e, 6); m.dimension()
        4
        sage: m.T(2).charpoly('x')
        x^4 - 917*x^2 - 42284

    This came up in a subtle bug (trac #5923)::

        sage: ModularForms(gp(1), gap(12))
        Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field

    This came up in another bug (related to trac #8630)::

        sage: chi = DirichletGroup(109, CyclotomicField(3)).0
        sage: ModularForms(chi, 2, base_ring = CyclotomicField(15))
        Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 15 and degree 8

    We create some weight 1 spaces. The first example works fine, since we can prove purely by Riemann surface theory that there are no weight 1 cusp forms::

        sage: M = ModularForms(Gamma1(11), 1); M
        Modular Forms space of dimension 5 for Congruence Subgroup Gamma1(11) of weight 1 over Rational Field
        sage: M.basis()
        [
        1 + 22*q^5 + O(q^6),
        q + 4*q^5 + O(q^6),
        q^2 - 4*q^5 + O(q^6),
        q^3 - 5*q^5 + O(q^6),
        q^4 - 3*q^5 + O(q^6)
        ]
        sage: M.cuspidal_subspace().basis()
        [
        ]
        sage: M == M.eisenstein_subspace()
        True

    This example doesn't work so well, because we can't calculate the cusp
    forms; but we can still work with the Eisenstein series.

        sage: M = ModularForms(Gamma1(57), 1); M
        Modular Forms space of dimension (unknown) for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
        sage: M.basis()
        Traceback (most recent call last):
        ...
        NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general
        sage: M.cuspidal_subspace().basis()
        Traceback (most recent call last):
        ...
        NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general

        sage: E = M.eisenstein_subspace(); E
        Eisenstein subspace of dimension 36 of Modular Forms space of dimension (unknown) for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
        sage: (E.0 + E.2).q_expansion(40)
        1 + q^2 + 1473/2*q^36 - 1101/2*q^37 + q^38 - 373/2*q^39 + O(q^40)

    """
    if isinstance(group, dirichlet.DirichletCharacter):
        if base_ring is None:
            base_ring = group.minimize_base_ring().base_ring()
    if base_ring is None:
        base_ring = rings.QQ

    if isinstance(group, dirichlet.DirichletCharacter) \
           or arithgroup.is_CongruenceSubgroup(group):
        level = group.level()
    else:
        level = group

    key = canonical_parameters(group, level, weight, base_ring)

    if use_cache and _cache.has_key(key):
         M = _cache[key]()
         if not (M is None):
             M.set_precision(prec)
             return M

    (level, group, weight, base_ring) = key

    M = None
    if arithgroup.is_Gamma0(group):
        M = ambient_g0.ModularFormsAmbient_g0_Q(group.level(), weight)
        if base_ring != rings.QQ:
            M = ambient_R.ModularFormsAmbient_R(M, base_ring)

    elif arithgroup.is_Gamma1(group):
        M = ambient_g1.ModularFormsAmbient_g1_Q(group.level(), weight)
        if base_ring != rings.QQ:
            M = ambient_R.ModularFormsAmbient_R(M, base_ring)

    elif arithgroup.is_GammaH(group):
        M = ambient_g1.ModularFormsAmbient_gH_Q(group, weight)
        if base_ring != rings.QQ:
            M = ambient_R.ModularFormsAmbient_R(M, base_ring)

    elif isinstance(group, dirichlet.DirichletCharacter):
        eps = group
        if eps.base_ring().characteristic() != 0:
            # TODO -- implement this
            # Need to add a lift_to_char_0 function for characters,
            # and need to still remember eps.
            raise NotImplementedError, "currently the character must be over a ring of characteristic 0."
        eps = eps.minimize_base_ring()
        if eps.is_trivial():
            return ModularForms(eps.modulus(), weight, base_ring,
                                use_cache = use_cache,
                                prec = prec)
        M = ambient_eps.ModularFormsAmbient_eps(eps, weight)
        if base_ring != eps.base_ring():
            M = M.base_extend(base_ring) # ambient_R.ModularFormsAmbient_R(M, base_ring)

    if M is None:
        raise NotImplementedError, \
           "computation of requested space of modular forms not defined or implemented"

    M.set_precision(prec)
    _cache[key] = weakref.ref(M)
    return M
Ejemplo n.º 13
0
def ModularForms(group=1,
                 weight=2,
                 base_ring=None,
                 eis_only=False,
                 use_cache=True,
                 prec=defaults.DEFAULT_PRECISION):
    r"""
    Create an ambient space of modular forms.

    INPUT:

    - ``group`` - A congruence subgroup or a Dirichlet character eps.

    - ``weight`` - int, the weight, which must be an integer >= 1.

    - ``base_ring`` - the base ring (ignored if group is a Dirichlet character)

    - ``eis_only`` - if True, compute only the Eisenstein part of the space.
      Only permitted (and only useful) in weight 1, where computing dimensions
      of cusp form spaces is expensive.

    Create using the command ModularForms(group, weight, base_ring)
    where group could be either a congruence subgroup or a Dirichlet
    character.

    EXAMPLES: First we create some spaces with trivial character::

        sage: ModularForms(Gamma0(11),2).dimension()
        2
        sage: ModularForms(Gamma0(1),12).dimension()
        2

    If we give an integer N for the congruence subgroup, it defaults to
    `\Gamma_0(N)`::

        sage: ModularForms(1,12).dimension()
        2
        sage: ModularForms(11,4)
        Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field

    We create some spaces for `\Gamma_1(N)`.

    ::

        sage: ModularForms(Gamma1(13),2)
        Modular Forms space of dimension 13 for Congruence Subgroup Gamma1(13) of weight 2 over Rational Field
        sage: ModularForms(Gamma1(13),2).dimension()
        13
        sage: [ModularForms(Gamma1(7),k).dimension() for k in [2,3,4,5]]
        [5, 7, 9, 11]
        sage: ModularForms(Gamma1(5),11).dimension()
        12

    We create a space with character::

        sage: e = (DirichletGroup(13).0)^2
        sage: e.order()
        6
        sage: M = ModularForms(e, 2); M
        Modular Forms space of dimension 3, character [zeta6] and weight 2 over Cyclotomic Field of order 6 and degree 2
        sage: f = M.T(2).charpoly('x'); f
        x^3 + (-2*zeta6 - 2)*x^2 - 2*zeta6*x + 14*zeta6 - 7
        sage: f.factor()
        (x - zeta6 - 2) * (x - 2*zeta6 - 1) * (x + zeta6 + 1)

    We can also create spaces corresponding to the groups `\Gamma_H(N)` intermediate
    between `\Gamma_0(N)` and `\Gamma_1(N)`::

        sage: G = GammaH(30, [11])
        sage: M = ModularForms(G, 2); M
        Modular Forms space of dimension 20 for Congruence Subgroup Gamma_H(30) with H generated by [11] of weight 2 over Rational Field
        sage: M.T(7).charpoly().factor()  # long time (7s on sage.math, 2011)
        (x + 4) * x^2 * (x - 6)^4 * (x + 6)^4 * (x - 8)^7 * (x^2 + 4)

    More examples of spaces with character::

        sage: e = DirichletGroup(5, RationalField()).gen(); e
        Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1

        sage: m = ModularForms(e, 2); m
        Modular Forms space of dimension 2, character [-1] and weight 2 over Rational Field
        sage: m == loads(dumps(m))
        True
        sage: m.T(2).charpoly('x')
        x^2 - 1
        sage: m = ModularForms(e, 6); m.dimension()
        4
        sage: m.T(2).charpoly('x')
        x^4 - 917*x^2 - 42284

    This came up in a subtle bug (:trac:`5923`)::

        sage: ModularForms(gp(1), gap(12))
        Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field

    This came up in another bug (related to :trac:`8630`)::

        sage: chi = DirichletGroup(109, CyclotomicField(3)).0
        sage: ModularForms(chi, 2, base_ring = CyclotomicField(15))
        Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 15 and degree 8

    We create some weight 1 spaces. Here modular symbol algorithms do not work.
    In some small examples we can prove using Riemann--Roch that there are no
    cusp forms anyway, so the entire space is Eisenstein::

        sage: M = ModularForms(Gamma1(11), 1); M
        Modular Forms space of dimension 5 for Congruence Subgroup Gamma1(11) of weight 1 over Rational Field
        sage: M.basis()
        [
        1 + 22*q^5 + O(q^6),
        q + 4*q^5 + O(q^6),
        q^2 - 4*q^5 + O(q^6),
        q^3 - 5*q^5 + O(q^6),
        q^4 - 3*q^5 + O(q^6)
        ]
        sage: M.cuspidal_subspace().basis()
        [
        ]
        sage: M == M.eisenstein_subspace()
        True

    When this does not work (which happens as soon as the level is more than
    about 30), we use the Hecke stability algorithm of George Schaeffer::

        sage: M = ModularForms(Gamma1(57), 1); M # long time
        Modular Forms space of dimension 38 for Congruence Subgroup Gamma1(57) of weight 1 over Rational Field
        sage: M.cuspidal_submodule().basis() # long time
        [
        q - q^4 + O(q^6),
        q^3 - q^4 + O(q^6)
        ]

    The Eisenstein subspace in weight 1 can be computed quickly, without
    triggering the expensive computation of the cuspidal part::

        sage: E = EisensteinForms(Gamma1(59), 1); E # indirect doctest
        Eisenstein subspace of dimension 29 of Modular Forms space for Congruence Subgroup Gamma1(59) of weight 1 over Rational Field
        sage: (E.0 + E.2).q_expansion(40)
        1 + q^2 + 196*q^29 - 197*q^30 - q^31 + q^33 + q^34 + q^37 + q^38 - q^39 + O(q^40)

    """
    if isinstance(group, dirichlet.DirichletCharacter):
        if base_ring is None:
            base_ring = group.minimize_base_ring().base_ring()
    if base_ring is None:
        base_ring = rings.QQ

    if isinstance(group, dirichlet.DirichletCharacter) \
           or arithgroup.is_CongruenceSubgroup(group):
        level = group.level()
    else:
        level = group

    eis_only = bool(eis_only)
    key = canonical_parameters(group, level, weight, base_ring) + (eis_only, )

    if eis_only and weight != 1:
        raise ValueError("eis_only parameter only valid in weight 1")

    if use_cache and key in _cache:
        M = _cache[key]()
        if not (M is None):
            M.set_precision(prec)
            return M

    (level, group, weight, base_ring, eis_only) = key

    M = None
    if arithgroup.is_Gamma0(group):
        M = ModularFormsAmbient_g0_Q(group.level(), weight)
        if base_ring != rings.QQ:
            M = ambient_R.ModularFormsAmbient_R(M, base_ring)

    elif arithgroup.is_Gamma1(group):
        M = ModularFormsAmbient_g1_Q(group.level(), weight, eis_only)
        if base_ring != rings.QQ:
            M = ambient_R.ModularFormsAmbient_R(M, base_ring)

    elif arithgroup.is_GammaH(group):
        M = ModularFormsAmbient_gH_Q(group, weight, eis_only)
        if base_ring != rings.QQ:
            M = ambient_R.ModularFormsAmbient_R(M, base_ring)

    elif isinstance(group, dirichlet.DirichletCharacter):
        eps = group
        if eps.base_ring().characteristic() != 0:
            # TODO -- implement this
            # Need to add a lift_to_char_0 function for characters,
            # and need to still remember eps.
            raise NotImplementedError(
                "currently the character must be over a ring of characteristic 0."
            )
        eps = eps.minimize_base_ring()
        if eps.is_trivial():
            return ModularForms(eps.modulus(),
                                weight,
                                base_ring,
                                use_cache=use_cache,
                                prec=prec)
        M = ModularFormsAmbient_eps(eps, weight, eis_only=eis_only)
        if base_ring != eps.base_ring():
            M = M.base_extend(
                base_ring)  # ambient_R.ModularFormsAmbient_R(M, base_ring)

    if M is None:
        raise NotImplementedError(
            "computation of requested space of modular forms not defined or implemented"
        )

    M.set_precision(prec)
    _cache[key] = weakref.ref(M)
    return M