$ \newcommand{\modularOrbit}[1]{\mathcal{O}_{#1}} \newcommand{\qPochhammer}[3][\infty]{\left( #2;#3 \right)_{#1}} \newcommand{\setC}{\mathbb{C}} \newcommand{\setH}{\mathbb{H}} \newcommand{\setQ}{\mathbb{Q}} $ Via jupytext this file can be shown as a jupyter notebook.

QEta is able to prove and find identities of eta-quotients (or their related $q$-Pochhammer counterparts).

This notebook demonstrates the ways to specify the input in QEta. In particular, it is shown, how to enter eta-quotients, quotients of $q$-Pochhammer symbols, dissections of such and linear combinations of those quotients.

It is available in text form as [qetaspex.input-test]

In [1]:
)cd ..
)read input/jfricas-test-support.input )quiet
)type on
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.

In [ ]:
)set output formatted off
)set output algebra on

SpecificationExpressions¶

In [2]:
-------------------------------------------------------------------
--test:specifications
-------------------------------------------------------------------

Overview¶

Historically, QEta started to work with 2-element lists of integers so that [d,e]stands for $\eta(d\tau)^e$ where $d>0$ and \begin{align*} \eta_{\delta}(\tau) &:= \eta(\delta\tau) := q^{\frac{\delta}{24}} \qPochhammer{q^\delta}{q^\delta} = q^{\frac{\delta}{24}} \prod_{n\ge1} (1-q^{\delta n}) = q^{\frac{\delta}{24}} \qPochhammer{q^\delta}{q^\delta} \end{align*} where $\setH=\{\tau\in \setC \mid \mathrm{Im}(\tau)>0 \}$ denotes the complex upper half-plane and $q=\exp(2\pi i\tau)$.

Products of such expressions where given by lists of such pairs. After extension of QEta to generalized eta-quotients, we added triples [d,g,e] to stand for the $e$-th power of the generalized eta-function ($0 \le g \le \delta$) \begin{align*} {\eta_{\delta,g}(\tau)} &:= q^{\frac{\delta}{2}P_2(\frac{g}{\delta})} \prod_{\substack{n>0\\n\equiv g\ (\mathrm{mod}\ \delta)}} (1-q^n) \prod_{\substack{n>0\\n\equiv -g\ (\mathrm{mod}\ \delta)}} (1-q^n) \end{align*} where \begin{gather*} {P_2(x)} = B(\{x\}) = \{x\}^2 - \{x\} + \frac{1}{6}. \end{gather*} and \begin{gather*} \{x\} = x - \lfloor x \rfloor \end{gather*} denotes the fractional part of $x$. See

    @InProceedings{Robins_GeneralizedDedekindEtaProducts_1994,
      author =       {Sinai Robins},
      title =        {Generalized Dedekind $\eta$-products},
      booktitle =    {The Rademacher Legacy to Mathematics},
      year =         1994,
      editor =       {G. E. Andrews and David M. Bressoud and L. Alayne
                      Parson},
      volume =       166,
      series =       {Contemporary Mathematics},
      pages =        {119--128},
      address =      {Providence, RI},
      publisher =    {American Mathematical Society},
      ISBN =         {978-0-8218-7757-9}
    }

For $0<g<\delta$ we have \begin{align*} \eta_{\delta,g}(\tau) &= q^{\frac{\delta}{2}P_2(\frac{g}{\delta})} \prod_{n=1}^\infty (1-q^{\delta (n-1)+g})(1-q^{\delta n-g}) \notag\\ &= q^{\frac{\delta}{2}P_2(\frac{g}{\delta})} \qPochhammer{q^{g}}{q^\delta} \qPochhammer{q^{\delta-g}}{q^\delta} = q^{\frac{\delta}{2}P_2(\frac{g}{\delta})} \qPochhammer{q^{g},q^{\delta-g}}{q^\delta}. \end{align*}

Note that \begin{gather*} \eta_{\delta,0}(\tau) = \eta_{\delta,\delta}(\tau) = \eta(\delta\tau)^2 \qquad\text{and}\qquad \eta_{\delta,\frac{\delta}{2}}(\tau) = \frac{\eta(\frac{\delta}{2}\tau)^2}{\eta(\delta\tau)^2}. \end{gather*}

Since lists of lists are too easily confused with other things, we chose to introduce the special type QEtaSpecificatioon (abbreviated by the macro SPEC) that holds the data for one eta-quotient.

Since initially we aimed at computing Ramanujan-Kolberg identities by an algorithm from the paper by Cristian-Silviu Radu, we also needed to specify dissections of eta-quotients together with an additional eta-quotient that had to be multiplied to the dissection in order to produce a modular function for a certain congruence subgroup. Up to QEta 4.0, we just carried around the quadruple [sspec, rspec, m, t].

For newer versions, we tried to improve the user interface and therefore, added another type QEtaSpecificationExpression.

This type can be considered to represent products and quotients of eta-functions, $q$-Pochhammer symbols and dissections of them, so that it is possible to express identities in a purely symbolic manner while at the same time it would be possible to compute expansions at the cusps for expressions that represent modular functions.

To understand the structure, a QEtaSpecificationExpression (abbreviated by the macro SPEX) is essentially a monoid ring where the coefficients are from a coefficient ring C (often the rational numbers $\setQ$) and the monomials are of type QEtaSpecificationExpressionMonomial (abbreviated by the macro SPEXMON). Such monomials are power products (negative exponents are allowed) of eta-functions, $q$-Pochhammer-symbols and (extended) dissections thereof. In fact, we have already introduced SPEC above. There is also QPochhammerSpecification (abbreviated by the macro QSPEC), QGeneratingFunctionVariable (abbreviated by the macro QGFVAR), QGeneratingFunctionSpecification (abbreviated by the macro QGFSPEC), and XGeneratingFunctionSpecification (abbreviated by the macro XGFSPEC).

For a list of all macros see input/qetamacros.input.

An element of QSPEC is a product of a (fractional) power of the variable $q=\exp(2\pi i \tau)$ and a quotient of $q$-Pochhammer symbols.

In [3]:
qspec := qPower(3/5) * qPochhammer(q^2,q^5)^2/qPochhammer(q)
Out[3]:
\[ {{q}}^{\frac{3}{5}}\, \frac{{{\left({{q}}^{2}; {{q}}^{5}\right)}_{\infty }}^{2}}{{\left({q}\right)}_{\infty }} \]
QPochhammerSpecification

An elements of SPEC is an eta-quotient.

In [4]:
spec := eqSPEC([[1,1],[2,-3],[5,1,2]])
Out[4]:
\[ \frac{\eta\left(\tau\right)\, {{\eta}_{5, 1}\left(\tau\right)}^{2}}{{\eta\left(2\, \tau\right)}^{3}} \]
QEtaSpecification

An element of QGFSPEC is a power product (negative exponents are allowed) of elements from QGeneratingFunctionVariable (abbreviated by the macro QGFVAR).

An element of QGFVAR essentially stands for a dissection of a (generalized) $q$-Pochhammer quotient.

In [5]:
gfv := generatingFunction(spec)
Out[5]:
\[ \sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable

Note that from the specification in the argument of generatingFuncttion only the that corresponds to products of the form $(1-q^n)$ are considered. In other words, if expanded such a $q$-series is a Taylor series with constant term 1. Therefore, the following specifications all give the same element of QGeneratingFunctionVariable.

In [6]:
qspec := eulerProduct spec
gfv1 := generatingFunction(qspec)
assertEquals(gfv, gfv1)
Out[6]:
\[ \frac{{\left({q}\right)}_{\infty }\, {{\left({q}; {{q}}^{5}\right)}_{\infty }}^{2}\, {{\left({{q}}^{4}; {{q}}^{5}\right)}_{\infty }}^{2}}{{{\left({{q}}^{2}\right)}_{\infty }}^{3}} \]
QPochhammerSpecification
Out[6]:
\[ \sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable
Out[6]:
\[ \mathtt{true} \]
Boolean
In [7]:
gfv2 := generatingFunction(qPower(10)*qspec)
assertEquals(gfv, gfv2)
Out[7]:
\[ \sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable
Out[7]:
\[ \mathtt{true} \]
Boolean

From that we can choose the $q$ powers that should be in the dissection.

In [8]:
gfv54 := choose(5,4)(gfv)
Out[8]:
\[ \sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable
In [9]:
qgfspec := gfv * gfv54
Out[9]:
\[ \left(\sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}}\right)\, \left(\sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}}\right) \]
QGeneratingFunctionSpecification

An element of XGFSPEC is an element of QGFSPEC multiplied by a certain power of $q=\exp(2 \pi i \tau)$. The exponent of $q$ is automatically computed by the function lift and corresponds to the summand of the second sum in the definition of $\alpha$ in the abstract of Radu's article.

In [10]:
xgfspec := lift qgfspec
Out[10]:
\[ {{q}}^{\frac{59}{100}}\, \left(\sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}}\right)\, \left(\sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}}\right) \]
XGeneratingFunctionSpecification

The respective inverse function (to remove that extra $q$ power) is called project.

In [11]:
assertEquals(project xgfspec, qgfspec)
Out[11]:
\[ \mathtt{true} \]
Boolean

An element from SPEXMON is simply a product of an element from QSPEC, an element from SPEC, and an element from XGFSPEC.

In [12]:
spexmon := qspec * spec::SPEXMON * xgfspec
Out[12]:
\[ {{q}}^{\frac{59}{100}}\, \frac{{\left({q}\right)}_{\infty }\, {{\left({q}; {{q}}^{5}\right)}_{\infty }}^{2}\, {{\left({{q}}^{4}; {{q}}^{5}\right)}_{\infty }}^{2}}{{{\left({{q}}^{2}\right)}_{\infty }}^{3}}\, \frac{\eta\left(\tau\right)\, {{\eta}_{5, 1}\left(\tau\right)}^{2}}{{\eta\left(2\, \tau\right)}^{3}}\, \left(\sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}}\right)\, \left(\sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}}\right) \]
QEtaSpecificationExpressionMonomial

It is also possible to use qgfspec directly. QEta takes care of the extra $q$ power.

In [13]:
qspexmon := qgfspec :: SPEXMON
xspexmon := xgfspec :: SPEXMON
assertEquals(qPochhammerPart qspexmon, qPower(- rhoInfinity qgfspec))
assertEquals(qPochhammerPart xspexmon, 1$QSPEC)
Out[13]:
\[ \left(\sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}}\right)\, \left(\sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}}\right) \]
QEtaSpecificationExpressionMonomial
Out[13]:
\[ {{q}}^{\frac{59}{100}}\, \left(\sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}}\right)\, \left(\sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}}\right) \]
QEtaSpecificationExpressionMonomial
Out[13]:
\[ \mathtt{true} \]
Boolean
Out[13]:
\[ \mathtt{true} \]
Boolean

An element of SPEX(C) is a C-linear combination of elements from SPEXMON.

Let us first assign C to stand for the rational numbers.

In [14]:
C ==> QQ
Out[14]:
Void
In [15]:
spex := qPower(-3/5)* qP(q) * (eqSPEC([[5,1,-2]]) * (qspec::SPEX(C) + spec + 3*spexmon))
Out[15]:
\[ 3\, {{q}}^{-\frac{1}{100}}\, \frac{{{\left({q}\right)}_{\infty }}^{2}\, {{\left({q}; {{q}}^{5}\right)}_{\infty }}^{2}\, {{\left({{q}}^{4}; {{q}}^{5}\right)}_{\infty }}^{2}}{{{\left({{q}}^{2}\right)}_{\infty }}^{3}}\, \frac{\eta\left(\tau\right)}{{\eta\left(2\, \tau\right)}^{3}}\, \left(\sum_{{n}=0}^{\infty }{a\left({n}\right)\, {{q}}^{{n}}}\right)\, \left(\sum_{{n}=0}^{\infty }{a\left(5\, {n}+4\right)\, {{q}}^{{n}}}\right)+{{q}}^{-\frac{3}{5}}\, \frac{{{\left({q}\right)}_{\infty }}^{2}\, {{\left({q}; {{q}}^{5}\right)}_{\infty }}^{2}\, {{\left({{q}}^{4}; {{q}}^{5}\right)}_{\infty }}^{2}}{{{\left({{q}}^{2}\right)}_{\infty }}^{3}}\, \frac{1}{{{\eta}_{5, 1}\left(\tau\right)}^{2}}+{{q}}^{-\frac{3}{5}}\, {\left({q}\right)}_{\infty }\, \frac{\eta\left(\tau\right)}{{\eta\left(2\, \tau\right)}^{3}} \]
QEtaSpecificationExpression(Fraction(Integer))

The partition function is given by the inverse of the $q$-Pochhammer symbol $\qPochhammer{q}{q}$. The file qetamacros.input provides a number of macros to simplify the work with QEta. In particular the qPochhammer function is abbreviated by qP. Thus, we can simply specify the generating funtion for the partition numbers $p(n)$ as.

In [16]:
pqspec := inv qP(q)
gfv := [pqspec, 1, 0, 'p, 'n] $ QGFVAR
Out[16]:
\[ \frac{1}{{\left({q}\right)}_{\infty }} \]
QPochhammerSpecification
Out[16]:
\[ \sum_{{n}=0}^{\infty }{p\left({n}\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable

Note that the variables p and n are only used for the output of the dissection.

The $(7n+5)$-dissection of this series, we get as follows.

In [17]:
gfv := [pqspec, 7, 5, 'p, 'n] $ QGFVAR
Out[17]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable

Of course, from gfv one can easily get all the parameters back.

In [18]:
assertEquals(qPochhammerSpecification gfv, pqspec)
assertEquals(multiplier gfv, 7)
assertEquals(offset gfv, 5)
Out[18]:
\[ \mathtt{true} \]
Boolean
Out[18]:
\[ \mathtt{true} \]
Boolean
Out[18]:
\[ \mathtt{true} \]
Boolean

An element of QGFVAR can be coerced into other types.

In [19]:
gfv :: QGFSPEC
gfv :: SPEXMON
pspex := gfv :: SPEX(C)
xspex := lift(gfv) :: SPEX(C)
Out[19]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionSpecification
Out[19]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QEtaSpecificationExpressionMonomial
Out[19]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QEtaSpecificationExpression(Fraction(Integer))
Out[19]:
\[ {{q}}^{\frac{17}{24}}\, \left(\sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}}\right) \]
QEtaSpecificationExpression(Fraction(Integer))

In the same way, this type conversion works for QSPEC and SPEC.

In [20]:
[pqspec :: SPEXMON, spec :: SPEXMON]
[pqspex := pqspec :: SPEX(C), spex := spec :: SPEX(C)]
Out[20]:
\[ \left[\frac{1}{{\left({q}\right)}_{\infty }}, \frac{\eta\left(\tau\right)\, {{\eta}_{5, 1}\left(\tau\right)}^{2}}{{\eta\left(2\, \tau\right)}^{3}}\right] \]
List(QEtaSpecificationExpressionMonomial)
Out[20]:
\[ \left[\frac{1}{{\left({q}\right)}_{\infty }}, \frac{\eta\left(\tau\right)\, {{\eta}_{5, 1}\left(\tau\right)}^{2}}{{\eta\left(2\, \tau\right)}^{3}}\right] \]
List(QEtaSpecificationExpression(Fraction(Integer)))

If the specification at hand is of the right format, one can also convert from the more general to the more specific type.

In [21]:
pqspex :: QSPEC
Out[21]:
\[ \frac{1}{{\left({q}\right)}_{\infty }} \]
QPochhammerSpecification
In [22]:
spex :: SPEC
Out[22]:
\[ \frac{\eta\left(\tau\right)\, {{\eta}_{5, 1}\left(\tau\right)}^{2}}{{\eta\left(2\, \tau\right)}^{3}} \]
QEtaSpecification
In [23]:
pspex :: QGFSPEC
pspex :: QGFVAR
xspex :: XGFSPEC
Out[23]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionSpecification
Out[23]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable
Out[23]:
\[ {{q}}^{\frac{17}{24}}\, \left(\sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}}\right) \]
XGeneratingFunctionSpecification

QEta allows to convert an eta-quotient into the corresponding $q$-Pochhammer expression.

In [24]:
spec
spec :: QSPEC
Out[24]:
\[ \frac{\eta\left(\tau\right)\, {{\eta}_{5, 1}\left(\tau\right)}^{2}}{{\eta\left(2\, \tau\right)}^{3}} \]
QEtaSpecification
Out[24]:
\[ {{q}}^{-\frac{7}{40}}\, \frac{{\left({q}\right)}_{\infty }\, {{\left({q}; {{q}}^{5}\right)}_{\infty }}^{2}\, {{\left({{q}}^{4}; {{q}}^{5}\right)}_{\infty }}^{2}}{{{\left({{q}}^{2}\right)}_{\infty }}^{3}} \]
QPochhammerSpecification

The reverse way also works, if the $q$-Pochhammer quotient comes with the right (fractional) $q$-power to turn it into an eta-quotient.

In [25]:
retractIfCan(pqspec) @ Union(SPEC, "failed")
Out[25]:
\[ \mathtt{\texttt{"}failed\texttt{"}} \]
Union("failed",...)
In [26]:
(qPower(-1/24)*pqspec) :: SPEC
Out[26]:
\[ \frac{1}{\eta\left(\tau\right)} \]
QEtaSpecification

It is also easy to compute the part that is missing for turning a $q$ Pochhammer quotient into an eta-quotient.

In [27]:
missingSpecificationForEta pqspec
Out[27]:
\[ {{q}}^{-\frac{1}{24}} \]
QPochhammerSpecification

The function lift adds this missing part automatically.

In [28]:
lift(pqspec)
[pqspec, lift(pqspec)::QSPEC]
Out[28]:
\[ \frac{1}{\eta\left(\tau\right)} \]
QEtaSpecification
Out[28]:
\[ \left[\frac{1}{{\left({q}\right)}_{\infty }}, {{q}}^{-\frac{1}{24}}\, \frac{1}{{\left({q}\right)}_{\infty }}\right] \]
List(QPochhammerSpecification)

Things get interesting, when it comes to the SPEX notation. We can have eta-quotients and $q$-Pochhammer quotients at the same time.

In [29]:
spexmon := inv(pqspec)::SPEXMON * eqSPEC([[2,3]])
Out[29]:
\[ {\left({q}\right)}_{\infty }\, {\eta\left(2\, \tau\right)}^{3} \]
QEtaSpecificationExpressionMonomial

This value can be turned into a $q$-Pochhammer notation or an eta-quotient (with possibly non-convertible remainders). The functions qExpression and etaExpression also work on elements of SPEX(C).

In [30]:
qspexmon := qExpression spexmon
espexmon := etaExpression spexmon
Out[30]:
\[ {{q}}^{\frac{1}{4}}\, {\left({q}\right)}_{\infty }\, {{\left({{q}}^{2}\right)}_{\infty }}^{3} \]
QEtaSpecificationExpressionMonomial
Out[30]:
\[ {{q}}^{-\frac{1}{24}}\, \eta\left(\tau\right)\, {\eta\left(2\, \tau\right)}^{3} \]
QEtaSpecificationExpressionMonomial

Such expressions can be added and count as different until they are converted into a $q$-Pochhammer- or an eta-expression.

In [31]:
spex := qspexmon :: SPEX(C) + espexmon
qex := qExpression spex
eex := etaExpression spex
assertEquals(qex, 2 * qspexmon)
assertEquals(eex, 2 * espexmon)
Out[31]:
\[ {{q}}^{-\frac{1}{24}}\, \eta\left(\tau\right)\, {\eta\left(2\, \tau\right)}^{3}+{{q}}^{\frac{1}{4}}\, {\left({q}\right)}_{\infty }\, {{\left({{q}}^{2}\right)}_{\infty }}^{3} \]
QEtaSpecificationExpression(Fraction(Integer))
Out[31]:
\[ 2\, {{q}}^{\frac{1}{4}}\, {\left({q}\right)}_{\infty }\, {{\left({{q}}^{2}\right)}_{\infty }}^{3} \]
QEtaSpecificationExpression(Fraction(Integer))
Out[31]:
\[ 2\, {{q}}^{-\frac{1}{24}}\, \eta\left(\tau\right)\, {\eta\left(2\, \tau\right)}^{3} \]
QEtaSpecificationExpression(Fraction(Integer))
Out[31]:
\[ \mathtt{true} \]
Boolean
Out[31]:
\[ \mathtt{true} \]
Boolean

If an element of SPEXMON is an appropriate monomial. It can be converted to the more specific type.

In [32]:
espexmon
Out[32]:
\[ {{q}}^{-\frac{1}{24}}\, \eta\left(\tau\right)\, {\eta\left(2\, \tau\right)}^{3} \]
QEtaSpecificationExpressionMonomial
In [33]:
assertEquals(retractIfCan(espexmon) @ Union(SPEC, "failed"), "failed")
assertEquals((qPower(1/24)*espexmon)::SPEC, eqSPEC([[1],[2,3]]))
assertEquals((qPower(1/24)*espexmon)::QSPEC, qPower(7/24)*qP(q)*qP(q^2,q^2)^3)
Out[33]:
\[ \mathtt{true} \]
Boolean
Out[33]:
\[ \mathtt{true} \]
Boolean
Out[33]:
\[ \mathtt{true} \]
Boolean

Because of the factor 2, the following fails.

In [34]:
assertEquals(retractIfCan(qPower(1/24) * spex) @ Union(SPEC,"failed"), "failed")
Out[34]:
\[ \mathtt{true} \]
Boolean

Clearly, the specification is not of generating function form.

In [35]:
assertEquals(retractIfCan(spex) @ Union(QGFSPEC, "failed"), "failed")
Out[35]:
\[ \mathtt{true} \]
Boolean

Although sspex is symbolically a sum, the following conversion works, because the input is normalized before it is retracted to the more specific type.

In [36]:
sspex := 1/2 * qPower(1/24) * spex
assertEquals(sspex :: SPEC, eqSPEC([[1],[2,3]]))
assertEquals(sspex :: QSPEC, qPower(7/24)*qP(q)*qP(q^2,q^2)^3)
Out[36]:
\[ \frac{1}{2}\, \eta\left(\tau\right)\, {\eta\left(2\, \tau\right)}^{3}+\frac{1}{2}\, {{q}}^{\frac{7}{24}}\, {\left({q}\right)}_{\infty }\, {{\left({{q}}^{2}\right)}_{\infty }}^{3} \]
QEtaSpecificationExpression(Fraction(Integer))
Out[36]:
\[ \mathtt{true} \]
Boolean
Out[36]:
\[ \mathtt{true} \]
Boolean

Other ways to enter specifications¶

Instead of entering the specification for $\eta(\tau)\eta(2\tau)^3$ via the eqSPEC macro and a list of lists of integers, it is also possible to do it from a polynomial or a rational function expression.

Essentially, this is done by the function specification of the respective domain. However, since this function is heavily overloaded, there are macros like eqSPEC, qpSPEC, eqSPEX(C), and pqSPEX(C) that implicitly name the target domains SPEC, QSPEC, and SPEX(C). The eq in the name stands for "eta quotient", and qp for "$q$-Pochhammer", i.e., the input must be in a form to interpret them as eta-quotients or $q$-Pochhamer quotients.

By default, the variable name "e" is used as the variable name that is then replaced by the eta-function, but it is possible to use any other variable by specifying it as the second parameter of the eqSPEC macro.

In [37]:
aspec := eqSPEC([[1],[2,3]])
assertEquals(eqSPEC(e1 * e2^3), aspec)
assertEquals(eqSPEC(f1 * f2^3, "f"), aspec)
Out[37]:
\[ \eta\left(\tau\right)\, {\eta\left(2\, \tau\right)}^{3} \]
QEtaSpecification
Out[37]:
\[ \mathtt{true} \]
Boolean
Out[37]:
\[ \mathtt{true} \]
Boolean

Generalized eta-functions are entered with a variable name that contains an underscore character.

In [38]:
rspec := eqSPEC([[5,1,1], [5,2,-1]])
assertEquals(eqSPEC(e5_1/e5_2), rspec)
Out[38]:
\[ \frac{{\eta}_{5, 1}\left(\tau\right)}{{\eta}_{5, 2}\left(\tau\right)} \]
QEtaSpecification
Out[38]:
\[ \mathtt{true} \]
Boolean

It also works for $q$-Pochhammer specifications like $\qPochhammer{q}{q}^{-1} \qPochhammer{q^2}{q^2}$ with the difference that the default variable name is "f".

In [39]:
bqspec := qP(q^2,q^2)/qP(q)
assertEquals(qpSPEC(f2/f1), bqspec)
assertEquals(qpSPEC(u2/u1, "u"), bqspec)
Out[39]:
\[ \frac{{\left({{q}}^{2}\right)}_{\infty }}{{\left({q}\right)}_{\infty }} \]
QPochhammerSpecification
Out[39]:
\[ \mathtt{true} \]
Boolean
Out[39]:
\[ \mathtt{true} \]
Boolean

With a similar command, it is possible to directly create expressions from rational functions (with a monomial denominator).

In [40]:
spex := eqSPEX(C)(e2^4 * e5^2 / (e1^2 * e10^4) + _
                  e2 * e5^5 / (e1 * e10^5) + _
                  e1^3 * e5 / (e2 * e10^3))
Out[40]:
\[ \frac{{\eta\left(\tau\right)}^{3}\, \eta\left(5\, \tau\right)}{\eta\left(2\, \tau\right)\, {\eta\left(10\, \tau\right)}^{3}}+\frac{\eta\left(2\, \tau\right)\, {\eta\left(5\, \tau\right)}^{5}}{\eta\left(\tau\right)\, {\eta\left(10\, \tau\right)}^{5}}+\frac{{\eta\left(2\, \tau\right)}^{4}\, {\eta\left(5\, \tau\right)}^{2}}{{\eta\left(\tau\right)}^{2}\, {\eta\left(10\, \tau\right)}^{4}} \]
QEtaSpecificationExpression(Fraction(Integer))

In fact, the monomials of the expression above are the generators of all eta-quotients of $\Gamma_0(10)$ that have a pole only at infinity, i.e. any other eta-quotient is a powerproduct (with non-negative exponents) of the monomials of spex. The function to compute such generators is abbreviated by the macro mSPECSInf.

In [41]:
idxs := etaFunctionIndices 10
mspecs := mSPECSInf(MGAMMA0 10)(idxs)
assertEquals(sort support spex, [x::SPEX(C) for x in mspecs])
Out[41]:
\[ \left[\left[1\right], \left[2\right], \left[5\right], \left[10\right]\right] \]
List(List(Integer))
Out[41]:
\[ \left[\frac{{\eta\left(2\, \tau\right)}^{4}\, {\eta\left(5\, \tau\right)}^{2}}{{\eta\left(\tau\right)}^{2}\, {\eta\left(10\, \tau\right)}^{4}}, \frac{\eta\left(2\, \tau\right)\, {\eta\left(5\, \tau\right)}^{5}}{\eta\left(\tau\right)\, {\eta\left(10\, \tau\right)}^{5}}, \frac{{\eta\left(\tau\right)}^{3}\, \eta\left(5\, \tau\right)}{\eta\left(2\, \tau\right)\, {\eta\left(10\, \tau\right)}^{3}}\right] \]
List(QEtaSpecification)
Out[41]:
\[ \mathtt{true} \]
Boolean

We can enter the same expression in $q$-Pochhammer notation as follows.

In [42]:
qspex := qpSPEX(C)((f2^4 * f5^2 / (f1^2 * f10^4) + _
                    f2 * f5^5 / (f1 * f10^5) + _
                    f1^3 * f5 / (f2 * f10^3)) / q)
Out[42]:
\[ {{q}}^{-1}\, \frac{{{\left({q}\right)}_{\infty }}^{3}\, {\left({{q}}^{5}\right)}_{\infty }}{{\left({{q}}^{2}\right)}_{\infty }\, {{\left({{q}}^{10}\right)}_{\infty }}^{3}}+{{q}}^{-1}\, \frac{{\left({{q}}^{2}\right)}_{\infty }\, {{\left({{q}}^{5}\right)}_{\infty }}^{5}}{{\left({q}\right)}_{\infty }\, {{\left({{q}}^{10}\right)}_{\infty }}^{5}}+{{q}}^{-1}\, \frac{{{\left({{q}}^{2}\right)}_{\infty }}^{4}\, {{\left({{q}}^{5}\right)}_{\infty }}^{2}}{{{\left({q}\right)}_{\infty }}^{2}\, {{\left({{q}}^{10}\right)}_{\infty }}^{4}} \]
QEtaSpecificationExpression(Fraction(Integer))
In [43]:
assertEquals(etaExpression qspex, spex)
Out[43]:
\[ \mathtt{true} \]
Boolean

The specification can be turned into a polynomial where the variables ed stand for $\eta(d\tau)$ and yd for $\eta(d\tau)^{-1}$.

In [44]:
polynomial spex
rationalFunction spex
Out[44]:
\[ {{e1}}^{3}\, {e5}\, {{y10}}^{3}\, {y2}+{e2}\, {{e5}}^{5}\, {y1}\, {{y10}}^{5}+{{e2}}^{4}\, {{e5}}^{2}\, {{y1}}^{2}\, {{y10}}^{4} \]
Polynomial(Fraction(Integer))
Out[44]:
\[ \frac{{e1}\, {{e2}}^{2}\, {{e5}}^{5}+{e10}\, {{e2}}^{5}\, {{e5}}^{2}+{{e1}}^{5}\, {{e10}}^{2}\, {e5}}{{{e1}}^{2}\, {{e10}}^{5}\, {e2}} \]
Fraction(Polynomial(Fraction(Integer)))

Of course, we can also turn it into an expression where fd stands for $\qPochhammer{q^d}{q^d}$, gd for $\qPochhammer{q^d}{q^d}^{-1}$, and qn for $q^{1/n}$.

In [45]:
polynomial(qPower(1)*qExpression spex)
rationalFunction qExpression spex
Out[45]:
\[ {{f1}}^{3}\, {f5}\, {{g10}}^{3}\, {g2}+{f2}\, {{f5}}^{5}\, {g1}\, {{g10}}^{5}+{{f2}}^{4}\, {{f5}}^{2}\, {{g1}}^{2}\, {{g10}}^{4} \]
Polynomial(Fraction(Integer))
Out[45]:
\[ \frac{{f1}\, {{f2}}^{2}\, {{f5}}^{5}+{f10}\, {{f2}}^{5}\, {{f5}}^{2}+{{f1}}^{5}\, {{f10}}^{2}\, {f5}}{{{f1}}^{2}\, {{f10}}^{5}\, {f2}\, {q}} \]
Fraction(Polynomial(Fraction(Integer)))
In [46]:
bspec := eqSPEC(e2)
bqspec := bspec :: QSPEC
monomial(bspec)
monomial(bqspec)
Out[46]:
\[ \eta\left(2\, \tau\right) \]
QEtaSpecification
Out[46]:
\[ {{q}}^{\frac{1}{12}}\, {\left({{q}}^{2}\right)}_{\infty } \]
QPochhammerSpecification
Out[46]:
\[ {e2} \]
Polynomial(Integer)
Out[46]:
\[ {f2}\, {q12} \]
Polynomial(Integer)

Of course, we get the original specifications back, if we use the resulting polynomials for a specification expression.

In [47]:
assertEquals(eqSPEC(e2), bspec)
assertEquals(qpSPEC(q12*f2), bqspec)
assertEquals(eqSPEX(C)(e2), bspec :: SPEX(C))
assertEquals(qpSPEX(C)(q12*f2), bqspec::SPEX(C))
Out[47]:
\[ \mathtt{true} \]
Boolean
Out[47]:
\[ \mathtt{true} \]
Boolean
Out[47]:
\[ \mathtt{true} \]
Boolean
Out[47]:
\[ \mathtt{true} \]
Boolean

Also specification involving dissections can be translated input polynomials, but there is corrently no way to transform such polynomials back into a specification expression.

Note that the respective variable (here p7_5) actually stands for $q^\rho \sum_{n=0} p(7n+5)q^n$ with $\rho=\frac{5+\rho_\infty(r)}{7}$ and $r$ corresponding to definingSpecification of this dissection, see eqref{eq:beta} in qeta.tex. The symbol q24 stands for $q^{1/24}$.

In [48]:
gfv
rationalFunction(gfv::SPEX(C))
Out[48]:
\[ \sum_{{n}=0}^{\infty }{p\left(7\, {n}+5\right)\, {{q}}^{{n}}} \]
QGeneratingFunctionVariable
Out[48]:
\[ \frac{{p7\_5}}{{{q24}}^{17}} \]
Fraction(Polynomial(Fraction(Integer)))

However, if gfv is not in the context of SPEX(C) or SPEXMON, i.e. rather when it is of type QGFVAR or QGFSPEC, then the symbol p7_5 stands directly for $\sum_{n=0} p(7n+5)q^n$. The symbol q12 stands for $q^{1/12}$.

In [49]:
monomial gfv
quotient(gfv^(-2))
rationalFunction((gfv^(-2))::SPEX(C))
Out[49]:
\[ {p7\_5} \]
Polynomial(Integer)
Out[49]:
\[ \frac{1}{{{p7\_5}}^{2}} \]
Fraction(Polynomial(Integer))
Out[49]:
\[ \frac{{{q12}}^{17}}{{{p7\_5}}^{2}} \]
Fraction(Polynomial(Fraction(Integer)))
In [50]:
-------------------------------------------------------------------
--endtest
-------------------------------------------------------------------