예제 #1
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)
예제 #2
0
    def _test__jacobi_corrected_taylor_expansions(nu, phi, weight):
        r"""
        Return the ``2 nu``-th corrected Taylor coefficient.
        INPUT:
        
        - ``nu`` -- An integer.  
        
        - ``phi`` -- A Fourier expansion of a Jacobi form.
        
        - ``weight`` -- An integer.
        
        OUTPUT:
        
        - A power series in `q`.
        
        ..TODO:
        
        Implement this for all Taylor coefficients.
        
        TESTS::
        
            sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import *
            sage: from psage.modform.jacobiforms.jacobiformd1nn_types import *
            sage: nu_bound = 10
            sage: precision = 100
            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: fss = [ [JacobiFormD1NNFactory_class._test__jacobi_corrected_taylor_expansions(nu, phi, weight) for phi in phis] for nu in range(nu_bound) ]
            sage: fss_vec = [ [vector(f.padded_list(precision)) for f in fs] for fs in fss ]
            sage: mf_spans = [ span([vector(b.qexp(precision).padded_list(precision)) for b in ModularForms(1, weight + 2 * nu).basis()]) for nu in range(nu_bound) ] 
            sage: all(f_vec in mf_span for (fs_vec, mf_span) in zip(fss_vec, mf_spans) for f_vec in fs_vec)
            True
        """
        ## We use EZ85, p.29 (3), the factorial in one of the factors is missing
        factors = [(-1)**mu * factorial(2 * nu) *
                   factorial(weight + 2 * nu - mu - 2) / ZZ(
                       factorial(mu) * factorial(2 * nu - 2 * mu) *
                       factorial(weight + nu - 2)) for mu in range(nu + 1)]
        gegenbauer = lambda n, r: sum(f * r**(2 * nu - 2 * mu) * n**mu
                                      for (mu, f) in enumerate(factors))
        ch = JacobiFormD1WeightCharacter(weight)
        jacobi_index = phi.precision().jacobi_index()

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

        return PowerSeriesRing(QQ, 'q')(coeffs)
예제 #3
0
def _weak_jacbi_form_by_taylor_expansion(precision, fs, weight, factory=None):
    r"""
    The lazy Fourier expansion of a Jacobi form of index ``len(fs) - 1``, whose first
    corrected Taylor coefficients are the ``fs``.
    
    INPUT:
    
    - ``precision`` -- A filter for the Fourier expansion of Jacobi forms of scalar index.
    
    - ``fs`` - A list of functions of one argument `p` that return a power series of
               precision `p`.  The coefficients must be integral.
    
    - ``weight`` -- An integer.
    
    - ``factory`` -- Either ``None``, or a factory class for Jacobi forms of degree 1 with
                     scalar index.
    
    OUTPUT:
    
    - A lazy Fourier expansion of a Jacobi form.
    
    TESTS::
    
        sage: from sage.rings import big_oh
        sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import _weak_jacbi_form_by_taylor_expansion
        sage: R = PowerSeriesRing(ZZ, 'q'); q = R.gen(0)
        sage: _weak_jacbi_form_by_taylor_expansion(10, 3 * [lambda p: big_oh.O(q**p)], 10).precision().jacobi_index()
        2
        sage: _weak_jacbi_form_by_taylor_expansion(10, 2 * [lambda p: big_oh.O(q**p)], 9).precision().jacobi_index()
        3
    """
    if factory is None:
        factory = JacobiFormD1NNFactory(precision, len(fs) - 1)

    if weight is None:
        raise ValueError( "Either one element of fs must be a modular form or " + \
                          "the weight must be passed." )

    expansion_ring = JacobiFormD1NNFourierExpansionModule(
        ZZ,
        len(fs) - 1 if weight % 2 == 0 else len(fs) + 1, True)
    return EquivariantMonoidPowerSeries_lazy(
        expansion_ring,
        expansion_ring.monoid().filter(precision),
        DelayedFactory_JacobiFormD1NN_taylor_expansion_weak(
            weight, fs, factory).getcoeff,
        [JacobiFormD1WeightCharacter(weight)])
예제 #4
0
    def __init__(self, precision, k, i):
        r"""
        INPUT:
    
        - ``precision`` -- A filter for Fourier expansions of Jacobi forms. 
        
        - `k` -- An integer; The weight of the Jacobi forms.
        
        - `i` -- A nonnegative integer less the dimension of the considered
                 space of Jacobi forms.
        """
        self.__precision = precision
        self.__weight = k
        self.__i = i

        self.__ch = JacobiFormD1WeightCharacter(
            k,
            precision.jacobi_index().matrix().nrows())
예제 #5
0
    def __init__(self, weight, fs, factory):
        r"""
        INPUT:
        
        - ``weight`` -- An integer.
        
        - ``fs`` -- A list of functions of one argument `p` that return a power series of
                    precision `p`.  The coefficients must be integral.
    
        - ``factory`` -- Either ``None``, or a factory class for Jacobi forms of degree 1 with
                         scalar index.
        """
        self.__weight = weight
        self.__fs = fs
        self.__factory = factory

        self.__series = None
        self.__ch = JacobiFormD1WeightCharacter(weight)
예제 #6
0
    def __init__(self, i, precision, weight, index):
        r"""
        INPUT:
        
        - ``precision`` -- A non-negative integer that corresponds to a precision of
                           the q-expansion.

        - ``weight`` -- An integer.
    
        - ``index`` -- A non-negative integer.    
        """
        self.__i = i
        self.__precision = precision
        self.__weight = weight
        self.__index = index

        self.__series = None
        self.__ch = JacobiFormD1WeightCharacter(weight)
예제 #7
0
def jacobi_form_by_taylor_expansion(i, precision, weight):
    r"""
    Lazy Fourier expansion of the i-th Jacobi form in a certain basis;
    see _jacobi_forms_by_taylor_expansion_coordinates.
    
    INPUT:
    
    - `i` -- A non-negative integer.

    - ``precision`` -- A filter for the Fourier indices of Jacobi forms.
    
    - ``weight`` -- An integer.
    
    OUTPUT:
    
    - A lazy element of the Fourier expansion module for Jacobi forms.
    
    TESTS:

    See also ``JacobiFormD1NNFactory_class._test__jacobi_corrected_taylor_expansions`` and
    ``JacobiFormD1NNFactory_class._test__jacobi_torsion_point``
    
    ::
    
        sage: from psage.modform.jacobiforms.jacobiformd1nn_fegenerators import *
        sage: JacobiFormD1NNFactory_class._test__jacobi_taylor_coefficients( jacobi_form_by_taylor_expansion(1, JacobiFormD1NNFilter(20, 1), 10), 10 )
        [O(q^20), q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + 84480*q^8 - 113643*q^9 - 115920*q^10 + 534612*q^11 - 370944*q^12 - 577738*q^13 + 401856*q^14 + 1217160*q^15 + 987136*q^16 - 6905934*q^17 + 2727432*q^18 + 10661420*q^19 + O(q^20)]
        sage: JacobiFormD1NNFactory_class._test__jacobi_taylor_coefficients( jacobi_form_by_taylor_expansion(1, JacobiFormD1NNFilter(20, 2), 10), 10 )
        [O(q^20), q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + 84480*q^8 - 113643*q^9 - 115920*q^10 + 534612*q^11 - 370944*q^12 - 577738*q^13 + 401856*q^14 + 1217160*q^15 + 987136*q^16 - 6905934*q^17 + 2727432*q^18 + 10661420*q^19 + O(q^20), q - 48*q^2 + 756*q^3 - 5888*q^4 + 24150*q^5 - 36288*q^6 - 117208*q^7 + 675840*q^8 - 1022787*q^9 - 1159200*q^10 + 5880732*q^11 - 4451328*q^12 - 7510594*q^13 + 5625984*q^14 + 18257400*q^15 + 15794176*q^16 - 117400878*q^17 + 49093776*q^18 + 202566980*q^19 + O(q^20)]
        sage: JacobiFormD1NNFactory_class._test__jacobi_taylor_coefficients( jacobi_form_by_taylor_expansion(0, JacobiFormD1NNFilter(20, 3), 9), 9 )
        [O(q^20), q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 - 16744*q^7 + 84480*q^8 - 113643*q^9 - 115920*q^10 + 534612*q^11 - 370944*q^12 - 577738*q^13 + 401856*q^14 + 1217160*q^15 + 987136*q^16 - 6905934*q^17 + 2727432*q^18 + 10661420*q^19 + O(q^20)]
    """
    jacobi_index = precision.jacobi_index()

    return EquivariantMonoidPowerSeries_lazy(
        JacobiFormD1NNFourierExpansionModule(ZZ, jacobi_index), precision,
        DelayedFactory_JacobiFormD1NN_by_taylor_expansion(
            i, precision.index(), weight, jacobi_index).getcoeff,
        [JacobiFormD1WeightCharacter(weight)])
예제 #8
0
def _test__coefficient_by_restriction(precision,
                                      k,
                                      relation_precision=None,
                                      additional_lengths=1):
    r"""
    TESTS::
    
        sage: from psage.modform.jacobiforms.jacobiformd1_fourierexpansion import *
        sage: from psage.modform.jacobiforms.jacobiformd1_fegenerators import _test__coefficient_by_restriction

    ::

        sage: indices = JacobiFormD1Indices(QuadraticForm(matrix(2, [2,1,1,2])))
        sage: precision = indices.filter(10)
        sage: _test__coefficient_by_restriction(precision, 10, additional_lengths = 10)
        
    ::

        sage: indices = JacobiFormD1Indices(QuadraticForm(matrix(2, [4,1,1,2])))
        sage: precision = JacobiFormD1Filter(5, indices.jacobi_index())
        sage: _test__coefficient_by_restriction(precision, 40, additional_lengths = 4) # long test
        
    We use different precisions for relations and restrictions::

        sage: indices = JacobiFormD1Indices(QuadraticForm(matrix(2, [2,1,1,2])))
        sage: precision = indices.filter(20)
        sage: relation_precision = indices.filter(2)
        sage: _test__coefficient_by_restriction(precision, 10, relation_precision, additional_lengths = 4)
    """
    from sage.misc.misc import verbose

    L = precision.jacobi_index()

    if relation_precision is not None and not relation_precision <= precision:
        raise ValueError(
            "Relation precision must be less than or equal to precision.")

    expansions = _coefficient_by_restriction(precision, k, relation_precision)
    verbose(
        "Start testing restrictions of {2} Jacobi forms of weight {0} and index {1}"
        .format(k, L, len(expansions)))

    ch1 = JacobiFormD1WeightCharacter(k)
    chL = JacobiFormD1WeightCharacter(k, L.matrix().nrows())

    R = precision.monoid()._r_representatives
    S_extended = _find_complete_set_of_restriction_vectors(L, R)

    S = list()
    for (s, _) in S_extended:
        if s not in S:
            S.append(s)
    max_S_length = max([L(s) for s in S])

    S = L.short_vector_list_up_to_length(max_S_length + 1 + additional_lengths,
                                         True)[1:]
    Sold = flatten(S[:max_S_length + 1], max_level=1)
    Snew = flatten(S[max_S_length + 1:], max_level=1)
    S = flatten(S, max_level=1)
    verbose("Will use the following restriction vectors: {0}".format(S))

    jacobi_forms_dict = dict()
    non_zero_expansions = list()
    for s in S:
        m = L(s)
        verbose("Restriction to index {0} via {1}".format(m, s))

        try:
            jacobi_forms = jacobi_forms_dict[m]
        except KeyError:
            jacobi_forms = JacobiFormsD1NN(
                QQ, JacobiFormD1NNGamma(k, m),
                JacobiFormD1NNFilter(precision.index(), m))
            jacobi_forms_dict[m] = jacobi_forms
        jacobi_forms_module = span([
            vector(b[(ch1, k)]
                   for k in jacobi_forms.fourier_expansion_precision())
            for b in map(lambda b: b.fourier_expansion(),
                         jacobi_forms.graded_submodule(None).basis())
        ])

        fourier_expansion_module = jacobi_forms.fourier_expansion_ambient()

        for (i, expansion) in enumerate(expansions):
            verbose("Testing restriction of {0}-th form".format(i))
            restricted_expansion_dict = dict()
            for (n, r) in precision.monoid_filter():
                rres = s.dot_product(vector(r))
                try:
                    restricted_expansion_dict[(n, rres)] += expansion[(chL,
                                                                       (n, r))]
                except KeyError:
                    restricted_expansion_dict[(n, rres)] = expansion[(chL,
                                                                      (n, r))]

            restricted_expansion = vector(
                restricted_expansion_dict.get(k, 0)
                for k in jacobi_forms.fourier_expansion_precision())
            if restricted_expansion not in jacobi_forms_module:
                raise RuntimeError(
                    "{0}-th restricted via {1} is not a Jacobi form".format(
                        i, s))

            if restricted_expansion != 0:
                non_zero_expansions.append(i)

    assert Set(non_zero_expansions) == Set(range(len(expansions)))
예제 #9
0
        global_restriction_matrix = global_restriction_matrix__big.matrix_from_rows_and_columns(
            row_indices__small,
            [column_labels.index(l) for l in column_labels_relations])
    else:
        global_restriction_matrix = global_restriction_matrix__big

    jacobi_indices = [m for (_, m, _, _) in row_groups]
    index_filters = dict((m, JacobiFormD1NNFilter(precision.index(), m))
                         for m in Set(jacobi_indices))
    jacobi_forms = dict(
        (m, JacobiFormsD1NN(QQ, JacobiFormD1NNGamma(k, m), prec))
        for (m, prec) in index_filters.iteritems())

    forms = list()
    nmb_forms_coords = row_groups[-1][2] + row_groups[-1][3]
    ch1 = JacobiFormD1WeightCharacter(k)
    for (s, m, start, length) in row_groups:
        row_labels_dict = row_labels[m]
        for f in jacobi_forms[m].graded_submodule(None).basis():
            f = f.fourier_expansion()
            v = vector(ZZ, len(row_labels_dict))
            for (l, i) in row_labels_dict.iteritems():
                v[i] = f[(ch1, l)]

            forms.append(
                vector(start * [0] + v.list() +
                       (nmb_forms_coords - start - length) * [0]))

    if relation_precision == precision:
        restriction_expansion = FreeModule(QQ, nmb_forms_coords).span(forms)
    else: