Esempio n. 1
0
File: space.py Progetto: roed314/OMS
class PSModularSymbolSpace(Module):
    r"""
    A class for spaces of modular symbols that use Glenn Stevens' conventions.
    This class should not be instantiated directly by the user: this is handled
    by the factory object ``PSModularSymbols``.

    INPUT:

    - ``group`` -- congruence subgroup

    - ``coefficients`` -- a coefficient module

    - ``sign`` -- (default: 0); 0, -1, or 1

    EXAMPLES::

        sage: D = Distributions(2, 11)
        sage: M = PSModularSymbols(Gamma0(2), coefficients=D); M.sign()
        0
        sage: M = PSModularSymbols(Gamma0(2), coefficients=D, sign=-1); M.sign()
        -1
        sage: M = PSModularSymbols(Gamma0(2), coefficients=D, sign=1); M.sign()
        1

    """
    def __init__(self, group, coefficients, sign=0):
        r"""
        INPUT:

            See :class:`PSModularSymbolSpace`

        EXAMPLES::

            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma0(11), coefficients=D)
            sage: type(M)
            <class 'sage.modular.pollack_stevens.space.PSModularSymbolSpace_with_category'>
            sage: TestSuite(M).run()

        """
        Module.__init__(self, coefficients.base_ring())
        if sign not in [0,-1,1]:
            # sign must be be 0, -1 or 1
            raise ValueError, "sign must be 0, -1, or 1"
        self._group = group
        self._coefficients = coefficients
        if coefficients.is_symk():
            self.Element = PSModularSymbolElement_symk
        else:
            self.Element = PSModularSymbolElement_dist
        self._sign = sign
        # should distingish between Gamma0 and Gamma1...
        self._source = ManinRelations(group.level())

        # Register the action of 2x2 matrices on self. 
        
        if coefficients.is_symk():
            action = PSModSymAction(Sigma0(1), self)
        else:
            action = PSModSymAction(Sigma0(self.prime()), self)
            
        self._populate_coercion_lists_(action_list=[action])

    def _element_constructor_(self, data):
        r"""
        Construct an element of self from data.
        """
        if isinstance(data, PSModularSymbolElement):
            data = data._map
        elif isinstance(data, ManinMap):
            pass
        else:
            # a dict, or a single distribution specifying a constant symbol, etc
            data = ManinMap(self._coefficients, self._source, data)

        if data._codomain != self._coefficients:
            data = data.extend_codomain(self._coefficients)
 
        return self.element_class(data, self, construct=True)

    def _coerce_map_from_(self, other):
        r"""
        Used for comparison and coercion.

        EXAMPLE::

            sage: M1 = PSModularSymbols(Gamma0(11), coefficients=Symk(3))
            sage: M2 = PSModularSymbols(Gamma0(11), coefficients=Symk(3,Qp(11)))
            sage: M3 = PSModularSymbols(Gamma0(11), coefficients=Symk(4))
            sage: M4 = PSModularSymbols(Gamma0(11), coefficients=Distributions(3, 11, 10))
            sage: M1.has_coerce_map_from(M2)
            False
            sage: M2.has_coerce_map_from(M1)
            True
            sage: M1.has_coerce_map_from(M3)
            False
            sage: M1.has_coerce_map_from(M4)
            False
            sage: M2.has_coerce_map_from(M4)
            True
        """
        if isinstance(other, PSModularSymbolSpace):
            if other.group() == self.group() \
                and self.coefficient_module().has_coerce_map_from(other.coefficient_module()):
                return True
        else:
            return False

    def _repr_(self):
        r"""
        Returns print representation.

        EXAMPLES::

            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M._repr_()
            'Space of overconvergent modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Space of 11-adic distributions with k=2 action and precision cap 20'

        """
        if self.coefficient_module().is_symk():
            s = "Space of modular symbols for "
        else:
            s = "Space of overconvergent modular symbols for "
        s += "%s with sign %s and values in %s"%(self.group(), self.sign(), self.coefficient_module())
        return s

    def source(self):
        r"""
        Return the domain of the modular symbols in this space.

        OUTPUT:

        A :class:`sage.modular.pollack_stevens.fund_domain.PSModularSymbolsDomain`

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.source()
            Manin Relations of level 2

        """
        return self._source

    def coefficient_module(self):
        r"""
        Return the coefficient module of this space.

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.coefficient_module()
            Space of 11-adic distributions with k=2 action and precision cap 20
            sage: M.coefficient_module() is D
            True

        """
        return self._coefficients

    def group(self):
        r"""
        Return the congruence subgroup of this space.

        EXAMPLES::

            sage: D = Distributions(2, 5)
            sage: G = Gamma0(23)
            sage: M = PSModularSymbols(G, coefficients=D)
            sage: M.group()
            Congruence Subgroup Gamma0(23)
            sage: D = Symk(4)
            sage: G = Gamma1(11)
            sage: M = PSModularSymbols(G, coefficients=D)
            sage: M.group()
            Congruence Subgroup Gamma1(11)

        """
        return self._group

    def sign(self):
        r"""
        Return the sign of this space.

        EXAMPLES::

            sage: D = Distributions(3, 17)
            sage: M = PSModularSymbols(Gamma(5), coefficients=D)
            sage: M.sign()
            0
            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma1(8), coefficients=D, sign=-1)
            sage: M.sign()
            -1

        """
        return self._sign

    def ngens(self):
        r"""
        Returns the number of generators defining this space.

        EXAMPLES::

            sage: D = Distributions(4, 29)
            sage: M = PSModularSymbols(Gamma1(12), coefficients=D)
            sage: M.ngens()
            5
            sage: D = Symk(2)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.ngens()
            2
        """
        return len(self._source.indices())

    def ncoset_reps(self):
        r"""
        Returns the number of coset representatives defining the domain of the
        modular symbols in this space.

        OUTPUT:

        The number of coset representatives stored in the manin relations.
        (Just the size of P^1(Z/NZ))

        EXAMPLES::

            sage: D = Symk(2)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.ncoset_reps()
            3

        """
        return len(self._source.reps())

    def level(self):
        r"""
        Returns the level `N`, where this space is of level `\Gamma_0(N)`.

        EXAMPLES::

            sage: D = Distributions(7, 11)
            sage: M = PSModularSymbols(Gamma1(14), coefficients=D)
            sage: M.level()
            14

        """
        return self._source.level()

    def _grab_relations(self):
        r"""
        This is used internally as part of a consistency check.

        EXAMPLES::

            sage: D = Distributions(4, 3)
            sage: M = PSModularSymbols(Gamma1(13), coefficients=D)
            sage: M._grab_relations()
            [[(1, [1 0]
            [0 1], 0)], [(-1, [-1 -1]
            [ 0 -1], 0)], [(1, [1 0]
            [0 1], 2)], [(1, [1 0]
                [0 1], 3)], [(1, [1 0]
                    [0 1], 4)], [(1, [1 0]
                        [0 1], 5)]]
        """
        S0N = Sigma0(self._source._N)
        v = []
        for r in range(len(self._source.gens())):
            for j in range(len(self._source.reps())):
                R = self._source.relations(j)
                if len(R) == 1 and R[0][2] == self._source.indices(r):
                    if R[0][0] != -1 or R[0][1] != S0N(1):
                        v = v + [R]
        return v

    def precision_cap(self):
        r"""
        Returns the number of moments of each element of this space.

        EXAMPLES::

            sage: D = Distributions(2, 5)
            sage: M = PSModularSymbols(Gamma1(13), coefficients=D)
            sage: M.precision_cap()
            20
            sage: D = Distributions(3, 7, prec_cap=10)
            sage: M = PSModularSymbols(Gamma0(7), coefficients=D)
            sage: M.precision_cap()
            10

        """
### WARNING -- IF YOU ARE WORKING IN SYM^K(Q^2) THIS WILL JUST RETURN K-1.  NOT GOOD

        return self.coefficient_module()._prec_cap

    def weight(self):
        r"""
        Returns the weight of this space.

        .. WARNING::

            We emphasize that in the Pollack-Stevens notation, this is the usual
            weight minus 2, so a classical weight 2 modular form corresponds to a
            modular symbol of "weight 0".

        EXAMPLES::

            sage: D = Symk(5)
            sage: M = PSModularSymbols(Gamma1(7), coefficients=D)
            sage: M.weight()
            5

        """
        return self.coefficient_module()._k

    def prime(self):
        r"""
        Returns the prime of this space.

        EXAMPLES:
            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma(2), coefficients=D)
            sage: M.prime()
            11

        """
        return self.coefficient_module()._p

    def _p_stabilize_parent_space(self, p, new_base_ring):
        r"""
        Returns the space of Pollack-Stevens modular symbols of level
        ``p * N``, with changed base ring.  This is used internally when
        constructing the p-stabilization of a modular symbol.

        INPUT:

        - ``p`` -- prime number
        - ``new_base_ring`` -- the base ring of the result

        OUTPUT:

        The space of modular symbols of level ``p * N``, where N is the level
        of this space.

        EXAMPLES::

            sage: D = Distributions(2, 7); M = PSModularSymbols(Gamma(13), coefficients=D)
            sage: M._p_stabilize_parent_space(7, M.base_ring())
            Space of overconvergent modular symbols for Congruence Subgroup
            Gamma(91) with sign 0 and values in Space of 7-adic distributions
            with k=2 action and precision cap 20

            sage: D = Distributions(4, 17); M = PSModularSymbols(Gamma1(3), coefficients=D)
            sage: M._p_stabilize_parent_space(17, Qp(17))
            Space of overconvergent modular symbols for Congruence
            Subgroup Gamma1(51) with sign 0 and values in Space of
            17-adic distributions with k=4 action and precision cap 20

        """
        N = self.level()
        if N % p == 0:
            raise ValueError("the level isn't prime to p")
        from sage.modular.arithgroup.all import Gamma, is_Gamma, Gamma0, is_Gamma0, Gamma1, is_Gamma1
        G = self.group()
        if is_Gamma0(G):
            G = Gamma0(N*p)
        elif is_Gamma1(G):
            G = Gamma1(N*p)
        elif is_Gamma(G):
            G = Gamma(N*p)
        else:
            raise NotImplementedError
        return PSModularSymbols(G, coefficients=self.coefficient_module().change_ring(new_base_ring), sign=self.sign())

    def _specialize_parent_space(self, new_base_ring):
        r"""
        Internal function that is used by the specialize method on
        elements.  It returns a space with same parameters as this
        one, but over ``new_base_ring``.

        INPUT:

        - ``new_base_ring`` -- a ring

        OUTPUT:

        A space of modular symbols to which our space specializes.

        EXAMPLES::

            sage: D = Distributions(7, 5);  M = PSModularSymbols(Gamma0(2), coefficients=D); M
            Space of overconvergent modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Space of 5-adic distributions with k=7 action and precision cap 20
            sage: M._specialize_parent_space(QQ)
            Space of modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Sym^7 Q^2
            sage: M.base_ring()
            5-adic Ring with capped absolute precision 20
            sage: M._specialize_parent_space(QQ).base_ring()
            Rational Field

        """
        return PSModularSymbols(self.group(), coefficients=self.coefficient_module().specialize(new_base_ring), sign=self.sign())

    def _lift_parent_space(self, p, M, new_base_ring):
        r"""
        Used internally to lift a space of modular symbols to space of
        overconvergent modular symbols.

        INPUT:

        - ``p`` -- prime
        - ``M`` -- precision cap
        - ``new_base_ring`` -- ring

        OUTPUT:

        A space of distribution valued modular symbols.

        EXAMPLES::

            sage: D = Distributions(4, 17, 2); M = PSModularSymbols(Gamma1(3), coefficients=D)
            sage: D.is_symk()
            False
            sage: M._lift_parent_space(17, 10, Qp(17))
            Traceback (most recent call last):
            ...
            TypeError: Coefficient module must be a Symk
            sage: PSModularSymbols(Gamma1(3), weight=1)._lift_parent_space(17,10,Qp(17))
            Space of overconvergent modular symbols for Congruence Subgroup Gamma1(3) with sign 0 and values in Space of 17-adic distributions with k=1 action and precision cap 10

        """
        if self.coefficient_module().is_symk():
            return PSModularSymbols(self.group(), coefficients=self.coefficient_module().lift(p, M, new_base_ring), sign=self.sign())
        else:
            raise TypeError("Coefficient module must be a Symk")

    def change_ring(self, new_base_ring):
        r"""
        Changes the base ring of this space to ``new_base_ring``.

        INPUT:

        - ``new_base_ring`` -- a ring

        OUTPUT:

        A space of modular symbols over the specified base.

        EXAMPLES::

            sage: from sage.modular.pollack_stevens.distributions import Symk
            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma(6), coefficients=D); M
            Space of modular symbols for Congruence Subgroup Gamma(6) with sign 0 and values in Sym^4 Q^2
            sage: M.change_ring(Qp(5,8))
            Space of modular symbols for Congruence Subgroup Gamma(6) with sign 0 and values in Sym^4 Q_5^2

        """
        return PSModularSymbols(self.group(), coefficients=self.coefficient_module().change_ring(new_base_ring), sign=self.sign())

    def _an_element_(self):
#        WARNING -- THIS ISN'T REALLY AN ELEMENT OF THE SPACE BECAUSE IT DOESN'T
#       SATISFY THE MANIN RELATIONS

        r"""
        Returns the cusps associated to an element of a congruence subgroup.

        OUTPUT:

        An element of the modular symbol space.

        Returns a "typical" element of this space; in this case the constant
        map sending every element to an element of the coefficient module.

        EXAMPLES::

            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma(6), coefficients=D)
            sage: x = M.an_element(); x       # indirect doctest
            Modular symbol of level 6 with values in Sym^4 Q^2
            sage: x.values()
            [(0, 1, 2, 3, 4), (0, 1, 2, 3, 4), (0, 1, 2, 3, 4)]
            sage: D = Symk(2, Qp(11)); M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: x = M.an_element(); x.values()
            [(0, 1 + O(11^20), 2 + O(11^20)), (0, 1 + O(11^20), 2 + O(11^20))]
            sage: x in M
            True

        """
        return self(self.coefficient_module().an_element())

    def random_element(self,M=None):
        r"""
        Returns a random OMS in this space with M moments

        INPUT:

        - ``M`` -- positive integer

        OUTPUT:

        An element of the modular symbol space with ``M`` moments

        Returns a random element in this space by randomly choosing values of distributions
        on all but one divisor, and solves the difference equation to determine the value
        on the last divisor.

        """
        if (M == None) and (not self.coefficient_module().is_symk()):
            M = self.coefficient_module().precision_cap()

        k = self.coefficient_module()._k
        p = self.prime()
        manin = self.source()

#        ## There must be a problem here with that +1 -- should be variable depending on a c of some matrix
#        ## We'll need to divide by some power of p and so we add extra accuracy here.
#        if k != 0:
#            MM = M + valuation(k,p) + 1 + M.exact_log(p)
#        else:
#            MM = M + M.exact_log(p) + 1

        ## this loop runs thru all of the generators (except (0)-(infty)) and randomly chooses a distribution 
        ## to assign to this generator (in the 2,3-torsion cases care is taken to satisfy the relevant relation)
        D = {}
        for g in manin.gens():
            D[g] = self.coefficient_module().random_element(M)
#            print "pre:",D[g]
            if g in manin.reps_with_two_torsion() and g in manin.reps_with_three_torsion:
                raise ValueError("Level 1 not implemented")
            if g in manin.reps_with_two_torsion():
                gamg = manin.two_torsion_matrix(g)
                D[g] = D[g] - D[g] * gamg 
            else:
                if g in manin.reps_with_three_torsion():
                    gamg = manin.three_torsion_matrix(g)
                    D[g] = 2*D[g] - D[g] * gamg - D[g] * gamg**2
#            print "post:",D[g]

        ## now we compute nu_infty of Prop 5.1 of [PS1]
        t = self.coefficient_module().zero_element()
        for g in manin.gens()[1:]:
            if (not g in manin.reps_with_two_torsion()) and (not g in manin.reps_with_three_torsion()):
#                print "g:", g
 #               print "D[g]:",D[g]
  #              print "manin",manin.gammas[g]
   #             print "D*m:",D[g] * manin.gammas[g]
    #            print "-------"
                t += D[g] * manin.gammas[g] - D[g]
            else:
                if g in MR.reps_with_two_torsion():
                    t -= D[g] 
                else:
                    t -= D[g]

        ## If k = 0, then t has total measure zero.  However, this is not true when k != 0  
        ## (unlike Prop 5.1 of [PS1] this is not a lift of classical symbol).  
        ## So instead we simply add (const)*mu_1 to some (non-torsion) v[j] to fix this
        ## here since (mu_1 |_k ([a,b,c,d]-1))(trival char) = chi(a) k a^{k-1} c , 
        ## we take the constant to be minus the total measure of t divided by (chi(a) k a^{k-1} c)

        if k != 0:
            j = 1
            g = manin.gens()[j]
            while (g in manin.reps_with_two_torsion()) or (g in manin.reps_with_three_torsion()) and (j < len(manin.gens())):
                j = j + 1
                g = manin.gens()[j]
            if j == len(manin.gens()):
                raise ValueError("everything is 2 or 3 torsion!  NOT YET IMPLEMENTED IN THIS CASE")

            gam = manin.gammas[g]
            a = gam.matrix()[0,0]
            c = gam.matrix()[1,0]

            if self.coefficient_module()._character != None:
                chara = self.coefficient_module()._character(a)
            else:
                chara = 1
            err = -t.moment(0)/(chara*k*a**(k-1)*c)
            v = [0 for j in range(M)]
            v[1] = 1
            mu_1 = err * self.coefficient_module()(v)
            D[g] += mu_1
#            print "Modifying: ",D[g]
            t = t + mu_1 * gam - mu_1

        Id = manin.gens()[0]
        if not self.coefficient_module().is_symk():
            mu = t.solve_diff_eqn()
            D[Id] = -mu
 #           print "Last:",D[Id]
        else:
            if self.coefficient_module()._k == 0:
                D[Id] = self.coefficient_module().random_element()
            else:
                raise ValueError("Not implemented for symk with k>0 yet")

        return self(D)
Esempio n. 2
0
class PSModularSymbolSpace(Module):
    r"""
    A class for spaces of modular symbols that use Glenn Stevens' conventions.
    This class should not be instantiated directly by the user: this is handled
    by the factory object ``PSModularSymbols``.

    INPUT:

    - ``group`` -- congruence subgroup

    - ``coefficients`` -- a coefficient module

    - ``sign`` -- (default: 0); 0, -1, or 1

    EXAMPLES::

        sage: D = Distributions(2, 11)
        sage: M = PSModularSymbols(Gamma0(2), coefficients=D); M.sign()
        0
        sage: M = PSModularSymbols(Gamma0(2), coefficients=D, sign=-1); M.sign()
        -1
        sage: M = PSModularSymbols(Gamma0(2), coefficients=D, sign=1); M.sign()
        1

    """
    def __init__(self, group, coefficients, sign=0):
        r"""
        INPUT:

            See :class:`PSModularSymbolSpace`

        EXAMPLES::

            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: type(M)
            <class 'sage.modular.pollack_stevens.space.PSModularSymbolSpace_with_category'>
            sage: TestSuite(M).run()

        """
        Module.__init__(self, coefficients.base_ring())
        if sign not in [0,-1,1]:
            # sign must be be 0, -1 or 1
            raise ValueError, "sign must be 0, -1, or 1"
        self._group = group
        self._coefficients = coefficients
        if coefficients.is_symk():
            self.Element = PSModularSymbolElement_symk
        else:
            self.Element = PSModularSymbolElement_dist
        self._sign = sign
        # should distingish between Gamma0 and Gamma1...
        self._source = ManinRelations(group.level())
        # We have to include the first action so that scaling by Z doesn't try to pass through matrices
        actions = [PSModSymAction(ZZ, self), PSModSymAction(M2ZSpace, self)]
        self._populate_coercion_lists_(action_list=actions)

    def _repr_(self):
        r"""
        Returns print representation.

        EXAMPLES::

            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M._repr_()
            'Space of overconvergent modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Space of 11-adic distributions with k=2 action and precision cap 20'

        """
        if self.coefficient_module().is_symk():
            s = "Space of modular symbols for "
        else:
            s = "Space of overconvergent modular symbols for "
        s += "%s with sign %s and values in %s"%(self.group(), self.sign(), self.coefficient_module())
        return s

    def source(self):
        r"""
        Return the domain of the modular symbols in this space.

        OUTPUT:

        A :class:`sage.modular.pollack_stevens.fund_domain.PSModularSymbolsDomain`

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.source()
            Manin Relations of level 2

        """
        return self._source

    def coefficient_module(self):
        r"""
        Return the coefficient module of this space.

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.coefficient_module()
            Space of 11-adic distributions with k=2 action and precision cap 20
            sage: M.coefficient_module() is D
            True

        """
        return self._coefficients

    def group(self):
        r"""
        Return the congruence subgroup of this space.

        EXAMPLES::

            sage: D = Distributions(2, 5)
            sage: G = Gamma0(23)
            sage: M = PSModularSymbols(G, coefficients=D)
            sage: M.group()
            Congruence Subgroup Gamma0(23)
            sage: D = Symk(4)
            sage: G = Gamma1(11)
            sage: M = PSModularSymbols(G, coefficients=D)
            sage: M.group()
            Congruence Subgroup Gamma1(11)

        """
        return self._group

    def sign(self):
        r"""
        Return the sign of this space.

        EXAMPLES::

            sage: D = Distributions(3, 17)
            sage: M = PSModularSymbols(Gamma(5), coefficients=D)
            sage: M.sign()
            0
            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma1(8), coefficients=D, sign=-1)
            sage: M.sign()
            -1

        """
        return self._sign

    def ngens(self):
        r"""
        Returns the number of generators defining this space.

        EXAMPLES::

            sage: D = Distributions(4, 29)
            sage: M = PSModularSymbols(Gamma1(12), coefficients=D)
            sage: M.ngens()
            5
            sage: D = Symk(2)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.ngens()
            2
        """
        return len(self._source.indices())

    def ncoset_reps(self):
        r"""
        Returns the number of coset representatives defining the domain of the
        modular symbols in this space.

        OUTPUT:

        The number of coset representatives stored in the manin relations.
        (Just the size of P^1(Z/NZ))

        EXAMPLES::

            sage: D = Symk(2)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.ncoset_reps()
            3

        """
        return len(self._source.reps())

    def level(self):
        r"""
        Returns the level `N`, where this space is of level `\Gamma_0(N)`.

        EXAMPLES::

            sage: D = Distributions(7, 11)
            sage: M = PSModularSymbols(Gamma1(14), coefficients=D)
            sage: M.level()
            14

        """
        return self._source.level()

    def _grab_relations(self):
        r"""
        This is used internally as part of a consistency check.

        EXAMPLES::

            sage: D = Distributions(4, 3)
            sage: M = PSModularSymbols(Gamma1(13), coefficients=D)
            sage: M._grab_relations()
            [[(1, [1 0]
            [0 1], 0)], [(-1, [-1 -1]
            [ 0 -1], 0)], [(1, [1 0]
            [0 1], 2)], [(1, [1 0]
                [0 1], 3)], [(1, [1 0]
                    [0 1], 4)], [(1, [1 0]
                        [0 1], 5)]]
        """
        v = []
        for r in range(len(self._source.gens())):
            for j in range(len(self._source.reps())):
                R = self._source.relations(j)
                if len(R) == 1 and R[0][2] == self._source.indices(r):
                    if R[0][0] != -1 or R[0][1] != M2ZSpace.one():
                        v = v + [R]
        return v

    def precision_cap(self):
        r"""
        Returns the number of moments of each element of this space.

        EXAMPLES::

            sage: D = Distributions(2, 5)
            sage: M = PSModularSymbols(Gamma1(13), coefficients=D)
            sage: M.precision_cap()
            20
            sage: D = Distributions(3, 7, prec_cap=10)
            sage: M = PSModularSymbols(Gamma0(7), coefficients=D)
            sage: M.precision_cap()
            10

        """
### WARNING -- IF YOU ARE WORKING IN SYM^K(Q^2) THIS WILL JUST RETURN K-1.  NOT GOOD

        return self.coefficient_module()._prec_cap

    def weight(self):
        r"""
        Returns the weight of this space.

        .. WARNING::

            We emphasize that in the Pollack-Stevens notation, this is the usual
            weight minus 2, so a classical weight 2 modular form corresponds to a
            modular symbol of "weight 0".

        EXAMPLES::

            sage: D = Symk(5)
            sage: M = PSModularSymbols(Gamma1(7), coefficients=D)
            sage: M.weight()
            5

        """
        return self.coefficient_module()._k

    def prime(self):
        r"""
        Returns the prime of this space.

        EXAMPLES:
            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma(2), coefficients=D)
            sage: M.prime()
            11

        """
        return self.coefficient_module()._p

    def _p_stabilize_parent_space(self, p, new_base_ring):
        r"""
        Returns the space of Pollack-Stevens modular symbols of level
        ``p * N``, with changed base ring.  This is used internally when
        constructing the p-stabilization of a modular symbol.

        INPUT:

        - ``p`` -- prime number
        - ``new_base_ring`` -- the base ring of the result

        OUTPUT:

        The space of modular symbols of level ``p * N``, where N is the level
        of this space.

        EXAMPLES::

            sage: D = Distributions(2, 7); M = PSModularSymbols(Gamma(13), coefficients=D)
            sage: M._p_stabilize_parent_space(7, M.base_ring())
            Space of overconvergent modular symbols for Congruence Subgroup
            Gamma(91) with sign 0 and values in Space of 7-adic distributions
            with k=2 action and precision cap 20

            sage: D = Distributions(4, 17); M = PSModularSymbols(Gamma1(3), coefficients=D)
            sage: M._p_stabilize_parent_space(17, Qp(17))
            Space of overconvergent modular symbols for Congruence
            Subgroup Gamma1(51) with sign 0 and values in Space of
            17-adic distributions with k=4 action and precision cap 20

        """
        N = self.level()
        if N % p == 0:
            raise ValueError("the level isn't prime to p")
        from sage.modular.arithgroup.all import Gamma, is_Gamma, Gamma0, is_Gamma0, Gamma1, is_Gamma1
        G = self.group()
        if is_Gamma0(G):
            G = Gamma0(N*p)
        elif is_Gamma1(G):
            G = Gamma1(N*p)
        elif is_Gamma(G):
            G = Gamma(N*p)
        else:
            raise NotImplementedError
        return PSModularSymbols(G, coefficients=self.coefficient_module().change_ring(new_base_ring), sign=self.sign())

    def _specialize_parent_space(self, new_base_ring):
        r"""
        Internal function that is used by the specialize method on
        elements.  It returns a space with same parameters as this
        one, but over ``new_base_ring``.

        INPUT:

        - ``new_base_ring`` -- a ring

        OUTPUT:

        A space of modular symbols to which our space specializes.

        EXAMPLES::

            sage: D = Distributions(7, 5);  M = PSModularSymbols(Gamma0(2), coefficients=D); M
            Space of overconvergent modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Space of 5-adic distributions with k=7 action and precision cap 20
            sage: M._specialize_parent_space(QQ)
            Space of modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Sym^7 Q^2
            sage: M.base_ring()
            5-adic Ring with capped absolute precision 20
            sage: M._specialize_parent_space(QQ).base_ring()
            Rational Field

        """
        return PSModularSymbols(self.group(), coefficients=self.coefficient_module().specialize(new_base_ring), sign=self.sign())

    def _lift_parent_space(self, p, M, new_base_ring):
        r"""
        Used internally to lift a space of modular symbols to space of
        overconvergent modular symbols.

        INPUT:

        - ``p`` -- prime
        - ``M`` -- precision cap
        - ``new_base_ring`` -- ring

        OUTPUT:

        A space of distribution valued modular symbols.

        EXAMPLES::

            sage: D = Distributions(4, 17, 2); M = PSModularSymbols(Gamma1(3), coefficients=D)
            sage: D.is_symk()
            False
            sage: M._lift_parent_space(17, 10, Qp(17))
            Traceback (most recent call last):
            ...
            TypeError: Coefficient module must be a Symk
            sage: PSModularSymbols(Gamma1(3), weight=3)._lift_parent_space(17,10,Qp(17))
            Space of overconvergent modular symbols for Congruence Subgroup Gamma1(3) with sign 0 and values in Space of 17-adic distributions with k=1 action and precision cap 10

        """
        if self.coefficient_module().is_symk():
            return PSModularSymbols(self.group(), coefficients=self.coefficient_module().lift(p, M, new_base_ring), sign=self.sign())
        else:
            raise TypeError("Coefficient module must be a Symk")

    def change_ring(self, new_base_ring):
        r"""
        Changes the base ring of this space to ``new_base_ring``.

        INPUT:

        - ``new_base_ring`` -- a ring

        OUTPUT:

        A space of modular symbols over the specified base.

        EXAMPLES::

            sage: from sage.modular.pollack_stevens.distributions import Symk
            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma(6), coefficients=D); M
            Space of modular symbols for Congruence Subgroup Gamma(6) with sign 0 and values in Sym^4 Q^2
            sage: M.change_ring(Qp(5,8))
            Space of modular symbols for Congruence Subgroup Gamma(6) with sign 0 and values in Sym^4 Q_5^2

        """
        return PSModularSymbols(self.group(), coefficients=self.coefficient_module().change_ring(new_base_ring), sign=self.sign())

    def _an_element_(self):
        r"""
        Returns the cusps associated to an element of a congruence subgroup.

        OUTPUT:

        An element of the modular symbol space.

        Returns a "typical" element of this space; in this case the constant
        map sending every element to an element of the coefficient module.

        EXAMPLES::

            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma(6), coefficients=D)
            sage: x = M.an_element(); x       # indirect doctest
            Modular symbol with values in Sym^4 Q^2
            sage: x.values()
            [(0, 1, 2, 3, 4), (0, 1, 2, 3, 4), (0, 1, 2, 3, 4)]
            sage: D = Symk(2, Qp(11)); M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: x = M.an_element(); x.values()
            [(0, 1 + O(11^20), 2 + O(11^20)), (0, 1 + O(11^20), 2 + O(11^20))]
            sage: x in M
            True

        """
        return self(self.coefficient_module().an_element())
Esempio n. 3
0
class ModularSymbolSpace_generic(Module):
    """
    This is the parent class for the generic category of modular symbol spaces. 

    A class for spaces of modular symbols that use Glenn Stevens'
    conventions.

    There are two main differences between the modular symbols in this
    directory and the ones in sage.modular.modsym.

    - There is a shift in the weight: weight `k=0` here corresponds to
      weight `k=2` there.

    - There is a duality: these modular symbols are functions from
      `Div^0(P^1(\QQ))`, the others are formal linear combinations of
      such elements.

    INPUT:

    - ``V`` -- the coefficient module, which should have a right action of `M_2(\ZZ)`
    - ``domain`` -- a set or None, giving the domain
    """
    def __init__(self, group, coefficients, sign=0):
        """
        INPUT:

        - ``group`` -- congruence subgroup
        - ``coefficients`` -- a coefficient module
        - ``sign`` -- (default: 0); 0, -1, 1

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: type(M)
            <class 'sage.modular.pollack_stevens.space.PSModularSymbolSpace_with_category'>
            sage: M.sign()
            0
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D, sign=-1); M.sign()
            -1
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D, sign=1); M.sign()
            1        
        """
        #NEW
        R = coefficients.base_ring()
        Parent.__init__(self, base = R, category = ModularSymbolSpaces(R))
        #NEW
        
        if sign not in [0,-1,1]:
            # sign must be be 0, -1 or 1
            raise ValueError, "sign must be 0, -1, or 1"
        self._group = group
        self._coefficients = coefficients
        if coefficients.is_symk():
            self.Element = SymkModSymElement
        else:
            self.Element = OverconvergentModSymElement
        self._sign = sign
        # should distingish between Gamma0 and Gamma1...
        self._source = ManinRelations(group.level())
        # We have to include the first action so that scaling by Z doesn't try to pass through matrices
        actions = [PSModSymAction(ZZ, self), PSModSymAction(M2ZSpace, self)]
        self._populate_coercion_lists_(action_list=actions)

    def _repr_(self):
        r"""
        Returns print representation.

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D); M._repr_()
            'Space of overconvergent modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Space of 11-adic distributions with k=2 action and precision cap 20'
        """
        if self.coefficient_module().is_symk():
            s = "Space of modular symbols for "
        else:
            s = "Space of overconvergent modular symbols for "
        s += "%s with sign %s and values in %s"%(self.group(), self.sign(), self.coefficient_module())
        return s

    def source(self):
        """
        Return object that represents the domain of the modular
        symbol elements.

        OUTPUT:

        - object of type fund_domain.PSModularSymbolsDomain

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.source()
            Manin Relations of level 2
        """
        return self._source

    def coefficient_module(self):
        r"""
        Returns the coefficient module of self.

        OUTPUT:

        - module

        EXAMPLES::

            sage: D = Distributions(2, 11);  M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.coefficient_module()
            Space of 11-adic distributions with k=2 action and precision cap 20
            sage: M.coefficient_module() == D
            True
            sage: M.coefficient_module() is D
            True
        """
        return self._coefficients

    def group(self):
        r"""
        Returns the congruence subgroup of self.

        EXAMPLES::

            sage: D = Distributions(2, 5)
            sage: G = Gamma0(23)
            sage: M = PSModularSymbols(G, coefficients=D)
            sage: M.group()
            Congruence Subgroup Gamma0(23)
            sage: D = Symk(4)
            sage: G = Gamma1(11)
            sage: M = PSModularSymbols(G, coefficients=D)
            sage: M.group()
            Congruence Subgroup Gamma1(11)
        """
        return self._group

    def sign(self):
        r"""
        Returns the sign of self.

        EXAMPLES::

            sage: D = Distributions(3, 17)
            sage: M = PSModularSymbols(Gamma(5), coefficients=D)
            sage: M.sign()
            0
            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma1(8), coefficients=D, sign=-1)
            sage: M.sign()
            -1
        """
        return self._sign

    def ngens(self):
        r"""
        Returns the number of generators defining self.

        EXAMPLES::

            sage: D = Distributions(4, 29)
            sage: M = PSModularSymbols(Gamma1(12), coefficients=D)
            sage: M.ngens()
            5
            sage: D = Symk(2)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.ngens()
            2
        """
        return len(self._source.indices())

    def ncoset_reps(self):
        r"""
        Returns the number of coset representatives defining the
        full_data of self.

        OUTPUT:

        - The number of coset representatives stored in the manin
          relations. (Just the size of P^1(Z/NZ))

        EXAMPLES::

            sage: D = Symk(2)
            sage: M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: M.ncoset_reps()
            3
        """
        return len(self._source.reps())

    def level(self):
        r"""
        Returns the level `N`, where self is of level `Gamma_0(N)`.

        OUTPUT:

        - The level `N`, where self is of level `Gamma_0(N)`

        EXAMPLES::

            sage: D = Distributions(7, 11)
            sage: M = PSModularSymbols(Gamma1(14), coefficients=D)
            sage: M.level()
            14
        """
        return self._source.level()

    def _grab_relations(self):
        r"""
        This is used internally as part of a consistency check.

        EXAMPLES::

            sage: D = Distributions(4, 3)
            sage: M = PSModularSymbols(Gamma1(13), coefficients=D)
            sage: M._grab_relations()
            [[(1, [1 0]
            [0 1], 0)], [(-1, [-1 -1]
            [ 0 -1], 0)], [(1, [1 0]
            [0 1], 2)], [(1, [1 0]
                [0 1], 3)], [(1, [1 0]
                    [0 1], 4)], [(1, [1 0]
                        [0 1], 5)]]
        """
        v = []
        for r in range(len(self._source.gens())):
            for j in range(len(self._source.reps())):
                R = self._source.relations(j)
                if len(R) == 1 and R[0][2] == self._source.indices(r):
                    if R[0][0] != -1 or R[0][1] != M2ZSpace.one():
                        v = v + [R]
        return v



    def precision_cap(self):
        r"""
        Returns the number of moments of each value of self.

        OUTPUT:

        - Integer

        EXAMPLES::

            sage: D = Distributions(2, 5)
            sage: M = PSModularSymbols(Gamma1(13), coefficients=D)
            sage: M.precision_cap()
            20
            sage: D = Distributions(3, 7, prec_cap=10)
            sage: M = PSModularSymbols(Gamma0(7), coefficients=D)
            sage: M.precision_cap()
            10
        """
        return self.coefficient_module()._prec_cap

    def weight(self):
        r""" 
        Returns the weight of self.

        We emphasize that in the Pollack-Stevens notation, this is the
        usual weight minus 2, so a classical weight 2 modular form corresponds
        to a modular symbol of "weight 0".

        OUTPUT:

        - Integer

        EXAMPLES::

            sage: D = Symk(5)
            sage: M = PSModularSymbols(Gamma1(7), coefficients=D)
            sage: M.weight()
            5
        """
        return self.coefficient_module()._k

    def prime(self):
        r"""
        Returns the prime of self.

        OUTPUT:

        - Integer

        EXAMPLES:
            sage: D = Distributions(2, 11)
            sage: M = PSModularSymbols(Gamma(2), coefficients=D)
            sage: M.prime()
            11
        """
        return self.coefficient_module()._p

    def _p_stabilize_parent_space(self, p, new_base_ring):
        r"""
        Returns the space of Pollack-Stevens modular symbols of level
        p * N, with changed base ring.  This is used internally when
        constructing the p-stabilization of a modular symbol.

        INPUT:

        - ``p`` -- prime number
        - ``new_base_ring`` -- the base ring of the result

        OUTPUT:

        - The space of modular symbols of level p * N, where N is the level of
          self, with precision M.

        EXAMPLES::

            sage: D = Distributions(2, 7); M = PSModularSymbols(Gamma(13), coefficients=D)
            sage: M._p_stabilize_parent_space(7, M.base_ring())
            Space of overconvergent modular symbols for Congruence Subgroup
            Gamma(91) with sign 0 and values in Space of 7-adic distributions
            with k=2 action and precision cap 20

            sage: D = Distributions(4, 17); M = PSModularSymbols(Gamma1(3), coefficients=D)
            sage: M._p_stabilize_parent_space(17, Qp(17))
            Space of overconvergent modular symbols for Congruence
            Subgroup Gamma1(51) with sign 0 and values in Space of
            17-adic distributions with k=4 action and precision cap 20
        """

        N = self.level()
        if N % p == 0:
            raise ValueError("the level isn't prime to p")
        from sage.modular.arithgroup.all import Gamma, is_Gamma, Gamma0, is_Gamma0, Gamma1, is_Gamma1
        G = self.group()
        if is_Gamma0(G):
            G = Gamma0(N*p)
        elif is_Gamma1(G):
            G = Gamma1(N*p)
        elif is_Gamma(G):
            G = Gamma(N*p)
        else:
            raise NotImplementedError
        return PSModularSymbols(G, coefficients=self.coefficient_module().change_ring(new_base_ring), sign=self.sign())

    def _specialize_parent_space(self, new_base_ring):
        """
        Internal function that is used by the specialize method on
        elements.  It returns a space with same parameters as this
        one, but over new_base_ring.

        EXAMPLES::

            sage: D = Distributions(7, 5);  M = PSModularSymbols(Gamma0(2), coefficients=D); M
            Space of overconvergent modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Space of 5-adic distributions with k=7 action and precision cap 20
            sage: M._specialize_parent_space(QQ)
            Space of modular symbols for Congruence Subgroup Gamma0(2) with sign 0 and values in Sym^7 Q^2
            sage: M.base_ring()
            5-adic Ring with capped absolute precision 20
            sage: M._specialize_parent_space(QQ).base_ring()
            Rational Field
        """
        return PSModularSymbols(self.group(), coefficients=self.coefficient_module().specialize(new_base_ring), sign=self.sign())

    def _lift_parent_space(self, p, M, new_base_ring):
        """
        Used internally when lifting modular symbols.

        INPUT:

        - `p` -- prime
        - `M` -- precision cap
        - ``new_base_ring`` -- ring

        EXAMPLES::

            sage: D = Distributions(4, 17, 2); M = PSModularSymbols(Gamma1(3), coefficients=D)
            sage: D.is_symk()
            False
            sage: M._lift_parent_space(17, 10, Qp(17))
            Traceback (most recent call last):
            ...
            TypeError: Coefficient module must be a Symk
            sage: PSModularSymbols(Gamma1(3), weight=3)._lift_parent_space(17,10,Qp(17))
            Space of overconvergent modular symbols for Congruence Subgroup Gamma1(3) with sign 0 and values in Space of 17-adic distributions with k=1 action and precision cap 10
        """
        if self.coefficient_module().is_symk():
            return PSModularSymbols(self.group(), coefficients=self.coefficient_module().lift(p, M, new_base_ring), sign=self.sign())
        else:
            raise TypeError("Coefficient module must be a Symk")

    def change_ring(self, new_base_ring):
        """
        Changes base ring of self to new_base_ring

        EXAMPLES::

            sage: from sage.modular.pollack_stevens.distributions import Symk
            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma(6), coefficients=D); M
            Space of modular symbols for Congruence Subgroup Gamma(6) with sign 0 and values in Sym^4 Q^2
            sage: M.change_ring(Qp(5,8))
            Space of modular symbols for Congruence Subgroup Gamma(6) with sign 0 and values in Sym^4 Q_5^2
        """
        return PSModularSymbols(self.group(), coefficients=self.coefficient_module().change_ring(new_base_ring), sign=self.sign())

    def _an_element_(self):
        r"""
        Returns a "typical" element of self; in this case the constant map sending every element
        to an element of the coefficient module.

        EXAMPLES::

            sage: D = Symk(4)
            sage: M = PSModularSymbols(Gamma(6), coefficients=D)
            sage: x = M.an_element(); x       # indirect doctest
            Modular symbol with values in Sym^4 Q^2
            sage: x.values()
            [(2, 1), (2, 1), (2, 1)]
            sage: D = Symk(2, Qp(11)); M = PSModularSymbols(Gamma0(2), coefficients=D)
            sage: x = M.an_element(); x.values()
            [(2 + O(11^20), 1 + O(11^20)), (2 + O(11^20), 1 + O(11^20))]
            sage: x in M
            True
        """
        return self(self.coefficient_module().an_element())