back to table · edit · history · where entries came from · files · download
7685 bytes, as of the version from 2026-10-27 17:40 (current). Recorded here, not run.
"""Reproducible numerical checks for numberdb.org/T554.
Run: sage -python checks.py > numerical-evidence.json
Place generate.py in the same directory. If stored-document.json is present,
checks include every decimal read back from the database. These are builder
checks, not the campaign's independent critique.
Independent method: DLMF 5.12.3 with t=u^M, splitting at 1 and substituting
u=1/v in the infinite part, gives
B(a,b)=M*integral_0^1 (u^(M*a-1)+u^(M*b-1))/(1+u^M)^(a+b) du.
The selected M makes endpoint exponents nonnegative integers. mpmath evaluates
these smooth integrals without Gamma or beta functions at two precisions.
Euclidean r=n/B(1/n,1-2/n); ideal r=B(1/2+1/n,1/2)/B(1/2-1/n,1/2).
The quadrature checks are heuristic independent confirmations. Rigorous
100-digit enclosures come from the generator's Arb arithmetic, not quadrature.
"""
import json
import hashlib
import platform
from pathlib import Path
from decimal import Decimal
from fractions import Fraction
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.rings.real_mpfi import RealIntervalField
from sage.env import SAGE_VERSION
from numberdb._write import to_text
import mpmath as mp
from generate import InteriorConformalRadius
HERE=Path(__file__).resolve().parent
MANIFEST='agents/runs/20261027T171124Z-build-skills/manifest.json'
SKILL_HASH='e37efb7e2ededf6c1d7134c673f152f648f26e0267c556aebdf3ec65765d8b4c'
def rational(q):
return Fraction(int(q.numerator()), int(q.denominator()))
def bounds(ball):
v=RealIntervalField(ball.parent().precision())(ball)
return rational(v.lower().exact_rational()),rational(v.upper().exact_rational())
def written_bounds(s):
d=Decimal(s); centre=Fraction(d); ulp=Fraction(10)**d.as_tuple().exponent
return centre-ulp,centre+ulp
def as_mp(q):
return mp.mpf(q.numerator)/q.denominator
def beta_quadrature(a,b,M):
# a,b are Fraction, so integer endpoint exponents are checked exactly.
pa=M*a-1; pb=M*b-1
assert pa.denominator==pb.denominator==1 and min(pa,pb)>=0
exponent=as_mp(a+b)
f=lambda u:(u**int(pa)+u**int(pb))/(1+u**M)**exponent
return M*mp.quad(f,[0,mp.mpf(1)/2,1])
def independent(geometry,n):
a=Fraction(1,n); half=Fraction(1,2)
if geometry=='euclidean':
return n/beta_quadrature(a,1-2*a,n)
return beta_quadrature(half+a,half,2*n)/beta_quadrature(half-a,half,2*n)
def safe(ball,accuracy=400):
assert ball.is_finite() and ball>0
lo,hi=bounds(ball)
assert (hi-lo)/lo < Fraction(1,2**accuracy)
return lo,hi
def agm_bracket(x,y,R):
a=R(x); g=R(y)
for _ in range(12):
a,g=(a+g)/2,(a*g).sqrt()
lo=bounds(g)[0]; hi=bounds(a)[1]
assert hi>=lo and hi-lo < Fraction(1,10**160)
I=RealIntervalField(R.precision())
return R(I(QQ(lo.numerator)/lo.denominator,QQ(hi.numerator)/hi.denominator))
def main():
gen=InteriorConformalRadius(); balls={}; records=[]
for p in gen.enumerate():
key=(p['geometry'],int(p['n'])); b=gen.value(p,100); lo,hi=safe(b)
s=to_text(b,100); sl,sh=written_bounds(s)
assert sl<=lo<=hi<=sh
assert len(s.replace('.','').lstrip('0'))==100
balls[key]=b
records.append({'params':p,'number':s,'ball':str(b),'lower':str(lo),'upper':str(hi),'relative_accuracy_bits':int(b.accuracy()),'serialization_contains_ball':True})
R=RealBallField(600); pi=R.pi()
agm_control=agm_bracket(1,1,R); assert bounds(agm_control)[0]<=1<=bounds(agm_control)[1]
M=agm_bracket(1,R(2).sqrt()/2,R); K=pi/(2*M); safe(K,500)
square_checks={'euclidean':R(2).sqrt()/K,'ideal-hyperbolic':pi/(2*K*K)}
for geometry,expected in square_checks.items():
safe(expected,500); assert expected.overlaps(balls[(geometry,4)])
for n in range(3,31):
a=QQ(1)/n
area=R(n)/2*(2*pi/n).sin()
ratio=R(1-a).gamma()*R(QQ(1)/2+a).gamma()/(R(1+a).gamma()*R(QQ(1)/2-a).gamma())
expected=(R(2)**(4*a)*area*ratio/pi).sqrt();safe(expected,500)
assert expected.overlaps(balls[('euclidean',n)])
assert balls[('ideal-hyperbolic',n)] < balls[('euclidean',n)] < 1
controls=[];quadrature=[];quad_values={}
for dps in [130,170]:
with mp.workdps(dps):
cases=[(Fraction(1),Fraction(1),1,mp.mpf(1)),(Fraction(1,2),Fraction(1,2),2,mp.pi),(Fraction(1,3),Fraction(2,3),3,2*mp.pi/mp.sqrt(3))]
for a,b,M,known in cases:
actual=beta_quadrature(a,b,M);err=abs(actual-known)
assert mp.isfinite(actual) and err<mp.mpf(10)**(-dps+10)
controls.append({'dps':dps,'a':str(a),'b':str(b),'answer':mp.nstr(actual,30),'absolute_error':mp.nstr(err,8)})
for record in records:
p=record['params'];key=(p['geometry'],p['n'])
v=independent(*key);lo,hi=bounds(balls[key]);mid=(lo+hi)/2
err=abs(v-as_mp(mid))/abs(v)
assert mp.isfinite(v) and 0<v<1 and err<mp.mpf('1e-120')
sl,sh=written_bounds(record['number']);assert as_mp(sl)<v<as_mp(sh)
quadrature.append({'geometry':key[0],'n':key[1],'dps':dps,'value':mp.nstr(v,110),'relative_difference_from_arb_midpoint':mp.nstr(err,8)})
if dps==170:quad_values[key]=mp.nstr(v,170)
stored_path=HERE/'stored-document.json'; stored_report=None
if stored_path.exists():
doc=json.loads(stored_path.read_text()); nums=doc['Numbers'];seen=[];stored_balls={}
for geometry,group in nums.items():
for n,entry in group.items():
key=(geometry,int(n));s=entry['number'] if isinstance(entry,dict) else entry
sl,sh=written_bounds(s);lo,hi=bounds(balls[key]);assert sl<=lo<=hi<=sh
I=RealIntervalField(600)
sb=R(I(QQ(sl.numerator)/sl.denominator,QQ(sh.numerator)/sh.denominator))
safe(sb,320);stored_balls[key]=sb
with mp.workdps(180):
v=mp.mpf(quad_values[key]);assert as_mp(sl)<v<as_mp(sh)
seen.append(key)
assert seen==list(balls)
for n in range(3,31):
area=R(n)/2*(2*pi/n).sin()
rhs=R(2)**(QQ(4)/n)*area*stored_balls[('ideal-hyperbolic',n)]/pi
lo,hi=bounds(stored_balls[('euclidean',n)]**2-rhs); assert lo<=0<=hi
for geometry,expected in square_checks.items():
assert expected.overlaps(stored_balls[(geometry,4)])
stored_report={'entries':len(seen),'ordered_enumeration_equal':True,'all_serialized_intervals_contain_arb_balls':True,'all_quadrature_values_inside_intervals':True,'cross_geometry_identity_count':28,'square_agm_checks':2,'document_sha256':hashlib.sha256(stored_path.read_bytes()).hexdigest()}
result={'table':'T554','instruction_manifest':MANIFEST,'skill_sha256':{'local':SKILL_HASH,'live':SKILL_HASH},'versions':{'sage':SAGE_VERSION,'numberdb':numberdb.__version__,'mpmath':mp.__version__,'python':platform.python_version()},'working_bits':numberdb.bits(100,losing=128),'digits':100,'entry_count':len(records),'minimum_relative_accuracy_bits':min(r['relative_accuracy_bits'] for r in records),'longest_serialized_value':max(len(r['number']) for r in records),'serialized_entries_bytes':len(json.dumps([{'params':r['params'],'number':r['number']} for r in records]).encode()),'arb_serialization_checks':56,'BHS_equation_1_5_checks':28,'strict_geometry_order_checks':28,'square_agm_checks':2,'agm_control':'AGM(1,1)=1','quadrature_controls':controls,'quadrature':quadrature,'records':records,'stored_checks':stored_report}
print(json.dumps(result,indent=2))
if __name__=='__main__':main()