generate.py

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

2886 bytes, as of the version from 2026-10-28 03:22 (current). Recorded here, not run.

"""Hankel asymptotic coefficient polynomials a_k(nu) -- numberdb.org/T569.

Run with SageMath or passagemath and the numberdb Python package:
    sage -pip install numberdb
    sage -python generate.py                 # verify the stored draft
    sage -python generate.py --fill          # fill with NUMBERDB_API_KEY set
    sage -python checks.py                  # independent offline checks

For a private draft, verification also needs its author's API key.
NUMBERDB_KEY_FROM_STDIN=1 reads that key from stdin. NUMBERDB_PUBLISH=1
is the campaign wrapper's equivalent of --fill. Filling sends entries and
sources to the existing draft; it does not offer, review or publish it.

DLMF 10.17.1 fixes the normalization: no external sign or phase factor is
absorbed into these expanded rational polynomials. DLMF 10.40.2 places a_k
in K_nu(z) ~ sqrt(pi/(2z))*exp(-z)*sum(a_k(nu)/z^k).
The sole index is k >= 0, enumerated 0,...,20 by default. The order nu is
an unsampled indeterminate. See argument-selection.md for the extent.
All arithmetic is exact in QQ[v], where v denotes the mathematical nu.
The single-letter spelling is required by the NumberDB polynomial parser.
There is no decimal precision claim.
"""
import os
import sys
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing

R = PolynomialRing(QQ, 'v')
nu = R.gen()
MAX_K = 20


def hankel_coefficient(k):
    """Return a_k(nu) using exact rational arithmetic."""
    k = int(k)
    if k < 0:
        raise ValueError('k must be nonnegative')
    a = R.one()
    for j in range(1, k + 1):
        a *= (4 * nu**2 - (2*j - 1)**2) * (QQ(1) / QQ(8*j))
    return a


class HankelCoefficients(numberdb.Generator):
    table = 'T569'
    parameters = ('k',)
    type = 'Q[]'
    rigour = 'exact'
    files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md',
             'skill-evidence.json', 'numerical-evidence.json')

    def enumerate(self, max_k=MAX_K):
        for k in range(int(max_k) + 1):
            yield {'k': k}

    def value(self, params, digits):
        return hankel_coefficient(params['k'])


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].replace('_', '').isalnum():
            key = key.split('=', 1)[1].strip().strip('\"\'')
        os.environ['NUMBERDB_API_KEY'] = key
    generator = HankelCoefficients()
    if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
        print(generator.publish(message='Fill exact Hankel coefficient polynomials through k=20',
                                assisted_by=os.environ.get('NUMBERDB_ASSISTED_BY', '')))
    result = generator.verify(sample=None)
    print(result)
    sys.exit(0 if result.ok else 1)