def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where the parameter ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! .. NOTE: The Fourier expansion of ``J_inv`` for ``d!=1`` is given by ``J_inv_ZZ(q/d)``. .. TODO: The functions that are used in this implementation are products of hypergeometric series with other, elementary, functions. Implement them and clean up this representation. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ F1 = lambda a, b: self._series_ring([ZZ(0)] + [ rising_factorial(a, k) * rising_factorial(b, k) / (ZZ(k).factorial())**2 * sum( ZZ(1) / (a + j) + ZZ(1) / (b + j) - ZZ(2) / ZZ(1 + j) for j in range(ZZ(0), ZZ(k))) for k in range(ZZ(1), ZZ(self._prec + 1)) ], ZZ(self._prec + 1)) F = lambda a, b, c: self._series_ring([ rising_factorial(a, k) * rising_factorial(b, k) / rising_factorial( c, k) / ZZ(k).factorial() for k in range(ZZ(0), ZZ(self._prec + 1)) ], ZZ(self._prec + 1)) a = self._group.alpha() b = self._group.beta() Phi = F1(a, b) / F(a, b, ZZ(1)) q = self._series_ring.gen() # the current implementation of power series reversion is slow # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse()) temp_f = (q * Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree() + 1) J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree() + 1))) return J_inv_ZZ
def _deflated(self, a, b, z): """ Private helper to return list of deflated terms. EXAMPLES:: sage: x = hypergeometric([5], [4], 3) sage: y = x.deflated() sage: y 7/4*hypergeometric((), (), 3) sage: x.n(); y.n() 35.1496896155784 35.1496896155784 """ new = self.eliminate_parameters() aa = new.operands()[0].operands() bb = new.operands()[1].operands() for i, aaa in enumerate(aa): for j, bbb in enumerate(bb): m = aaa - bbb if m in ZZ and m > 0: aaaa = aa[:i] + aa[i + 1:] bbbb = bb[:j] + bb[j + 1:] terms = [] for k in range(m + 1): # TODO: could rewrite prefactors as recurrence term = binomial(m, k) for c in aaaa: term *= rising_factorial(c, k) for c in bbbb: term /= rising_factorial(c, k) term *= z**k term /= rising_factorial(aaa - m, k) F = hypergeometric([c + k for c in aaaa], [c + k for c in bbbb], z) unique = [] counts = [] for c, f in F._deflated(): if f in unique: counts[unique.index(f)] += c else: unique.append(f) counts.append(c) Fterms = zip(counts, unique) terms += [(term * termG, G) for (termG, G) in Fterms] return terms return ((1, new), )
def _deflated(cls, self, a, b, z): """ Private helper to return list of deflated terms. EXAMPLES:: sage: x = hypergeometric([5], [4], 3) sage: y = x.deflated() sage: y 7/4*hypergeometric((), (), 3) sage: x.n(); y.n() 35.1496896155784 35.1496896155784 """ new = self.eliminate_parameters() aa = new.operands()[0].operands() bb = new.operands()[1].operands() for i, aaa in enumerate(aa): for j, bbb in enumerate(bb): m = aaa - bbb if m in ZZ and m > 0: aaaa = aa[:i] + aa[i + 1:] bbbb = bb[:j] + bb[j + 1:] terms = [] for k in xrange(m + 1): # TODO: could rewrite prefactors as recurrence term = binomial(m, k) for c in aaaa: term *= rising_factorial(c, k) for c in bbbb: term /= rising_factorial(c, k) term *= z ** k term /= rising_factorial(aaa - m, k) F = hypergeometric([c + k for c in aaaa], [c + k for c in bbbb], z) unique = [] counts = [] for c, f in F._deflated(): if f in unique: counts[unique.index(f)] += c else: unique.append(f) counts.append(c) Fterms = zip(counts, unique) terms += [(term * termG, G) for (termG, G) in Fterms] return terms return ((1, new),)
def _sympysage_rf(self): """ EXAMPLES:: sage: from sympy import Symbol, rf sage: _ = var('x, y') sage: rfxy = rf(Symbol('x'), Symbol('y')) sage: assert rising_factorial(x,y)._sympy_() == rfxy.rewrite('gamma') sage: assert rising_factorial(x,y) == rfxy._sage_() """ from sage.arith.all import rising_factorial return rising_factorial(self.args[0]._sage_(), self.args[1]._sage_())
def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where the parameter ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! .. NOTE:: The Fourier expansion of ``J_inv`` for ``d!=1`` is given by ``J_inv_ZZ(q/d)``. .. TODO:: The functions that are used in this implementation are products of hypergeometric series with other, elementary, functions. Implement them and clean up this representation. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field sage: MFSeriesConstructor(group=infinity, prec=3).J_inv_ZZ() q^-1 + 3/8 + 69/1024*q + O(q^2) """ F1 = lambda a,b: self._series_ring( [ ZZ(0) ] + [ rising_factorial(a,k) * rising_factorial(b,k) / (ZZ(k).factorial())**2 * sum(ZZ(1)/(a+j) + ZZ(1)/(b+j) - ZZ(2)/ZZ(1+j) for j in range(ZZ(0),ZZ(k)) ) for k in range(ZZ(1), ZZ(self._prec+1)) ], ZZ(self._prec+1) ) F = lambda a,b,c: self._series_ring( [ rising_factorial(a,k) * rising_factorial(b,k) / rising_factorial(c,k) / ZZ(k).factorial() for k in range(ZZ(0), ZZ(self._prec+1)) ], ZZ(self._prec+1) ) a = self._group.alpha() b = self._group.beta() Phi = F1(a,b) / F(a,b,ZZ(1)) q = self._series_ring.gen() # the current implementation of power series reversion is slow # J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reverse()) temp_f = (q*Phi.exp()).polynomial() new_f = temp_f.revert_series(temp_f.degree()+1) J_inv_ZZ = ZZ(1) / (new_f + O(q**(temp_f.degree()+1))) return J_inv_ZZ