コード例 #1
0
    def decomposition_matrix(self):
        r"""
        Returns the matrix whose columns form a basis for the canonical
        sorted decomposition of self coming from the Hecke operators.

        If the simple factors are `D_0, \ldots, D_n`, then the
        first few columns are an echelonized basis for `D_0`, the
        next an echelonized basis for `D_1`, the next for
        `D_2`, etc.

        EXAMPLE::

            sage: S = ModularSymbols(37, 2)
            sage: S.decomposition_matrix()
            [   1    0    0    0 -1/3]
            [   0    1   -1    0  1/2]
            [   0    0    0    1 -1/2]
            [   0    1    1    1    0]
            [   0    0    0    0    1]
        """
        try:
            return self.__decomposition_matrix_cache
        except AttributeError:
            rows = []
            for A in self.decomposition():
                for x in A.basis():
                    rows.append(x.list())
            A = matrix_space.MatrixSpace(self.base_ring(), self.rank())(rows)
            self.__decomposition_matrix_cache = A
            return self.__decomposition_matrix_cache
コード例 #2
0
    def restrict_domain(self, sub):
        """
        Restrict self to the subvariety sub of self.domain().

        EXAMPLES::

            sage: J = J0(37) ; A, B = J.decomposition()
            sage: A.lattice().matrix()
            [ 1 -1  1  0]
            [ 0  0  2 -1]
            sage: B.lattice().matrix()
            [1 1 1 0]
            [0 0 0 1]
            sage: T = J.hecke_operator(2) ; T.matrix()
            [-1  1  1 -1]
            [ 1 -1  1  0]
            [ 0  0 -2  1]
            [ 0  0  0  0]
            sage: T.restrict_domain(A)
            Abelian variety morphism:
              From: Simple abelian subvariety 37a(1,37) of dimension 1 of J0(37)
              To:   Abelian variety J0(37) of dimension 2
            sage: T.restrict_domain(A).matrix()
            [-2  2 -2  0]
            [ 0  0 -4  2]
            sage: T.restrict_domain(B)
            Abelian variety morphism:
              From: Simple abelian subvariety 37b(1,37) of dimension 1 of J0(37)
              To:   Abelian variety J0(37) of dimension 2
            sage: T.restrict_domain(B).matrix()
            [0 0 0 0]
            [0 0 0 0]
        """
        if not sub.is_subvariety(self.domain()):
            raise ValueError("sub must be a subvariety of self.domain()")

        if sub == self.domain():
            return self

        L = self.domain().lattice()
        B = sub.lattice().basis()
        ims = sum([(L(b) * self.matrix()).list() for b in B], [])
        MS = matrix_space.MatrixSpace(self.base_ring(), len(B),
                                      self.codomain().rank())
        H = sub.Hom(self.codomain(), self.category_for())
        return H(MS(ims))
コード例 #3
0
def gens_to_basis_matrix(syms, relation_matrix, mod, field, sparse):
    """
    Compute echelon form of 3-term relation matrix, and read off each
    generator in terms of basis.

    INPUT:

    -  ``syms`` - a ManinSymbols object

    -  ``relation_matrix`` - as output by
       ``__compute_T_relation_matrix(self, mod)``

    -  ``mod`` - quotient of modular symbols modulo the
       2-term S (and possibly I) relations

    -  ``field`` - base field

    -  ``sparse`` - (bool): whether or not matrix should be
       sparse

    OUTPUT:

    -  ``matrix`` - a matrix whose ith row expresses the
       Manin symbol generators in terms of a basis of Manin symbols
       (modulo the S, (possibly I,) and T rels) Note that the entries of
       the matrix need not be integers.

    -  ``list`` - integers i, such that the Manin symbols `x_i` are a basis.

    EXAMPLE::

        sage: from sage.modular.modsym.relation_matrix import *
        sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma1(4, 3)
        sage: modS = sparse_2term_quotient(modS_relations(L), 24, GF(3))
        sage: gens_to_basis_matrix(L, T_relation_matrix_wtk_g0(L, modS, GF(3), 24), modS, GF(3), True)
        (24 x 2 sparse matrix over Finite Field of size 3, [13, 23])
    """
    if not sage.matrix.all.is_Matrix(relation_matrix):
        raise TypeError, "relation_matrix must be a matrix"
    if not isinstance(mod, list):
        raise TypeError, "mod must be a list"

    misc.verbose(str(relation_matrix.parent()))

    try:
        h = relation_matrix.height()
    except AttributeError:
        h = 9999999
    tm = misc.verbose("putting relation matrix in echelon form (height = %s)"%h)
    if h < 10:
        A = relation_matrix.echelon_form(algorithm='multimodular', height_guess=1)
    else:
        A = relation_matrix.echelon_form()
    A.set_immutable()
    tm = misc.verbose('finished echelon', tm)

    tm = misc.verbose("Now creating gens --> basis mapping")

    basis_set = set(A.nonpivots())
    pivots = A.pivots()

    basis_mod2 = set([j for j,c in mod if c != 0])

    basis_set = basis_set.intersection(basis_mod2)
    basis = list(basis_set)
    basis.sort()

    ONE = field(1)

    misc.verbose("done doing setup",tm)


    tm = misc.verbose("now forming quotient matrix")
    M = matrix_space.MatrixSpace(field, len(syms), len(basis), sparse=sparse)

    B = M(0)
    cols_index = dict([(basis[i], i) for i in range(len(basis))])

    for i in basis_mod2:
        t, l = search(basis, i)
        if t:
            B[i,l] = ONE
        else:
            _, r = search(pivots, i)    # so pivots[r] = i
            # Set row i to -(row r of A), but where we only take
            # the non-pivot columns of A:
            B._set_row_to_negative_of_row_of_A_using_subset_of_columns(i, A, r, basis, cols_index)

    misc.verbose("done making quotient matrix",tm)

    # The following is very fast (over Q at least).
    tm = misc.verbose('now filling in the rest of the matrix')
    k = 0
    for i in range(len(mod)):
        j, s = mod[i]
        if j != i and s != 0:   # ignored in the above matrix
            k += 1
            B.set_row_to_multiple_of_row(i, j, s)
    misc.verbose("set %s rows"%k)
    tm = misc.verbose("time to fill in rest of matrix", tm)

    return B, basis
コード例 #4
0
def T_relation_matrix_wtk_g0(syms, mod, field, sparse):
    r"""
    Compute a matrix whose echelon form gives the quotient by 3-term T
    relations. Despite the name, this is used for all modular symbols spaces
    (including those with character and those for `\Gamma_1` and `\Gamma_H`
    groups), not just `\Gamma_0`.

    INPUT:

    -  ``syms`` - ManinSymbols

    -  ``mod`` - list that gives quotient modulo some two-term relations, i.e.,
       the S relations, and if sign is nonzero, the I relations.

    -  ``field`` - base_ring

    -  ``sparse`` - (True or False) whether to use sparse rather than dense
       linear algebra

    OUTPUT: A sparse matrix whose rows correspond to the reduction of
    the T relations modulo the S and I relations.

    EXAMPLE::

        sage: from sage.modular.modsym.relation_matrix import *
        sage: L = sage.modular.modsym.manin_symbols.ManinSymbolList_gamma_h(GammaH(36, [17,19]), 2)
        sage: modS = sparse_2term_quotient(modS_relations(L), 216, QQ)
        sage: T_relation_matrix_wtk_g0(L, modS, QQ, False)
        72 x 216 dense matrix over Rational Field
        sage: T_relation_matrix_wtk_g0(L, modS, GF(17), True)
        72 x 216 sparse matrix over Finite Field of size 17
    """
    tm = misc.verbose()
    row = 0
    entries = {}
    already_seen = set()
    w = syms.weight()
    for i in xrange(len(syms)):
        if i in already_seen:
            continue
        iT_plus_iTT = syms.apply_T(i) + syms.apply_TT(i)
        j0, s0 = mod[i]
        v = {j0:s0}
        for j, s in iT_plus_iTT:
            if w==2: already_seen.add(j)
            j0, s0 = mod[j]
            s0 = s*s0
            if v.has_key(j0):
                v[j0] += s0
            else:
                v[j0] = s0
        for j0 in v.keys():
            entries[(row, j0)] = v[j0]
        row += 1

    MAT = matrix_space.MatrixSpace(field, row,
                                len(syms), sparse=True)
    R = MAT(entries)
    if not sparse:
        R = R.dense_matrix()
    misc.verbose("finished (number of rows=%s)"%row, tm)
    return R
コード例 #5
0
    def degeneracy_map(self, codomain, t=1):
        """
        The `t`-th degeneracy map from self to the module ``codomain``.  The
        level of the codomain must be a divisor or multiple of level, and t
        must be a divisor of the quotient.

        INPUT:

        -  ``codomain`` - a Hecke module, which should be of the same type as
           self, or a positive integer (in which case Sage will use
           :meth:`~hecke_module_of_level` to find the "natural" module of the
           corresponding level).
        -  ``t`` - int, the parameter of the degeneracy map, i.e., the map is
           related to `f(q)` - `f(q^t)`.


        OUTPUT: A morphism from self to codomain.

        EXAMPLES::

            sage: M = ModularSymbols(11,sign=1)
            sage: d1 = M.degeneracy_map(33); d1
            Hecke module morphism degeneracy map corresponding to f(q) |--> f(q) defined by the matrix
            [ 1  0  0  0 -2 -1]
            [ 0  0 -2  2  0  0]
            Domain: Modular Symbols space of dimension 2 for Gamma_0(11) of weight ...
            Codomain: Modular Symbols space of dimension 6 for Gamma_0(33) of weight ...
            sage: M.degeneracy_map(33,3).matrix()
            [ 3  2  2  0 -2  1]
            [ 0  2  0 -2  0  0]
            sage: M = ModularSymbols(33,sign=1)
            sage: d2 = M.degeneracy_map(11); d2.matrix()
            [  1   0]
            [  0 1/2]
            [  0  -1]
            [  0   1]
            [ -1   0]
            [ -1   0]
            sage: (d2*d1).matrix()
            [4 0]
            [0 4]

        ::

            sage: M = ModularSymbols(3,12,sign=1)
            sage: M.degeneracy_map(1)
            Hecke module morphism degeneracy map corresponding to f(q) |--> f(q) defined by the matrix
            [1 0]
            [0 0]
            [0 1]
            [0 1]
            [0 1]
            Domain: Modular Symbols space of dimension 5 for Gamma_0(3) of weight ...
            Codomain: Modular Symbols space of dimension 2 for Gamma_0(1) of weight ...

        ::

            sage: S = M.cuspidal_submodule()
            sage: S.degeneracy_map(1)
            Hecke module morphism defined by the matrix
            [1 0]
            [0 0]
            [0 0]
            Domain: Modular Symbols subspace of dimension 3 of Modular Symbols space ...
            Codomain: Modular Symbols space of dimension 2 for Gamma_0(1) of weight ...

        ::

            sage: D = ModularSymbols(10,4).cuspidal_submodule().decomposition()
            sage: D
            [
            Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 10 for Gamma_0(10) of weight 4 with sign 0 over Rational Field,
            Modular Symbols subspace of dimension 4 of Modular Symbols space of dimension 10 for Gamma_0(10) of weight 4 with sign 0 over Rational Field
            ]
            sage: D[1].degeneracy_map(5)
            Hecke module morphism defined by the matrix
            [   0    0   -1    1]
            [   0  1/2  3/2   -2]
            [   0   -1    1    0]
            [   0 -3/4 -1/4    1]
            Domain: Modular Symbols subspace of dimension 4 of Modular Symbols space ...
            Codomain: Modular Symbols space of dimension 4 for Gamma_0(5) of weight ...

        We check for a subtle caching bug that came up in work on trac #10453::

            sage: loads(dumps(J0(33).decomposition()[0].modular_symbols()))
            Modular Symbols subspace of dimension 2 of Modular Symbols space of dimension 9 for Gamma_0(33) of weight 2 with sign 0 over Rational Field

        We check that certain absurd inputs are correctly caught::

            sage: chi = kronecker_character(7)
            sage: ModularSymbols(Gamma0(7), 4).degeneracy_map(ModularSymbols(chi, 4))
            Traceback (most recent call last):
            ...
            ValueError: The characters of the domain and codomain must match
        """
        if is_AmbientHeckeModule(codomain):
            M = codomain
            level = int(M.level())
        else:
            level = int(codomain)
            M = None

        t = int(t)

        err = False
        if self.level() % level == 0:
            quo = self.level() // level
            if quo % t != 0:
                err = True
        elif level % self.level() == 0:
            quo = level // self.level()
            if quo % t != 0:
                err = True
        else:
            err = True
        if err:
            raise ValueError(("The level of self (=%s) must be a divisor or multiple of " + \
                               "level (=%s), and t (=%s) must be a divisor of the quotient.")%\
                               (self.level(), level, t))

        eps = self.character()
        if not (eps is None) and level % eps.conductor() != 0:
            raise ArithmeticError("The conductor of the character of this space " + \
                  "(=%s) must be divisible by the level (=%s)."%\
                  (eps.conductor(), level))

        if M is None:
            M = self.hecke_module_of_level(level)

        if eps is not None and M.character() is not None:
            if eps.primitive_character() != M.character().primitive_character(
            ):
                raise ValueError(
                    "The characters of the domain and codomain must match")

        key = (M.group(), t)
        # bad idea to use (M, t) as the key, because using complicated objects
        # like modular forms spaces as dictionary keys causes weird behaviour;
        # on the other hand, (M.level(), t) isn't enough information.
        try:
            self._degeneracy_maps
        except AttributeError:
            self._degeneracy_maps = {}

        if key in self._degeneracy_maps:
            return self._degeneracy_maps[key]

        if M.rank() == 0:

            A = matrix_space.MatrixSpace(self.base_ring(), self.rank(), 0)(0)

        elif self.level() % level == 0:  # lower the level

            A = self._degeneracy_lowering_matrix(M, t)

        elif level % self.level() == 0:  # raise the level

            A = self._degeneracy_raising_matrix(M, t)

        d = degenmap.DegeneracyMap(A, self, M, t)
        self._degeneracy_maps[key] = d
        return d