def statistic(self, func, q=None): """ Return .. MATH:: prod_{(d, \lambda)\in \tau} n_\lambda(q^d) where `n_\lambda(q)` is the value returned by ``func`` on the input `\lambda`. INPUT: - ``func`` -- a function that takes a partition to a polynomial in ``q`` - ``q`` -- an integer or an indeterminate EXAMPLES:: sage: tau = SimilarityClassType([[1, [1]], [1, [2, 1]], [2, [1, 1]]]) sage: from sage.combinat.similarity_class_type import fq sage: tau.statistic(lambda la: prod([fq(m) for m in la.to_exp()])) (q^9 - 3*q^8 + 2*q^7 + 2*q^6 - 4*q^5 + 4*q^4 - 2*q^3 - 2*q^2 + 3*q - 1)/q^9 sage: q = ZZ['q'].gen() sage: tau.statistic(lambda la: q**la.size(), q = q) q^8 """ if q is None: q = FractionField(ZZ['q']).gen() return prod([PT.statistic(func, q=q) for PT in self])
def centralizer_group_card(self, q=None): """ Return the cardinality of the centralizer group of a matrix of type ``self`` in a field of order ``q``. INPUT: ``q`` -- an integer or an indeterminate EXAMPLES:: sage: PT = PrimarySimilarityClassType(1, []) sage: PT.centralizer_group_card() 1 sage: PT = PrimarySimilarityClassType(2, [1, 1]) sage: PT.centralizer_group_card() q^8 - q^6 - q^4 + q^2 """ if q == None: R = FractionField(ZZ["q"]) q = R.gen() return self.statistic(centralizer_group_cardinality, q=q)
def centralizer_group_card(self, q=None): """ Return the cardinality of the centralizer group of a matrix of type ``self`` in a field of order ``q``. INPUT: ``q`` -- an integer or an indeterminate EXAMPLES:: sage: PT = PrimarySimilarityClassType(1, []) sage: PT.centralizer_group_card() 1 sage: PT = PrimarySimilarityClassType(2, [1, 1]) sage: PT.centralizer_group_card() q^8 - q^6 - q^4 + q^2 """ if q == None: R = FractionField(ZZ['q']) q = R.gen() return self.statistic(centralizer_group_cardinality, q=q)
def mod5family(a, b): """ Formulas for computing the family of elliptic curves with congruent mod-5 representation. EXAMPLES:: sage: from sage.schemes.elliptic_curves.mod5family import mod5family sage: mod5family(0,1) Elliptic Curve defined by y^2 = x^3 + (t^30+30*t^29+435*t^28+4060*t^27+27405*t^26+142506*t^25+593775*t^24+2035800*t^23+5852925*t^22+14307150*t^21+30045015*t^20+54627300*t^19+86493225*t^18+119759850*t^17+145422675*t^16+155117520*t^15+145422675*t^14+119759850*t^13+86493225*t^12+54627300*t^11+30045015*t^10+14307150*t^9+5852925*t^8+2035800*t^7+593775*t^6+142506*t^5+27405*t^4+4060*t^3+435*t^2+30*t+1) over Fraction Field of Univariate Polynomial Ring in t over Rational Field """ J = 4 * a**3 / (4 * a**3 + 27 * b**2) alpha = [0 for _ in range(21)] alpha[0] = 1 alpha[1] = 0 alpha[2] = 190 * (J - 1) alpha[3] = -2280 * (J - 1)**2 alpha[4] = 855 * (J - 1)**2 * (-17 + 16 * J) alpha[5] = 3648 * (J - 1)**3 * (17 - 9 * J) alpha[6] = 11400 * (J - 1)**3 * (17 - 8 * J) alpha[7] = -27360 * (J - 1)**4 * (17 + 26 * J) alpha[8] = 7410 * (J - 1)**4 * (-119 - 448 * J + 432 * J**2) alpha[9] = 79040 * (J - 1)**5 * (17 + 145 * J - 108 * J**2) alpha[10] = 8892 * (J - 1)**5 * (187 + 2640 * J - 5104 * J**2 + 1152 * J**3) alpha[11] = 98800 * (J - 1)**6 * (-17 - 388 * J + 864 * J**2) alpha[12] = 7410 * (J - 1)**6 * (-187 - 6160 * J + 24464 * J**2 - 24192 * J**3) alpha[13] = 54720 * (J - 1)**7 * (17 + 795 * J - 3944 * J**2 + 9072 * J**3) alpha[14] = 2280 * (J - 1)**7 * (221 + 13832 * J - 103792 * J**2 + 554112 * J**3 - 373248 * J**4) alpha[15] = 1824 * (J - 1)**8 * (-119 - 9842 * J + 92608 * J**2 - 911520 * J**3 + 373248 * J**4) alpha[16] = 4275 * (J - 1)**8 * (-17 - 1792 * J + 23264 * J**2 - 378368 * J**3 + 338688 * J**4) alpha[17] = 18240 * (J - 1)**9 * (1 + 133 * J - 2132 * J**2 + 54000 * J**3 - 15552 * J**4) alpha[18] = 190 * (J - 1)**9 * (17 + 2784 * J - 58080 * J**2 + 2116864 * J**3 - 946944 * J**4 + 2985984 * J**5) alpha[19] = 360 * (J - 1)**10 * (-1 + 28 * J - 1152 * J**2) * ( 1 + 228 * J + 176 * J**2 + 1728 * J**3) alpha[20] = (J - 1)**10 * (-19 - 4560 * J + 144096 * J**2 - 9859328 * J**3 - 8798976 * J**4 - 226934784 * J**5 + 429981696 * J**6) beta = [0 for _ in range(31)] beta[0] = 1 beta[1] = 30 beta[2] = -435 * (J - 1) beta[3] = 580 * (J - 1) * (-7 + 9 * J) beta[4] = 3915 * (J - 1)**2 * (7 - 8 * J) beta[5] = 1566 * (J - 1)**2 * (91 - 78 * J + 48 * J**2) beta[6] = -84825 * (J - 1)**3 * (7 + 16 * J) beta[7] = 156600 * (J - 1)**3 * (-13 - 91 * J + 92 * J**2) beta[8] = 450225 * (J - 1)**4 * (13 + 208 * J - 144 * J**2) beta[9] = 100050 * (J - 1)**4 * (143 + 4004 * J - 5632 * J**2 + 1728 * J**3) beta[10] = 30015 * (J - 1)**5 * (-1001 - 45760 * J + 44880 * J**2 - 6912 * J**3) beta[11] = 600300 * (J - 1)**5 * (-91 - 6175 * J + 9272 * J**2 - 2736 * J**3) beta[12] = 950475 * (J - 1)**6 * (91 + 8840 * J - 7824 * J**2) beta[13] = 17108550 * (J - 1)**6 * (7 + 926 * J - 1072 * J**2 + 544 * J**3) beta[14] = 145422675 * (J - 1)**7 * (-1 - 176 * J + 48 * J**2 - 384 * J**3) beta[15] = 155117520 * (J - 1)**8 * (1 + 228 * J + 176 * J**2 + 1728 * J**3) beta[16] = 145422675 * (J - 1)**8 * (1 + 288 * J + 288 * J**2 + 5120 * J**3 - 6912 * J**4) beta[17] = 17108550 * (J - 1)**8 * (7 + 2504 * J + 3584 * J**2 + 93184 * J**3 - 283392 * J**4 + 165888 * J**5) beta[18] = 950475 * (J - 1)**9 * (-91 - 39936 * J - 122976 * J**2 - 2960384 * J**3 + 11577600 * J**4 - 5971968 * J**5) beta[19] = 600300 * (J - 1)**9 * (-91 - 48243 * J - 191568 * J**2 - 6310304 * J**3 + 40515072 * J**4 - 46455552 * J**5 + 11943936 * J**6) beta[20] = 30015 * (J - 1)**10 * (1001 + 634920 * J + 3880800 * J**2 + 142879744 * J**3 - 1168475904 * J**4 + 1188919296 * J**5 - 143327232 * J**6) beta[21] = 100050 * (J - 1)**10 * (143 + 107250 * J + 808368 * J**2 + 38518336 * J**3 - 451953408 * J**4 + 757651968 * J**5 - 367276032 * J**6) beta[22] = 450225 * (J - 1)**11 * (-13 - 11440 * J - 117216 * J**2 - 6444800 * J**3 + 94192384 * J**4 - 142000128 * J**5 + 95551488 * J**6) beta[23] = 156600 * (J - 1)**11 * ( -13 - 13299 * J - 163284 * J**2 - 11171552 * J**3 + 217203840 * J**4 - 474406656 * J**5 + 747740160 * J**6 - 429981696 * J**7) beta[24] = 6525*(J - 1)**12*(91 + 107536*J + 1680624*J**2 + 132912128*J**3 -\ 3147511552*J**4 + 6260502528*J**5 - 21054173184*J**6 + 10319560704*J**7) beta[25] = 1566*(J - 1)**12*(91 + 123292*J + 2261248*J**2 + 216211904*J**3 - \ 6487793920*J**4 + 17369596928*J**5 - 97854234624*J**6 + 96136740864*J**7 - 20639121408*J**8) beta[26] = 3915*(J - 1)**13*(-7 - 10816*J - 242352*J**2 - 26620160*J**3 + 953885440*J**4 - \ 2350596096*J**5 + 26796552192*J**6 - 13329432576*J**7) beta[27] = 580*(J - 1)**13*(-7 - 12259*J - 317176*J**2 - 41205008*J**3 + \ 1808220160*J**4 - 5714806016*J**5 + 93590857728*J**6 - 70131806208*J**7 - 36118462464*J**8) beta[28] = 435*(J - 1)**14*(1 + 1976*J + 60720*J**2 + 8987648*J**3 - 463120640*J**4 + 1359157248*J**5 - \ 40644882432*J**6 - 5016453120*J**7 + 61917364224*J**8) beta[29] = 30*(J - 1)**14*(1 + 2218*J + 77680*J**2 + 13365152*J**3 - \ 822366976*J**4 + 2990693888*J**5 - 118286217216*J**6 - 24514928640*J**7 + 509958291456*J**8 - 743008370688*J**9) beta[30] = (J - 1)**15*(-1 - 2480*J - 101040*J**2 - 19642496*J**3 + 1399023872*J**4 - \ 4759216128*J**5 + 315623485440*J**6 + 471904911360*J**7 - 2600529297408*J**8 + 8916100448256*J**9) R = PolynomialRing(QQ, 't') b4 = a * R(alpha) b6 = b * R(beta) c2 = b4 c3 = b6 d = lcm(c2.denominator(), c3.denominator()) F = FractionField(R) E = EllipticCurve(F, [c2 * d**4, c3 * d**6]) return E
def __init__(self, group, base_ring, prec, fix_d, set_d, d_num_prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` - A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``base_ring`` - The base ring (default: ZZ) - ``prec`` - An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. - ``fix_d`` - ``True`` or ``False`` (default: ``False``). If ``fix_d == False`` the base ring of the power series is (the fraction field) of the polynomial ring over the base ring in one formal parameter ``d``. If ``fix_d == True`` the formal parameter ``d`` is replaced by its numerical value with numerical precision at least ``d_num_prec`` (or exact in case n=3, 4, 6). The base ring of the PowerSeriesRing or LaurentSeriesRing is changed to a common parent of ``base_ring`` and the parent of the mentioned value ``d``. - ``set_d`` - A number which replaces the formal parameter ``d``. The base ring of the PowerSeriesRing or LaurentSeriesRing is changed to a common parent of ``base_ring`` and the parent of the specified value for ``d``. Note that in particular ``set_d=1`` will produce rational Fourier expansions. - ``d_num_prec`` - An integer, a lower bound for the precision of the numerical value of ``d``. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: MFC = MFSeriesConstructor() sage: MFC Power series constructor for Hecke modular forms for n=3, base ring=Integer Ring with (basic series) precision 10 with formal parameter d sage: MFC.group() Hecke triangle group for n = 3 sage: MFC.prec() 10 sage: MFC.d().parent() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFC._ZZseries_ring Power Series Ring in q over Rational Field sage: MFSeriesConstructor(set_d=CC(1)) Power series constructor for Hecke modular forms for n=3, base ring=Complex Field with 53 bits of precision with (basic series) precision 10 with parameter d=1.00000000000000 sage: MFSeriesConstructor(group=4, fix_d=True) Power series constructor for Hecke modular forms for n=4, base ring=Rational Field with (basic series) precision 10 with parameter d=1/256 sage: MFSeriesConstructor(group=5, fix_d=True) Power series constructor for Hecke modular forms for n=5, base ring=Real Field with 53 bits of precision with (basic series) precision 10 with parameter d=0.00705223418128563 """ self._group = group self._base_ring = base_ring self._prec = prec self._fix_d = fix_d self._set_d = set_d self._d_num_prec = d_num_prec if (set_d): self._coeff_ring = FractionField(base_ring) self._d = set_d else: self._coeff_ring = FractionField(PolynomialRing(base_ring,"d")) self._d = self._coeff_ring.gen() self._ZZseries_ring = PowerSeriesRing(QQ,'q',default_prec=self._prec) self._qseries_ring = PowerSeriesRing(self._coeff_ring,'q',default_prec=self._prec)
class MFSeriesConstructor(SageObject,UniqueRepresentation): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. The constructor is used by forms elements in case their Fourier expansion is needed or requested. """ @staticmethod def __classcall__(cls, group = HeckeTriangleGroup(3), base_ring = ZZ, prec=ZZ(10), fix_d=False, set_d=None, d_num_prec=ZZ(53)): r""" Return a (cached) instance with canonical parameters. In particular in case ``fix_d = True`` or if ``set_d`` is set then the ``base_ring`` is replaced by the common parent of ``base_ring`` and the parent of ``set_d`` (resp. the numerical value of ``d`` in case ``fix_d=True``). EXAMPLES:: sage: MFSeriesConstructor() == MFSeriesConstructor(3, ZZ, 10, False, None, 53) True sage: MFSeriesConstructor(base_ring = CC, set_d=CC(1)) == MFSeriesConstructor(set_d=CC(1)) True sage: MFSeriesConstructor(group=4, fix_d=True).base_ring() == QQ True sage: MFSeriesConstructor(group=5, fix_d=True).base_ring() == RR True """ if (group==infinity): group = HeckeTriangleGroup(infinity) else: try: group = HeckeTriangleGroup(ZZ(group)) except TypeError: group = HeckeTriangleGroup(group.n()) prec=ZZ(prec) #if (prec<1): # raise Exception("prec must be an Integer >=1") fix_d = bool(fix_d) if (fix_d): n = group.n() d = group.dvalue() if (group.is_arithmetic()): d_num_prec = None set_d = 1/base_ring(1/d) else: d_num_prec = ZZ(d_num_prec) set_d = group.dvalue().n(d_num_prec) else: d_num_prec = None if (set_d is not None): base_ring=(base_ring(1)*set_d).parent() #elif (not base_ring.is_exact()): # raise NotImplementedError return super(MFSeriesConstructor,cls).__classcall__(cls, group, base_ring, prec, fix_d, set_d, d_num_prec) def __init__(self, group, base_ring, prec, fix_d, set_d, d_num_prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` - A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``base_ring`` - The base ring (default: ZZ) - ``prec`` - An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. - ``fix_d`` - ``True`` or ``False`` (default: ``False``). If ``fix_d == False`` the base ring of the power series is (the fraction field) of the polynomial ring over the base ring in one formal parameter ``d``. If ``fix_d == True`` the formal parameter ``d`` is replaced by its numerical value with numerical precision at least ``d_num_prec`` (or exact in case n=3, 4, 6). The base ring of the PowerSeriesRing or LaurentSeriesRing is changed to a common parent of ``base_ring`` and the parent of the mentioned value ``d``. - ``set_d`` - A number which replaces the formal parameter ``d``. The base ring of the PowerSeriesRing or LaurentSeriesRing is changed to a common parent of ``base_ring`` and the parent of the specified value for ``d``. Note that in particular ``set_d=1`` will produce rational Fourier expansions. - ``d_num_prec`` - An integer, a lower bound for the precision of the numerical value of ``d``. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: MFC = MFSeriesConstructor() sage: MFC Power series constructor for Hecke modular forms for n=3, base ring=Integer Ring with (basic series) precision 10 with formal parameter d sage: MFC.group() Hecke triangle group for n = 3 sage: MFC.prec() 10 sage: MFC.d().parent() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFC._ZZseries_ring Power Series Ring in q over Rational Field sage: MFSeriesConstructor(set_d=CC(1)) Power series constructor for Hecke modular forms for n=3, base ring=Complex Field with 53 bits of precision with (basic series) precision 10 with parameter d=1.00000000000000 sage: MFSeriesConstructor(group=4, fix_d=True) Power series constructor for Hecke modular forms for n=4, base ring=Rational Field with (basic series) precision 10 with parameter d=1/256 sage: MFSeriesConstructor(group=5, fix_d=True) Power series constructor for Hecke modular forms for n=5, base ring=Real Field with 53 bits of precision with (basic series) precision 10 with parameter d=0.00705223418128563 """ self._group = group self._base_ring = base_ring self._prec = prec self._fix_d = fix_d self._set_d = set_d self._d_num_prec = d_num_prec if (set_d): self._coeff_ring = FractionField(base_ring) self._d = set_d else: self._coeff_ring = FractionField(PolynomialRing(base_ring,"d")) self._d = self._coeff_ring.gen() self._ZZseries_ring = PowerSeriesRing(QQ,'q',default_prec=self._prec) self._qseries_ring = PowerSeriesRing(self._coeff_ring,'q',default_prec=self._prec) def _repr_(self): r""" Return the string representation of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True) Power series constructor for Hecke modular forms for n=4, base ring=Rational Field with (basic series) precision 10 with parameter d=1/256 sage: MFSeriesConstructor(group=5) Power series constructor for Hecke modular forms for n=5, base ring=Integer Ring with (basic series) precision 10 with formal parameter d """ if (self._set_d): return "Power series constructor for Hecke modular forms for n={}, base ring={} with (basic series) precision {} with parameter d={}".\ format(self._group.n(), self._base_ring, self._prec, self._d) else: return "Power series constructor for Hecke modular forms for n={}, base ring={} with (basic series) precision {} with formal parameter d".\ format(self._group.n(), self._base_ring, self._prec) def group(self): r""" Return the (Hecke triangle) group of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).group() Hecke triangle group for n = 4 """ return self._group def hecke_n(self): r""" Return the parameter ``n`` of the (Hecke triangle) group of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).hecke_n() 4 """ return self._group.n() def base_ring(self): r""" Return base ring of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True).base_ring() Real Field with 53 bits of precision sage: MFSeriesConstructor(group=5, fix_d=True, d_num_prec=100).base_ring() Real Field with 100 bits of precision """ return self._base_ring def prec(self): r""" Return the used default precision for the PowerSeriesRing or LaurentSeriesRing. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True).prec() 10 sage: MFSeriesConstructor(group=5, prec=20).prec() 20 """ return self._prec def fix_d(self): r""" Return whether the numerical value for the parameter ``d`` will be substituted or not. Note: Depending on whether ``set_d`` is ``None`` or not ``d`` might still be substituted despite ``fix_d`` being ``False``. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True, set_d=1).fix_d() True sage: MFSeriesConstructor(group=5, fix_d=True, set_d=1).set_d() 0.00705223418128563 sage: MFSeriesConstructor(group=5, set_d=1).fix_d() False """ return self._fix_d def set_d(self): r""" Return the numerical value which is substituted for the parameter ``d``. Default: ``None``, meaning the formal parameter ``d`` is used. EXAMPLES:: sage: MFSeriesConstructor(group=5, fix_d=True, set_d=1).set_d() 0.00705223418128563 sage: MFSeriesConstructor(group=5, set_d=1).set_d() 1 sage: MFSeriesConstructor(group=5, set_d=1).set_d().parent() Integer Ring """ return self._set_d def is_exact(self): r""" Return whether used ``base_ring`` is exact. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).is_exact() True sage: MFSeriesConstructor(group=5, fix_d=True).is_exact() False sage: MFSeriesConstructor(group=5, set_d=1).is_exact() True """ return self._base_ring.is_exact() def d(self): r""" Return the formal parameter ``d`` respectively its (possibly numerical) value in case ``set_d`` is not ``None``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).d() 1/256 sage: MFSeriesConstructor(group=4).d() d sage: MFSeriesConstructor(group=4).d().parent() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, fix_d=True).d() 0.00705223418128563 sage: MFSeriesConstructor(group=5, set_d=1).d() 1 """ return self._d def q(self): r""" Return the generator of the used PowerSeriesRing. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).q() q sage: MFSeriesConstructor(group=4, fix_d=True).q().parent() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=5, fix_d=True).q().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self._qseries_ring.gen() def coeff_ring(self): r""" Return coefficient ring of ``self``. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).coeff_ring() Rational Field sage: MFSeriesConstructor(group=4).coeff_ring() Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, fix_d=True).coeff_ring() Real Field with 53 bits of precision sage: MFSeriesConstructor(group=5).coeff_ring() Fraction Field of Univariate Polynomial Ring in d over Integer Ring """ return self._coeff_ring def qseries_ring(self): r""" Return the used PowerSeriesRing. EXAMPLES:: sage: MFSeriesConstructor(group=4, fix_d=True).qseries_ring() Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=4).qseries_ring() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, fix_d=True).qseries_ring() Power Series Ring in q over Real Field with 53 bits of precision sage: MFSeriesConstructor(group=5).qseries_ring() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring """ return self._qseries_ring @cached_method def J_inv_ZZ(self): r""" Return the rational Fourier expansion of ``J_inv``, where ``d`` is replaced by ``1``. This is the main function used to determine all Fourier expansions! EXAMPLES:: sage: MFSeriesConstructor(prec=3).J_inv_ZZ() q^-1 + 31/72 + 1823/27648*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv_ZZ() q^-1 + 79/200 + 42877/640000*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv_ZZ().parent() Laurent Series Ring in q over Rational Field """ F1 = lambda a,b: self._ZZseries_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._ZZseries_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._ZZseries_ring.gen() J_inv_ZZ = ZZ(1) / ((q*Phi.exp()).reversion()) return J_inv_ZZ @cached_method def J_inv(self): r""" Return the Fourier expansion of ``J_inv``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).J_inv() 1/1728*q^-1 + 31/72 + 1823/16*q + O(q^2) sage: MFSeriesConstructor(prec=3).J_inv_ZZ() == MFSeriesConstructor(prec=3, set_d=1).J_inv() True sage: MFSeriesConstructor(group=5, prec=3).J_inv() d*q^-1 + 79/200 + 42877/(640000*d)*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv() 0.00705223418128563*q^-1 + 0.395000000000000 + 9.49987064777062*q + O(q^2) sage: MFSeriesConstructor(group=5, prec=3).J_inv().parent() Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).J_inv().parent() Laurent Series Ring in q over Real Field with 53 bits of precision """ return self.J_inv_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def F_rho_ZZ(self): r""" Return the rational Fourier expansion of ``F_rho``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).F_rho_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho_ZZ() 1 + 7/100*q + 21/160000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() temp_expr = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() F_rho_ZZ = (temp_expr.log()/(n-2)).exp() return F_rho_ZZ @cached_method def F_rho(self): r""" Return the Fourier expansion of ``F_rho``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).F_rho() 1 + 240*q + 2160*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).F_rho_ZZ() == MFSeriesConstructor(prec=3, set_d=1).F_rho() True sage: MFSeriesConstructor(group=5, prec=3).F_rho() 1 + 7/(100*d)*q + 21/(160000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho() 1.00000000000000 + 9.92593243510795*q + 2.63903932249093*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).F_rho().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_rho().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.F_rho_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def F_i_ZZ(self): r""" Return the rational Fourier expansion of ``F_i``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).F_i_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i_ZZ() 1 - 13/40*q - 351/64000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() temp_expr = ((-q*self.J_inv_ZZ().derivative())**n/(self.J_inv_ZZ()**(n-1)*(self.J_inv_ZZ()-1))).power_series() F_i_ZZ = (temp_expr.log()/(n-2)).exp() return F_i_ZZ @cached_method def F_i(self): r""" Return the Fourier expansion of ``F_i``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).F_i() 1 - 504*q - 16632*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).F_i_ZZ() == MFSeriesConstructor(prec=3, set_d=1).F_i() True sage: MFSeriesConstructor(group=5, prec=3).F_i() 1 - 13/(40*d)*q - 351/(64000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i() 1.00000000000000 - 46.0846863058583*q - 110.274143118371*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).F_i().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_i().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.F_i_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def F_inf_ZZ(self): r""" Return the rational Fourier expansion of ``F_inf``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).F_inf_ZZ() q - 1/72*q^2 + 7/82944*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf_ZZ() q - 9/200*q^2 + 279/640000*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() temp_expr = ((-q*self.J_inv_ZZ().derivative())**(2*n)/(self.J_inv_ZZ()**(2*n-2)*(self.J_inv_ZZ()-1)**n)/q**(n-2)).power_series() F_inf_ZZ = (temp_expr.log()/(n-2)).exp()*q return F_inf_ZZ @cached_method def F_inf(self): r""" Return the Fourier expansion of ``F_inf``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).F_inf() q - 24*q^2 + 252*q^3 + O(q^4) sage: MFSeriesConstructor(prec=3).F_inf_ZZ() == MFSeriesConstructor(prec=3, set_d=1).F_inf() True sage: MFSeriesConstructor(group=5, prec=3).F_inf() q - 9/(200*d)*q^2 + 279/(640000*d^2)*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf() 0.000000000000000 + 1.00000000000000*q - 6.38095656542654*q^2 + 8.76538060684488*q^3 + O(q^4) sage: MFSeriesConstructor(group=5, prec=3).F_inf().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).F_inf().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self._d*self.F_inf_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def G_inv_ZZ(self): r""" Return the rational Fourier expansion of ``G_inv``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(group=4, prec=3).G_inv_ZZ() q^-1 - 3/32 - 955/16384*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv_ZZ() q^-1 - 15/128 - 15139/262144*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv_ZZ().parent() Laurent Series Ring in q over Rational Field """ n = self.hecke_n() if (ZZ(2).divides(n)): return self.F_i_ZZ()*(self.F_rho_ZZ()**(ZZ(n/ZZ(2))))/self.F_inf_ZZ() else: #return self._qseries_ring([]) raise Exception("G_inv doesn't exist for n={}.".format(self.hecke_n())) @cached_method def G_inv(self): r""" Return the Fourier expansion of ``G_inv``. EXAMPLES:: sage: MFSeriesConstructor(group=4, prec=3, fix_d=True).G_inv() 1/16777216*q^-1 - 3/2097152 - 955/4194304*q + O(q^2) sage: MFSeriesConstructor(group=4, prec=3).G_inv_ZZ() == MFSeriesConstructor(group=4, prec=3, set_d=1).G_inv() True sage: MFSeriesConstructor(group=8, prec=3).G_inv() d^3*q^-1 - 15*d^2/128 - 15139*d/262144*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv() 1.64838830030189e-6*q^-1 - 0.0000163526310530017 - 0.000682197999433738*q + O(q^2) sage: MFSeriesConstructor(group=8, prec=3).G_inv().parent() Laurent Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=8, prec=3, fix_d=True).G_inv().parent() Laurent Series Ring in q over Real Field with 53 bits of precision """ return (self._d)**2*self.G_inv_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def E4_ZZ(self): r""" Return the rational Fourier expansion of ``E_4``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).E4_ZZ() 1 + 5/36*q + 5/6912*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4_ZZ() 1 + 21/100*q + 483/32000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() E4_ZZ = ((-q*self.J_inv_ZZ().derivative())**2/(self.J_inv_ZZ()*(self.J_inv_ZZ()-1))).power_series() return E4_ZZ @cached_method def E4(self): r""" Return the Fourier expansion of ``E_4``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).E4() 1 + 240*q + 2160*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).E4_ZZ() == MFSeriesConstructor(prec=3, set_d=1).E4() True sage: MFSeriesConstructor(group=5, prec=3).E4() 1 + 21/(100*d)*q + 483/(32000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4() 1.00000000000000 + 29.7777973053239*q + 303.489522086457*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E4().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E4().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.E4_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def E6_ZZ(self): r""" Return the rational Fourier expansion of ``E_6``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).E6_ZZ() 1 - 7/24*q - 77/13824*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6_ZZ() 1 - 37/200*q - 14663/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() n = self.hecke_n() E6_ZZ = ((-q*self.J_inv_ZZ().derivative())**3/(self.J_inv_ZZ()**2*(self.J_inv_ZZ()-1))).power_series() return E6_ZZ @cached_method def E6(self): r""" Return the Fourier expansion of ``E_6``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).E6() 1 - 504*q - 16632*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).E6_ZZ() == MFSeriesConstructor(prec=3, set_d=1).E6() True sage: MFSeriesConstructor(group=5, prec=3).E6() 1 - 37/(200*d)*q - 14663/(320000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6() 1.00000000000000 - 26.2328214356424*q - 921.338894897250*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E6().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E6().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.E6_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def Delta_ZZ(self): r""" Return the rational Fourier expansion of ``Delta``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).Delta_ZZ() q - 1/72*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta_ZZ() 71/50*q + 28267/16000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta_ZZ().parent() Power Series Ring in q over Rational Field """ n = self.hecke_n() return self.E4_ZZ()**(2*n-6)*(self.E4_ZZ()**n-self.E6_ZZ()**2) @cached_method def Delta(self): r""" Return the Fourier expansion of ``Delta``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).Delta() q - 24*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).Delta_ZZ() == MFSeriesConstructor(prec=3, set_d=1).Delta() True sage: MFSeriesConstructor(group=5, prec=3).Delta() 71/50*q + 28267/(16000*d)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta() 0.000000000000000 + 1.42000000000000*q + 250.514582270711*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).Delta().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).Delta().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return (self._d)*self.Delta_ZZ()(self._qseries_ring.gen()/self._d) @cached_method def E2_ZZ(self): r""" Return the rational Fourier expansion of ``E2``, where ``d`` is replaced by ``1``. EXAMPLES:: sage: MFSeriesConstructor(prec=3).E2_ZZ() 1 - 1/72*q - 1/41472*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2_ZZ() 1 - 9/200*q - 369/320000*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2_ZZ().parent() Power Series Ring in q over Rational Field """ q = self._ZZseries_ring.gen() E2_ZZ = (q*self.F_inf_ZZ().derivative())/self.F_inf_ZZ() return E2_ZZ @cached_method def E2(self): r""" Return the Fourier expansion of ``E2``. EXAMPLES:: sage: MFSeriesConstructor(prec=3, fix_d=True).E2() 1 - 24*q - 72*q^2 + O(q^3) sage: MFSeriesConstructor(prec=3).E2_ZZ() == MFSeriesConstructor(prec=3, set_d=1).E2() True sage: MFSeriesConstructor(group=5, prec=3).E2() 1 - 9/(200*d)*q - 369/(320000*d^2)*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2() 1.00000000000000 - 6.38095656542654*q - 23.1858454761703*q^2 + O(q^3) sage: MFSeriesConstructor(group=5, prec=3).E2().parent() Power Series Ring in q over Fraction Field of Univariate Polynomial Ring in d over Integer Ring sage: MFSeriesConstructor(group=5, prec=3, fix_d=True).E2().parent() Power Series Ring in q over Real Field with 53 bits of precision """ return self.E2_ZZ()(self._qseries_ring.gen()/self._d)
def rational_type(f, n=ZZ(3), base_ring=ZZ): r""" Return the basic analytic properties that can be determined directly from the specified rational function ``f`` which is interpreted as a representation of an element of a FormsRing for the Hecke Triangle group with parameter ``n`` and the specified ``base_ring``. In particular the following degree of the generators is assumed: `deg(1) := (0, 1)` `deg(x) := (4/(n-2), 1)` `deg(y) := (2n/(n-2), -1)` `deg(z) := (2, -1)` The meaning of homogeneous elements changes accordingly. INPUT: - ``f`` -- A rational function in ``x,y,z,d`` over ``base_ring``. - ``n`` -- An integer greater or equal to `3` corresponding to the ``HeckeTriangleGroup`` with that parameter (default: `3`). - ``base_ring`` -- The base ring of the corresponding forms ring, resp. polynomial ring (default: ``ZZ``). OUTPUT: A tuple ``(elem, h**o, k, ep, analytic_type)`` describing the basic analytic properties of `f` (with the interpretation indicated above). - ``elem`` -- ``True`` if `f` has a homogeneous denominator. - ``h**o`` -- ``True`` if `f` also has a homogeneous numerator. - ``k`` -- ``None`` if `f` is not homogeneous, otherwise the weight of `f` (which is the first component of its degree). - ``ep`` -- ``None`` if `f` is not homogeneous, otherwise the multiplier of `f` (which is the second component of its degree) - ``analytic_type`` -- The ``AnalyticType`` of `f`. For the zero function the degree `(0, 1)` is choosen. This function is (heavily) used to determine the type of elements and to check if the element really is contained in its parent. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.constructor import rational_type sage: (x,y,z,d) = var("x,y,z,d") sage: rational_type(0, n=4) (True, True, 0, 1, zero) sage: rational_type(1, n=12) (True, True, 0, 1, modular) sage: rational_type(x^3 - y^2) (True, True, 12, 1, cuspidal) sage: rational_type(x * z, n=7) (True, True, 14/5, -1, quasi modular) sage: rational_type(1/(x^3 - y^2) + z/d) (True, False, None, None, quasi weakly holomorphic modular) sage: rational_type(x^3/(x^3 - y^2)) (True, True, 0, 1, weakly holomorphic modular) sage: rational_type(1/(x + z)) (False, False, None, None, None) sage: rational_type(1/x + 1/z) (True, False, None, None, quasi meromorphic modular) sage: rational_type(d/x, n=10) (True, True, -1/2, 1, meromorphic modular) sage: rational_type(1.1 * z * (x^8-y^2), n=8, base_ring=CC) (True, True, 22/3, -1, quasi cuspidal) sage: rational_type(x-y^2, n=infinity) (True, True, 4, 1, modular) sage: rational_type(x*(x-y^2), n=infinity) (True, True, 8, 1, cuspidal) sage: rational_type(1/x, n=infinity) (True, True, -4, 1, weakly holomorphic modular) """ from .analytic_type import AnalyticType AT = AnalyticType() # Determine whether f is zero if (f == 0): # elem, h**o, k, ep, analytic_type return (True, True, QQ(0), ZZ(1), AT([])) analytic_type = AT(["quasi", "mero"]) R = PolynomialRing(base_ring, 'x,y,z,d') F = FractionField(R) (x, y, z, d) = R.gens() R2 = PolynomialRing(PolynomialRing(base_ring, 'd'), 'x,y,z') dhom = R.hom(R2.gens() + (R2.base().gen(), ), R2) f = F(f) num = R(f.numerator()) denom = R(f.denominator()) ep_num = set([ ZZ(1) - 2 * ((sum([g.exponents()[0][m] for m in [1, 2]])) % 2) for g in dhom(num).monomials() ]) ep_denom = set([ ZZ(1) - 2 * ((sum([g.exponents()[0][m] for m in [1, 2]])) % 2) for g in dhom(denom).monomials() ]) if (n == infinity): hom_num = R(num.subs(x=x**4, y=y**2, z=z**2)) hom_denom = R(denom.subs(x=x**4, y=y**2, z=z**2)) else: n = ZZ(n) hom_num = R(num.subs(x=x**4, y=y**(2 * n), z=z**(2 * (n - 2)))) hom_denom = R(denom.subs(x=x**4, y=y**(2 * n), z=z**(2 * (n - 2)))) # Determine whether the denominator of f is homogeneous if (len(ep_denom) == 1 and dhom(hom_denom).is_homogeneous()): elem = True else: # elem, h**o, k, ep, analytic_type return (False, False, None, None, None) # Determine whether f is homogeneous if (len(ep_num) == 1 and dhom(hom_num).is_homogeneous()): h**o = True if (n == infinity): weight = (dhom(hom_num).degree() - dhom(hom_denom).degree()) else: weight = (dhom(hom_num).degree() - dhom(hom_denom).degree()) / (n - 2) ep = ep_num.pop() / ep_denom.pop() # TODO: decompose f (resp. its degrees) into homogeneous parts else: h**o = False weight = None ep = None # Note that we intentionally leave out the d-factor! if (n == infinity): finf_pol = (x - y**2) else: finf_pol = x**n - y**2 # Determine whether f is modular if not ((num.degree(z) > 0) or (denom.degree(z) > 0)): analytic_type = analytic_type.reduce_to("mero") # Determine whether f is holomorphic if (dhom(denom).is_constant()): analytic_type = analytic_type.reduce_to(["quasi", "holo"]) # Determine whether f is cuspidal in the sense that finf divides it... # Bug in singular: finf_pol.divides(1.0) fails over RR if (not dhom(num).is_constant() and finf_pol.divides(num)): if (n != infinity or x.divides(num)): analytic_type = analytic_type.reduce_to(["quasi", "cusp"]) else: # -> Because of a bug with singular in some cases try: while (finf_pol.divides(denom)): # a simple "denom /= finf_pol" is strangely not enough for non-exact rings # and dividing would/may result with an element of the quotient ring of the polynomial ring denom = denom.quo_rem(finf_pol)[0] denom = R(denom) if (n == infinity): while (x.divides(denom)): # a simple "denom /= x" is strangely not enough for non-exact rings # and dividing would/may result with an element of the quotient ring of the polynomial ring denom = denom.quo_rem(x)[0] denom = R(denom) except TypeError: pass # Determine whether f is weakly holomorphic in the sense that at most powers of finf occur in denom if (dhom(denom).is_constant()): analytic_type = analytic_type.reduce_to(["quasi", "weak"]) return (elem, h**o, weight, ep, analytic_type)