back to table · edit · history · where entries came from · files · download
3327 bytes, as of the version from 2026-10-26 21:52 (current). Recorded here, not run.
"""Moments of the positive-part Brownian bridge area -- numberdb.org/T529.
Run with SageMath (or a suitable passagemath installation):
sage -pip install numberdb
sage -python generate.py # verify all stored entries
sage -python generate.py --fill # fill an authorized draft
Set NUMBERDB_API_KEY to read or fill a private draft. In the campaign,
NUMBERDB_KEY_FROM_STDIN=1 reads that key from stdin and NUMBERDB_PUBLISH=1
selects --fill. Filling entries does not offer or publish the table.
The centered bridge has covariance min(s,t)-st on [0,1], and the area is
integral max(b(t),0) dt. Only raw moments of orders 1 through 12 are selected.
The rational recurrences are Janson (2007), equations (7), (240), (245).
See argument-selection.md for the selection and derivation.md for checks.
At 100 digits the 180 guard bits give 513 working bits; checks.py measures
a minimum relative accuracy of 509 bits and verifies the final decimal interval, not just its center.
"""
import os
import sys
from math import factorial
from functools import lru_cache
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
MAX_ORDER = 12
WORKING_GUARD = 180
@lru_cache(maxsize=None)
def coefficients(order):
"""Exact K_n and P_n=D_n^+ through the requested order."""
k = [QQ(-1)/QQ(2)]
p = [QQ(1)]
for n in range(1, order+1):
k.append(QQ(3*n-4)/QQ(4)*k[n-1]
+ sum((k[j]*k[n-j] for j in range(1,n)), QQ(0)))
p.append(sum((k[j]*p[n-j] for j in range(1,n+1)), QQ(0)))
return tuple(k), tuple(p)
def rational_factor(n):
"""M_n, with sqrt(pi/2) removed when n is odd."""
if n < 0:
raise ValueError('The moment order must be nonnegative')
p = coefficients(n)[1][n]
m = n//2
if n % 2:
return QQ(factorial(n))*p / QQ(2**m*factorial(3*m+1))
return QQ(factorial(n)*4**(3*m)*factorial(3*m))*p / QQ(2**m*factorial(6*m))
class PositiveBridgeMoments(numberdb.Generator):
table = 'T529'
parameters = ('n',)
type = 'R'
digits = 100
rigour = 'proven'
files = ('generate.py', 'checks.py', 'check.py', 'argument-selection.md',
'derivation.md', 'numerical-evidence.json', 'skill-manifest.json',
'skill-read-evidence.json')
def enumerate(self, max_order=MAX_ORDER):
for n in range(1, max_order+1):
yield {'n': str(n)}
def value(self, params, digits):
n = int(params['n'])
if n < 1:
raise ValueError('Stored moment orders are positive')
q = rational_factor(n)
if n % 2 == 0:
return q
r = RealBallField(numberdb.bits(digits, losing=WORKING_GUARD))
return r(q)*(r.pi()/r(2)).sqrt()
if __name__ == '__main__':
if os.environ.get('NUMBERDB_KEY_FROM_STDIN') == '1':
numberdb.configure(api_key=sys.stdin.read().strip())
generator = PositiveBridgeMoments()
if '--fill' in sys.argv or os.environ.get('NUMBERDB_PUBLISH') == '1':
result = generator.publish(message='fill twelve independently checked positive-bridge moments')
print(result)
print('run:', result.run)
else:
result = generator.verify(sample=None)
print(result)
sys.exit(0 if result.ok else 1)