generate.py

back to table · edit · history · where entries came from · files · download

3280 bytes, as of the version from 2026-10-29 08:32 (current). Recorded here, not run.

"""Neumann spectral determinants of Laplacians on hemispheres -- numberdb.org/T604.

Run with SageMath and numberdb (sage -pip install numberdb):
    sage -python generate.py             # verify every stored entry
    sage -python generate.py --fill      # fill the existing draft only
Download finite_formulas.py alongside this file. --fill requires
NUMBERDB_API_KEY and does not publish, offer, or review a draft.

The radius-one, unshifted scalar Neumann Laplacian has positive eigenvalues
k(k+d-1), multiplicity binomial(k+d-1,d-1), k>=1. Its single constant zero
mode is omitted. Equatorial reflection splits the full sphere spectrum into
Dirichlet and Neumann sectors. Therefore L_N = L_sphere - L_D, recomputed
from the finite formulas of Cunha and Freitas, Theorems 2.7, 2.8 and 3.2.
This is additivity of spectral zeta functions, not multiplicativity under
factoring eigenvalues. All coefficients are exact; Arb encloses every step.

150 working decimal digits and a repeat at 200 are measured by checks.py.
The independent continuation of the Neumann spectrum includes an explicit
series remainder in a ball. See derivation.md and argument-selection.md.
"""
import os
import sys
from functools import lru_cache
import numberdb.sage as numberdb
from finite_formulas import sphere_logdet, dirichlet_logdet

MAX_DIMENSION = 20
WORKING_DIGITS = 150
EXTRA_DIGITS = 50


@lru_cache(None)
def logdet(d, working=WORKING_DIGITS):
    if not isinstance(d, int) or d < 1:
        raise ValueError('dimension must be a positive integer')
    result = sphere_logdet(d, working)-dirichlet_logdet(d, working)
    assert result.is_finite()
    return result


class HemisphereNeumann(numberdb.Generator):
    table = 'T604'
    parameters = ('d', 'convention')
    type = 'R'
    digits = 100
    rigour = 'proven'
    files = ('generate.py', 'finite_formulas.py', 'independent.py', 'checks.py',
             'check.py', 'postfill.py', 'argument-selection.md', 'derivation.md',
             'skill-evidence.json', 'source-evidence.json', 'numerical-evidence.jsonl')

    def enumerate(self, max_dimension=MAX_DIMENSION):
        for d in range(1, max_dimension+1):
            for convention in ('det', 'logdet'):
                yield {'d': str(d), 'convention': convention}

    def value(self, params, digits):
        L = logdet(int(params['d']), max(WORKING_DIGITS, digits+EXTRA_DIGITS))
        if params['convention'] == 'det':
            result = L.exp()
        elif params['convention'] == 'logdet':
            result = L
        else:
            raise ValueError('unknown convention')
        assert result.is_finite() and result.accuracy() > numberdb.bits(digits+10)
        return result


if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        raw = sys.stdin.read().strip()
        if raw.startswith('NUMBERDB_') and '=' in raw:
            raw = raw.split('=', 1)[1].strip().strip('\"\'')
        os.environ['NUMBERDB_API_KEY'] = raw
    generator = HemisphereNeumann()
    if '--fill' in sys.argv:
        print(generator.publish(message='Enclose Neumann hemisphere determinants in dimensions 1 through 20'))
    else:
        report = generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)