Graded quasimodular forms ring#

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

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')#

Bases: sage.structure.parent.Parent, sage.structure.unique_representation.UniqueRepresentation

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#

alias of sage.modular.quasimodform.element.QuasiModularFormsElement

from_polynomial(polynomial)#

Convert the given polynomial \(P(X, Y, Z)\) to the graded quasiform \(P(E_2, E_4, E_6)\) where \(E_2\), \(E_4\) and \(E_6\) are the generators given by gens().

INPUT:

  • plynomial – A multivariate polynomial

OUTPUT: the graded quasimodular forms \(P(E_2, E_4, E_6)\)

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)
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='E2, E4, E6')#

Return a multivariate polynomial ring isomorphic to the given graded quasimodular forms ring.

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: 'E2, E4, E6') – a list or tuple of names (strings), or a comma separated string. Correspond to the names of the variables.

OUTPUT: A multivariate polynomial ring in the variables names

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: P.<E2, E4, E6> = QM.polynomial_ring(); P
Multivariate Polynomial Ring in E2, E4, E6 over Rational Field
sage: E2.degree()
2
sage: E4.degree()
4
sage: E6.degree()
6
sage: P.<x, y, z, w> = QQ[]
sage: QM.from_polynomial(x+y+z+w)
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
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