generate.py

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

2793 bytes, as of the version from 2026-10-27 06:27 (current). Recorded here, not run.

"""Neumann spectral determinants of homogeneous oscillators -- numberdb.org/T540.

Run with SageMath (install numberdb once with sage -pip install numberdb):
    sage -python generate.py            # verify every stored entry
    sage -python generate.py --publish  # fill this draft; NUMBERDB_API_KEY needed
    sage -python checks.py              # independent offline checks

Publishing entries fills an existing table; it does not publish or offer a draft.
The campaign wrapper also accepts NUMBERDB_KEY_FROM_STDIN=1 and NUMBERDB_PUBLISH=1.

Voros, Exercises in exact quantization, corrected preprint math-ph/0005029v2,
equation (136): nu=1/(N+2), D_N^+(0)=Gamma(1-nu)*nu^(nu-1/2)/sqrt(pi).
The exponent and every input are exact rationals; Arb propagates all errors.
At 100 digits, 96 guard bits give 429 working bits. checks.py measures the
retained accuracy and compares an independent boundary-value reconstruction.
The single discrete family index is N=1,...,12; see argument-selection.md.
"""
import os
import sys
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField

WORKING_GUARD = 96


class NeumannDeterminants(numberdb.Generator):
    table = 'T540'
    parameters = ('N',)
    type = 'R'
    digits = 100
    rigour = 'proven'
    files = ('generate.py', 'checks.py', 'argument-selection.md', 'check.py',
             'dry_run.py', 'skill-evidence.json', 'numerical-evidence.md')

    def enumerate(self, maximum=12):
        for degree in range(1, maximum + 1):
            yield {'N': str(degree)}

    def value(self, params, digits):
        degree = int(params['N'])
        if degree < 1:
            raise ValueError('The degree must be a positive integer.')
        nu = QQ(1) / (degree + 2)
        B = RealBallField(numberdb.bits(digits, losing=WORKING_GUARD))
        result = B(1-nu).gamma() * B(nu)**(nu-QQ(1)/2) / B.pi().sqrt()
        assert result.is_finite() and result > 0
        names = {1: 'Linear oscillator with a Neumann boundary.',
                 2: 'Harmonic oscillator with a Neumann boundary.',
                 4: 'Pure quartic oscillator with a Neumann boundary.'}
        if degree in names:
            return {'number': result, 'comment': names[degree]}
        return result


if __name__ == '__main__':
    if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
        os.environ['NUMBERDB_API_KEY'] = sys.stdin.read().strip()
    generator = NeumannDeterminants()
    if '--publish' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        print(generator.publish(message='Fill twelve Neumann determinants with certified 100-digit enclosures'))
    else:
        report = generator.verify(sample=None)
        print(report)
        sys.exit(0 if report.ok else 1)