Exemple #1
0
    def weil_representation(self) :
        r"""
        OUTPUT:
        
        - A pair of matrices corresponding to T and S.
        """
        disc_bilinear = lambda a, b: (self._dual_basis * vector(QQ, a.lift())) * self._L * (self._dual_basis * vector(QQ, b.lift()))
        disc_quadratic = lambda a: disc_bilinear(a, a) / ZZ(2)
        
        zeta_order = ZZ(lcm([8, 12, prod(self.invariants())] + map(lambda ed: 2 * ed, self.invariants())))
        K = CyclotomicField(zeta_order); zeta = K.gen()

        R = PolynomialRing(K, 'x'); x = R.gen()
#        sqrt2s = (x**2 - 2).factor()
#        if sqrt2s[0][0][0].complex_embedding().real() > 0 :        
#            sqrt2  = sqrt2s[0][0][0]
#        else : 
#            sqrt2  = sqrt2s[0][1]
        Ldet_rts = (x**2 - prod(self.invariants())).factor()
        if Ldet_rts[0][0][0].complex_embedding().real() > 0 :
            Ldet_rt  = Ldet_rts[0][0][0] 
        else :
            Ldet_rt  = Ldet_rts[0][0][0]
                
        Tmat  = diagonal_matrix( K, [zeta**(zeta_order*disc_quadratic(a)) for a in self] )
        Smat = zeta**(zeta_order / 8 * self._L.nrows()) / Ldet_rt  \
               * matrix( K,  [ [ zeta**ZZ(-zeta_order * disc_bilinear(gamma,delta))
                                 for delta in self ]
                               for gamma in self ])
        
        return (Tmat, Smat)
Exemple #2
0
    def _test__jacobi_torsion_point(phi, weight, torsion_point):
        r"""
        Given a list of power series, which are the corrected Taylor coefficients
        of a Jacobi form, return the specialization to ``torsion_point``.
        
        INPUT:
        
        - ``phi`` -- A Fourier expansion of a Jacobi form.
        
        - ``weight`` -- An integer.
        
        - ``torsion_point`` -- A rational.
        
        OUPUT:
        
        - A power series.
        
        TESTS:
                
        See jacobi_form_by_taylor_expansion.
        
            sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import *
            sage: from psage.modform.jacobiforms.jacobiformd1nn_types import *
            sage: precision = 50
            sage: weight = 10; index = 7
            sage: phis = [jacobi_form_by_taylor_expansion(i, JacobiFormD1NNFilter(precision, index), weight) for i in range(JacobiFormD1NN_Gamma(weight, index)._rank(QQ))]
            sage: fs = [JacobiFormD1NNFactory_class._test__jacobi_torsion_point(phi, weight, 2/3) for phi in phis]
            sage: fs_vec = [vector(f.padded_list(precision)) for f in fs]
            sage: mf_span = span([vector(b.qexp(precision).padded_list(precision)) for b in ModularForms(GammaH(9, [4]), weight).basis()])
            sage: all(f_vec in mf_span for f_vec in fs_vec)
            True
        
        FIXME: The case of torsion points of order 5, which should lead to forms for Gamma1(25) fails even in the simplest case.
        """
        from sage.rings.all import CyclotomicField

        K = CyclotomicField(QQ(torsion_point).denominator())
        zeta = K.gen()
        R = PowerSeriesRing(K, 'q')
        q = R.gen(0)

        ch = JacobiFormD1WeightCharacter(weight)

        coeffs = dict((n, QQ(0)) for n in range(phi.precision().index()))
        for (n, r) in phi.precision().monoid_filter():
            coeffs[n] += zeta**r * phi[(ch, (n, r))]

        return PowerSeriesRing(K, 'q')(coeffs)
Exemple #3
0
def __common_minimal_basering(chi, psi):
    """
    Find the smallest basering over which chi and psi are valued, and
    return new chi and psi valued in that ring.

    EXAMPLES::

        sage: sage.modular.modform.eis_series.__common_minimal_basering(DirichletGroup(1)[0], DirichletGroup(1)[0])
        (Dirichlet character modulo 1 of conductor 1, Dirichlet character modulo 1 of conductor 1)

        sage: sage.modular.modform.eis_series.__common_minimal_basering(DirichletGroup(3).0, DirichletGroup(5).0)
        (Dirichlet character modulo 3 of conductor 3 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4)

        sage: sage.modular.modform.eis_series.__common_minimal_basering(DirichletGroup(12).0, DirichletGroup(36).0)
        (Dirichlet character modulo 12 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 36 of conductor 4 mapping 19 |--> -1, 29 |--> 1)
    """
    chi = chi.minimize_base_ring()
    psi = psi.minimize_base_ring()
    n = lcm(chi.base_ring().zeta().multiplicative_order(),
                  psi.base_ring().zeta().multiplicative_order())
    if n <= 2:
        K = QQ
    else:
        K = CyclotomicField(n)
    chi = chi.change_ring(K)
    psi = psi.change_ring(K)
    return chi, psi
    def _test__jacobi_torsion_point(phi, weight, torsion_point) :
        r"""
        Given a list of power series, which are the corrected Taylor coefficients
        of a Jacobi form, return the specialization to ``torsion_point``.
        
        INPUT:
        
        - ``phi`` -- A Fourier expansion of a Jacobi form.
        
        - ``weight`` -- An integer.
        
        - ``torsion_point`` -- A rational.
        
        OUPUT:
        
        - A power series.
        
        TESTS:
                
        See jacobi_form_by_taylor_expansion.
        
            sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import *
            sage: from psage.modform.jacobiforms.jacobiformd1nn_types import *
            sage: precision = 50
            sage: weight = 10; index = 7
            sage: phis = [jacobi_form_by_taylor_expansion(i, JacobiFormD1NNFilter(precision, index), weight) for i in range(JacobiFormD1NN_Gamma(weight, index)._rank(QQ))]
            sage: fs = [JacobiFormD1NNFactory_class._test__jacobi_torsion_point(phi, weight, 2/3) for phi in phis]
            sage: fs_vec = [vector(f.padded_list(precision)) for f in fs]
            sage: mf_span = span([vector(b.qexp(precision).padded_list(precision)) for b in ModularForms(GammaH(9, [4]), weight).basis()])
            sage: all(f_vec in mf_span for f_vec in fs_vec)
            True
        
        FIXME: The case of torsion points of order 5, which should lead to forms for Gamma1(25) fails even in the simplest case.
        """
        from sage.rings.all import CyclotomicField
        
        K = CyclotomicField(QQ(torsion_point).denominator()); zeta = K.gen()
        R = PowerSeriesRing(K, 'q'); q = R.gen(0)

        ch = JacobiFormD1WeightCharacter(weight)
    
        coeffs = dict( (n, QQ(0)) for n in range(phi.precision().index()) )
        for (n, r) in phi.precision().monoid_filter() :
            coeffs[n] += zeta**r * phi[(ch, (n,r))]
        
        return PowerSeriesRing(K, 'q')(coeffs) 
    def weil_representation(self):
        r"""
        OUTPUT:
        
        - A pair of matrices corresponding to T and S.
        """
        disc_bilinear = lambda a, b: (self._dual_basis * vector(QQ, a.lift(
        ))) * self._L * (self._dual_basis * vector(QQ, b.lift()))
        disc_quadratic = lambda a: disc_bilinear(a, a) / ZZ(2)

        zeta_order = ZZ(
            lcm([8, 12, prod(self.invariants())] +
                map(lambda ed: 2 * ed, self.invariants())))
        K = CyclotomicField(zeta_order)
        zeta = K.gen()

        R = PolynomialRing(K, 'x')
        x = R.gen()
        #        sqrt2s = (x**2 - 2).factor()
        #        if sqrt2s[0][0][0].complex_embedding().real() > 0 :
        #            sqrt2  = sqrt2s[0][0][0]
        #        else :
        #            sqrt2  = sqrt2s[0][1]
        Ldet_rts = (x**2 - prod(self.invariants())).factor()
        if Ldet_rts[0][0][0].complex_embedding().real() > 0:
            Ldet_rt = Ldet_rts[0][0][0]
        else:
            Ldet_rt = Ldet_rts[0][0][0]

        Tmat = diagonal_matrix(
            K, [zeta**(zeta_order * disc_quadratic(a)) for a in self])
        Smat = zeta**(zeta_order / 8 * self._L.nrows()) / Ldet_rt  \
               * matrix( K,  [ [ zeta**ZZ(-zeta_order * disc_bilinear(gamma,delta))
                                 for delta in self ]
                               for gamma in self ])

        return (Tmat, Smat)
    def character_table(self):
        r"""
        Return the matrix of values of the irreducible characters of this
        group `G` at its conjugacy classes.

        The columns represent the conjugacy classes of
        `G` and the rows represent the different irreducible
        characters in the ordering given by GAP.

        OUTPUT: a matrix defined over a cyclotomic field

        EXAMPLES::

            sage: MatrixGroup(SymmetricGroup(2)).character_table()
            [ 1 -1]
            [ 1  1]
            sage: MatrixGroup(SymmetricGroup(3)).character_table()
            [ 1  1 -1]
            [ 2 -1  0]
            [ 1  1  1]
            sage: MatrixGroup(SymmetricGroup(5)).character_table()
            [ 1 -1 -1  1 -1  1  1]
            [ 4  0  1 -1 -2  1  0]
            [ 5  1 -1  0 -1 -1  1]
            [ 6  0  0  1  0  0 -2]
            [ 5 -1  1  0  1 -1  1]
            [ 4  0 -1 -1  2  1  0]
            [ 1  1  1  1  1  1  1]
        """
        #code from function in permgroup.py, but modified for
        #how gap handles these groups.
        G = self._gap_()
        cl = self.conjugacy_classes()
        from sage.rings.integer import Integer
        n = Integer(len(cl))
        irrG = G.Irr()
        ct = [[irrG[i][j] for j in range(n)] for i in range(n)]

        from sage.rings.all import CyclotomicField
        e = irrG.Flat().Conductor()
        K = CyclotomicField(e)
        ct = [[K(x) for x in v] for v in ct]

        # Finally return the result as a matrix.
        from sage.matrix.all import MatrixSpace
        MS = MatrixSpace(K, n)
        return MS(ct)
Exemple #7
0
    def __init__(self, G, values):
        r"""
        Return the character of the group ``G`` with values given by the list
        values. The order of the values must correspond to the output of
        ``G.conjugacy_classes_representatives()``.

        EXAMPLES::

            sage: G = CyclicPermutationGroup(4)
            sage: values  = [1, -1, 1, -1]
            sage: chi = ClassFunction(G, values); chi
            Character of Cyclic group of order 4 as a permutation group
        """
        self._group = G
        if isinstance(values, GapElement) and gap.IsClassFunction(values):
            self._gap_classfunction = values
        else:
            self._gap_classfunction = gap.ClassFunction(G, list(values))
        e = self._gap_classfunction.Conductor()
        self._base_ring = CyclotomicField(e)
def cyclotomic_restriction(L, K):
    r"""
    Given two cyclotomic fields L and K, compute the compositum
    M of K and L, and return a function and the index [M:K]. The
    function is a map that acts as follows (here `M = Q(\zeta_m)`):

    INPUT:

    element alpha in L

    OUTPUT:

    a polynomial `f(x)` in `K[x]` such that `f(\zeta_m) = \alpha`,
    where we view alpha as living in `M`. (Note that `\zeta_m`
    generates `M`, not `L`.)

    EXAMPLES::

        sage: L = CyclotomicField(12) ; N = CyclotomicField(33) ; M = CyclotomicField(132)
        sage: z, n = sage.modular.modform.eisenstein_submodule.cyclotomic_restriction(L,N)
        sage: n
        2

        sage: z(L.0)
        -zeta33^19*x
        sage: z(L.0)(M.0)
        zeta132^11

        sage: z(L.0^3-L.0+1)
        (zeta33^19 + zeta33^8)*x + 1
        sage: z(L.0^3-L.0+1)(M.0)
        zeta132^33 - zeta132^11 + 1
        sage: z(L.0^3-L.0+1)(M.0) - M(L.0^3-L.0+1)
        0
    """
    if not L.has_coerce_map_from(K):
        M = CyclotomicField(lcm(L.zeta_order(), K.zeta_order()))
        f = cyclotomic_restriction_tower(M, K)

        def g(x):
            r"""
            Function returned by cyclotomic restriction.

            INPUT:

            element alpha in L

            OUTPUT:

            a polynomial `f(x)` in `K[x]` such that `f(\zeta_m) = \alpha`,
            where we view alpha as living in `M`. (Note that `\zeta_m`
            generates `M`, not `L`.)

            EXAMPLES::

                sage: L = CyclotomicField(12)
                sage: N = CyclotomicField(33)
                sage: g, n = sage.modular.modform.eisenstein_submodule.cyclotomic_restriction(L,N)
                sage: g(L.0)
                -zeta33^19*x
            """
            return f(M(x))

        return g, euler_phi(M.zeta_order()) // euler_phi(K.zeta_order())
    else:
        return cyclotomic_restriction_tower(L,K), \
               euler_phi(L.zeta_order())//euler_phi(K.zeta_order())
Exemple #9
0
def cyclotomic_restriction(L,K):
    r"""
    Given two cyclotomic fields L and K, compute the compositum
    M of K and L, and return a function and the index [M:K]. The
    function is a map that acts as follows (here `M = Q(\zeta_m)`):

    INPUT:

    element alpha in L

    OUTPUT:

    a polynomial `f(x)` in `K[x]` such that `f(\zeta_m) = \alpha`,
    where we view alpha as living in `M`. (Note that `\zeta_m`
    generates `M`, not `L`.)

    EXAMPLES::

        sage: L = CyclotomicField(12) ; N = CyclotomicField(33) ; M = CyclotomicField(132)
        sage: z, n = sage.modular.modform.eisenstein_submodule.cyclotomic_restriction(L,N)
        sage: n
        2

        sage: z(L.0)
        -zeta33^19*x
        sage: z(L.0)(M.0)
        zeta132^11

        sage: z(L.0^3-L.0+1)
        (zeta33^19 + zeta33^8)*x + 1
        sage: z(L.0^3-L.0+1)(M.0)
        zeta132^33 - zeta132^11 + 1
        sage: z(L.0^3-L.0+1)(M.0) - M(L.0^3-L.0+1)
        0
    """
    if not L.has_coerce_map_from(K):
        M = CyclotomicField(lcm(L.zeta_order(), K.zeta_order()))
        f = cyclotomic_restriction_tower(M,K)
        def g(x):
            """
            Function returned by cyclotomic restriction.

            INPUT:

            element alpha in L

            OUTPUT:

            a polynomial `f(x)` in `K[x]` such that `f(\zeta_m) = \alpha`,
            where we view alpha as living in `M`. (Note that `\zeta_m`
            generates `M`, not `L`.)

            EXAMPLES::

                sage: L = CyclotomicField(12)
                sage: N = CyclotomicField(33)
                sage: g, n = sage.modular.modform.eisenstein_submodule.cyclotomic_restriction(L,N)
                sage: g(L.0)
                -zeta33^19*x
            """
            return f(M(x))
        return g, euler_phi(M.zeta_order())//euler_phi(K.zeta_order())
    else:
        return cyclotomic_restriction_tower(L,K), \
               euler_phi(L.zeta_order())//euler_phi(K.zeta_order())
Exemple #10
0
def hecke_operator_on_basis(B, n, k, eps=None, already_echelonized=False):
    r"""
    Given a basis `B` of `q`-expansions for a space of modular forms
    with character `\varepsilon` to precision at least `\#B\cdot n+1`,
    this function computes the matrix of `T_n` relative to `B`.

    .. note::

       If the elements of B are not known to sufficient precision,
       this function will report that the vectors are linearly
       dependent (since they are to the specified precision).

    INPUT:

    - ``B`` - list of q-expansions

    - ``n`` - an integer >= 1

    - ``k`` - an integer

    - ``eps`` - Dirichlet character

    - ``already_echelonized`` -- bool (default: False); if True, use that the
      basis is already in Echelon form, which saves a lot of time.

    EXAMPLES::

        sage: sage.modular.modform.constructor.ModularForms_clear_cache()
        sage: ModularForms(1,12).q_expansion_basis()
        [
        q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6),
        1 + 65520/691*q + 134250480/691*q^2 + 11606736960/691*q^3 + 274945048560/691*q^4 + 3199218815520/691*q^5 + O(q^6)
        ]
        sage: hecke_operator_on_basis(ModularForms(1,12).q_expansion_basis(), 3, 12)
        Traceback (most recent call last):
        ...
        ValueError: The given basis vectors must be linearly independent.

        sage: hecke_operator_on_basis(ModularForms(1,12).q_expansion_basis(30), 3, 12)
        [   252      0]
        [     0 177148]

    TESTS:

    This shows that the problem with finite fields reported at trac #8281 is solved::

        sage: bas_mod5 = [f.change_ring(GF(5)) for f in victor_miller_basis(12, 20)]
        sage: hecke_operator_on_basis(bas_mod5, 2, 12)
        [4 0]
        [0 1]

    This shows that empty input is handled sensibly (trac #12202)::

        sage: x = hecke_operator_on_basis([], 3, 12); x
        []
        sage: x.parent()
        Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 1 and degree 1
        sage: y = hecke_operator_on_basis([], 3, 12, eps=DirichletGroup(13).0^2); y
        []
        sage: y.parent()
        Full MatrixSpace of 0 by 0 dense matrices over Cyclotomic Field of order 12 and degree 4
    """
    if not isinstance(B, (list, tuple)):
        raise TypeError, "B (=%s) must be a list or tuple" % B
    if len(B) == 0:
        if eps is None:
            R = CyclotomicField(1)
        else:
            R = eps.base_ring()
        return MatrixSpace(R, 0)(0)
    f = B[0]
    R = f.base_ring()
    if eps is None:
        eps = DirichletGroup(1, R).gen(0)
    all_powerseries = True
    for x in B:
        if not is_PowerSeries(x):
            all_powerseries = False
    if not all_powerseries:
        raise TypeError, "each element of B must be a power series"
    n = Integer(n)
    k = Integer(k)
    prec = (f.prec() - 1) // n
    A = R**prec
    V = A.span_of_basis([g.padded_list(prec) for g in B],
                        already_echelonized=already_echelonized)
    return _hecke_operator_on_basis(B, V, n, k, eps)