Elements of quasimodular forms rings

AUTHORS:

  • DAVID AYOTTE (2021-03-18): initial version

  • Seewoo Lee (2023-09): coefficients method

class sage.modular.quasimodform.element.QuasiModularFormsElement(parent, polynomial)[source]

Bases: ModuleElement

A quasimodular forms ring element. Such an element is described by SageMath as a polynomial

F=f0+f1E2+f2E22++fmE2m

where each fi a graded modular form element (see GradedModularFormElement)

For an integer k, we say that F is homogeneous of weight k if it lies in an homogeneous component of degree k of the graded ring of quasimodular 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.0 + QM.1
2 + 216*q + 2088*q^2 + 6624*q^3 + 17352*q^4 + 30096*q^5 + O(q^6)
sage: QM.0 * QM.1
1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6)
sage: (QM.0)^2
1 - 48*q + 432*q^2 + 3264*q^3 + 9456*q^4 + 21600*q^5 + O(q^6)
sage: QM.0 == QM.1
False
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> 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))
>>> QM.gen(0) + QM.gen(1)
2 + 216*q + 2088*q^2 + 6624*q^3 + 17352*q^4 + 30096*q^5 + O(q^6)
>>> QM.gen(0) * QM.gen(1)
1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6)
>>> (QM.gen(0))**Integer(2)
1 - 48*q + 432*q^2 + 3264*q^3 + 9456*q^4 + 21600*q^5 + O(q^6)
>>> QM.gen(0) == QM.gen(1)
False
QM = QuasiModularForms(1)
QM.gens()
QM.0 + QM.1
QM.0 * QM.1
(QM.0)^2
QM.0 == QM.1

Quasimodular forms ring element can be created via a polynomial in E2 over the ring of modular forms:

sage: E2 = QM.polygen()
sage: E2.parent()
Univariate Polynomial Ring in E2 over Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
sage: QM(E2)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: M = QM.modular_forms_subring()
sage: QM(M.0 * E2 + M.1 * E2^2)
2 - 336*q + 4320*q^2 + 398400*q^3 - 3772992*q^4 - 89283168*q^5 + O(q^6)
>>> from sage.all import *
>>> E2 = QM.polygen()
>>> E2.parent()
Univariate Polynomial Ring in E2 over Ring of Modular Forms for Modular Group SL(2,Z) over Rational Field
>>> QM(E2)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
>>> M = QM.modular_forms_subring()
>>> QM(M.gen(0) * E2 + M.gen(1) * E2**Integer(2))
2 - 336*q + 4320*q^2 + 398400*q^3 - 3772992*q^4 - 89283168*q^5 + O(q^6)
E2 = QM.polygen()
E2.parent()
QM(E2)
M = QM.modular_forms_subring()
QM(M.0 * E2 + M.1 * E2^2)

One may convert a quasimodular form into a multivariate polynomial in the generators of the ring by calling polynomial():

sage: QM = QuasiModularForms(1)
sage: F = QM.0^2 + QM.1^2 + QM.0*QM.1*QM.2
sage: F.polynomial()
E2*E4*E6 + E4^2 + E2^2
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> F = QM.gen(0)**Integer(2) + QM.gen(1)**Integer(2) + QM.gen(0)*QM.gen(1)*QM.gen(2)
>>> F.polynomial()
E2*E4*E6 + E4^2 + E2^2
QM = QuasiModularForms(1)
F = QM.0^2 + QM.1^2 + QM.0*QM.1*QM.2
F.polynomial()

If the group is not the full modular group, the default names of the generators are given by Ek_i and Sk_i to denote the i-th basis element of the weight k Eisenstein subspace and cuspidal subspace respectively (for more details, see the documentation of polynomial_ring())

sage: QM = QuasiModularForms(Gamma1(4))
sage: F = (QM.0^4)*(QM.1^3) + QM.3
sage: F.polynomial()
-512*E2^4*E2_1^3 + E2^4*E3_0^2 + 48*E2^4*E3_1^2 + E3_0
>>> from sage.all import *
>>> QM = QuasiModularForms(Gamma1(Integer(4)))
>>> F = (QM.gen(0)**Integer(4))*(QM.gen(1)**Integer(3)) + QM.gen(3)
>>> F.polynomial()
-512*E2^4*E2_1^3 + E2^4*E3_0^2 + 48*E2^4*E3_1^2 + E3_0
QM = QuasiModularForms(Gamma1(4))
F = (QM.0^4)*(QM.1^3) + QM.3
F.polynomial()
coefficients(X)[source]

Return the coefficients of qn of the q-expansion of this, graded quasimodular form for n in the list X.

If X is an integer, return coefficients for indices from 1 to X. This method caches the result.

EXAMPLES:

sage: E2, E4 = QuasiModularForms(1).0, QuasiModularForms(1).1
sage: f = E2^2
sage: g = E2^3 * E4
sage: f.coefficients(10)
[-48, 432, 3264, 9456, 21600, 39744, 66432, 105840, 147984, 220320]
sage: f.coefficients([0,1])
[1, -48]
sage: f.coefficients([0,1,2,3])
[1, -48, 432, 3264]
sage: f.coefficients([2,3])
[432, 3264]
sage: g.coefficients(10)
[168,
 -13608,
 210336,
 1805496,
 -22562064,
 -322437024,
 -2063087808,
 -9165872520,
 -32250917496,
 -96383477232]
sage: g.coefficients([3, 7])
[210336, -2063087808]
>>> from sage.all import *
>>> E2, E4 = QuasiModularForms(Integer(1)).gen(0), QuasiModularForms(Integer(1)).gen(1)
>>> f = E2**Integer(2)
>>> g = E2**Integer(3) * E4
>>> f.coefficients(Integer(10))
[-48, 432, 3264, 9456, 21600, 39744, 66432, 105840, 147984, 220320]
>>> f.coefficients([Integer(0),Integer(1)])
[1, -48]
>>> f.coefficients([Integer(0),Integer(1),Integer(2),Integer(3)])
[1, -48, 432, 3264]
>>> f.coefficients([Integer(2),Integer(3)])
[432, 3264]
>>> g.coefficients(Integer(10))
[168,
 -13608,
 210336,
 1805496,
 -22562064,
 -322437024,
 -2063087808,
 -9165872520,
 -32250917496,
 -96383477232]
>>> g.coefficients([Integer(3), Integer(7)])
[210336, -2063087808]
E2, E4 = QuasiModularForms(1).0, QuasiModularForms(1).1
f = E2^2
g = E2^3 * E4
f.coefficients(10)
f.coefficients([0,1])
f.coefficients([0,1,2,3])
f.coefficients([2,3])
g.coefficients(10)
g.coefficients([3, 7])
degree()[source]

Return the weight of the given quasimodular form.

Note that the given form must be homogeneous. An alias of this method is degree.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0).weight()
2
sage: (QM.0 * QM.1 + QM.2).weight()
6
sage: QM(1/2).weight()
0
sage: (QM.0).degree()
2
sage: (QM.0 + QM.1).weight()
Traceback (most recent call last):
...
ValueError: the given graded quasiform is not an homogeneous element
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0)).weight()
2
>>> (QM.gen(0) * QM.gen(1) + QM.gen(2)).weight()
6
>>> QM(Integer(1)/Integer(2)).weight()
0
>>> (QM.gen(0)).degree()
2
>>> (QM.gen(0) + QM.gen(1)).weight()
Traceback (most recent call last):
...
ValueError: the given graded quasiform is not an homogeneous element
QM = QuasiModularForms(1)
(QM.0).weight()
(QM.0 * QM.1 + QM.2).weight()
QM(1/2).weight()
(QM.0).degree()
(QM.0 + QM.1).weight()
depth()[source]

Return the depth of this quasimodular form.

Note that the quasimodular form must be homogeneous of weight k. Recall that the depth is the integer p such that

f=f0+f1E2++fpE2p,

where fi is a modular form of weight k2i and fp is nonzero.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: E2, E4, E6 = QM.gens()
sage: E2.depth()
1
sage: F = E4^2 + E6*E2 + E4*E2^2 + E2^4
sage: F.depth()
4
sage: QM(7/11).depth()
0
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> E2, E4, E6 = QM.gens()
>>> E2.depth()
1
>>> F = E4**Integer(2) + E6*E2 + E4*E2**Integer(2) + E2**Integer(4)
>>> F.depth()
4
>>> QM(Integer(7)/Integer(11)).depth()
0
QM = QuasiModularForms(1)
E2, E4, E6 = QM.gens()
E2.depth()
F = E4^2 + E6*E2 + E4*E2^2 + E2^4
F.depth()
QM(7/11).depth()
derivative()[source]

Return the derivative qddq of the given quasimodular form.

If the form is not homogeneous, then this method sums the derivative of each homogeneous component.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: E2, E4, E6 = QM.gens()
sage: dE2 = E2.derivative(); dE2
-24*q - 144*q^2 - 288*q^3 - 672*q^4 - 720*q^5 + O(q^6)
sage: dE2 == (E2^2 - E4)/12 # Ramanujan identity
True
sage: dE4 = E4.derivative(); dE4
240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + O(q^6)
sage: dE4 == (E2 * E4 - E6)/3 # Ramanujan identity
True
sage: dE6 = E6.derivative(); dE6
-504*q - 33264*q^2 - 368928*q^3 - 2130912*q^4 - 7877520*q^5 + O(q^6)
sage: dE6 == (E2 * E6 - E4^2)/2 # Ramanujan identity
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> E2, E4, E6 = QM.gens()
>>> dE2 = E2.derivative(); dE2
-24*q - 144*q^2 - 288*q^3 - 672*q^4 - 720*q^5 + O(q^6)
>>> dE2 == (E2**Integer(2) - E4)/Integer(12) # Ramanujan identity
True
>>> dE4 = E4.derivative(); dE4
240*q + 4320*q^2 + 20160*q^3 + 70080*q^4 + 151200*q^5 + O(q^6)
>>> dE4 == (E2 * E4 - E6)/Integer(3) # Ramanujan identity
True
>>> dE6 = E6.derivative(); dE6
-504*q - 33264*q^2 - 368928*q^3 - 2130912*q^4 - 7877520*q^5 + O(q^6)
>>> dE6 == (E2 * E6 - E4**Integer(2))/Integer(2) # Ramanujan identity
True
QM = QuasiModularForms(1)
E2, E4, E6 = QM.gens()
dE2 = E2.derivative(); dE2
dE2 == (E2^2 - E4)/12 # Ramanujan identity
dE4 = E4.derivative(); dE4
dE4 == (E2 * E4 - E6)/3 # Ramanujan identity
dE6 = E6.derivative(); dE6
dE6 == (E2 * E6 - E4^2)/2 # Ramanujan identity

Note that the derivative of a modular form is not necessarily a modular form:

sage: dE4.is_modular_form()
False
sage: dE4.weight()
6
>>> from sage.all import *
>>> dE4.is_modular_form()
False
>>> dE4.weight()
6
dE4.is_modular_form()
dE4.weight()
homogeneous_component(weight)[source]

Return the homogeneous component of the given quasimodular form ring element.

An alias of this method is homogeneous_component.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: E2, E4, E6 = QM.gens()
sage: F = E2 + E4*E6 + E2^3*E6
sage: F[2]
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: F[10]
1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6)
sage: F[12]
1 - 576*q + 21168*q^2 + 308736*q^3 - 15034608*q^4 - 39208320*q^5 + O(q^6)
sage: F[4]
0
sage: F.homogeneous_component(2)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> E2, E4, E6 = QM.gens()
>>> F = E2 + E4*E6 + E2**Integer(3)*E6
>>> F[Integer(2)]
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
>>> F[Integer(10)]
1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6)
>>> F[Integer(12)]
1 - 576*q + 21168*q^2 + 308736*q^3 - 15034608*q^4 - 39208320*q^5 + O(q^6)
>>> F[Integer(4)]
0
>>> F.homogeneous_component(Integer(2))
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
QM = QuasiModularForms(1)
E2, E4, E6 = QM.gens()
F = E2 + E4*E6 + E2^3*E6
F[2]
F[10]
F[12]
F[4]
F.homogeneous_component(2)
homogeneous_components()[source]

Return a dictionary where the values are the homogeneous components of the given graded form and the keys are the weights of those components.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0).homogeneous_components()
{2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
sage: (QM.0 + QM.1 + QM.2).homogeneous_components()
{2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
 4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
 6: 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)}
sage: (1 + QM.0).homogeneous_components()
{0: 1, 2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
sage: QM5 = QuasiModularForms(Gamma1(3))
sage: F = QM.1 + QM.1*QM.2 + QM.1*QM.0 + (QM.1 + QM.2^2)*QM.0^3
sage: F.homogeneous_components()
{4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
 6: 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6),
 10: 2 - 96*q - 149040*q^2 - 4986240*q^3 - 67535952*q^4 - 538187328*q^5 + O(q^6),
 18: 1 - 1080*q + 294840*q^2 - 902880*q^3 - 452402280*q^4 + 105456816*q^5 + O(q^6)}
sage: F = QM.zero()
sage: F.homogeneous_components()
{0: 0}
sage: F = QM(42/13)
sage: F.homogeneous_components()
{0: 42/13}
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0)).homogeneous_components()
{2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
>>> (QM.gen(0) + QM.gen(1) + QM.gen(2)).homogeneous_components()
{2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6),
 4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
 6: 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)}
>>> (Integer(1) + QM.gen(0)).homogeneous_components()
{0: 1, 2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)}
>>> QM5 = QuasiModularForms(Gamma1(Integer(3)))
>>> F = QM.gen(1) + QM.gen(1)*QM.gen(2) + QM.gen(1)*QM.gen(0) + (QM.gen(1) + QM.gen(2)**Integer(2))*QM.gen(0)**Integer(3)
>>> F.homogeneous_components()
{4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6),
 6: 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6),
 10: 2 - 96*q - 149040*q^2 - 4986240*q^3 - 67535952*q^4 - 538187328*q^5 + O(q^6),
 18: 1 - 1080*q + 294840*q^2 - 902880*q^3 - 452402280*q^4 + 105456816*q^5 + O(q^6)}
>>> F = QM.zero()
>>> F.homogeneous_components()
{0: 0}
>>> F = QM(Integer(42)/Integer(13))
>>> F.homogeneous_components()
{0: 42/13}
QM = QuasiModularForms(1)
(QM.0).homogeneous_components()
(QM.0 + QM.1 + QM.2).homogeneous_components()
(1 + QM.0).homogeneous_components()
QM5 = QuasiModularForms(Gamma1(3))
F = QM.1 + QM.1*QM.2 + QM.1*QM.0 + (QM.1 + QM.2^2)*QM.0^3
F.homogeneous_components()
F = QM.zero()
F.homogeneous_components()
F = QM(42/13)
F.homogeneous_components()
is_graded_modular_form()[source]

Return whether the given quasimodular form is a graded modular form element (see GradedModularFormElement).

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0).is_graded_modular_form()
False
sage: (QM.1).is_graded_modular_form()
True
sage: (QM.1 + QM.0^2).is_graded_modular_form()
False
sage: (QM.1^2 + QM.2).is_graded_modular_form()
True
sage: QM = QuasiModularForms(Gamma0(6))
sage: (QM.0).is_graded_modular_form()
False
sage: (QM.1 + QM.2 + QM.1 * QM.3).is_graded_modular_form()
True
sage: QM.zero().is_graded_modular_form()
True
sage: QM = QuasiModularForms(Gamma0(6))
sage: (QM.0).is_graded_modular_form()
False
sage: (QM.0 + QM.1*QM.2 + QM.3).is_graded_modular_form()
False
sage: (QM.1*QM.2 + QM.3).is_graded_modular_form()
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0)).is_graded_modular_form()
False
>>> (QM.gen(1)).is_graded_modular_form()
True
>>> (QM.gen(1) + QM.gen(0)**Integer(2)).is_graded_modular_form()
False
>>> (QM.gen(1)**Integer(2) + QM.gen(2)).is_graded_modular_form()
True
>>> QM = QuasiModularForms(Gamma0(Integer(6)))
>>> (QM.gen(0)).is_graded_modular_form()
False
>>> (QM.gen(1) + QM.gen(2) + QM.gen(1) * QM.gen(3)).is_graded_modular_form()
True
>>> QM.zero().is_graded_modular_form()
True
>>> QM = QuasiModularForms(Gamma0(Integer(6)))
>>> (QM.gen(0)).is_graded_modular_form()
False
>>> (QM.gen(0) + QM.gen(1)*QM.gen(2) + QM.gen(3)).is_graded_modular_form()
False
>>> (QM.gen(1)*QM.gen(2) + QM.gen(3)).is_graded_modular_form()
True
QM = QuasiModularForms(1)
(QM.0).is_graded_modular_form()
(QM.1).is_graded_modular_form()
(QM.1 + QM.0^2).is_graded_modular_form()
(QM.1^2 + QM.2).is_graded_modular_form()
QM = QuasiModularForms(Gamma0(6))
(QM.0).is_graded_modular_form()
(QM.1 + QM.2 + QM.1 * QM.3).is_graded_modular_form()
QM.zero().is_graded_modular_form()
QM = QuasiModularForms(Gamma0(6))
(QM.0).is_graded_modular_form()
(QM.0 + QM.1*QM.2 + QM.3).is_graded_modular_form()
(QM.1*QM.2 + QM.3).is_graded_modular_form()

Note

A graded modular form in SageMath is not necessarily a modular form as it can have mixed weight components. To check for modular forms only, see the method is_modular_form().

is_homogeneous()[source]

Return whether the graded quasimodular form is a homogeneous element, that is, it lives in a unique graded components of the parent of self.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: E2, E4, E6 = QM.gens()
sage: (E2).is_homogeneous()
True
sage: (E2 + E4).is_homogeneous()
False
sage: (E2 * E4 + E6).is_homogeneous()
True
sage: QM(1).is_homogeneous()
True
sage: (1 + E2).is_homogeneous()
False
sage: F = E6^3 + E4^4*E2 + (E4^2*E6)*E2^2 + (E4^3 + E6^2)*E2^3
sage: F.is_homogeneous()
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> E2, E4, E6 = QM.gens()
>>> (E2).is_homogeneous()
True
>>> (E2 + E4).is_homogeneous()
False
>>> (E2 * E4 + E6).is_homogeneous()
True
>>> QM(Integer(1)).is_homogeneous()
True
>>> (Integer(1) + E2).is_homogeneous()
False
>>> F = E6**Integer(3) + E4**Integer(4)*E2 + (E4**Integer(2)*E6)*E2**Integer(2) + (E4**Integer(3) + E6**Integer(2))*E2**Integer(3)
>>> F.is_homogeneous()
True
QM = QuasiModularForms(1)
E2, E4, E6 = QM.gens()
(E2).is_homogeneous()
(E2 + E4).is_homogeneous()
(E2 * E4 + E6).is_homogeneous()
QM(1).is_homogeneous()
(1 + E2).is_homogeneous()
F = E6^3 + E4^4*E2 + (E4^2*E6)*E2^2 + (E4^3 + E6^2)*E2^3
F.is_homogeneous()
is_modular_form()[source]

Return whether the given quasimodular form is a modular form.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0).is_modular_form()
False
sage: (QM.1).is_modular_form()
True
sage: (QM.1 + QM.2).is_modular_form() # mixed weight components
False
sage: QM.zero().is_modular_form()
True
sage: QM = QuasiModularForms(Gamma0(4))
sage: (QM.0).is_modular_form()
False
sage: (QM.1).is_modular_form()
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0)).is_modular_form()
False
>>> (QM.gen(1)).is_modular_form()
True
>>> (QM.gen(1) + QM.gen(2)).is_modular_form() # mixed weight components
False
>>> QM.zero().is_modular_form()
True
>>> QM = QuasiModularForms(Gamma0(Integer(4)))
>>> (QM.gen(0)).is_modular_form()
False
>>> (QM.gen(1)).is_modular_form()
True
QM = QuasiModularForms(1)
(QM.0).is_modular_form()
(QM.1).is_modular_form()
(QM.1 + QM.2).is_modular_form() # mixed weight components
QM.zero().is_modular_form()
QM = QuasiModularForms(Gamma0(4))
(QM.0).is_modular_form()
(QM.1).is_modular_form()
is_one()[source]

Return whether the given quasimodular form is 1, i.e. the multiplicative identity.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.one().is_one()
True
sage: QM(1).is_one()
True
sage: (QM.0).is_one()
False
sage: QM = QuasiModularForms(Gamma0(2))
sage: QM(1).is_one()
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> QM.one().is_one()
True
>>> QM(Integer(1)).is_one()
True
>>> (QM.gen(0)).is_one()
False
>>> QM = QuasiModularForms(Gamma0(Integer(2)))
>>> QM(Integer(1)).is_one()
True
QM = QuasiModularForms(1)
QM.one().is_one()
QM(1).is_one()
(QM.0).is_one()
QM = QuasiModularForms(Gamma0(2))
QM(1).is_one()
is_zero()[source]

Return whether the given quasimodular form is zero.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: QM.zero().is_zero()
True
sage: QM(0).is_zero()
True
sage: QM(1/2).is_zero()
False
sage: (QM.0).is_zero()
False
sage: QM = QuasiModularForms(Gamma0(2))
sage: QM(0).is_zero()
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> QM.zero().is_zero()
True
>>> QM(Integer(0)).is_zero()
True
>>> QM(Integer(1)/Integer(2)).is_zero()
False
>>> (QM.gen(0)).is_zero()
False
>>> QM = QuasiModularForms(Gamma0(Integer(2)))
>>> QM(Integer(0)).is_zero()
True
QM = QuasiModularForms(1)
QM.zero().is_zero()
QM(0).is_zero()
QM(1/2).is_zero()
(QM.0).is_zero()
QM = QuasiModularForms(Gamma0(2))
QM(0).is_zero()
polynomial(names=None)[source]

Return a multivariate polynomial such that every variable corresponds to a generator of the ring, ordered by the method: gens().

An alias of this method is to_polynomial.

INPUT:

  • names– string (default: None); 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 form ABCk where k is a number corresponding to the weight of the form ABC.

OUTPUT: a multivariate polynomial in the variables names

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0 + QM.1).polynomial()
E4 + E2
sage: (1/2 + QM.0 + 2*QM.1^2 + QM.0*QM.2).polynomial()
E2*E6 + 2*E4^2 + E2 + 1/2
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0) + QM.gen(1)).polynomial()
E4 + E2
>>> (Integer(1)/Integer(2) + QM.gen(0) + Integer(2)*QM.gen(1)**Integer(2) + QM.gen(0)*QM.gen(2)).polynomial()
E2*E6 + 2*E4^2 + E2 + 1/2
QM = QuasiModularForms(1)
(QM.0 + QM.1).polynomial()
(1/2 + QM.0 + 2*QM.1^2 + QM.0*QM.2).polynomial()

Check that Issue #34569 is fixed:

sage: QM = QuasiModularForms(Gamma1(3))
sage: QM.ngens()
5
sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).polynomial()
E3_1*E4_0 + E2_0*E3_0 + E2 + E2_0
>>> from sage.all import *
>>> QM = QuasiModularForms(Gamma1(Integer(3)))
>>> QM.ngens()
5
>>> (QM.gen(0) + QM.gen(1) + QM.gen(2)*QM.gen(1) + QM.gen(3)*QM.gen(4)).polynomial()
E3_1*E4_0 + E2_0*E3_0 + E2 + E2_0
QM = QuasiModularForms(Gamma1(3))
QM.ngens()
(QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).polynomial()
q_expansion(prec=6)[source]

Return the q-expansion of the given quasimodular form up to precision prec (default: 6).

An alias of this method is qexp.

EXAMPLES:

sage: QM = QuasiModularForms()
sage: E2 = QM.0
sage: E2.q_expansion()
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: E2.q_expansion(prec=10)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
>>> from sage.all import *
>>> QM = QuasiModularForms()
>>> E2 = QM.gen(0)
>>> E2.q_expansion()
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
>>> E2.q_expansion(prec=Integer(10))
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
QM = QuasiModularForms()
E2 = QM.0
E2.q_expansion()
E2.q_expansion(prec=10)
qexp(prec=6)[source]

Return the q-expansion of the given quasimodular form up to precision prec (default: 6).

An alias of this method is qexp.

EXAMPLES:

sage: QM = QuasiModularForms()
sage: E2 = QM.0
sage: E2.q_expansion()
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
sage: E2.q_expansion(prec=10)
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
>>> from sage.all import *
>>> QM = QuasiModularForms()
>>> E2 = QM.gen(0)
>>> E2.q_expansion()
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)
>>> E2.q_expansion(prec=Integer(10))
1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 - 288*q^6 - 192*q^7 - 360*q^8 - 312*q^9 + O(q^10)
QM = QuasiModularForms()
E2 = QM.0
E2.q_expansion()
E2.q_expansion(prec=10)
serre_derivative()[source]

Return the Serre derivative of the given quasimodular form.

If the form is not homogeneous, then this method sums the Serre derivative of each homogeneous component.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: E2, E4, E6 = QM.gens()
sage: DE2 = E2.serre_derivative(); DE2
-1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
sage: DE2 == (-E2^2 - E4)/12
True
sage: DE4 = E4.serre_derivative(); DE4
-1/3 + 168*q + 5544*q^2 + 40992*q^3 + 177576*q^4 + 525168*q^5 + O(q^6)
sage: DE4 == (-1/3) * E6
True
sage: DE6 = E6.serre_derivative(); DE6
-1/2 - 240*q - 30960*q^2 - 525120*q^3 - 3963120*q^4 - 18750240*q^5 + O(q^6)
sage: DE6 == (-1/2) * E4^2
True
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> E2, E4, E6 = QM.gens()
>>> DE2 = E2.serre_derivative(); DE2
-1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
>>> DE2 == (-E2**Integer(2) - E4)/Integer(12)
True
>>> DE4 = E4.serre_derivative(); DE4
-1/3 + 168*q + 5544*q^2 + 40992*q^3 + 177576*q^4 + 525168*q^5 + O(q^6)
>>> DE4 == (-Integer(1)/Integer(3)) * E6
True
>>> DE6 = E6.serre_derivative(); DE6
-1/2 - 240*q - 30960*q^2 - 525120*q^3 - 3963120*q^4 - 18750240*q^5 + O(q^6)
>>> DE6 == (-Integer(1)/Integer(2)) * E4**Integer(2)
True
QM = QuasiModularForms(1)
E2, E4, E6 = QM.gens()
DE2 = E2.serre_derivative(); DE2
DE2 == (-E2^2 - E4)/12
DE4 = E4.serre_derivative(); DE4
DE4 == (-1/3) * E6
DE6 = E6.serre_derivative(); DE6
DE6 == (-1/2) * E4^2

The Serre derivative raises the weight of homogeneous elements by 2:

sage: F = E6 + E4 * E2
sage: F.weight()
6
sage: F.serre_derivative().weight()
8
>>> from sage.all import *
>>> F = E6 + E4 * E2
>>> F.weight()
6
>>> F.serre_derivative().weight()
8
F = E6 + E4 * E2
F.weight()
F.serre_derivative().weight()

Check that Issue #34569 is fixed:

sage: QM = QuasiModularForms(Gamma1(3))
sage: E2 = QM.weight_2_eisenstein_series()
sage: E2.serre_derivative()
-1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
sage: F = QM.0 + QM.1*QM.2
>>> from sage.all import *
>>> QM = QuasiModularForms(Gamma1(Integer(3)))
>>> E2 = QM.weight_2_eisenstein_series()
>>> E2.serre_derivative()
-1/6 - 16*q - 216*q^2 - 832*q^3 - 2248*q^4 - 4320*q^5 + O(q^6)
>>> F = QM.gen(0) + QM.gen(1)*QM.gen(2)
QM = QuasiModularForms(Gamma1(3))
E2 = QM.weight_2_eisenstein_series()
E2.serre_derivative()
F = QM.0 + QM.1*QM.2
to_polynomial(names=None)[source]

Return a multivariate polynomial such that every variable corresponds to a generator of the ring, ordered by the method: gens().

An alias of this method is to_polynomial.

INPUT:

  • names– string (default: None); 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 form ABCk where k is a number corresponding to the weight of the form ABC.

OUTPUT: a multivariate polynomial in the variables names

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0 + QM.1).polynomial()
E4 + E2
sage: (1/2 + QM.0 + 2*QM.1^2 + QM.0*QM.2).polynomial()
E2*E6 + 2*E4^2 + E2 + 1/2
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0) + QM.gen(1)).polynomial()
E4 + E2
>>> (Integer(1)/Integer(2) + QM.gen(0) + Integer(2)*QM.gen(1)**Integer(2) + QM.gen(0)*QM.gen(2)).polynomial()
E2*E6 + 2*E4^2 + E2 + 1/2
QM = QuasiModularForms(1)
(QM.0 + QM.1).polynomial()
(1/2 + QM.0 + 2*QM.1^2 + QM.0*QM.2).polynomial()

Check that Issue #34569 is fixed:

sage: QM = QuasiModularForms(Gamma1(3))
sage: QM.ngens()
5
sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).polynomial()
E3_1*E4_0 + E2_0*E3_0 + E2 + E2_0
>>> from sage.all import *
>>> QM = QuasiModularForms(Gamma1(Integer(3)))
>>> QM.ngens()
5
>>> (QM.gen(0) + QM.gen(1) + QM.gen(2)*QM.gen(1) + QM.gen(3)*QM.gen(4)).polynomial()
E3_1*E4_0 + E2_0*E3_0 + E2 + E2_0
QM = QuasiModularForms(Gamma1(3))
QM.ngens()
(QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).polynomial()
weight()[source]

Return the weight of the given quasimodular form.

Note that the given form must be homogeneous. An alias of this method is degree.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0).weight()
2
sage: (QM.0 * QM.1 + QM.2).weight()
6
sage: QM(1/2).weight()
0
sage: (QM.0).degree()
2
sage: (QM.0 + QM.1).weight()
Traceback (most recent call last):
...
ValueError: the given graded quasiform is not an homogeneous element
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0)).weight()
2
>>> (QM.gen(0) * QM.gen(1) + QM.gen(2)).weight()
6
>>> QM(Integer(1)/Integer(2)).weight()
0
>>> (QM.gen(0)).degree()
2
>>> (QM.gen(0) + QM.gen(1)).weight()
Traceback (most recent call last):
...
ValueError: the given graded quasiform is not an homogeneous element
QM = QuasiModularForms(1)
(QM.0).weight()
(QM.0 * QM.1 + QM.2).weight()
QM(1/2).weight()
(QM.0).degree()
(QM.0 + QM.1).weight()
weights_list()[source]

Return the list of the weights of all the graded components of the given graded quasimodular form.

EXAMPLES:

sage: QM = QuasiModularForms(1)
sage: (QM.0).weights_list()
[2]
sage: (QM.0 + QM.1 + QM.2).weights_list()
[2, 4, 6]
sage: (QM.0 * QM.1 + QM.2).weights_list()
[6]
sage: QM(1/2).weights_list()
[0]
sage: QM = QuasiModularForms(Gamma1(3))
sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).weights_list()
[2, 5, 7]
>>> from sage.all import *
>>> QM = QuasiModularForms(Integer(1))
>>> (QM.gen(0)).weights_list()
[2]
>>> (QM.gen(0) + QM.gen(1) + QM.gen(2)).weights_list()
[2, 4, 6]
>>> (QM.gen(0) * QM.gen(1) + QM.gen(2)).weights_list()
[6]
>>> QM(Integer(1)/Integer(2)).weights_list()
[0]
>>> QM = QuasiModularForms(Gamma1(Integer(3)))
>>> (QM.gen(0) + QM.gen(1) + QM.gen(2)*QM.gen(1) + QM.gen(3)*QM.gen(4)).weights_list()
[2, 5, 7]
QM = QuasiModularForms(1)
(QM.0).weights_list()
(QM.0 + QM.1 + QM.2).weights_list()
(QM.0 * QM.1 + QM.2).weights_list()
QM(1/2).weights_list()
QM = QuasiModularForms(Gamma1(3))
(QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).weights_list()