Let $$E_2$$ be the weight 2 Eisenstein series defined by

$E_2(z) = 1 - \frac{2k}{B_k} \sum_{n=1}^{\infty} \sigma(n) q^n$

where $$\sigma$$ is the sum of divisors function and $$q = \mathrm{exp}(2\pi i z)$$ is the classical parameter at infinity, with $$\mathrm{im}(z)>0$$. This weight 2 Eisenstein series is not a modular form as it does not satisfy the modularity condition:

$z^2 E_2(-1/z) = E_2(z) + \frac{2k}{4\pi i B_k z}.$

$$E_2$$ is a quasimodular form of weight 2. General quasimodular forms of given weight can also be defined. We denote by $$QM$$ the graded ring of quasimodular forms for the full modular group $$\SL_2(\ZZ)$$.

The SageMath implementation of the graded ring of quasimodular forms uses the following isomorphism:

$QM \cong M_* [E_2]$

where $$M_* \cong \CC[E_4, E_6]$$ is the graded ring of modular forms for $$\SL_2(\ZZ)$$. (see sage.modular.modform.ring.ModularFormsRing).

More generally, if $$\Gamma \leq \SL_2(\ZZ)$$ is a congruence subgroup, then the graded ring of quasimodular forms for $$\Gamma$$ is given by $$M_*(\Gamma)[E_2]$$ where $$M_*(\Gamma)$$ is the ring of modular forms for $$\Gamma$$.

The SageMath implementation of the graded quasimodular forms ring allows computation of a set of generators and perform usual arithmetic operations.

EXAMPLES:

sage: QM = QuasiModularForms(1); QM
Ring of Quasimodular Forms for Modular Group SL(2,Z) over Rational Field
sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]
sage: E2 = QM.0; E4 = QM.1; E6 = QM.2
sage: E2 * E4 + E6
2 - 288*q - 20304*q^2 - 185472*q^3 - 855216*q^4 - 2697408*q^5 + O(q^6)
sage: E2.parent()
Ring of Quasimodular Forms for Modular Group SL(2,Z) over Rational Field


The polygen method also return the weight-2 Eisenstein series as a polynomial variable over the ring of modular forms:

sage: QM = QuasiModularForms(1)
sage: E2 = QM.polygen(); E2
E2
sage: E2.parent()
Univariate Polynomial Ring in E2 over Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field


An element of a ring of quasimodular forms can be created via a list of modular forms or graded modular forms. The $$i$$-th index of the list will correspond to the $$i$$-th coefficient of the polynomial in $$E_2$$:

sage: QM = QuasiModularForms(1)
sage: E2 = QM.0
sage: Delta = CuspForms(1, 12).0
sage: E4 = ModularForms(1, 4).0
sage: F = QM([Delta, E4, Delta + E4]); F
2 + 410*q - 12696*q^2 - 50424*q^3 + 1076264*q^4 + 10431996*q^5 + O(q^6)
sage: F == Delta + E4 * E2 + (Delta + E4) * E2^2
True


One may also create rings of quasimodular forms for certain congruence subgroups:

sage: QM = QuasiModularForms(Gamma0(5)); QM
Ring of Quasimodular Forms for Congruence Subgroup Gamma0(5) over Rational Field
sage: QM.ngens()
4


The first generator is the weight 2 Eisenstein series:

sage: E2 = QM.0; E2
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)


The other generators correspond to the generators given by the method sage.modular.modform.ring.ModularFormsRing.gens():

sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 6*q + 18*q^2 + 24*q^3 + 42*q^4 + 6*q^5 + O(q^6),
1 + 240*q^5 + O(q^6),
q + 10*q^3 + 28*q^4 + 35*q^5 + O(q^6)]
sage: QM.modular_forms_subring().gens()
[1 + 6*q + 18*q^2 + 24*q^3 + 42*q^4 + 6*q^5 + O(q^6),
1 + 240*q^5 + O(q^6),
q + 10*q^3 + 28*q^4 + 35*q^5 + O(q^6)]


It is possible to convert a graded quasimodular form into a polynomial where each variable corresponds to a generator of the ring:

sage: QM = QuasiModularForms(1)
sage: E2, E4, E6 = QM.gens()
sage: F = E2*E4*E6 + E6^2; F
2 - 1296*q + 91584*q^2 + 14591808*q^3 + 464670432*q^4 + 6160281120*q^5 + O(q^6)
sage: p = F.polynomial('E2, E4, E6'); p
E2*E4*E6 + E6^2
sage: P = p.parent(); P
Multivariate Polynomial Ring in E2, E4, E6 over Rational Field


The generators of the polynomial ring have degree equal to the weight of the corresponding form:

sage: P.inject_variables()
Defining E2, E4, E6
sage: E2.degree()
2
sage: E4.degree()
4
sage: E6.degree()
6


This works also for congruence subgroup:

sage: QM = QuasiModularForms(Gamma1(4))
sage: QM.ngens()
5
sage: QM.polynomial_ring()
Multivariate Polynomial Ring in E2, E2_0, E2_1, E3_0, E3_1 over Rational Field
sage: (QM.0 + QM.1*QM.0^2 + QM.3 + QM.4^3).polynomial()
E3_1^3 + E2^2*E2_0 + E3_0 + E2


One can also convert a multivariate polynomial into a quasimodular form:

sage: QM.polynomial_ring().inject_variables()
Defining E2, E2_0, E2_1, E3_0, E3_1
sage: QM.from_polynomial(E3_1^3 + E2^2*E2_0 + E3_0 + E2)
3 - 72*q + 396*q^2 + 2081*q^3 + 19752*q^4 + 98712*q^5 + O(q^6)


Note

• Currently, the only supported base ring is the Rational Field;

• Spaces of quasimodular forms of fixed weight are not yet implemented.

REFERENCE:

See section 5.3 (page 58) of [Zag2008]

AUTHORS:

• David Ayotte (2021-03-18): initial version

class sage.modular.quasimodform.ring.QuasiModularForms(group=1, base_ring=Rational Field, name='E2')#

The graded ring of quasimodular forms for the full modular group $$\SL_2(\ZZ)$$, with coefficients in a ring.

EXAMPLES:

sage: QM = QuasiModularForms(1); QM
Ring of Quasimodular Forms for Modular Group SL(2,Z) over Rational Field
sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]


It is possible to access the weight 2 Eisenstein series:

sage: QM.weight_2_eisenstein_series()
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)


Currently, the only supported base ring is the rational numbers:

sage: QuasiModularForms(1, GF(5))
Traceback (most recent call last):
...
NotImplementedError: base ring other than Q are not yet supported for quasimodular forms ring

Element#
from_polynomial(polynomial)#

Convert the given polynomial $$P(x,\ldots, y)$$ to the graded quasiform $$P(g_0, \ldots, g_n)$$ where the $$g_i$$ are the generators given by gens().

INPUT:

• polynomial – A multivariate polynomial

OUTPUT: the graded quasimodular forms $$P(g_0, \ldots, g_n)$$

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: P.<x, y, z> = QQ[]
sage: QM.from_polynomial(x)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: QM.from_polynomial(x) == QM.0
True
sage: QM.from_polynomial(y) == QM.1
True
sage: QM.from_polynomial(z) == QM.2
True
sage: QM.from_polynomial(x^2 + y + x*z + 1)
4 - 336*q - 2016*q^2 + 322368*q^3 + 3691392*q^4 + 21797280*q^5 + O(q^6)
sage: QM = QuasiModularForms(Gamma0(2))
sage: P = QM.polynomial_ring()
sage: P.inject_variables()
Defining E2, E2_0, E4_0
sage: QM.from_polynomial(E2)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: QM.from_polynomial(E2 + E4_0*E2_0) == QM.0 + QM.2*QM.1
True


Naturally, the number of variable must not exceed the number of generators:

sage: P = PolynomialRing(QQ, 'F', 4)
sage: P.inject_variables()
Defining F0, F1, F2, F3
sage: QM.from_polynomial(F0 + F1 + F2 + F3)
Traceback (most recent call last):
...
ValueError: the number of variables (4) of the given polynomial cannot exceed the number of generators (3) of the quasimodular forms ring

gen(n)#

Return the $$n$$-th generator of the quasimodular forms ring.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.0
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: QM.1
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6)
sage: QM.2
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)
sage: QM = QuasiModularForms(5)
sage: QM.0
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: QM.1
1 + 6*q + 18*q^2 + 24*q^3 + 42*q^4 + 6*q^5 + O(q^6)
sage: QM.2
1 + 240*q^5 + O(q^6)
sage: QM.3
q + 10*q^3 + 28*q^4 + 35*q^5 + O(q^6)
sage: QM.4
Traceback (most recent call last):
...
IndexError: list index out of range

generators()#

Return a list of generators of the quasimodular forms ring.

Note that the generators of the modular forms subring are the one given by the method sage.modular.modform.ring.ModularFormsRing.gen_forms()

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]
sage: QM.modular_forms_subring().gen_forms()
[1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]
sage: QM = QuasiModularForms(5)
sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 6*q + 18*q^2 + 24*q^3 + 42*q^4 + 6*q^5 + O(q^6),
1 + 240*q^5 + O(q^6),
q + 10*q^3 + 28*q^4 + 35*q^5 + O(q^6)]


An alias of this method is generators:

sage: QuasiModularForms(1).generators()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]

gens()#

Return a list of generators of the quasimodular forms ring.

Note that the generators of the modular forms subring are the one given by the method sage.modular.modform.ring.ModularFormsRing.gen_forms()

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]
sage: QM.modular_forms_subring().gen_forms()
[1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]
sage: QM = QuasiModularForms(5)
sage: QM.gens()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 6*q + 18*q^2 + 24*q^3 + 42*q^4 + 6*q^5 + O(q^6),
1 + 240*q^5 + O(q^6),
q + 10*q^3 + 28*q^4 + 35*q^5 + O(q^6)]


An alias of this method is generators:

sage: QuasiModularForms(1).generators()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]

group()#

Return the congruence subgroup attached to the given quasimodular forms ring.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.group()
Modular Group SL(2,Z)
sage: QM.group() is SL2Z
True
sage: QuasiModularForms(3).group()
Congruence Subgroup Gamma0(3)
sage: QuasiModularForms(Gamma1(5)).group()
Congruence Subgroup Gamma1(5)

modular_forms_of_weight(weight)#

Return the space of modular forms on this group of the given weight.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.modular_forms_of_weight(12)
Modular Forms space of dimension 2 for Modular Group SL(2,Z) of weight 12 over Rational Field
sage: QM = QuasiModularForms(Gamma1(3))
sage: QM.modular_forms_of_weight(4)
Modular Forms space of dimension 2 for Congruence Subgroup Gamma1(3) of weight 4 over Rational Field

modular_forms_subring()#

Return the subring of modular forms of this ring of quasimodular forms.

EXAMPLES:

sage: QuasiModularForms(1).modular_forms_subring()
Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
sage: QuasiModularForms(5).modular_forms_subring()
Ring of Modular Forms for Congruence Subgroup Gamma0(5) over Rational Field

ngens()#

Return the number of generators of the given graded quasimodular forms ring.

EXAMPLES:

sage: QuasiModularForms(1).ngens()
3

one()#

Return the one element of this ring.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.one()
1
sage: QM.one().is_one()
True

polygen()#

Return the generator of this quasimodular form space as a polynomial ring over the modular form subring.

Note that this generator correspond to the weight-2 Eisenstein series. The default name of this generator is E2.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.polygen()
E2
sage: QuasiModularForms(1, name='X').polygen()
X
sage: QM.polygen().parent()
Univariate Polynomial Ring in E2 over Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field

polynomial_ring(names=None)#

Return a multivariate polynomial ring of which the quasimodular forms ring is a quotient.

In the case of the full modular group, this ring is $$R[E_2, E_4, E_6]$$ where $$E_2$$, $$E_4$$ and $$E_6$$ have degrees 2, 4 and 6 respectively.

INPUT:

• names (str, default: None) – a list or tuple of names (strings), or a comma separated string. Defines the names for the generators of the multivariate polynomial ring. The default names are of the following form:

• E2 denotes the weight 2 Eisenstein series;

• Ek_i and Sk_i denote the $$i$$-th basis element of the weight $$k$$ Eisenstein subspace and cuspidal subspace respectively;

• If the level is one, the default names are E2, E4 and E6;

• In any other cases, we use the letters Fk, Gk, Hk, …, FFk, FGk, … to denote any generator of weight $$k$$.

OUTPUT: A multivariate polynomial ring in the variables names

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: P = QM.polynomial_ring(); P
Multivariate Polynomial Ring in E2, E4, E6 over Rational Field
sage: P.inject_variables()
Defining E2, E4, E6
sage: E2.degree()
2
sage: E4.degree()
4
sage: E6.degree()
6


Example when the level is not one:

sage: QM = QuasiModularForms(Gamma0(29))
sage: P_29 = QM.polynomial_ring()
sage: P_29
Multivariate Polynomial Ring in E2, F2, S2_0, S2_1, E4_0, F4, G4, H4 over Rational Field
sage: P_29.inject_variables()
Defining E2, F2, S2_0, S2_1, E4_0, F4, G4, H4
sage: F2.degree()
2
sage: E4_0.degree()
4


The name Sk_i stands for the $$i$$-th basis element of the cuspidal subspace of weight $$k$$:

sage: F2 = QM.from_polynomial(S2_0)
sage: F2.qexp(10)
q - q^4 - q^5 - q^6 + 2*q^7 - 2*q^8 - 2*q^9 + O(q^10)
sage: CuspForms(Gamma0(29), 2).0.qexp(10)
q - q^4 - q^5 - q^6 + 2*q^7 - 2*q^8 - 2*q^9 + O(q^10)
sage: F2 == CuspForms(Gamma0(29), 2).0
True


The name Ek_i stands for the $$i$$-th basis element of the Eisenstein subspace of weight $$k$$:

sage: F4 = QM.from_polynomial(E4_0)
sage: F4.qexp(30)
1 + 240*q^29 + O(q^30)
sage: EisensteinForms(Gamma0(29), 4).0.qexp(30)
1 + 240*q^29 + O(q^30)
sage: F4 == EisensteinForms(Gamma0(29), 4).0
True


One may also choose the name of the variables:

sage: QM = QuasiModularForms(1)
sage: QM.polynomial_ring(names="P, Q, R")
Multivariate Polynomial Ring in P, Q, R over Rational Field

quasimodular_forms_of_weight(weight)#

Return the space of quasimodular forms on this group of the given weight.

INPUT:

• weight (int, Integer)

OUTPUT: A quasimodular forms space of the given weight.

EXAMPLES:

sage: QuasiModularForms(1).quasimodular_forms_of_weight(4)
Traceback (most recent call last):
...
NotImplementedError: spaces of quasimodular forms of fixed weight not yet implemented

some_elements()#

Return a list of generators of self.

EXAMPLES:

sage: QuasiModularForms(1).some_elements()
[1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)]

weight_2_eisenstein_series()#

Return the weight 2 Eisenstein series.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: E2 = QM.weight_2_eisenstein_series(); E2
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: E2.parent()
Ring of Quasimodular Forms for Modular Group SL(2,Z) over Rational Field

zero()#

Return the zero element of this ring.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.zero()
0
sage: QM.zero().is_zero()
True