ZZZZZZZZZZZZZZZZZZZ tttt Z:::::::::::::::::Z ttt:::t Z:::::::::::::::::Z t:::::t Z:::ZZZZZZZZ:::::Z t:::::t ZZZZZ Z:::::Z eeeeeeeeeeee ttttttt:::::ttttttt aaaaaaaaaaaaa Z:::::Z ee::::::::::::ee t:::::::::::::::::t a::::::::::::a Z:::::Z e::::::eeeee:::::et:::::::::::::::::t aaaaaaaaa:::::a Z:::::Z e::::::e e:::::tttttt:::::::tttttt a::::a Z:::::Z e:::::::eeeee::::::e t:::::t aaaaaaa:::::a Z:::::Z e:::::::::::::::::e t:::::t aa::::::::::::a Z:::::Z e::::::eeeeeeeeeee t:::::t a::::aaaa::::::a ZZZ:::::Z ZZZZe:::::::e t:::::t ttttta::::a a:::::a Z::::::ZZZZZZZZ:::e::::::::e t::::::tttt:::::a::::a a:::::a Z:::::::::::::::::Ze::::::::eeeeeeee tt::::::::::::::a:::::aaaa::::::a Z:::::::::::::::::Z ee:::::::::::::e tt:::::::::::tta::::::::::aa:::a ZZZZZZZZZZZZZZZZZZZ eeeeeeeeeeeeee ttttttttttt aaaaaaaaaa aaaa by Tobias Rossmann

- Description
- Download and setup
- Basic usage
- The built-in database of examples
- Advanced usage
- References
- Funding
- Acknowledgements
- License
- Contact

Zeta provides methods for computing local and topological zeta functions arising from the enumeration of subalgebras, ideals, submodules, representations, and conjugacy classes of suitable algebraic structures, as well as some other types of zeta functions. For theoretical background and descriptions of the methods used, see [1, 2, 3, 4, 5, 6, 7]. Zeta is distributed as a Python-package for the computer algebra system SageMath. In addition to Singular and other software included with Sage, Zeta also relies on LattE integrale and Normaliz.

This software requires a recent version of SageMath. Zeta 0.4.2 has been developed for Sage 9.2 on 64-bit Linux (x86_64) systems; other platforms and versions of Sage may or may not work as expected.

The (sources of the) most recent version of Zeta are available as a public repository on GitHub.

On a 64-bit Linux (x86_64) system, the easiest way to
install Zeta is to download
this archive and extract it into some directory,
`$DIR`

say.
This will create a subdirectory
`$DIR/Zeta`

;
please make sure that any previous version of Zeta is removed beforehand.
Next, you will then have to run `make`

from within `$DIR/Zeta`

.

If Sage is started from within
`$DIR`

or if `$DIR`

is among the directories
listed in `$SAGE_PATH`

, then Zeta can be imported
via

```
import Zeta
```

If `$DIR`

is not listed in `$SAGE_PATH`

,
you can permanently include it by adding a line

```
export SAGE_PATH="$DIR:$SAGE_PATH"
```

to `$HOME/.bashrc`

(if you use bash), where
`$DIR`

is replaced by the actual directory name from
above; having applied this change, you will want to start a new
shell. Alternatively, for a temporary solution, after executing

```
sys.path.append('$DIR')
```

from within Sage, you should be able to import Zeta.

During its operation, Zeta will try to invoke the
programs `count`

(a part of LattE integrale),
`scdd_gmp`

(part
of cddlib
and also bundled with LattE integrale),
and `normaliz`

.
These programs should be placed inside `$DIR/Zeta/bin`

; copies are
included with the archive linked to above.

Zeta requires a patched version of `count`

.
To that end, the file `latte-int-1.7.3/code/latte/genFunction/maple.cpp`

in the sources of LattE integrale 1.7.3 should be replaced by the
file `maple.cpp`

included with Zeta.
In order to compile the patched version of LattE integrale 1.7.3 from
scratch, you may want to
use this
modified version
(26M) of the LattE integrale 1.7.3 bundle.

The following table lists all versions of Zeta released so far.

File | Size | Released |
---|---|---|

Zeta-0.4.2.tar.bz2 | 120K | 02/2022 |

Zeta-0.4.1.tar.bz2 | 120K | 02/2021 |

Zeta-0.4.tar.bz2 | 120K | 08/2019 |

Zeta-0.3.2.tar.bz2 | 116K | 04/2017 |

Zeta-0.3.1.tar.bz2 | 108K | 07/2016 |

Zeta-0.3.tar.bz2 | 108K | 02/2016 |

Zeta-0.2.1.tar.bz2 | 72K | 06/2015 |

Zeta-0.2.tar.bz2 | 72K | 03/2015 |

Zeta-0.1.tar.bz2 | 56K | 09/2014 |

By an **algebra**, we mean a free $\mathbf Z$-module of
finite rank endowed with a biadditive multiplication; we do not
require this multiplication to be associative or Lie. Given a
$\mathbf Z$-basis $x_1,\dotsc,x_d$ of an algebra $L$, define
$\alpha_{ije}\in \mathbf Z$ by

The numbers $\alpha_{ije}$ are the **structure constants** of
$L$ with respect to the chosen basis $(x_1,\dotsc,x_d)$. The
principal method for specifying an algebra in Zeta is to provide
structure constants as a nested list

as the first argument of `Zeta.Algebra`

. (We note
that the table of structure constants of an instance of
`Zeta.Algebra`

is stored in the `table`

attribute.)

Given an algebra obtained via `Zeta.Algebra`

, the
function `Zeta.topological_zeta_function`

can be used to
attempt to compute an associated topological zeta function.
Specifically, ```
Zeta.topological_zeta_function(L,
'subalgebras')
```

will attempt to compute the topological subalgebra zeta
function of $L$ as a rational function in $s$, while
`Zeta.topological_zeta_function(L, 'ideals')`

will do
the same for ideals.
If $L$ is a nilpotent Lie algebra, then
`Zeta.topological_zeta_function(L, 'reps')`

will attempt to compute the topological representation zeta function
of the unipotent algebraic group over $\mathbf Q$ corresponding to
$L\otimes_{\mathbf Z} \mathbf Q$.

In general, such computations are not guaranteed to succeed. If
the method for computing topological zeta functions from [1,2] (for subalgebras and ideals) or
[3] (for representations) fails,
`Zeta.topological_zeta_function`

will raise an exception of type `Zeta.ReductionError`

.
Disregarding bugs in Zeta, Sage, or elsewhere,
whenever `Zeta.topological_zeta_function`

does
finish successfully, its output is supposed to be correct.

To illustrate the computation of topological subobject zeta functions, consider the commutative algebra $L = \mathbf Z[X]/X^3$. As a $\mathbf Z$-basis of $L$, we choose $(1,x,x^2)$, where $x$ is the image of $X$ in $L$. The associated nested list of structure constants is

\[ \begin{matrix} [[(1, 0, 0), & (0, 1, 0), & (0, 0, 1)]\phantom],\\ \phantom[ [(0, 1, 0), & (0, 0, 1), & (0, 0, 0)]\phantom],\\ \phantom[[(0, 0, 1), & (0, 0, 0), & (0, 0, 0)]]. \end{matrix} \]The following documents a complete Sage session leading to the computation of the topological subalgebra and ideal zeta functions of $L$.

```
sage: import Zeta
sage: L = Zeta.Algebra([[(1, 0, 0), (0, 1, 0), (0, 0, 1)], [(0, 1, 0), (0, 0,1), (0, 0, 0)], [(0, 0, 1), (0, 0, 0), (0, 0, 0)]])
sage: Zeta.topological_zeta_function(L, 'subalgebras')
2*(15*s - 8)/((5*s - 4)*(3*s - 2)^2*s)
sage: Zeta.topological_zeta_function(L, 'ideals')
1/((3*s - 2)*(2*s - 1)*s)
```

We illustrate the computation of topological representation zeta functions of unipotent algebraic groups (over $\mathbf Q$) using the familiar example of the Heisenberg group $\mathbf H$. The first step is to construct a $\mathbf Z$-form of its Lie algebra. We choose the natural $\mathbf Z$-form $L = \mathbf Z x_1 \oplus \mathbf Z x_2 \oplus \mathbf Z x_3$ with $[x_1,x_2] = x_3$, $[x_2,x_1] = -x_3$ and $[x_i,x_j] = 0$ in the remaining cases. The list of structure constants of $L$ with respect to the basis $(x_1,x_2,x_3)$ is

\[ \begin{matrix} [[(0, 0, \phantom-0), & (0, 0, 1), & (0, 0, 0)]\phantom],\\ \phantom[ [(0, 0, -1), & (0, 0, 0), & (0, 0,0)]\phantom],\\ \phantom[[(0, 0, \phantom-0), & (0, 0, 0), & (0, 0, 0)]]. \end{matrix} \]The following documents a complete Sage session leading to the computation of the topological representation zeta function of $\mathbf H$.

```
sage: import Zeta
sage: L = Zeta.Algebra([[(0, 0, 0), (0, 0, 1), (0, 0, 0)], [(0, 0,-1), (0, 0, 0), (0, 0, 0)], [(0, 0, 0), (0, 0, 0), (0, 0, 0)]])
sage: Zeta.topological_zeta_function(L, 'reps')
s/(s - 1)
```

Using most of the same arguments as `Zeta.topological_zeta_function`

from §3.2, the
function `Zeta.local_zeta_function`

can be used to attempt to
compute *generic* local subalgebra, ideal, or representation zeta
functions—that is to say, computed zeta functions will be valid for all but finitely
many primes $p$ and arbitrary finite extensions of $\mathbf Q_p$ as in
[1,§5.2] and
[3,§2.2].
If the method from [4] is unable to compute a
specific zeta function, an exception of type `Zeta.ReductionError`

will be raised.

By default, `Zeta.local_zeta_function`

will attempt to construct a
single rational function, $W(q,t)$ say, in $(q,t)$ such that for almost all
primes $p$ and all $q = p^f$ ($f \ge 1$), the local zeta function in question
obtained after base extension from $\mathbf Q_p$ to a degree $f$ extension is
given by $W(q,q^{-s})$.
Crucially, such a rational function $W(q,t)$ need not exist and even if it does, Zeta may be unable
to compute it.

Let $L$ be the Heisenberg Lie algebra as above. The following computes the associated generic local subalgebra, ideal, and representation zeta functions.

```
sage: Zeta.local_zeta_function(L, 'subalgebras')
-(q^2*t^2 + q*t + 1)/((q^3*t^2 - 1)*(q*t + 1)*(q*t - 1)*(t - 1))
sage: Zeta.local_zeta_function(L, 'ideals')
-1/((q^2*t^3 - 1)*(q*t - 1)*(t - 1))
sage: Zeta.local_zeta_function(L, 'reps')
(t - 1)/(q*t - 1)
```

That is, for almost all primes $p$ and all finite extensions $K/\mathbf Q_p$, the subalgebra and ideal zeta functions of $L \otimes \mathfrak O_K$ are exactly the first two rational functions in $q$ and $t = q^{-s}$; here, $\mathfrak O_K$ denotes the valuation ring of $K$ and $q$ the residue field size. These results are due to Grunewald, Segal, and Smith and in fact valid for arbitrary $p$; the restriction to $K = \mathbf Q_p$ in their work is not essential. Similarly, the above computation using Zeta shows that if $H \leqslant \mathrm{GL}_3$ is the Heisenberg group scheme, then for almost all primes $p$ and all finite extensions $K/\mathbf Q_p$, the representation zeta function of $H(\mathfrak O_K)$ is $(q^{-s}-1)/(q^{1-s}-1)$, as proved (for all $p$) by Stasinski and Voll.

Assuming the method from [4] applies,
Zeta supports limited computations of non-uniform generic local zeta
functions—that is, instances where no rational function $W(q,t)$ as above exists.
For that purpose, `symbolic=True`

needs to be
passed to `Zeta.local_zeta_function`

.
If successful, the output will then be given by a rational function in $q$, $t$,
and finitely many variables of the form `sc_i`

, each corresponding to the
number of rational points over the residue field of $K$ of (the reduction modulo
$p$ of) the subvariety `Zeta.common.symbolic_count_varieties[i]`

of
some algebraic torus.

Let $L$ be the Lie algebra with $\mathbf Z$-basis $(x_1,\dotsc,x_6)$ and non-trivial commutators $[x_1,x_2] = x_3$, $[x_1,x_3] = x_5$, $[x_1,x_4] = 3x_6$, $[x_2,x_3] = x_6$, and $[x_2,x_4] = x_5$; this algebra is called $L_{6,24}(3)$ in de Graaf's classification. We may compute the generic local representation zeta functions associated with $L$ as follows.

```
sage: Zeta.local_zeta_function(L, 'reps', symbolic=True)
-(q*sc_0*t - q*t^2 - sc_0*t + 1)*(t - 1)/((q^3*t^2 - 1)*(q*t - 1))
sage: Zeta.common.symbolic_count_varieties[0]
Subvariety of 1-dimensional torus defined by [x^2 - 3]
```

We thus see how the generic local representation zeta functions associated with
$L$ depend on whether $3$ is a square in the residue field of $K$.
Calling `Zeta.local_zeta_function(L, 'reps')`

without
`symbolic=True`

will result in an error.
As computations with `symbolic=True`

are generally substantially more
computationally demanding, they should only be attempted as a last resort.

Zeta also provides rudimentary support for the computation of local and topological zeta functions associated with polynomials and polynomial mappings under the non-degeneracy assumptions from [1]. Given $f_1,\dotsc,f_r \in \mathbf Q[X_1,\dotsc,X_n]$, Zeta can be used to attempt to compute the generic local zeta functions (in the sense discussed above) defined by \[ \int_{\mathfrak O_K^n} \lVert f_1(x),\dotsc, f_r(x) \rVert^s_K \mathrm d\mu_K(x) \] or the associated topological zeta function; here, $\mu_K$ denotes the Haar measure and $\lVert \cdotp \rVert_K$ the maximum norm, both normalised as usual.

For a single polynomial, the method used by Zeta is very closely related to
combinatorial formulae of Denef and Loeser and
Denef and Hoornaert.
In order to attempt to compute topological or generic local zeta functions
associated with a polynomial (or a polynomial mapping), pass a
multivariate polynomial (or a list of these)
to `Zeta.topological_zeta_function`

or `Zeta.local_zeta_function`

, respectively
while providing `'poly'`

as the second argument.

```
sage: R.<x,y,z> = QQ[]
sage: f = x^3 -x*y*z
sage: g = x^2 - y^2
sage: Zeta.local_zeta_function(f, 'poly')
(q^4 + q^2*t^2 - q^3 - 2*q^2*t - q*t^2 + q^2 + t^2)*(q - 1)/((q^2 + q*t + t^2)*(q - t)^3)
sage: Zeta.topological_zeta_function(f, 'poly')
1/3*(s^2 + 2*s + 3)/(s + 1)^3
sage: Zeta.local_zeta_function([f,g], 'poly')
(q^2 + 2*q + t)*(q - 1)^2/((q^2 - t)*(q + t)*(q - t))
sage: Zeta.topological_zeta_function([f,g], 'poly')
2/((s + 2)*(s + 1))
```

Non-uniform examples can be handled as in §3.3.2.

In [1,2], (topological) ideal zeta functions were treated as special cases of submodule zeta functions. In Zeta, we regard modules as special cases of algebras with operators. Namely, each algebra $L$ in Zeta is endowed with a possibly empty set $\Omega$ of operators, i.e. $\Omega$ consists of additive endomorphisms of $L$. The topological and local subalgebra and ideal zeta functions of $L$ are always understood to be those arising from the enumeration of $\Omega$-invariant subalgebras or ideals, respectively. Thus, if the multiplication of $L$ is trivial, then the $\Omega$-invariant subalgebras (and ideals) of $L$ are precisely the submodules of $L$ under the action of the enveloping associative unital ring of $\Omega$ within $\mathrm{End}(L)$.

In practice, $\Omega$ is given by a finite list of matrices (or
nested lists of integers representing those matrices) corresponding
to the defining basis of $L$. This list is then supplied to
`Zeta.Algebra`

using the keyword parameter
`operators`

. For algebras with zero multiplication,
instead of entering structure constants, you can provide a keyword
argument `rank`

to `Zeta.Algebra`

which
initialises all structure constants to zero.

We illustrate the computation of the topological submodule zeta function arising from the enumeration of sublattices within $\mathbf Z^3$ invariant under the matrix \[ \begin{bmatrix} 1 & 1 & -1 \\ 0 & 1 & 1 \\ 0 & 0 & 1 \end{bmatrix} \]

```
sage: M = Zeta.Algebra(rank=3, operators=[ [[1,1,-1],[0,1,1],[0,0,1]] ])
sage: Zeta.topological_zeta_function(M)
1/((3*s - 2)*(2*s - 1)*s)
```

In the database included with Zeta, for examples of algebras with trivial multiplication but non-empty lists of operators, we did not include ideal zeta functions; they coincide with the corresponding subalgebra and submodule zeta functions.

Subject to the same restrictions as above, Zeta supports the computation of the (local) “ask zeta functions” defined and studied in [5,6].

Let $\mathfrak{O}$ be a compact discrete valuation ring
with maximal ideal $\mathfrak{P}$.
Let $M \subset \mathrm{M}_{d\times e}(\mathfrak{O})$ be a submodule.
Let $M_n \subset \mathrm{M}_{d\times e}(\mathfrak{O}/\mathfrak{P}^n)$
denote the image of $M$ under the natural map
$\mathrm{M}_{d\times e}(\mathfrak{O}) \to \mathrm{M}_{d\times e}(\mathfrak{O}/\mathfrak{P}^n)$.
The **ask zeta function** of $M$ is
\[
\mathsf{Z}_M(t) = \sum_{n=0}^\infty
\mathrm{ask}(M_n) t^n,
\]
where $\mathrm{ask}(M_n)$ denotes the average size of the kernels of the
elements of $M_n$ acting by right-multiplication on $(\mathfrak{O}/\mathfrak{P}^n)^d$.

Zeta can be used to attempt to compute generic local ask zeta
functions in the following global setting.
Let $M \subset \mathrm{M}_{d\times e}(\mathbf{Z})$ be a submodule of
rank $\ell$. Let $A$ be an integral $d \times e$ matrix of linear
forms in $\ell$ variables such that $M$ is precisely the module of
specialisations of $A$. Then ```
Zeta.local_zeta_function(A,
'ask')
```

attempts to compute $\mathsf{Z}_{M \otimes
\mathfrak{O}_K}(t)$
for almost all primes $p$ and all finite extensions $K/\mathbf{Q}_p$
in the same sense as in §3.3.
The optional keyword parameter `mode`

determines whether
Zeta attempts to compute ask zeta functions
using the functions $\mathrm{K}_M$ (`mode='K'`

)
or $\mathrm{O}_M$ (`mode='O'`

) from [5, §4],
respectively; the default is `mode='O'`

.
To perform a computation using the “bullet dual” operation from
[6, §4], use `mode='BK'`

.

We compute the generic local ask zeta functions associated with $\mathrm{M}_{2\times 3}(\mathbf{Z})$.

```
sage: R.<a,b,c,d,e,f> = QQ[]
sage: A = matrix([[a,b,c],[d,e,f]])
sage: Zeta.local_zeta_function(A, 'ask')
-(q^3 - t)/((q - t)*q^2*(t - 1))
```

Let $L$ be a nilpotent Lie algebra constructed as
in §3.1.
Then `Zeta.local_zeta_function(L, 'cc')`

attempts to
compute the generic local conjugacy class zeta functions associated
with the unipotent algebraic group corresponding to $L \otimes
\mathbf{Q}$; see [5, §7.5].
The optional keyword parameter `mode`

has the same
interpretation as in §3.6.

We compute the generic local conjugacy class zeta functions of the Heisenberg group.

```
sage: L = Zeta.Algebra([[(0, 0, 0), (0, 0, 1), (0, 0, 0)], [(0, 0,-1), (0, 0, 0), (0, 0, 0)], [(0, 0, 0), (0, 0, 0), (0, 0, 0)]])
sage: Zeta.local_zeta_function(L, 'cc')
-(t - 1)/((q^2*t - 1)*(q*t - 1))
```

Zeta supports the computation of the rational functions $W_H(q,t)$ and $W^\pm_G(q,t)$ introduced and studied in [7]. These functions are the uniform ask zeta functions associated with modules of suitable types of matrices with support constraints defined by a hypergraph $H$ or graph $G$, respectively. By [7, Cor. B], the functions $W^-_G(q,t)$ enumerate conjugacy classes of suitable groups derived from $G$. The same is true of the functions $W_H(q,t)$ whenever $H$ is a modelling hypergraph of a cograph; see [7, Thm D].

Hypergraphs can be specified using incidence matrices.
An $n\times m$ $(0,1)$-matrix $A = [a_{ij}]$ defines a hypergraph
$H$ on the vertex set $\{0,\dotsc,n-1\}$ with hyperedges
$e_0,\dotsc,e_{m-1}$, where the support of $e_j$ is the set of those $i =
0,\dotsc,n-1$ with $a_{i+1,j+1} = 1$.
The rational function $W_H(q,t)$ can be computed
using `Zeta.local_zeta_function(A, 'inc')`

.

The following computation determines the ask zeta function of the module of upper triangular $3\times 3$ matrices, in accordance with both [5, Prop. 5.15] and [7, Prop. 5.9].

```
sage: A = matrix([[1,1,1], [0,1,1], [0,0,1]])
sage: Zeta.local_zeta_function(A, 'inc')
(q - t)^3/(q^3*(t - 1)^4)
```

Alternatively, hypergraphs can be specified in terms of their hyperedge
multiplicities.
Let `D`

be a Python dictionary whose keys are tuples
$a = (a_1,\dotsc,a_\ell)$ of integers with $0 \le a_j < n$ and
$a_1 < a_2 < \dotsb < a_\ell$ and whose values are non-negative
integers.
Then `D`

defines a hypergraph $H$ with vertex set $\{0,\dotsc,n-1\}$
such that each value `k = D[a]`

for a tuple as above
corresponds to $k$ hyperedges of $H$, each with support
$\{a_1,\dotsc,a_\ell\}$.
The rational function $W_H(q,t)$ can be computed
using `Zeta.local_zeta_function(n, 'inc', mu=D)`

.

The following computation determines the ask zeta function of the module of all $4 \times 6$ matrices of the form $$ \begin{bmatrix} * & * & * & * & * & *\\ * & * & * & * & * & *\\ 0 & 0 & * & * & * & *\\ 0 & 0 & 0 & * & * & * \end{bmatrix}. $$

```
sage: D = { (0,1): 2, (0,1,2): 1, (0,1,2,3): 3 }
sage: Zeta.local_zeta_function(4, 'inc', mu=D)
-(q^4 - t)*(q^3 - t)^2/((q^2 - t)^3*q^4*(t - 1))
```

This formula can also be obtained using [7, Prop. 5.9].

Given a
graph
$G$, the rational function $W_G^-(q,t)$ from [7] can be
computed using `Zeta.local_zeta_function(G, 'adj')`

.

The following determines the rational function $W^-_G(q,t)$, where $G$ is the butterfly graph.

```
sage: G = Graph(5)
sage: G.add_edges([ (0,1), (0,4), (1,4), (2,3), (2,4), (3,4) ])
sage: Zeta.local_zeta_function(G, 'adj')
-(q^3*t + q^3 - 2*q^2*t - 2*q*t + t^2 + t)/((q*t - 1)^2*q^3*(t - 1))
```

By the Cograph Modelling Theorem [7, Thm D], the preceding rational function coincides with $W_H(q,t)$, where $H$ is a hypergraph with incidence matrix $$\begin{bmatrix} 1 & 1 & 1 & 1 \\ 1 & 1 & 0 & 0 \\ 1 & 1 & 0 & 0 \\ 1 & 0 & 1 & 0 \\ 1 & 0 & 1 & 0\end{bmatrix}.$$ We can confirm this as follows.

```
sage: A = matrix([[1,1,1,1], [1,1,0,0], [1,1,0,0], [1,0,1,0], [1,0,1,0]])
sage: Zeta.local_zeta_function(A, 'inc')
-(q^3*t + q^3 - 2*q^2*t - 2*q*t + t^2 + t)/((q*t - 1)^2*q^3*(t - 1))
```

In order to compute the rational function $W_G^+(q,t)$ for a graph $G$,
simply provide the keyword argument `signs=1`

when calling
`Zeta.local_zeta_function`

.

Let $G$ be the butterfly graph from above.

```
sage: Zeta.local_zeta_function(G, 'adj', signs=1)
(q^6*t^6 + q^5*t^7 - q^6*t^5 - 3*q^5*t^6 - 6*q^4*t^7 + q^7*t^3 - 5*q^6*t^4 + 3*q^5*t^5 + 3*q^4*t^6 + 14*q^3*t^7 - 3*q^7*t^2 + 7*q^6*t^3 + 5*q^5*t^4 + 17*q^4*t^5 - 12*q^3*t^6 - 14*q^2*t^7 - q^7*t + 24*q^6*t^2 - 58*q^5*t^3 + 45*q^4*t^4 - 83*q^3*t^5 + 46*q^2*t^6 - 2*q*t^7 + t^8 - q^7 + 2*q^6*t - 46*q^5*t^2 + 83*q^4*t^3 - 45*q^3*t^4 + 58*q^2*t^5 - 24*q*t^6 + t^7 + 14*q^5*t + 12*q^4*t^2 - 17*q^3*t^3 - 5*q^2*t^4 - 7*q*t^5 + 3*t^6 - 14*q^4*t - 3*q^3*t^2 - 3*q^2*t^3 + 5*q*t^4 - t^5 + 6*q^3*t + 3*q^2*t^2 + q*t^3 - q^2*t - q*t^2)/((q*t - 1)*(q - t)^3*q^4*(t + 1)*(t - 1)^4)
```

The methods for determining generic local zeta functions described in Section 3.3 rely on functionality for symbolically enumerating rational points of affine schemes. As it might be of independent interest, this functionality can also be invoked directly as follows.

Let $f_1,\dotsc,f_r\in \mathbf Z[X_1,\dotsc,X_n]$ and let $Y$ be the subscheme of $\mathbf A^n_{\mathbf Z}$ defined by $f_1 = \dotsb = f_r = 0$. (The polynomials $f_1,\dotsc,f_r$ can actually have coefficients in $\mathbf Q$ in which case $Y$ is to be replaced by the corresponding subscheme of affine $n$-space over $\mathbf Z[1/N]$ for a suitable integer $N \geqslant 1$.)

A call `Zeta.count_points([`

$f_1,\dotsc,f_r$`])`

constructs a symbolic expression, `E`

say, involving (in general) symbols `q`

and `sc_i`

(see Section 3.3.2).
For almost all primes $p$ and all powers $q$ of $p$, the number $\# Y(\mathbf F_q)$ is
then obtained from `E`

by replacing `q`

by $q$ and
each `sc_i`

by the number of $\mathbf F_q$-rational points of
`Zeta.common.symbolic_count_varieties[i]`

, a subscheme of a torus.
We note that `Zeta.count_points`

does not keep track of
the finitely many exceptional primes that need to be excluded.

The function `Zeta.count_points`

attempts to detect when
$\#Y(\mathbf F_q)$ is polynomial in $q$ (excluding small
characteristics). Of course, these attempts are not guaranteed to succeed.

```
sage: R = PolynomialRing(QQ,'x', 8)
sage: R.inject_variables(verbose=False)
sage: F = [x2*x3^2 - x1*x3*x4 + 1/4*x0*x4^2, x0*x5*x6 + 2*x1*x3*x7 - x0*x4*x7]
sage: Zeta.count_points(F)
(q^3 + 2*q^2 - 3*q + 1)*(2*q - 1)*q^2
```

Zeta includes a “database” of algebras. When topological or local zeta functions associated with an algebra in the database have been successfully computed using Zeta, these are stored as well.

Each algebra stored in Zeta can be referred to using its unique
identification number or one of finitely many names; identification numbers may
change between versions of Zeta. Access to
these algebras is provided using the function
`Zeta.lookup`

.

If `Zeta.lookup`

is called with precisely one
argument `entry`

, then `entry`

should be
either an identification number or a name of an algebra, $L$ say,
in the database. In this case, `Zeta.lookup`

will return
$L$. Optional further arguments to `Zeta.lookup`

can be
used to access other information about $L$:

- If the second argument is
`'subalgebras'`

,`'ideals'`

, or`'reps'`

and the third argument is`'local'`

or`'topological'`

, then`Zeta.lookup`

will return the local or topological subalgebra, ideal, or representation zeta function of $L$, respectively, if it is known, and`None`

otherwise. - If the second argument is
`'id'`

, then`Zeta.lookup`

returns the identification number of $L$. - If the second argument is
`'names'`

, then`Zeta.lookup`

returns a list of the stored names of $L$.

When called without arguments, `Zeta.lookup`

returns
a list of pairs `(i,names)`

, where `i`

ranges
over the identification numbers of all algebras in the database and
`names`

is a possibly empty list of names associated
with the `i`

th algebra.

The algebra $L = \mathbf Z[X]/X^3$ from Section 3.1 is known to Zeta under the name
`'ZZ[X]/X^3'`

; it can be retrieved via `L = Zeta.lookup('ZZ[X]/X^3')`

.
We may recover the pre-computed topological zeta functions of $L$ as follows:

```
sage: Zeta.lookup('ZZ[X]/X^3', 'subalgebras', 'topological')
2*(15*s - 8)/((5*s - 4)*(3*s - 2)^2*s)
sage: Zeta.lookup('ZZ[X]/X^3', 'ideals', 'topological')
1/((3*s - 2)*(2*s - 1)*s)
```

Apart from self-explanatory names such as
`'sl(2,ZZ)'`

and `'gl(2,ZZ)'`

, Zeta also
includes algebras $L_{d,i}$, $L_{d,i}(\varepsilon)$, $L^i$,
$L^i_a$, $M^i$, and $M^i_a$ taken from de Graaf's tables of
nilpotent
and soluble Lie
algebras; their corresponding names in Zeta are of the form
`'L(d,i)'`

, `'L(d,i;eps)'`

, `'L^i'`

,
`'L^i(a)'`

, `'M^i'`

, and `'M^i(a)'`

.
For the infinite families among these algebras, we only included
selected specialisations of the parameters.
Recall [1, Prop. 5.19(ii)] that the
topological subalgebra and ideal zeta functions of an algebra $L$
(over $\mathbf Z$) only depend on the $\mathbf C$-isomorphism type
of $L\otimes_{\mathbf Z}\mathbf C$;
a similar statement holds for topological representation zeta functions
by [3, Prop. 4.3].

Similar to Woodward's tables, we use the notation `'g(...)'`

to refer
to $\mathbf Z$-forms of algebras
from Seeley's list of
7-dimensional nilpotent Lie algebras over $\mathbf C$; for
example `'g(147A)'`

is a $\mathbf Z$-form of the algebra $1,4,7_A$
in Seeley's list.

The algebras `'N_i^(8,d)'`

are taken
from the lists of
Ren and Zhu,
and Yan and Deng.

The algebras called `'C(d,i)'`

and `'C(d,i;eps)'`

in
Zeta are “commutative versions” of the nilpotent Lie
rings `'L(d,i)'`

and `'L(d,i;eps)'`

respectively:
they were obtained by inverting the signs of all entries underneath
the diagonal in the matrices of structure constants.

An algebra called `'name[eps]'`

in Zeta is obtained by
tensoring `'name'`

with the dual numbers as
in [3, §6].

The function `Zeta.examples.printall`

generates a
text-based list of

- algebras known to Zeta,
- structural information about each algebra,
- known associated topological zeta functions,
- numerical invariants of these zeta functions (degree, complex roots, ...)

and writes these to an optional file-like object (which defaults
to `stdout`

). The output of this function is also
available for download.

By the **essential value** of a rational function $Z\in
\mathbf Q(s)$ at a point $w\in \mathbf C$, we mean the value of
$Z/(s-w)^m$ at $s = w$, where $m$ is the order of $Z$ at $w$;
similarly, for $w = \infty$. The output of
`Zeta.examples.printall`

(and hence the content of the
file linked to above) contains the essential values of topological
zeta functions at $0$ and $\infty$; these are related to
Conjectures IV–V from [1,2].

As an integral version of terminology used by Evseev, we say that
a $\mathbf Z$-basis $(x_1,\dotsc,x_d)$ of an algebra $L$ is
**simple** if each product $x_ix_j$ is of the form
$\varepsilon_{ij} x_{a_{ij}}$ for $\varepsilon_{ij} \in
\{-1,0,1\}$. In this case, the structure constants of $L$ with
respect to $(x_1,\dotsc,x_d)$ are determined by the matrix $A =
[\varepsilon_{ij} a_{ij}]_{i,j=1,\dotsc,d}$. Zeta supports the
creation of algebras from such a matrix $A$ by passing
`simple_basis=True`

and `matrix=`

$A$ as
arguments to `Zeta.Algebra`

.

For example, the Heisenberg Lie ring with $\mathbf Z$-basis
$(x_1,x_2,x_3)$ and non-trivial products $[x_1,x_2] = x_3$ and
$[x_2,x_1] = -x_3$ from above can be defined in Zeta via
```
Zeta.Algebra(simple_basis=True, matrix=[[0,3,0], [-3,0,0],
[0,0,0] ])
```

.

Zeta supports the computation of graded subalgebra and ideal zeta functions
as in [4].
These zeta functions enumerate homogeneous subobjects with respect to a given
additive decomposition of the underlying module.
Such decompositions are specified using the keyword
argument `blocks`

of `Zeta.Algebra`

.
To that end, `blocks`

should be assigned a list $(\beta_1,\dotsc,\beta_r)$
of positive integers summing up to the rank of the algebra $L$ in question.
If $(x_1,\dotsc,x_d)$ is the defining basis of $L$, then the associated
additive decomposition is $L = L_1 \oplus \dotsb \oplus L_r$ for
$L_j = \bigoplus_{i=\sigma_{j-1}+1}^{\sigma_j} \mathbf Z x_i$
and $\sigma_i = \sum_{e=1}^i \beta_e$.

```
sage: L = Zeta.Algebra([[(0, 0, 0), (0, 0, 1), (0, 0, 0)], [(0, 0,-1), (0, 0, 0), (0, 0, 0)], [(0, 0, 0), (0, 0, 0), (0, 0, 0)]], blocks=[2,1])
sage: Zeta.local_zeta_function(L, 'subalgebras')
-(q*t^3 - 1)/((q*t^2 - 1)*(q*t - 1)*(t + 1)*(t - 1)^2)
```

(The following only applies to the computation of subalgebra
and ideal zeta functions and not to representation or Igusa-type zeta functions.)
Computations using Zeta are usually very sensitive to the choice
of the basis used to define the structure constants of the algebra
under consideration. If a particular zeta function cannot be
directly computed using Zeta, it might be useful to consider
different bases. Given an algebra `L`

of rank $d$ and an
invertible $d\times d$ matrix `A`

over $\mathbf Z$, the
algebra obtained from $L$ by taking the rows of `A`

as a
basis (relative to the original one) can be constructed via
`L.change_basis(A)`

. In the presence of a non-trivial
grading, the latter is required to be respected by `A`

.

Unless `Zeta.local_zeta_function`

or `Zeta.topological_zeta_function`

is called with the keyword
argument `optimise_basis=False`

, Zeta will attempt to find a
basis of the algebra, $L$ say, in question such that the associated toric datum
(see [2]) is “small”.
Currently, Zeta simply loops over permutations of the defining basis of $L$.

If `Zeta.local_zeta_function`

or `Zeta.topological_zeta_function`

is called with the keyword
argument `verbose=True`

, then detailed
information on the various stages of computations will be
displayed. Apart from illustrating the key steps explained in
[1,2,3,4],
this
can often be helpful when it comes to estimating the feasibility of
the intended computation.

An upper bound on the number of CPUs used by
`Zeta.local_zeta_function`

and
`Zeta.topological_zeta_function`

can be enforced by
providing a numerical value for the keyword parameter
`ncpus`

.

During computations of zeta functions, Zeta uses various temporary files. Be warned that for some computations carried out by the author, the combined size of these files exceeded 50G.

Zeta can be equally demanding when it comes to system memory, in
particular when computing local zeta functions.
If computations run out of memory, you can try reducing the number
of CPUs used as indicated above or try setting the keyword
parameter `profile`

to `Zeta.Profile.SAVE_MEMORY`

. Setting
`profile=Zeta.Profile.SPEED`

will result in slightly
better performance at the cost of increased memory use.

(The following only applies to the computation of subalgebra
and ideal zeta functions.)
The reduction step explained in [2]
depends on a strategy for choosing “reduction
candidates”.
A particular strategy can be chosen using the keyword
parameter `strategy`

of `Zeta.local_zeta_function`

or
`Zeta.topological_zeta_function`

. In particular, setting
`strategy=Zeta.Strategy.NONE`

disables reduction
completely while `strategy=Zeta.Strategy.NORMAL`

yields the strategy used
in the paper. Passing `strategy=Zeta.Strategy.PREEMPTIVE`

will
result in a more aggressive reduction strategy which tries to anticipate and
remove causes of singularity in advance. While often slower than
the `Zeta.Strategy.NORMAL`

, this strategy is needed to reproduce some of the
computations recorded in the database (Section 4).

[1] T. Rossmann.
*Computing topological zeta functions of groups, algebras, and
modules, I*. Proc. Lond. Math. Soc. (3) 110 (2015), no. 5,
1099–1134.
(preprint)

[2] T. Rossmann.
*Computing topological zeta functions of groups, algebras, and
modules, II*.
J. Algebra 444 (2015), 567–605.
(preprint)

[3] T. Rossmann.
*Topological representation zeta functions of unipotent groups*.
J. Algebra 448 (2016), 210–237.
(preprint)

[4] T. Rossmann.
*Computing local zeta functions of groups, algebras, and modules*.
Trans. Amer. Math. Soc. 370 (2018), no. 7, 4841–4879.
(preprint)

[5] T. Rossmann.
*The average size of the kernel of a matrix and orbits of linear groups*.
Proc. Lond. Math. Soc. (3) 117 (2018), no. 3, 574–616.
(preprint)

[6] T. Rossmann.
*The average size of
the kernel of a matrix and orbits of linear groups, II: duality*.
J. Pure Appl. Algebra. (2019).
(preprint)

[7] T. Rossmann and C. Voll.
*Groups, graphs, and hypergraphs: average sizes of kernels of generic
matrices with support constraints*.
To appear in Mem. Amer. Math. Soc.
(preprint)

The development of Zeta work was supported by the Alexander von Humboldt Foundation (2016–2018) and by the DFG Priority Programme “Algorithmic and Experimental Methods in Algebra, Geometry and Number Theory” (2013–2016).

I am grateful to Frédéric Chapoton for help with getting Zeta to work with SageMath 9.x.

Copyright © 2014, 2015, 2016, 2017, 2019, 2021, 2022 Tobias Rossmann.

Zeta is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

Zeta is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with Zeta. If not, see http://www.gnu.org/licenses.

Tobias Rossmann

School of Mathematical and Statistical Sciences

University of Galway

Galway

H91 TK33

Ireland

E-mail: tobias.rossmann (at) universityofgalway.ie

last modified: 12 August 2023