back to table · edit · history · where entries came from · files · download
3511 bytes, as of the version from 2026-10-26 23:00. Recorded here, not run.
"""Airy zeta values -- numberdb.org/T531.
Run with SageMath (or compatible passagemath) and numberdb installed:
sage -python generate.py # verify all stored entries, read only
sage -python generate.py --fill # fill this draft, with NUMBERDB_API_KEY
In the campaign use agents/sage.sh; NUMBERDB_KEY_FROM_STDIN=1 reads the key
from stdin, and NUMBERDB_PUBLISH=1 is the wrapper's entry-fill switch.
Neither entry-fill route publishes or offers the draft.
Z_D(n) = sum_k (-a_k)^(-n), where a_k are the negative Ai zeros.
Default selection: every integer 2 <= n <= 20. See argument-selection.md.
The genus-one product gives Ai'(z)/Ai(z) = -kappa +
sum_{n>=2} (-1)^(n-1) Z_D(n) z^(n-1). The Riccati equation q'=z-q^2
computes each coefficient as an exact polynomial over QQ in kappa.
Evaluate these polynomials in Arb balls with kappa =
3^(1/3) Gamma(2/3)/Gamma(1/3); all arguments are exact rationals.
The 96-bit guard is measured over the full selection by checks.py.
No roots are truncated and no analytic continuation is used for these values.
"""
import os
import sys
from functools import lru_cache
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
WORKING_GUARD = 96
MAX_ORDER = 20
@lru_cache(maxsize=None)
def zeta_polynomials(max_order):
"""Exact rational polynomials P_n(X) with Z_D(n)=P_n(kappa)."""
ring = PolynomialRing(QQ, 'X')
x = ring.gen()
q = [-x]
for m in range(max_order - 1):
rhs = ring(1 if m == 1 else 0)
rhs -= sum((q[j] * q[m-j] for j in range(m+1)), ring.zero())
q.append(rhs * (QQ(1) / QQ(m+1)))
return {n: (-1)**(n-1) * q[n-1] for n in range(2, max_order+1)}
def kappa_ball(precision):
field = RealBallField(precision)
return (field(3)**(QQ(1)/QQ(3)) * field(QQ(2)/QQ(3)).gamma()
/ field(QQ(1)/QQ(3)).gamma())
def evaluate(n, precision):
value = zeta_polynomials(n)[n](kappa_ball(precision))
if not value.is_finite() or not value > 0:
raise ArithmeticError('Airy zeta must be a finite positive ball')
return value
class AiryZeta(numberdb.Generator):
table = 'T531'
parameters = ('n',)
type = 'R'
digits = 100
rigour = 'proven'
files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md',
'numerical-evidence.md', 'numerical-evidence.json', 'skill-manifest.json')
def enumerate(self, max_order=MAX_ORDER):
for n in range(2, max_order+1):
yield {'n': str(n)}
def value(self, params, digits):
n = int(params['n'])
if n < 2:
raise ValueError('The unregularized sum requires n >= 2')
return evaluate(n, numberdb.bits(digits, losing=WORKING_GUARD))
def main():
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
token = sys.stdin.read().strip()
if token.startswith('NUMBERDB_') and '=' in token:
token = token.split('=', 1)[1].strip().strip('\"\'')
os.environ['NUMBERDB_API_KEY'] = token
generator = AiryZeta()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
outcome = generator.publish(message='Add nineteen certified Airy spectral moments at 100 digits')
print(outcome)
report = generator.verify(sample=None)
print(report)
return 0 if report.ok else 1
if __name__ == '__main__':
sys.exit(main())