$ \newcommand{\setC}{\mathbb{C}} \newcommand{\setH}{\mathbb{H}} \newcommand{\setN}{\mathbb{N}} \newcommand{\setQ}{\mathbb{Q}} \newcommand{\setZ}{\mathbb{Z}} \newcommand{\modularOrbit}[1]{\mathcal{O}_{#1}} \newcommand{\qPochhammer}[3][\infty]{\left( #2;#3 \right)_{#1}} $ Via jupytext this file can be shown as a jupyter notebook.
)cd ..
)read input/jfricas-test-support.input )quiet
The current FriCAS default directory is /home/hemmecke/backup/git/qeta All user variables and function definitions have been cleared. All )browse facility databases have been cleared. Internally cached functions and constructors have been cleared. )clear completely is finished. The current FriCAS default directory is /home/hemmecke/backup/git/qeta/tmp
The following cell should only be evaluated, if you want the traditional 2D ASCII output of FriCAS.
)set output formatted off
)set output algebra on
QEta Tutorial¶
This file contains a short tutorial of some of the features of QEta.
Follow the instructions on the QEta website in order to install it.
This notebook itself is available in a text form as
QEtaTutorial.input-test.
You just have to rename the file extension to .input
in order to run it through the computer algebra system
FriCAS.
If you have installed FriCAS, together with jFriCAS and JupyText (see the FriCAS installation guide), you can load and run this QEtaTutorial inside a Jupyther notebook.
In order to test the commands appearing here,
the tutorial contains a number of commands like
assertTrue or assertEquals, that can be run
automatically as a testsuite check.
Init¶
-------------------------------------------------------------------
--setup
-------------------------------------------------------------------
To work with QEta, you first have to compile and load it.
Compilation must only be done once from a terminal, inside
the directory where the QEta source code resides.
In the following we assume that the QEta source code lives
in the fricas/qeta subdirectory of your home directory.
cd $HOME/fricas/qeta
make compile-spad
That will compile everything into fricas/qeta/tmp.
To load QEta, do the following inside a Jupyter notebook (running the FriCAS kernel).
)cd
)cd fricas/qeta/tmp
)set message time off
)set message type off
)read projectlibs.input )quiet
)read qetamacros.input )quiet
If you want the output look nicer in the Jupyter notebook, then issue the following commands.
)set output algebra off
setFormat!(FormatMathJax)$JFriCASSupport
In qetamacros.input quite a number of macros are defined that make working with QEta functions a bit simpler. Inside this notebook, we use the abbreviations defined there.
C ==> QQ
RKI ==> QEtaRamanujanKolbergIdentity(C)
QEtaIdeal ==> QEtaIdealHemmecke
oo ==> infinity()$Cusp
)set stream calc 2
-------------------------------------------------------------------
--endsetup
-------------------------------------------------------------------
Ramanujan congruences¶
-------------------------------------------------------------------
--test:RamanujanCongruences
-------------------------------------------------------------------
Ramanujan discovered that \begin{align} p(5n+4) &\equiv 0 \pmod{5}\label{eq:p5}\\ p(7n+5) &\equiv 0 \pmod{7}\label{eq:p7}\\ p(11n+6) &\equiv 0 \pmod{11}\label{eq:p11} \end{align} for all natural numbers $n\in\setN$ where $p(n)$ denotes the number of partitions of $n$.
In QEta a sequence $(a(n))_{n\geq0}$ given by its generating series as \begin{align*} \sum_{n=0}^\infty a(n)q^n &= \prod_{\delta|M} \qPochhammer{q^\delta}{q^\delta}^{r_\delta} \end{align*} can be specified by the $(\delta, r_\delta)$ pairs.
Learn more of how to specify the input in the tutorial
qetaspex.input
that you can find in the tutorials subdirectory of the
QEta distribution.
For the partition function $p$, we have $M=1$ and $r_1=-1$, so we specify the generating function as follows.
$p(5n+4) \equiv 0 \pmod{5}$¶
gfv: QGFVAR := generatingFunction(qP(q,q)^(-1), 'p)
We get the $(5n+4)$-dissection as follows.
dissect := choose(5,4) gfv
In this tutorial, we always use that $q=\exp(2\pi i \tau)$.
We want an expansion in terms of eta-functions $\eta(\tau)$ and $\eta(5\tau)$, so we use the following indices.
idxs := [[1],[5]];
We compute an identities for \begin{gather*} \sum_{n=0}^\infty p(mn+k)q^n \end{gather*} in terms of eta-quotients. This identity is an identity of modular functions for $\Gamma_0(5)$.
The function to call is findId as
id := findId(C,MGAMMA0(nn))(dissect,idxs)
where C is the coefficient domain and MGAMMA0(nn) stands for the
wish to look for modular eta-quotients of $\Gamma_0(N)$ whose
incredient eta-functions are given by the indices idxs.
The variable id will contain all relevant data, but
this data structure is usually rather big and uninteresting
to show as a whole, so we add a semicolon at the end of the
command in order to prevent its printing.
id := findId(C, MGAMMA0 5)(dissect, idxs);
-- numOfGaps:=[0, 0]
In a compact form the following polynomial equates to 0
identityPolynomial id
if the variable $F$ is replaced by
f id
In expanded form the relation can be shown with eta functions or q-Pochhammer symbols by the following commands.
etaEquation id
qEquation id
Note that findId is a macro.
It is refers to a function findIdentity from
the package QEtaRamanujanKolberg(C, MGAMMA0 5).
The package implements Radu's algorithm
generically over various coefficient domains
and for $\Gamma_0(M)$ and $\Gamma_1(M)$ which
have to be given as concrete arguments to QEtaRamanujanKolberg.
Usage of the macro findId shortens the
otherwise quite lengthy function call.
$p(7n+5) \equiv 0 \pmod{7}$¶
We can do similar steps for the Ramanujan congruence modulo 7.
idxs := [[1],[7]];
id := findId(C, MGAMMA0 7)(choose(7,5) gfv, idxs);
etaEquation id
qEquation id
-- == z:=[zinhom=[[1]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
The variable id, in fact, contains all the data to show
the identity in different formats.
For example, to bring the cofactor of the generating function to the right-hand side, proceed as follows.
inv(qPochhammerPart qExpression f id) * qEquation id
Note that for turning the dissection into a modular function,
not only an eta-quotient has to be multiplied, but also
a fractional $q$ power is inherently connected to it.
The exponent can be extracted by alphaOrbitInfinity.
orbitProduct id
cofac1 := qPower(alphaOrbitInfinity id)
cofac2 := coSpecification(id)::SPEX(QQ)
We can bring the cofactors to the right-hand side of the equation
eqn := inv(cofac1 * cofac2) * qEquation(id);
and simplify it to an expression with eta-functions
map(etaExpression, eqn)
or to an expression with $q$-Pochhammer symbols.
map(qExpression, eqn)
Since this might sometimes be a too lengthy expression, we can turn the right-hand side into a polynomial or a rational function with variables $f_\delta$ that stand for $\qPochhammer{q^\delta}{q^\delta}$ and $g_\delta=f_\delta^{-1}$.
qexpr := qExpression rhs eqn
polynomial(qexpr)
rationalFunction(qexpr)
If you need the output for further computation in another computer algebra system, you can define a macro for one-dimensional output.
print1D x ==> display((x::OutputForm)::Formatter(Format1D))
print1D rationalFunction qexpr
(49*f7^7*q+7*f1^4*f7^3)/f1^8
$p(11n+6) \equiv 0 \pmod{11}$ (with $\Gamma_0(22)$)¶
The modulo 11 case is a bit more complicated, since for $\Gamma_0(11)$ we cannot find an identity
idxs := [[1],[11]];
id := findId(C, MGAMMA0 11)(choose(11, 6) gfv, idxs);
-- == z:=[zinhom=[[0]], zhom=[], zfree=[]] -- numOfGaps:=[120, 1]
This fact is encoded in QEta by returning the trivial identity $0=0$.
qEquation id
assertEquals(identityPolynomial id, 0);
If one needs this in another procedure, one can ask for the
idenityPolynomial(id). If this is 0, then there is no identity
for the respective parameter, i.e. here for $\Gamma_0(11)$
and in terms of eta-functions $\eta(\tau)$ and $\eta(11\tau)$.
zero? identityPolynomial id
We can, however, resort to level 22 and then an identity can be found.
idxs := [[1],[2],[11],[22]];
id := findId(C, MGAMMA0 22)(choose(11, 6) gfv, idxs);
-- == z:=[zinhom=[], zhom=[], zfree=[]] -- >= z:=[zinhom=[[4, -1, 1], [5, -1, 2], [4, -1, 2]], zhom=[[3, -1, 0], [4, -1, 1], [1, -1, 1], [2, -1, 1], [3, -1, 1], [0, -1, 1], [2, 0, 1]], zfree=[]] -- numOfGaps:=[216, 2] -- numOfGaps:=[162, 2] -- numOfGaps:=[108, 2] -- numOfGaps:=[55, 2] -- numOfGaps:=[55, 2] -- numOfGaps:=[2, 2]
cofac11q := qPower(alphaOrbitInfinity id);
cofac11s := qExpression coSpecification(id)::SPEX(QQ);
eqn := inv(cofac11q * cofac11s) * qEquation id
qpol := numer(rationalFunction rhs eqn)
content((8*qpol)::Pol(ZZ))
Even though there are denominators of 4 and 8 in this representation, it clearly shows that the left-hand side is divisible by 11.
In fact, the original generating series multiplied by some cofactor gives a modular function for $\Gamma_0(22)$, (left-hand side).
It can be represented by a linear combination of eta-quotients with coefficients in $\setQ$, (right-hand side).
In fact,
Radu's original algorithm
AB, as well as
the
samba algorithm
(which is implemented in QEta)
return a representation as a linear combination of
finitely many eta-quotients over $\setQ[t]$ where $t$
itself is an eta-quotient.
From the identity polynomial, we see that $p(11n+6)$ is divisible by 11, i.e. all terms not involving $F$ are divisible by 11.
Here $F$ corresponds to the left-hand side from qEquation(id) above.
identityPolynomial(id)=0
$M_1$ corresponds to the $t$ and the $M_i$ are eta-quotients with the following specifications.
mspecs := monoidSpecifications id
So $M_1=t$ stands for $\frac{\eta(2\tau)^8 \eta(11\tau)^4}{\eta(\tau)^4\eta(22\tau)^8}$, etc. It can be shown easily by functions from QEta.
$p(11n+6) \equiv 0 \pmod{11}$ (with $\Gamma_1(11)$)¶
QEta allows to find an identity for the generating function of $p(11n+6)$ in term of generalized eta-quotients by an implementation of ideas of Chen, Du, and Zhao. This also yields a witness identity for the divisibility by 11.
idxs := [[1],[11],[11,1],[11,2],[11,3],[11,4]];
id := findId(C, MGAMMA1 11)(choose(11, 6) gfv, idxs);
qEquation id
-- == z:=[zinhom=[[2, 2, -7, 5, 2]], zhom=[], zfree=[]] -- numOfGaps:=[75, 1] -- numOfGaps:=[75, 1] -- numOfGaps:=[1, 1]
identityPolynomial id
qpol := numer(rationalFunction rhs qEquation id)
content(qpol::Pol(ZZ))
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Kolberg identity for $p(5n+1)$¶
-------------------------------------------------------------------
--test:KolbergIdentity
-------------------------------------------------------------------
Kolberg (1957) found an identity for the generating function of $p(5n+1)$. That, however, also involves the generating function for $p(5n+2)$.
gfv: QGFVAR := generatingFunction(qP(q,q)^(-1), 'p)
dissect := choose(5,1) gfv
idxs := [[1],[5]];
id := findId(C, MGAMMA0 5)(dissect, idxs);
-- == z:=[zinhom=[[1]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
qEquation id
The above identity is based on transformations with respect to $\Gamma_0(5)$. In such transformations $\sum_{n=0}^\infty a(5n+1)q^n$ and $\sum_{n=0}^\infty a(5n+2)q^n$ cannot be considered separately. Since they lie in the same orbit with respect to $\Gamma_0(5)$, only their product can be turned into a modular function for $\Gamma_0(5)$.
If we consider $\Gamma_1(5)$ and allow generalized eta-quotients, we get the following identity.
id1 := findId(C, MGAMMA1 5)(dissect, [[1],[5],[5,1]]);
qEquation id1
identityPolynomial id1
-- == z:=[zinhom=[[1, 0]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
Let us take this example (over $\Gamma_0(5)$) for an explanation
of what the variable id actually contains.
id
definingDissection describes the generating function
for $(a(n))_{n\ge0}$ as it was given on input.
orbit gives the list of offsets $k'$ that must be
considered together with the initially given offset $k$.
coSpecification describes the (generalized) eta-quotient
that must be multiplied to the dissected generating series
in order to arrive at a modular function.
coefficient is the constant coefficient of the left hand side.
QEta does not generally divide by this coefficient, since
QEta can work with coefficient rings that are not fields.
monoidSpecifications describe the eta-quotients that can
potentially appear of the right-hand side of the identity,
where the first element can appear in any non-negative power
while the others may only appear linearly.
identityPolynomial is a condensed version of the identity
where $F$ stands for the modular function on the left-hand side
and the $M_i$ are the eta-quotients given by monoidSpecifications.
alphaInfinity gives the order of $q$ of the left-hand side
when expanded as a $q$-series while alphaOrbitInfinity only
gives the part of the $q$ exponent that is (technically) connected
to the orbit product of the dissected generating series.
We can extract that information also individually from
the id variable.
coSpecification id
definingDissection id
orbit id
monoidSpecifications id
identityPolynomial id
coefficient id
alphaInfinity id
alphaOrbitInfinity id
There are more function available that you can apply
to the id variable.
For example, we can transform the identity into an equation of FriCAS expressions that can then be manipulated further.
)set message type on
eeqn1 := etaEquation id
qeqn1 := qEquation id
)set message type off
We can do the same for the generating series of $p(5n+3)$.
id3 := findId(C, MGAMMA0 5)(choose(5, 3) gfv, idxs);
eeqn3 := etaEquation id3;
qeqn3 := qEquation id3
-- == z:=[zinhom=[[1]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
From looking at the right-hand side we easily see that we
can eliminate the $q$-Pochhammer symbol by combining the
equations qeqn1 and qeqn3.
eq1 := qPower(1) * qP(q)^(-12) * qP(q^5,q^5)^10 * (3*qeqn1 - 2*qeqn3)
Let us compare this with the identity for the generating series of $p(5n+4)$.
id4 := findId(C, MGAMMA0 5)(choose(5, 4) gfv, idxs);
qeqn4 := qEquation id4
-- numOfGaps:=[0, 0]
With a few manipulation we find an identity that already appears as equation (4.4) in Kolberg (1957).
zeqn := eq1 - qPower(1) * ((qP(q^5,q^5)^5 * qP(q)^(-6))*qeqn4)^2
assertTrue(zero? rhs zeqn)
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Relations among 5-dissections of $p(n)$¶
-------------------------------------------------------------------
--test:time40-RelationsAmong5Dissections
-------------------------------------------------------------------
Setting up¶
The above relation can also be found automatically by QEta. The idea is to find a relation for the involved generating functions in terms of (generalized) eta-quotients.
Whereas the relation given in the previous section can be computed while working with ordinary Dedekind eta-functions, for other relations of this type, we must employ generalized eta-functions and their transformations with respect to $\Gamma_1(N)$.
Let us first setup a few helpers, i.e. compute
the identities for the generating functions of
$p(5n+k)$ into the list ids.
idxs := [[1],[5],[5,1]];
gfv: QGFVAR := generatingFunction(qP(q,q)^(-1), 'p)
id := findId(C, MGAMMA1 5)(choose(5,0) gfv, idxs); -- prepare id for reuse
ids := [findId(C, MGAMMA1 5)(idxs, choose(5, k) gfv, id) for k in 0..4];
-- == z:=[zinhom=[[1, 0]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0] -- == z:=[zinhom=[[1, 0]], zhom=[], zfree=[]] -- == z:=[zinhom=[[1, 0]], zhom=[], zfree=[]] -- == z:=[zinhom=[[1, 0]], zhom=[], zfree=[]] -- == z:=[zinhom=[[1, 0]], zhom=[], zfree=[]]
Generators for relations ideal¶
We can extract the various parts of the respective equation ...
eqn1 := inv coSpecification ids.1 * etaEquation ids.1
definingDissection ids.1
orb1 := orbitProduct(ids.1);
... and replace the orbit product by p5_0 and eta-function
$\eta_d(\tau)$ by ed.
polynomial(orb1)::OF = orb1
numer rationalFunction(lhs eqn1 - rhs eqn1)
With this knowledge, we replace each orbit product for $p(5n+k)$ by
p5_k and the eta-functions by the respective variables.
idPol(id) == (_
eqn := inv coSpecification id * etaEquation id;_
(numer rationalFunction(lhs eqn - rhs eqn))::Pol(ZZ))
With that substitution and bringing everything to one side. we obtain the following set of polynomials that represent the relations among the $f_k$ and eta-functions.
psyms := [polynomial(orbitProduct id)::Symbol for id in ids]
mps := [idPol id for id in ids]
Compiling function idPol with type QEtaRamanujanKolbergIdentity(Fraction( Integer)) -> Polynomial(Integer)
Eliminate generalized eta-quotients¶
The following computation takes about 1 sec and eliminates the variables $e_d$ and $y_d$ so that only the relations among the $f_k$ survive.
algrels := algebraicRelations(idxs, mps, psyms) _
$ QEtaIdeal(MGAMMA1 5);
-- numOfGaps:=[0, -1] -- numOfGaps:=[0, -1] -- TIME:=1.01
print1D x ==> display((x::OutputForm)::Formatter(Format1D))
for x in algrels repeat print1D pToHdmp(x)$PolToPol(psyms, ZZ)
10*p5_0^2*p5_3^2-9*p5_0^2*p5_2*p5_4-9*p5_1*p5_3^2*p5_4+4*p5_0*p5_3*p5_4^2+4*p5_4^4 5*p5_0*p5_1*p5_3-3*p5_0^2*p5_4-6*p5_2*p5_3*p5_4+4*p5_1*p5_4^2 5*p5_0*p5_2*p5_3-6*p5_0*p5_1*p5_4-3*p5_3^2*p5_4+4*p5_2*p5_4^2 2*p5_1^2-p5_0*p5_2-p5_3*p5_4 3*p5_1*p5_2-2*p5_0*p5_3-p5_4^2 2*p5_2^2-p5_1*p5_3-p5_0*p5_4
assertEquals(algrels, [_
10*p5_0^2*p5_3^2 - 9*p5_0^2*p5_2*p5_4 - 9*p5_1*p5_3^2*p5_4 _
+ 4*p5_0*p5_3*p5_4^2 + 4*p5_4^4, _
5*p5_0*p5_1*p5_3 - 3*p5_0^2*p5_4 - 6*p5_2*p5_3*p5_4 + 4*p5_1*p5_4^2,_
5*p5_0*p5_2*p5_3 - 6*p5_0*p5_1*p5_4 - 3*p5_3^2*p5_4 + 4*p5_2*p5_4^2,_
2*p5_1^2 - p5_0*p5_2 - p5_3*p5_4,_
3*p5_1*p5_2 - 2*p5_0*p5_3 - p5_4^2,_
2*p5_2^2 - p5_1*p5_3 - p5_0*p5_4])
Selected results¶
Among the relations is relation (4.4) of a paper of Kolberg (1957) that we have found manually in the previous section.
algrels.5 = 0
Shown as a relation among the generating series, it is as follows.
fs := [f = orbitProduct(ids.k) for f in psyms for k in 1..5]
eval(algrels.5, fs) * qPower(-7/12) = 0
The following identities involve other pairs. See congruence at bottom of page 86 in Kolberg (1957).
eval(algrels.4, fs) * qPower(-23/60) = 0
eval(algrels.6, fs) * qPower(-47/60) = 0
eval(algrels.3, fs) * qPower(-39/40) = 0
eval(algrels.2, fs) * qPower(-31/40) = 0
eval(algrels.1, fs) * qPower(-7/6) = 0
Altogether, algrels is a Gröbner basis for the
ideal of all relations among these generating series.
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Check Eta-quotient identities¶
-------------------------------------------------------------------
--test:CheckEtaQuotientIdentity
-------------------------------------------------------------------
Let us check the validity of an eta-quotient identity from Lemma 13 of "Elementary Proofs of Congruences for Pond and Pend Partitions" by James Sellers, namely \begin{gather*} \frac{f_3^3}{f_1} - q \frac{f_{12}^3}{f_4} = \frac{f_4^3 f_6^2}{f_2^2 f_{12}}, \end{gather*} which appears as equation (22.7.5) in "The Power of q" by Michael D. Hirschhorn.
We can enter it in QEta via the QEtaSpecificationExpression,
lemma13 := f3^3/f1 - q*f12^3/f4 - f4^3*f6^2/(f2^2*f12);
qspex13 := qpSPEX(C)(lemma13)
In eta-quotients. this equation looks as follows: \begin{gather*} \frac{e_3^3}{e_1} - \frac{e_{12}^3}{e_4} = \frac{e_4^3 e_6^2}{e_2^2 e_{12}}. \end{gather*}
spex13 := qPower(1/3) * etaExpression qspex13
As can be seen from above, the expression in eta-functions is actually only the same as the initial expression up to a factor of $q^\frac{-1}{3}$.
Note that QEta abbreviates the $q$-Pochhammer symbol $(q^k;q^k)$ by the variable $f_k$
That this expression corresponds to the zero function can be shown in two ways.
- We find an eta-quotient factor that (after multiplying with it) turns each term of the expression into a modular function for $\Gamma_0(12)$ with only a pole at $\infty$. If all the respective $q$-expansion then sum to a $q$-series of positive order, it proves that this series is identically 0.
- Expand each eta-quotient in the expression into a vector of $q$-series (one for each cusp of $\Gamma_0(12)$) and sum these vectors. If that gives a vector whose entries have all positive orders, it proves that the expression is identically 0.
Below we show both ways.
First method¶
Let us start with computing a eta-quotient that (after multiplication)
turns each term of the expression into a modular function with only
a pole at $\infty$.
The QEta functionn etaCofactorInfinity even works with the
non-modular eta-quotients of the original expression.
nn := level spex13
MG ==> MGAMMA0 nn -- abbreviation for the group that we are working with
specs := [leadingSupport(x)::SPEC for x in monomials spex13]
idxs := etaFunctionIndices(nn);
sspec := etaCofactorInfinity(idxs,specs)$QEtaModularPackage(MG)
-- == z:=[zinhom=[[-2, -2, 5, -2, -1]], zhom=[], zfree=[]]
sspex13 := sspec * spex13
The variable sspecx13 now stands for a
modular (wrt. $\Gamma_0(12)$) function.
In fact, it is the zero function as we show below.
qModular?(C,MG) sspex13
sser13 := spexMA1(C,MG)(sspex13)
assertTrue(zero? sser13)
The corresponding series of each term are given below.
sspex13terms := [spexMA1(C,MG)(t) for t in support sspex13]
If you want to see more terms of the expansion, just increase the number of terms to be shown.
)set stream calculate 10
sspex13terms
)set stream calculate 2
Second method¶
Unfortunately, the original expression does not correspond to a modular function for $\Gamma_0(12)$.
qModular?(C,MG) spex13
-- eq:sum=0 sspec:=1 -- eq:sum=0 rspec:=eta(12*tau)^3/eta(4*tau) -- eq:sum=0 orbitSize:=1
It can be turned into one by dividing by one of the involved eta-quotients.
spexmon := inv leadingSupport last monomials spex13
mspex13 := spexmon * spex13
qModular?(C,MG) mspex13
Let us determine the orders at each of the cusps for each of the three terms.
cusps()$GAMMA0(nn)
qGrades(C,MG)(mspex13) -- returns the pole orderes
Obviously there are poles at the cusp $\frac{1}{3}$.
In the most general case the expansion involves an extension of
the coefficient ring.
For eta-quotients it is enough to extend by a certain root of unity.
The order of the root of unity can be determined by the function
minRootOfUnity. See also Section "Expansion at cusps" below.
xiord := minRootOfUnity(C,MG) mspex13
Only a second root of unity, i.e. -1 is needed. We can do the expansion over rational numbers. Nevertheless, we demonstrate here the general case. For a precise expansion, we actually need not the cusp value, but rather the exact transformation matrix corresponding to the cusp.
C ==> QQ
EXTENDEDCOEFFICIENTRING(C, xiord, CX, xi);
trfs := cuspMatrices() $ MG
We compute the expansions at each cusps either from the
specification mspex13.
spexMAn(trfs,CX,MG)(mspex13)
Indeed, we get positive orders at all cusps. That proves that we are dealing with the modular function 0.
The expansion or the terms of mspex13 separately,
can be shown like this.
[spexMAn(trfs,CX,MG)(t) for t in support sspex13]
Relations among eta-functions¶
QEta can even do more. It can compute a Gröbner basis of all relations among eta-functions of a certain level and then represent the original expression by a linear combination of Gröbner basis elements divided by the common denominator of the original expression.
rf := rationalFunction(spex13)
pol := numer rf
We first compute the the monoid basis $\{M_1,\ldots,M_5\}$ of all eta-quotients of $\Gamma_0(12)$ that only have a pole at the cusp $\infty$.
idxs := etaFunctionIndices nn;
mspecs := mSPECSInf(MG)(idxs)
These eta-quotients have the following $q$-expansion at the cusp $\infty$.
)set stream calc 4
agens := [specMA1(QQ,MG)(x) for x in mspecs]
From these expansions the samba algorithm (see “Dancing Samba with Ramanujan Partition Congruences”) is used to compute an algebra basis of $\setQ[M_1,\ldots,M_5]$ where the $M_k$ represent the eta-quotients above.
msyms: List Symbol := indexedSymbols("M", #mspecs)$QAuxiliaryTools
xgens := [toX1(C, x, sym::Pol(C)) for x in agens for sym in msyms]
gen := genus() $ MG
xab := samba(xgens, gen, oneVerboseStep!(1,1,1,1))$QSAMBA(C,X1,QTOPRED)
-- numOfGaps:=[0, 0]
We find, that $\setQ[M_1,\ldots,M_5]=\setQ[M_1]$.
With this information we can express each of the $M_i$ by a polynomial in $M_1$ with rational coefficients. The following polynomials vanish if the $M_i$ are replaced by their respective eta-quotients.
)expose QAuxiliaryTools
eqigens := [integerPrimitivePart(second(reduce(x,xab)$QTOPRED(C,X1))::Pol(QQ))_
for x in rest xgens]
assertEquals(eqigens, [M2 - M1 + 2, M3 - M1 + 3, M4 - M1 + 4, M5 - M1 + 6])
QAuxiliaryTools is already explicitly exposed in frame initial
We can turn the above polynomials to a linear combination of eta-quotients
(represented by their specifications), by simply replacing Mi by the
respective eta-quotient.
spexs := [specification(x,"M",mspecs) for x in eqigens]
There are now two ways to translate the information into polynomials...
[polynomial x for x in spexs]
... or rational functions.
[rationalFunction(x) for x in spexs]
We take the first representation where the $y_i$ represent $\frac{1}{e_i}$ and then eliminate the $y_i$ by the Gröber basis method modulo the relations $e_i y_1 = 1$. The result is a Gröbner basis (here with respect to a degrevlex order) of the ideal of all relations among eta-functions.
In QEta the whole process in encoded in the function etaRelations.
If you have installed the
QEta-Data
repository with precomputed data, you can point the etaRelations
function to it and the data will simply be read from the disk, ...
)read projectdir )quiet
basedir := PROJECTDIR "/data/etafiles/Hemmecke/Gamma0"
nn
idxs
erels := etaRelations(idxs, basedir) $ QEtaIdeal(MG)
... otherwise, the relations will be computed which takes less than 30 seconds for the level 12 case.
erels := etaRelations(idxs) $ QEtaIdeal(MG)
-- numOfGaps:=[0, 0] -- TIME:=12.38
We find that the relation from Lemma 13 is (up to a factor of eta-quotients) identical to the last-but-one element in the above Gröbner basis of eta-relations of level 12.
dim := #idxs;
syms := indexedSymbols("e", idxs)$QAuxiliaryTools;
D ==> HomogeneousDirectProduct(dim, NN);
E ==> Monomials(dim, NN, D, syms)
R ==> PolynomialRing(ZZ, E)
xnf ==> extendedNormalForm$QEtaGroebner(ZZ, E);
numerlemma13eta := numer(rationalFunction spex13) :: Pol(ZZ)
assertEquals(xnf(numerlemma13eta, erels, syms, 'F, "G"), G97+F)
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Ideal of relations among eta-functions¶
-------------------------------------------------------------------
--test:time19-EtaRelations
-------------------------------------------------------------------
With similar ideas as above, we can also compute the ideal of all relations among eta-functions. The corresponding theory is described in “Construction of all Polynomial Relations among Dedekind Eta Functions of Level N”.
In QEta there exists the functions etaRelations to
do the computation.
idxs := etaFunctionIndices 6
er := etaRelations(idxs) $ QEtaIdeal(MGAMMA0 6)
-- numOfGaps:=[0, 0] -- TIME:=0.13
For bigger levels $N$ the computation becomes increasingly more involved since it is based on
- computing a monoid basis for the monoid of all eta-quotients with the help of the program 4ti2,
- setting up relations in variables $e_\delta$ and $y_\delta$ ($\delta$ ranging over all divisors of $N$, and $e_\delta$ and $y_\delta$ representing $\eta(\delta\tau)$ and $1/\eta(\delta\tau)$, respectively),
- eliminating the $y_\delta$ variables from the system.
Let us consider the case $N=16$.
We first compute the the monoid basis.
nn := 16
idxs := etaFunctionIndices nn
MG ==> MGAMMA0 nn
QI0 ==> QEtaIdeal(MG)
mspecs := mSPECSInf(MG)(idxs)
These eta-quotients have the following $q$-expansion at the cusp infinity.
)set stream calc 4
[specMA1(QQ,MG)(x) for x in mspecs]
From these expansions the samba algorithm (see “Dancing Samba with Ramanujan Partition Congruences”) is used to compute an algebra basis of $\setQ[M_1,\ldots,M_4]$ where the $M_k$ represent the eta-quotients above.
eqigens := etaQuotientIdealGenerators(mspecs)$QI0
-- numOfGaps:=[0, 0]
Let the elements in the above list be denoted by $z_1,z_2,z_3$. In terms of the $q$-series we have \begin{gather*} \setQ[M_1,\ldots,M_4] = \{p_0 + p_1 z_1 + p_2 z_2 + p_3 z_3 \mid p_0,p_1,p_2,p_3\in \setQ[M_1] \} \end{gather*}
By substituting the $M_k$ variables with the respective eta-functions $e_\delta$, and their inverses $y_\delta$, we arrive at the following system.
eligens := etaLaurentIdealGenerators(idxs, mspecs, eqigens)$QI0
Now, we must "only" eliminate the $y_\delta$ variables. For that we can use the QEta interface to some Gröbner engine.
ysyms := indexedSymbols("y", idxs)$QAuxiliaryTools;
esyms := indexedSymbols("e", idxs)$QAuxiliaryTools;
We compute the Gröbner basis for that order.
gb := groebnerEliminate(eligens, ysyms, esyms)$QEtaGroebnerBasisTools
-- TIME:=0.77
Clearly, we are not restricted to pure Dedekind eta-functions, but can also consider relations among generalized eta-functions.
For simplicity, let us consider level 5.
idxs := generalizedEtaFunctionIndices 5
ger := etaRelations(idxs) $ QEtaIdeal(MGAMMA1 5)
-- numOfGaps:=[0, -1] -- numOfGaps:=[0, -1] -- TIME:=0.0
Naturally, we find the relation \begin{align*} \eta(\tau) = \eta(5\tau) \, \eta_{5,1}(\tau) \, \eta_{5,2}(\tau) \end{align*} as the last expression in the above list.
If we take the last-but-one polynomial from the above list and divide every term by $e_{5,1}^5 e_{5,2}^5 e_5^6$, we get the following list of terms.
[x/(e5_1^5*e5_2^5*e5^6) for x in monomials(ger(#ger-1))]
By taking the above computed relation
ger(#ger) = 0
into account, we see that the last element in the above list is equal to 11.
In fact, we have computed, the relation for the Rogers-Ramanujan continued fraction \begin{align*} R(q) = \frac{\eta_{5;1}(\tau)}{\eta_{5;2}(\tau)}, \end{align*} namely, \begin{align*} \frac{1}{R(q)^5} - R(q)^5 = \frac{\eta_{5;2}(\tau)^5}{\eta_{5;1}(\tau)^5} - \frac{\eta_{5;1}(\tau)^5}{\eta_{5;2}(\tau)^5} &= 11 + \frac{\eta(\tau)^6}{\eta(5\tau)^6}. %\tag{1.5} \end{align*}
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Rogers-Ramanujan Continued Fraction¶
Identiity for 5-dissection of $R(q)$¶
-------------------------------------------------------------------
--test:RogersRamanujanContinuedFraction
-------------------------------------------------------------------
Define \begin{align} G(q) &= \sum_{n=0}^\infty \frac{q^{n^2}}{(q;q)_n} = \prod_{n=0}^\infty \frac{1}{(1-q^{5n+1})(1-q^{5n+4})} = \frac{1}{\qPochhammer{q,q^4}{q^5}} \\ H(q) &= \sum_{n=0}^\infty \frac{q^{n(n+1)}}{(q;q)_n} = \prod_{n=0}^\infty \frac{1}{(1-q^{5n+2})(1-q^{5n+3})} = \frac{1}{\qPochhammer{q^2,q^3}{q^5}} \end{align}
and Rogers-Ramanujan continued fraction. \begin{gather*} R(q) = q^{\frac15} \dfrac{1}{1+\dfrac{q}{1+\dfrac{q^2}{1+\dfrac{q^3}{1+\ddots}}}} = q^{\frac15} \frac{\qPochhammer{q,q^4}{q^5}} {\qPochhammer{q^2,q^3}{q^5}} = \frac{\eta_{5,1}(\tau)}{\eta_{5,2}(\tau)} \end{gather*}
Let us consider 5-dissections of $\frac{R(q)^5}{q} = \frac{H(q)^5}{G(q)^5} = \frac{\qPochhammer{q,q^4}{q^5}^5} {\qPochhammer{q^2,q^3}{q^5}^5}$ and $\frac{q}{R(q)^5} = \frac{G(q)^5}{H(q)^5} = \frac{\qPochhammer{q^2,q^3}{q^5}^5} {\qPochhammer{q,q^4}{q^5}^5}$.
For the input into the algorithms of QEta they are specified as follows.
g: QSPEC := inv qP([q, q^4, q^5]);
h: QSPEC := inv qP([q^2,q^3, q^5]);
r5gf := choose(5, 0) generatingFunction((h/g)^5, a[1]);
A relation for the 5-dissection of $\frac{R(q)^5}{q} = \frac{H(q)^5}{G(q)^5} = \frac{\qPochhammer{q,q^4}{q^5}^5} {\qPochhammer{q^2,q^3}{q^5}^5}$ is
idxs := [[5,1],[5,2]];
idr5 := findId(C, MGAMMA1 5)(r5gf, idxs);
-- == z:=[zinhom=[[1, 1]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
(f idr5) :: OF = identityPolynomial idr5 + F
where M1 is given by
first monoidSpecifications idr5
and for the 5-dissection of $\frac{q}{R(q)^5} = \frac{G(q)^5}{H(q)^5} = \frac{\qPochhammer{q^2,q^3}{q^5}^5} {\qPochhammer{q,q^4}{q^5}^5}$ it is the following
i5gf: QGFVAR := choose(5, 0) generatingFunction((g/h)^5, a[2]);
idi5 := findId(C, MGAMMA1 5)(i5gf, idxs);
(f idi5) :: OF = identityPolynomial idi5 + F
-- == z:=[zinhom=[[1, 1]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
Interestingly, the right-hand side of the above equations look equal. However, they have different cofactors. And since they were done by different computations, the $M_1$ may stand for different eta-quotients. In the above case, it turns out, they are same.
assertEquals(first monoidSpecifications idi5,_
first monoidSpecifications idr5)
Thus, both left-hand sides must be equal.
After multiplying appropriately, we get the following.
eqn := qPower(2) * g*h^11 * (lhs qEquation idr5 = lhs qEquation idi5)
[h/g * lhs eqn, g/h * rhs eqn]
It says that \begin{align*} \frac{G(q)}{H(q)} \, U_5\!\left(\frac{H(q)^5}{G(q)^5}\right) &= \frac{H(q)}{G(q)} \, U_5\!\left(\frac{G(q)^5}{H(q)^5}\right) \end{align*} or \begin{align*} U_5\!\left(\frac{R(q)^5}{R(q^5)}\right) &= U_5\!\left(\frac{R(q^5)}{R(q)^5}\right) \end{align*}
where $U_5$ is the operator that acts as follows: \begin{gather*} U_5\left(\sum_{n=k}^\infty a(n)q^n\right) = \sum_{n=\lceil k/5 \rceil}^\infty a(5n)q^n. \end{gather*}
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Find Relation for $R(q)^5$ and $R(q^5)$¶
-------------------------------------------------------------------
--test:RogersRamanujanContinuedFraction-modpol
-------------------------------------------------------------------
In Entry 3.2.14 of Andrews and Berndt Ramanujan's Lost Notebook, Part I, Springer, 2005. there is a relation \begin{align*} R(q)^5 &= R(q^5)\cdot \frac{1 - 2 R(q^5) + 4 R(q^5)^2 - 3 R(q^5)^3 + R(q^5)^4} {1 + 3 R(q^5) + 4 R(q^5)^2 + 2 R(q^5)^3 + R(q^5)^4}, \end{align*} where $R(q)$ is defined by \begin{gather*} R(q) = \frac{\eta_{5,1}(\tau)}{\eta_{5,2}(\tau)}. \end{gather*}
This relation involves only $R(q)^5$ and $R(q^5)$, ...
rspec := eqSPEC(e5_1/e5_2);
xspexmon := (rspec^5) :: SPEXMON
yspexmon := dilate(rspec, 5) :: SPEXMON
... which are both modular functions for $\Gamma_1(25)$.
MG ==> MGAMMA1 25 -- set global variable for following computation
[qModular?(C,MG) xspexmon, qModular?(C,MG) yspexmon]
Let us compute the modular polynomial between the two.
spexmons := [xspexmon, yspexmon];
qgrdss := qGrades(C,MG) spexmons
Cusps that correspond to non-poles in the series expansions for both $R(q)^5$ and $R(q^5)$ can be excluded for the computation of the modular polynomial between the two, since no division will ever be performed.
gammas := cuspMatrices()$MG
trfs := [gammas.i for i in 1..#qgrdss.1 | qgrdss.1.i > 0 or qgrdss.2.i > 0]
spitzen := map(cusp, trfs)
For the expansions at the remaining cusps, the coefficient ring must be extended. From the data we have, we conclude that an extension by a 10-th root of unity (we call it $\xi$) is enough.
xiord := minRootOfUnity(C,MG)(spexmons, trfs)
EXTENDEDCOEFFICIENTRING(C, xiord, CX, xi);
ans := [spexMAn(trfs,CX,MG)(x) for x in spexmons];
a1 := ans.1
a2 := ans.2
modPolynomial ==> modularPolynomial $ QEtaModularEquation(CX, An(trfs)(CX))
The modular polynomial between $x=R(q)^5$ and $y=R(q^5)$ can easily be computed and agrees with the equation given above.
mp := modPolynomial([a1,a2],[x,y],[])
c0 := coefficient(mp,x,0); c1 := -coefficient(mp,x,1);
x = c0/c1
assertEquals(c0/c1, y * ((1-2*y+4*y^2-3*y^3+y^4)) / (1+3*y+4*y^2+2*y^3+y^4))
Note that $\xi$ is a primitive 10-th root of unity.
factor c0
factor c1
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
More functions¶
-------------------------------------------------------------------
--test:Specification
-------------------------------------------------------------------
Specification of eta-quotients¶
Look into the notebook qetaspex.
Let us specify some eta-quotient via a list of list.
rspec := eqSPEC([[1,-5],[3,7],[5,1,-2],[15,3,1]])
We can check whether an eta-quotient is actually a modular function with respect to $\Gamma_0(15)$. That is obviously not the case here. In fact, if there are generalized eta-quotients involve, QEta immediately returns false, even though the eta-quotient can actually be expressed in ordinary eta-function that is modular for some $\Gamma_0(N)$.
qModular?(C, MGAMMA0 15)(rspec)
The following call results in an error, because the function does not accepts only generalized eta-quotients.
--modular?(rspec)$MGAMMA0(15)
It is also not a modular function for $\Gamma_1(15)$.
assertEquals(modular?(rspec) $ MGAMMA1(15), false)
In the second variant, it prints out a reason why the eta-quotient is not modular.
assertEquals(qModular?(C,MGAMMA1 15)(rspec), false)
-- Chen: Theorem 10.1(1) sspec:=1 -- Chen: Theorem 10.1(1) rspec:=(eta(3*tau)^7*subscript(eta, [15, 3])(tau))/(eta(tau)^5*subscript(eta, [5, 1])(tau)^2)
QEta can find a cofactor eta-quotient such that (when
multiplied to rspec) the result is a modular function for
$\Gamma_1(15)$. With the idxs variable we tell which eta-function
we allow in this cofactor.
idxs := [[1],[3],[5],[15],[15,1],[15,2],[15,3]];
sspec := cofactInf(MGAMMA1 15)(idxs, rspec, 1, 0)
-- == z:=[zinhom=[], zhom=[], zfree=[]] -- >= z:=[zinhom=[[-1, 1, 1, 0, 2, -2], [-2, 2, 1, 0, 3, -3], [-1, 2, 1, 0, 2, -2], [0, 1, 1, 0, 1, -1], [-2, 3, 1, 0, 3, -3], [-2, 2, 2, 0, 4, -2], [0, 1, 1, -1, 2, -2], [-2, 2, 1, 0, 2, -2], [-1, 1, 1, 0, 1, -1], [-3, 3, 1, 0, 3, -3], [-3, 2, 2, 0, 4, -2], [-1, 1, 1, -1, 2, -2], [-1, 1, 1, 0, 2, -1], [-3, 3, 1, 1, 3, -3], [-1, 1, 1, 1, 1, -1], [-2, 2, 1, 1, 2, -2], [-4, 4, 1, 1, 4, -4], [-1, 1, 1, 0, 3, -3], [-2, 2, 1, 0, 3, -2]], zhom=[[-3, 2, 1, 2, 2, -2], [-2, 1, 1, 2, 1, -1], [-2, 2, 1, 1, 2, -2], [-1, 1, 1, 1, 1, -1], [-2, 1, 1, 1, 2, -2], [0, 1, 1, 0, 1, -1], [-3, 2, 1, 1, 2, -2], [-2, 1, 1, 1, 1, -1], [-1, 1, 1, 0, 1, -1], [-2, 1, 1, 0, 1, -1], [-4, 3, 1, 2, 3, -3], [-2, 1, 1, 1, 2, -1], [-3, 2, 2, 2, 4, -4], [-4, 2, 2, 3, 4, -4], [-5, 3, 2, 3, 5, -5], [-6, 3, 3, 4, 7, -7]], zfree=[]]
Note that in QEta the specifications themselves form a (multiplicative) group, just like the corresponding eta-quotients do. Thus, we can multiply and divide them.
spec := sspec * rspec
The resulting eta-quotient is modular for $\Gamma_1(15)$.
qModular?(C,MGAMMA1 15) spec
In particular when dealing with dissections we should expect that we must consider eta-functions with bigger indices. QEta suggests that to find an eta-quotient cofactor $c$ (and a certain fractional $q$-power) to make \begin{gather*} q^\beta c \sum_{n=0}^\infty a(mn+k)q^n \end{gather*} modular for $\Gamma_1(N)$ where \begin{align*} \sum_{n=0}^\infty a(n)q^n &= \qPochhammer{q^2,q^5}{q^7}^{-1} \qPochhammer{q^3, q^4}{q^7}^{-2}, \end{align*} we need at least $N=21$. See Section 2 of Chen, Du, Zhao: "Finding Modular Functions for Ramanujan-Type Identities".
qrspec := qP([q^2,q^5,q^7])^(-1) * qP([q^3,q^4,q^7])^(-2)
dissect := choose(9,5) generatingFunction(qrspec)
nn := minLevelM1 dissect
However, even if we find a cofactor eta-quotient so that we arrive at a modular function, there might not be enough eta-quotients in that level to find a $\setQ$-linear combination of those for this modular function.
dissect := choose(11, 6) generatingFunction(qP(q)^(-1))
nn := minLevelM1 dissect
idxs := etaFunctionIndices nn
sspec := cofactInf(MGAMMA0 nn)(idxs, dissect)
-- == z:=[zinhom=[[0]], zhom=[], zfree=[]]
rspec := definingSpecification dissect;
m := multiplier dissect;
t := offset dissect;
orbprod := lift(dissect) :: SPEXMON
At least, we know that this
mf := sspec * orbprod
qExpression mf
is a modular function for $\Gamma_0(11)$ with only a pole at $\infty$.
As a $q$-expansion it looks like this.
MG ==> MGAMMA0 nn
specMA1(QQ,MG)(sspec, rspec, m, t)
The monoid of modular eta-quotients of level 11 having at most a pole at $\infty$ is generated by only one element with the following expansion.
mspecs := mSPECSInf(MG)(idxs)
[specMA1(QQ, MG)(x) for x in mspecs]
From that is clear that we are not able to represent a function with a 4-fold pole by a function with a 5-fold pole at infinity.
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Expansion into $q$-series¶
-------------------------------------------------------------------
--test:qseries-expansion
-------------------------------------------------------------------
Any specification of a (generalized) eta-quotient can be expanded
(at $\infty$) into a $q$-series (with possibly fractional exponents
according to the definition of the (generalized) Dedekind
eta-function given in the previous section by means of the function
specEQI (specification to Eta-Quotient at Infinity).
rspec7 := eqSPEC [[7,2,-1],[7,3,-2]]
eqi7 := specEQI(QQ)(rspec7)
rspec := eqSPEC [[1,-1]]
eqi := specEQI(QQ)(rspec)
Note that the type EtaQuotientQSeriesInfinity (abbreviated by
EQI) was only meant to compute an expansion into a product of a
fractional $q=\exp(2\pi i \tau$ power times a Laurent series in
$q$, but not to do algebraic computations with that result.
Nevertheless, you can turn the result into QEtaPuiseuxSeries and
then do algebraic computations, if necessary.
)set stream calc 100
puiseuxExpansion eqi7
)set stream calc 5
QEta can also deal with $q$-Pochhammer symbols, since it just means to ignore the respective fractional $q$-power prefactor of an eta-quotient.
eulerExpansion specEQI(QQ)(rspec7)
To arrive at the $q$ expansion of the generating series for $p(7n+5)$, we can enter the following.
choose(7, 5, eulerExpansion specEQI(QQ)(rspec))
If the specification happens to be a modular function, then
QEta offers another way to compute the series expansion at
$\infty$, namely by the function specMA1 (abbreviation for
specification to Modular Algebra for 1 cusp).
rrspec := eqSPEC [[5,1,-1],[5,2,-11]]
MG ==> MGAMMA1 5
qModular?(QQ,MG)(rrspec)
specMA1(QQ,MG)(rrspec)
specEQI(QQ)(rrspec)
The difference between specMA1 and specEQI mainly is that the
first only works for modular eta-quotients and returns a Laurent
series whereas the latter, just gives a formal product of a
fractional $q$-power and a Laurent series, which is not meant for
further computation.
Note that becaus the function corresponding to rrspec has no pole
at $\infty$, it must have poles at cusps different from $\infty$.
cusps() $ MG
If we want to investigate \begin{gather*} \sum_{n=0}^\infty a(mn+k)q^n \end{gather*} for the sequence $(a(n))_{n\in\setN}$ given by \begin{gather*} \sum_{n=0}^\infty a(n)q^n = \qPochhammer{q,q^4}{q^5}^{-1} \qPochhammer{q^2, q^3}{q^5}^{-11}, \end{gather*} we first compute an eta-quotient cofactor to turn the product into a modular function for $\Gamma_1(5)$ with only a pole at $\infty$.
As said above the tuple (sspec, rspec, m, k) actually
(implicityly) involves a certian factor $q^\beta$ that is
determined by (rspec,m,k). Details can be found in equation
labelled eq:beta in the file
qeta.tex.
It is described by the second term in the definition of $\alpha$ in
the abstract of Radu's
article or the
$q$-factor in equation (10.4) of the article of Chen, Du, and
Zhao.
idxs := [[5,1],[5,2]]
sspec := cofactInf(MG)(idxs, rrspec, 5, 4)
modularOrbit(rrspec, 5, 4) $ MG
modular?(sspec, rrspec, 5, 4) $ MG
-- == z:=[zinhom=[[4, 2]], zhom=[], zfree=[]]
In fact, (sspec,rspec,5,4) represents the
following expression.
gfspec := (choose(5, 4) generatingFunction rrspec) :: QGFSPEC
spexmon := sspec * lift(gfspec)
The factor $q^{6/5}$ is inherently connected to the modularity of the $(5n+4)$-dissection.
The expansion at $\infty$ can then be done like this.
spexMA1(QQ, MG)(spexmon)
That expansion suggests that there is a congruence modulo 5 hidden in the coefficients. And indeed, here is a corresponding witness identity.
id := findId(C,MG)(rrspec, 5, 4, idxs);
ipol := inv coefficient id * identityPolynomial id
m11 := first monoidSpecifications id
assertEquals(content(coefficient(ipol, F, 0)::Pol(ZZ)), 5)
-- == z:=[zinhom=[[4, 2]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
Choosing other index sets, one can also get an identity with eta-quotients with those indices.
id := findId(C,MG)(rrspec, 5, 4, [[1],[5],[5,1]]);
ipol := inv coefficient id * identityPolynomial id
m12 := first monoidSpecifications id
-- == z:=[zinhom=[[4, 2]], zhom=[], zfree=[]] -- numOfGaps:=[0, 0]
Above you see the same polynomial (in the variables M1 and F,
but the meaning of M1 (given by the command
first(monoidSpecifications(id))) is different.
However, dividing both specifications gives a modular function
with no poles at any cusp and a constant term 1, i.e., both
eta-quotients represent the same modular function on $\Gamma_1(5)$.
modm1 := m11 / m12
trfs := cuspMatrices() $ MG
assertTrue(qModular?(C,MG) modm1)
assertEquals(qGrades(C,MG) modm1, [0,0,0,0])
xiord := minRootOfUnity(C,MG)(modm1, trfs)
EXTENDEDCOEFFICIENTRING(C, xiord, CX, xi);
((specMAn(trfs,CX, MG)(modm1)))
assertTrue(zero?(1$An(trfs)(CX) - specMAn(trfs,CX, MG)(modm1)))
Since m11 and m12 are modular themselves, we can check the difference of their expansions direcctly at all cusps.
assertTrue(qModular?(C,MG) m11)
assertTrue(qModular?(C,MG) m12)
In fact, these eta-quotients only have cusps at infinity. So it would be enough to expand just at infinity.
cusps() $ MG
assertEquals(qGrades(C,MG) m11, [0,-1,0,1])
assertEquals(qGrades(C,MG) m12, [0,-1,0,1])
specMA1(C,MG) m11 - specMA1(C,MG) m12
Clearly, the expansion at all cusps yields 0 for the expansion at each cusp, no matter whether the expansions of the eta-quotients are subtracted or whether we first form a symbolich specification expression and then turn this into an expansion at all cusps.
zser := specMAn(trfs,CX,MG) m11 - specMAn(trfs,CX,MG) m12
yser := spexMAn(trfs,CX,MG)(m11::SPEX(CX) - m12::SPEX(CX))
assertTrue(zero? zser)
assertTrue(zero? yser)
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
$\Gamma_0(N)$, $\Gamma_1(N)$, cusps and more¶
-------------------------------------------------------------------
--test:Gamma
-------------------------------------------------------------------
QEta provides the domains
CongruenceSubgroupGamma0
and
CongruenceSubgroupGamma1
for a number of functions connected to
$\Gamma_0(N)$ and $\Gamma_1(N)$.
These domains are abbreviated by GAMMA0 and GAMMA1,
respectively through qetamacros.input.
nn := 22
genus()$GAMMA0(nn)
numberOfCusps()$GAMMA0(nn)
spitzen := cusps()$GAMMA0(nn)
ws := [width(c)$GAMMA0(nn) for c in spitzen]
assertEquals(ws, [22,2,11,1])
[cuspToMatrix(c)$GAMMA0(nn) for c in spitzen]
doubleCosetRepresentatives()$GAMMA0(nn)
We can do similar things for $\Gamma_1(22)$.
genus()$GAMMA1(nn)
numberOfCusps()$GAMMA1(nn)
spitzen := cusps()$GAMMA1(nn)
[width(c)$GAMMA1(nn) for c in spitzen]
[cuspToMatrix(c)$GAMMA1(nn) for c in spitzen]
doubleCosetRepresentatives()$GAMMA1(nn)
Which of the cusps of $\Gamma_1(22)$ are $\Gamma_0(22)$-equivalent to $\infty$.
cis := [c for c in spitzen | equivalentCusps?(oo, c)$GAMMA0(nn)]
assertEquals(cis, [cusp(3,22),cusp(5,22),cusp(7,22),cusp(9,22),oo])
So, if we "normalize" these cusps, i.e. replace them by an equivalent cusp, they should all look the same. When we do this over all cusps of $\Gamma_1(22)$, they collapse to the cusps of $\Gamma_0(22)$.
assertEquals([normalizeCusp(c)$GAMMA0(nn) for c in cis], [oo,oo,oo,oo,oo])
ll := [normalizeCusp(c)$GAMMA0(nn) for c in cusps()$GAMMA1(nn)]
cs := cusps()$GAMMA0(nn)
assertEquals(ll, [cs.n for n in [1,2,3,1,3,4,1,3,2,1,4,3,2,4,1,2,4,2,3,4]])
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Expansion at cusps¶
-------------------------------------------------------------------
--test:expansion-at-cusps
-------------------------------------------------------------------
Rogers-Ramanujan continued fraction¶
Let us consider the Rogers-Ramanujan continued fraction. \begin{gather*} R(q) = q^{\frac15} \dfrac{1}{1+\dfrac{q}{1+\dfrac{q^2}{1+\dfrac{q^3}{1+\ddots}}}} = q^{\frac15} \frac{\qPochhammer{q,q^4}{q^5}} {\qPochhammer{q^2,q^3}{q^5}} = \frac{\eta_{5,1}(\tau)}{\eta_{5,2}(\tau)} \end{gather*}
rspec := eqSPEC [[5,1,1],[5,2,-1]];
r5spec := rspec^5
MG ==> MGAMMA1 5
qModular?(C,MG)(r5spec)
For specifications without dissections, the order at the cusps can be directly read off from the following command. We also print the respective cusps for the orders of expansion.
trfs := cuspMatrices() $ MG
qGrades(C,MG) r5spec
Let us check the following identity.
\begin{align*} \frac{1}{R(q)^5} - R(q)^5 &= 11 + \frac{\eta(\tau)^6}{\eta(5\tau)^6} \end{align*}
\begin{align} \frac{\eta_{5;2}(\tau)^5}{\eta_{5;1}(\tau)^5} - \frac{\eta_{5;1}(\tau)^5}{\eta_{5;2}(\tau)^5} &= 11 + \frac{\eta(\tau)^6}{\eta(5\tau)^6} %\tag{1.5} \end{align}
We can enter the equation directly.
rr := e5_1/e5_2
spex := eqSPEX(C)(1/rr^5 - rr^5 - 11 - (e1/e5)^6)
qModular?(C,MG) spex
The terms of spex have the following pole orders at the cusps.
qGrades(C,MG) spex
Obviously, we have poles not only at $\infty$.
Let us show another identity from which the above will follow, namely: \begin{align*} \frac{1}{R(q)^{10}} - 11 \frac{1}{R(q)^5} - \frac{\eta(\tau)^6}{\eta(5\tau)^6 R(q)^5} &= 1 \end{align*}
\begin{align} \frac{\eta_{5;2}(\tau)^{10}}{\eta_{5;1}(\tau)^{10}} - 11 \frac{\eta_{5;2}(\tau)^5}{\eta_{5;1}(\tau)^5} - \frac{\eta(\tau)^6}{\eta(5\tau)^6} \frac{\eta_{5;2}(\tau)^5}{\eta_{5;1}(\tau)^5} &= 1 \end{align}
spex2 := spex * eqSPEX(C)(1/rr^5)
qModular?(C,MG) spex2
All terms of spex2 are modular functions for $\Gamma_1(5)$.
Even more, they only have poles at the cusp $\infty$.
qGrades(C,MG) spex2
So we only need to check whether the principal part of the $q$-expansion at infinity of the left-hand side vanishes and the constant term is 1. This is indeed the case.
z := spexMA1(ZZ, MG)(spex2)
assertTrue(zero? z)
The expansion of the actual eta-quotient of the terms of
spex is as follows.
[spexMA1(ZZ, MG)(spexmon) for spexmon in support spex2]
QEta does not only implement the expansion of a modular function at the cusp infinity, but also at other cusps. For example, the expansion of $R(q)^5$ at all cusps of $\Gamma_1(5)$ is given below.
The expansion at all cusps cannot be done with series over $\setQ$, but needs an extension with a primitive root of unity $\xi$. In our case, $\setQ[\xi]$ works as the ring of coefficients when $\xi^{10}=1$.
xiord := minRootOfUnity(C,MG) spex;
assertEquals(xiord,10)
Let us first read another set of macros provided by QEta.
C ==> QQ
EXTENDEDCOEFFICIENTRING(C, xiord, CX, xi);
map(cusp, trfs)
)set stream calc 3
r5 := eqSPEX(C)(rr^5)
spexMAn(trfs,CX,MG)(r5)
Now we can also show the original identity directly by checking that the principle part (including the constant term) vanishes at all cusps.
assertTrue(zero? spexMAn(trfs,CX,MG)(spex))
We can also turns each of the terms of spex
into a tuple of expansions at each of the cusps.
spexterms := listOfTerms spex
serterms := [t.c * spexMAn(trfs,CX,MG)(t.k) for t in spexterms]
z := reduce(_+, serterms)
assertTrue(zero? z)
Identity for $P$ and $Q$¶
Similarly, we can check \begin{align*} PQ + \frac{9}{PQ} = \frac{Q^3}{P^3} + \frac{P^3}{Q^3} \end{align*} where $P = \frac{\eta(\tau)^2}{\eta(3\tau)^2}$ and $Q = \frac{\eta(2\tau)^2}{\eta(6\tau)^2}$.
This time, we confirm the identity at the cusps of $\Gamma_0(6)$.
pp := eqSPEC((e1/e3)^2) :: SPEX(C);
qq := eqSPEC((e2/e6)^2) :: SPEX(C);
idospex := pp * qq + 9 / (pp * qq) - ((qq/pp)^3 + (pp/qq)^3)
MG ==> MGAMMA0 6
qModular?(C,MG) idospex
-- eq:pure-rhoinfinity sspec:=1 -- eq:pure-rhoinfinity rspec:=(eta(tau)^6*eta(6*tau)^6)/(eta(2*tau)^6*eta(3*tau)^6) -- eq:pure-rhoinfinity orbitSize:=1 -- eq:pure-rhoinfinity alpha:=1/2
Unfortunately, the identity does not consist of terms that are modular for $\Gamma_0(6)$, so we divide by $PQ$ and check this identity.
idspex := idospex/(pp*qq)
assertTrue(qModular?(C,MG) idspex)
Here we actually need no field extension.
xiord := minRootOfUnity(C,MG) idspex
EXTENDEDCOEFFICIENTRING(C, xiord, CX, xi);
trfs := cuspMatrices() $ MG
)set stream calc 3
z := spexMAn(trfs, CX, MG) idspex
assertTrue(zero? z)
The expansions at each individual term is as follows.
idspexterms := listOfTerms idspex
idserterms := [t.c * spexMAn(trfs,CX,MG)(t.k) for t in idspexterms]
z := reduce(_+, idserterms)
assertTrue(zero? z)
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------
Recognize series as (generalized) eta-quotients¶
-------------------------------------------------------------------
--test:recognize-eta-quotients
-------------------------------------------------------------------
QEta is able to guess a representation of a $q$-series in terms of a (generalized) eta-quotient. As an example we use the identity of the Rogers-Ramanujan continued fraction. \begin{align} \frac{\eta_{5;2}(\tau)^5}{\eta_{5;1}(\tau)^5} - \frac{\eta_{5;1}(\tau)^5}{\eta_{5;2}(\tau)^5} &= 11 + \frac{\eta(\tau)^6}{\eta(5\tau)^6} %\tag{1.5} \end{align}
We try to recognize $\frac{\eta(\tau)^6}{\eta(5\tau)^6}$ from the $q$-series.
rr := eqSPEC(e5_1/e5_2) :: SPEX(C)
spex := 1/rr^5 - rr^5 - 11
MG ==> MGAMMA1(5)
qModular?(C,MG) spex
)set stream calc 10
f := spexMA1(C, MG) spex
We use the coefficient of $f$ up to $q^{20}$ in
order to find the specification.
The value in fser is what remains after cancelling
the eta-quotient given by fspec from the input series.
rec := guessEtaQuotientSpecification([[1],[5]], f :: L1(C), 20)
assertEquals(rec.fspec, eqSPEC [[1,6],[5,-6]])
Compiling function G11825 with type NonNegativeInteger -> Boolean
Of course rec.fspec is just a guess and must be
verified by other means, but we have already done that
in another section above.
Similarly, we can guess a generalized eta-quotient by simply listing the indices that we allow in the eta-quotient.
rec := guessEtaQuotientSpecification([[5,1],[5,2]], f:: L1(C), 20)
assertEquals(rec.fspec, eqSPEC [[5,1,6],[5,2,6]])
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------