Exemple #1
0
def canonical_parameters(group, weight, sign, base_ring):
    """
    Return the canonically normalized parameters associated to a choice
    of group, weight, sign, and base_ring. That is, normalize each of
    these to be of the correct type, perform all appropriate type
    checking, etc.

    EXAMPLES::

        sage: p1 = sage.modular.modsym.modsym.canonical_parameters(5,int(2),1,QQ) ; p1
        (Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
        sage: p2 = sage.modular.modsym.modsym.canonical_parameters(Gamma0(5),2,1,QQ) ; p2
        (Congruence Subgroup Gamma0(5), 2, 1, Rational Field)
        sage: p1 == p2
        True
        sage: type(p1[1])
        <type 'sage.rings.integer.Integer'>
    """
    sign = rings.Integer(sign)
    if not (sign in [-1, 0, 1]):
        raise ValueError("sign must be -1, 0, or 1")

    weight = rings.Integer(weight)
    if weight <= 1:
        raise ValueError("the weight must be at least 2")

    if isinstance(group, (int, rings.Integer)):
        group = arithgroup.Gamma0(group)

    elif isinstance(group, dirichlet.DirichletCharacter):
        try:
            eps = group.minimize_base_ring()
        except NotImplementedError:
            # TODO -- implement minimize_base_ring over finite fields
            eps = group
        G = eps.parent()
        if eps.is_trivial():
            group = arithgroup.Gamma0(eps.modulus())
        else:
            group = (eps, G)
        if base_ring is None: base_ring = eps.base_ring()

    if base_ring is None: base_ring = rational_field.RationalField()

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

    if not base_ring.is_field():
        raise TypeError("(currently) base_ring (=%s) must be a field" %
                        base_ring)

    return group, weight, sign, base_ring
Exemple #2
0
def parse_label(s):
    """
    Given a string s corresponding to a newform label, return the
    corresponding group and index.

    EXAMPLES::

        sage: sage.modular.modform.constructor.parse_label('11a')
        (Congruence Subgroup Gamma0(11), 0)
        sage: sage.modular.modform.constructor.parse_label('11aG1')
        (Congruence Subgroup Gamma1(11), 0)
        sage: sage.modular.modform.constructor.parse_label('11wG1')
        (Congruence Subgroup Gamma1(11), 22)
    """
    m = re.match(r'(\d+)([a-z]+)((?:G.*)?)$', s)
    if not m:
        raise ValueError, "Invalid label: %s" % s
    N, order, G = m.groups()
    N = int(N)
    index = 0
    for c in reversed(order):
        index = 26*index + ord(c)-ord('a')
    if G == '' or G == 'G0':
        G = arithgroup.Gamma0(N)
    elif G == 'G1':
        G = arithgroup.Gamma1(N)
    elif G[:2] == 'GH':
        if G[2] != '[' or G[-1] != ']':
            raise ValueError, "Invalid congruence subgroup label: %s" % G
        gens = [int(g.strip()) for g in G[3:-1].split(',')]
        return arithgroup.GammaH(N, gens)
    else:
        raise ValueError, "Invalid congruence subgroup label: %s" % G
    return G, index
Exemple #3
0
    def __init__(self, level, weight, sign, F):
        """
        Initialize a space of boundary symbols of weight k for Gamma_0(N)
        over base field F.

        INPUT:

        -  ``level`` - int, the level

        -  ``weight`` - integer weight = 2.

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

        -  ``F`` - field

        EXAMPLES::

            sage: B = ModularSymbols(Gamma0(2), 5).boundary_space()
            sage: type(B)
            <class 'sage.modular.modsym.boundary.BoundarySpace_wtk_g0_with_category'>
            sage: B == loads(dumps(B))
            True
        """
        level = int(level)
        sign = int(sign)
        weight = int(weight)
        if not sign in [-1, 0, 1]:
            raise ArithmeticError, "sign must be an int in [-1,0,1]"
        if level <= 0:
            raise ArithmeticError, "level must be positive"
        BoundarySpace.__init__(self,
                               weight=weight,
                               group=arithgroup.Gamma0(level),
                               sign=sign,
                               base_ring=F)
Exemple #4
0
    def __init__(self, level, weight):
        r"""
        Create a space of modular symbols for `\Gamma_0(N)` of given
        weight defined over `\QQ`.

        EXAMPLES::

            sage: m = ModularForms(Gamma0(11),4); m
            Modular Forms space of dimension 4 for Congruence Subgroup Gamma0(11) of weight 4 over Rational Field
            sage: type(m)
            <class 'sage.modular.modform.ambient_g0.ModularFormsAmbient_g0_Q_with_category'>
        """
        ambient.ModularFormsAmbient.__init__(self, arithgroup.Gamma0(level), weight, rings.QQ)
Exemple #5
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())
    def _modular_symbols_space_gamma0(self):
        """
        Return a space of modular symbols for Gamma0, with level a
        random choice from self.levels, weight from self.weights, and
        sign chosen randomly from [1, 0, -1].

        EXAMPLES:
            sage: sage.modular.modsym.tests.Test()._modular_symbols_space_gamma0() # random
            level = 1, weight = 3, sign = 0
            Modular Symbols space of dimension 0 for Gamma_0(1) of weight 3 with sign 0 over Rational Field
        """
        level, weight, sign = self._level_weight_sign()
        M = modsym.ModularSymbols(arithgroup.Gamma0(level), weight, sign)
        self.current_space = M
        return M
Exemple #7
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
Exemple #8
0
    def _coerce_cusp(self, c):
        """
        Coerce the cusp c into ``self``.

        EXAMPLES::

            sage: B = ModularSymbols(DirichletGroup(13).0**3, 5, sign=0).boundary_space()
            sage: [ B(Cusp(i,13)) for i in range(13) ]
            [[0],
            [1/13],
            -zeta4*[1/13],
            [1/13],
            -[1/13],
            -zeta4*[1/13],
            -zeta4*[1/13],
            zeta4*[1/13],
            zeta4*[1/13],
            [1/13],
            -[1/13],
            zeta4*[1/13],
            -[1/13]]
            sage: B._is_equiv(Cusp(oo), Cusp(1,13))
            (True, 1)
            sage: B._is_equiv(Cusp(0), Cusp(1,13))
            (False, None)
            sage: B = ModularSymbols(DirichletGroup(13).0**3, 5, sign=1).boundary_space()
            sage: [ B(Cusp(i,13)) for i in range(13) ]
            [[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
            sage: B._coerce_cusp(Cusp(oo))
            0
            sage: B = ModularSymbols(DirichletGroup(13).0**3, 5, sign=-1).boundary_space()
            sage: [ B(Cusp(i,13)) for i in range(13) ]
            [0,
            [1/13],
            -zeta4*[1/13],
            [1/13],
            -[1/13],
            -zeta4*[1/13],
            -zeta4*[1/13],
            zeta4*[1/13],
            zeta4*[1/13],
            [1/13],
            -[1/13],
            zeta4*[1/13],
            -[1/13]]
            sage: B = ModularSymbols(DirichletGroup(13).0**4, 5, sign=1).boundary_space()
            sage: B._coerce_cusp(Cusp(0))
            [0]
            sage: B = ModularSymbols(DirichletGroup(13).0**4, 5, sign=-1).boundary_space()
            sage: B._coerce_cusp(Cusp(0))
            0
        """
        sign = self.sign()
        i, eps = self._cusp_index(c)
        if i != -1:
            if i == -2:
                return self(0)
            else:
                return BoundarySpaceElement(self, {i : eps})

        if sign != 0:
            i2, eps = self._cusp_index(-c)
            if i2 != -1:
                if i2 == -2: return self(0)
                else: return BoundarySpaceElement(self, {i2:sign*eps})

        # found a new cusp class
        g = self._known_gens
        g.append(c)

        # Does cusp vanish because of stabiliser?
        s = arithgroup.Gamma0(self.level()).cusp_data(c)[0]
        if self.__eps(s[1,1]) != 1:
            self._zero_cusps.append(c)
            del self._known_gens[-1]
            return self(0)

        # Does class vanish because of sign relations?  The relevant
        # relations are
        #
        #    [(u,v)] = (-1)^k [(-u,-v)]
        #    [(u,v)] = sign * [(-u,v)]
        #    [(u,v)] = eps(d) * [(-u,v)]
        #
        # where, in the last line, eps is the character defining
        # our space, and [a,b;c,d] takes (u,v) to (-u,v).
        #
        # Thus (other than for 0 and Infinity), we have that [(u,v)]
        # can only be killed by sign relations when the sign is not
        # equal to eps(d).
        #
        if sign:
            if c.is_zero():
                if sign == -1:
                    self._zero_cusps.append(c)
                    del self._known_gens[-1]
                    return self(0)
            elif c.is_infinity():
                if sign != (-1)**self.weight():
                    self._zero_cusps.append(c)
                    del self._known_gens[-1]
                    return self(0)
            else:
                t, s = self._is_equiv(c, -c)
                if t:
                    if sign != self.__eps(s):
                        self._zero_cusps.append(c)
                        del self._known_gens[-1]
                        return self(0)

        return BoundarySpaceElement(self, {(len(g)-1):1})