back to table · edit · history · where entries came from · files · download
2706 bytes, as of the version from 2026-10-30 10:45 (current). Recorded here, not run.
"""Atiyah–Patodi–Singer rho invariants of lens spaces -- numberdb.org/T623.
Run with SageMath and the numberdb package:
sage -pip install numberdb
sage -python generate.py # verify every stored entry
sage -python generate.py --fill # fill the existing draft with a key
sage -python checks.py # independent local checks
For a private draft, set NUMBERDB_API_KEY or pipe its key on stdin with
NUMBERDB_KEY_FROM_STDIN=1. --fill writes entries and attachments; it does not
publish or offer the draft. The default selection is justified in
argument-selection.md. All values are exact rationals, with no rounding.
Toffoli (2022), Proposition 2.10, labels the character by zeta_p**(k*q).
Here u is the exponent on the quotient generator, so k = u*q**(-1) mod p.
The sawtooth is zero at integers. No realification or kernel correction is
made. Independent checks use weighted lattice points and 512-bit Arb balls.
"""
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from math import gcd
import os
import sys
def rho(p, q, u):
"""Exact complex rank-one APS rho, on the full character domain."""
p, q, u = int(p), int(q), int(u)
if p < 2 or not 1 <= q < p or gcd(p, q) != 1 or not 0 <= u < p:
raise ValueError('Require p>=2, 1<=q<p, gcd(p,q)=1, 0<=u<p')
k = (u * pow(q, -1, p)) % p
def saw(n):
residue = n % p
return QQ(0) if residue == 0 else QQ(residue)/QQ(p) - QQ(1)/QQ(2)
return -4*sum((saw(q*j) for j in range(1, k)), QQ(0)) - 2*saw(q*k)
class LensSpaceRho(numberdb.Generator):
table = 'T623'
parameters = ('p', 'q', 'u')
type = 'Q'
rigour = 'exact'
digits = 100
files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md',
'numerical-evidence.json', 'skill-manifest.json')
def enumerate(self, max_p=20):
for p in range(2, int(max_p)+1):
for q in range(1, p):
if gcd(p, q) == 1 and q <= pow(q, -1, p):
for u in range(1, p//2+1):
yield {'p': p, 'q': q, 'u': u}
def value(self, params, digits):
return rho(params['p'], params['q'], params['u'])
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()
generator = LensSpaceRho()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
print(generator.publish(message='Fill exact lens-space rho invariants after independent checks.'))
else:
report = generator.verify(sample=None)
print(report)
sys.exit(0 if report.ok else 1)