back to table · edit · history · where entries came from · files · download
3966 bytes, as of the version from 2026-10-26 08:15 (current). Recorded here, not run.
"""Multiple zeta values of length 5 -- numberdb.org/T508.
Run with SageMath (or passagemath with its modular multiple-zeta module):
sage -pip install numberdb
sage -python generate.py # verify every stored entry
sage -python checks.py # independent checks, no API writes
sage -python generate.py --fill # fill with NUMBERDB_API_KEY set
The five parameters use descending summation indices. Sage's multiple-zeta
indices are reversed. All admissible length-five indices of weight <= 12 are
included. The two PARI caches are explicitly recomputed at 150 and 200 decimal
working digits (plus 16 guard bits), rather than rounding one shared cache to
two precisions. Adapted from the published generator at numberdb.org/files/T465/generate.py.
The measured agreement and independent evidence are attached
in checks.py and build-evidence.json. Values are written to 100 significant
digits under the heuristic (agreement-checked) rigour level.
--fill writes entries to the existing table; it does not publish the draft.
"""
from functools import lru_cache
import os
import sys
import numberdb.sage as numberdb
from sage.modular.multiple_zeta import MultizetaValues
MAX_WEIGHT = 12
WORKING_DIGITS = (150, 200)
GUARD_BITS = 16
PARAMETERS = ('s1', 's2', 's3', 's4', 's5')
def indices(max_weight=MAX_WEIGHT):
"""Lexicographic order, with every admissible weight represented in full."""
def extend(prefix, remaining, slots):
if slots == 0:
yield prefix
return
minimum = 2 if not prefix else 1
for a in range(minimum, remaining - slots + 2):
yield from extend(prefix + (a,), remaining - a, slots - 1)
yield from extend((), max_weight, 5)
@lru_cache(maxsize=2)
def working_values(working):
"""A fresh PARI zetamultall computation at this working precision."""
precision = numberdb.bits(working, losing=GUARD_BITS)
cache = MultizetaValues()
cache.reset(max_weight=MAX_WEIGHT, prec=precision)
return {index: cache(tuple(reversed(index)), prec=precision)
for index in indices()}
class LengthFiveMZV(numberdb.Generator):
table = 'T508'
parameters = PARAMETERS
type = 'R'
digits = 100
rigour = 'heuristic (agreement-checked)'
files = ('generate.py', 'checks.py', 'check.py', 'build-evidence.json')
def enumerate(self):
for index in indices():
yield dict(zip(self.parameters, index))
def value(self, params, digits):
if digits > 100:
raise ValueError('This generator is validated for 100 stored digits.')
index = tuple(int(params[name]) for name in self.parameters)
value = numberdb.agreeing(
lambda working: str(working_values(working)[index]),
at=WORKING_DIGITS)
# Equalities are theorems, not numerical duplicate guesses.
annotations = {}
if index == (2, 1, 1, 1, 1):
annotations = {
'comment': r'Duality identifies this value with HREF{Values_of_the_Riemann_zeta_function_at_rational_numbers#6}[$\zeta(6)$].',
'equals': r'HREF{Values_of_the_Riemann_zeta_function_at_rational_numbers#6}[$\zeta(6)$]'}
elif index == (2, 2, 2, 2, 2):
annotations = {'comment': r'$\zeta(2,2,2,2,2)=\pi^{10}/11!$.'}
return {'number': value, **annotations}
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
key = sys.stdin.read().strip()
if '=' in key and key.split('=', 1)[0].isupper():
key = key.split('=', 1)[1].strip().strip('\'"')
numberdb.configure(api_key=key)
generator = LengthFiveMZV()
if '--fill' in sys.argv:
print(generator.publish(message='Fill 462 independently checked length-five multiple zeta values'))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)