back to table · edit · history · where entries came from · files · download
4072 bytes, as of the version from 2026-11-01 16:24 (current). Recorded here, not run.
"""Augmentation Hilbert series of finite p-groups -- numberdb.org/T653.
Run with SageMath (or a suitable passagemath installation):
sage -pip install numberdb
sage -python generate.py # verify all stored entries
sage -python generate.py --write # fill the existing draft, with a key
sage -python checks.py # independent exact checks
The generator multiplies Jennings factors in ZZ[t], with no floating-point
arithmetic. The single parameter G denotes an actual finite group, using
UT-n-p for U_n(F_p) and Heis-r-p for the triple-law Heisenberg group. The
rank-one Heisenberg group is represented only by UT-3-p. Enumeration is by
increasing prime, then unitriangular size, then Heisenberg rank. See the
attached argument-selection.md for the structural families and finite bounds.
--write (or NUMBERDB_PUBLISH=1 for the campaign wrapper) writes entries into
the existing table. It does not offer, review, or publish the table.
NUMBERDB_KEY_FROM_STDIN=1 reads an API token from standard input.
"""
import os
import sys
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
R = PolynomialRing(ZZ, 't')
t = R.gen()
def parse_group(identity):
family, size, prime = identity.split('-')
size, prime = int(size), int(prime)
if not ZZ(prime).is_prime():
raise ValueError('The characteristic must be prime')
if family == 'UT' and size >= 2:
return family, size, prime
if family == 'Heis' and size >= 1:
return family, size, prime
raise ValueError('Use UT-n-p with n >= 2 or Heis-r-p with r >= 1')
def jennings_degrees(identity):
family, size, prime = parse_group(identity)
if family == 'UT':
return prime, [(j, size-j) for j in range(1, size)]
return prime, [(1, 2*size), (2, 1)]
class AugmentationHilbert(numberdb.Generator):
table = 'T653'
parameters = ('G',)
files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md')
type = 'Z[]'
rigour = 'exact'
digits = 100 # ignored for exact polynomials
def enumerate(self):
for p in (2, 3, 5, 7):
for n in range(3, 7):
degree = (p-1)*n*(n*n-1)//6
if degree <= 80:
yield {'G': 'UT-%d-%d' % (n, p)}
for r in range(2, 5):
yield {'G': 'Heis-%d-%d' % (r, p)}
def value(self, params, digits=100):
identity = params['G']
family, size, p = parse_group(identity)
_, degrees = jennings_degrees(identity)
polynomial = R.one()
for weight, multiplicity in degrees:
factor = sum((t**(weight*k) for k in range(p)), R.zero())
polynomial *= factor**multiplicity
label = (r'$U_{%d}(\mathbb F_{%d})$' if family == 'UT'
else r'$\operatorname{Heis}_{%d}(\mathbb F_{%d})$') % (size, p)
entry = {'number': polynomial, 'param-latex': label}
if identity == 'UT-3-2':
entry['comment'] = (r'This group is the dihedral group of order $8$, '
r'also $\operatorname{Heis}_1(\mathbb F_2)$. Its Hilbert series '
r'equals the HREF{Poincaré_polynomials_of_the_finite_Coxeter_groups#B2}'
r'[Poincaré polynomial of the Coxeter group $B_2$].')
return entry
def main():
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
token = sys.stdin.read().strip()
if '=' in token and token.split('=', 1)[0].strip().isidentifier():
token = token.split('=', 1)[1].strip().strip('\"\'')
os.environ['NUMBERDB_API_KEY'] = token
generator = AugmentationHilbert()
if '--write' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Fill exact augmentation Hilbert series'))
else:
report = generator.verify(sample=None)
print(report)
if not report.ok:
raise SystemExit(1)
if __name__ == '__main__':
main()