back to table · edit · history · where entries came from · files · download
7349 bytes, as of the version from 2026-10-27 16:59 (current). Recorded here, not run.
"""Independent numerical checks for numberdb.org/T553.
Run `sage -python checks.py`; add --stored to check the website's actual rows.
The unpublished draft needs NUMBERDB_API_KEY. Dependencies: generate.py and
check.py (the campaign's unmodified check helpers), SageMath and mpmath.
The generator evaluates a Gamma quotient with Arb. Independent paths:
(1) the area-normalized formula, Solynin--Zalgaller (2004), eq. (1.2),
implemented directly with 600-bit Arb;
(2) Schwarz--Christoffel boundary length, using mpmath quadrature with no
Gamma evaluations, at 130 and 170 decimal digits;
(3) the square via a manually iterated AGM, with a certified bracket.
For (2), F'(w)=c*(1-w**(-n))**(2/n), branch tending to c at infinity.
The side length 2*sin(pi/n) is c times the arc integral of |F'|/c, hence
c=n*sin(pi/n)/(2**(1+2/n)*int_0^(pi/2) sin(t)**(2/n) dt).
See Batista (2026), J. Engineering Mathematics 160, 8, sec. 3.2.1, eq. (46),
https://doi.org/10.1007/s10665-026-10553-z. Controls are the exact integrals
int_0^(pi/2) 1 dt=pi/2 and int_0^(pi/2) sin(t) dt=1, run first at each precision.
Quadrature is an independent agreement check, not the certified error bound.
The certified bound comes from Arb and exact containment of serialized values.
Policy manifest: agents/runs/20261027T162618Z-build-skills/manifest.json.
Both archived skills: e37efb7e2ededf6c1d7134c673f152f648f26e0267c556aebdf3ec65765d8b4c.
"""
import json
import sys
from decimal import Decimal
from fractions import Fraction
import importlib.metadata
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.env import SAGE_VERSION
from numberdb._write import to_text
import mpmath as mp
from generate import PolygonCapacity
from check import exactness, measure, names_its_rings
def rational_decimal(text):
f = Fraction(text)
return QQ(f.numerator) / QQ(f.denominator)
def decimal_interval(text):
d = Decimal(text)
centre = rational_decimal(text)
ulp = QQ(10)**int(d.as_tuple().exponent)
return centre-ulp, centre+ulp, ulp
def source_formula(n):
R = RealBallField(600)
a = QQ(1)/QQ(n)
theta = R.pi()*R(a)
area = R(n)*(2*theta).sin()/2
ratio = R(n)*theta.tan()*R(1+a).gamma()**2
ratio /= R.pi()*R(2)**R(4*a)*R(QQ(1)/2+a).gamma()**2
return (area*ratio).sqrt()
def agm_square():
R=RealBallField(600)
# The AGM of (1,1) is exactly 1; this checks the recurrence's control.
a=b=R(1)
for _ in range(12):
a,b=(a+b)/2,(a*b).sqrt()
assert 1 in a and 1 in b
a,b=R(1),1/R(2).sqrt()
for _ in range(12):
a,b=(a+b)/2,(a*b).sqrt()
# The true AGM lies between each geometric and arithmetic iterate.
lo,hi=QQ(b.lower()),QQ(a.upper())
assert 0 < hi-lo < QQ(1)/10**170
bracket=R((lo+hi)/2,(hi-lo)/2)
answer=1/(R(2).sqrt()*bracket)
assert answer.is_finite() and QQ(answer.rad()) < QQ(1)/10**170
return answer
def quadratures():
outputs={}
controls={}
for dps in (130,170):
with mp.workdps(dps):
c0=mp.quad(lambda t: mp.mpf(1), [0,mp.pi/2])
c1=mp.quad(lambda t: mp.sin(t), [0,mp.pi/2])
error=max(abs(c0-mp.pi/2),abs(c1-1))
assert error < mp.mpf(10)**(-dps+10)
controls[str(dps)]=mp.nstr(error,8)
outputs[dps]={}
for n in range(3,31):
power=mp.mpf(2)/n
integral=mp.quad(lambda t: mp.sin(t)**power,[0,mp.pi/4,mp.pi/2])
value=n*mp.sin(mp.pi/n)/(mp.power(2,1+power)*integral)
assert mp.isfinite(value) and value>0
outputs[dps][n]=mp.nstr(value,dps-5)
return outputs,controls
def stored_numbers(client=None):
# check.stored needs Django and a database; this build uses the public API.
document=numberdb.table('T553',client=client)
block=document['Numbers']
if isinstance(block,list):
return {int(r['params']['n']):r['number'] for r in block}
return {int(n):(v['number'] if isinstance(v,dict) else v) for n,v in block.items()}
def run(stored=False,client=None):
gen=PolygonCapacity()
assert not names_its_rings(__file__.replace('checks.py','generate.py'))
params=list(gen.enumerate())
assert params==[{'n':n} for n in range(3,31)]
values={p['n']:gen.value(p,100) for p in params}
assert not exactness(values)
texts=stored_numbers(client) if stored else {n:to_text(v,digits=100) for n,v in values.items()}
assert list(texts)==list(range(3,31))
quadrature,controls=quadratures()
square=agm_square()
rows=[]
worst_agreement=QQ(0)
for n,v in values.items():
lo,hi,ulp=decimal_interval(texts[n])
assert hi-lo == 2*ulp
assert lo <= QQ(v.lower()) and QQ(v.upper()) <= hi
alt=source_formula(n)
assert alt.is_finite() and QQ(alt.rad())<QQ(1)/10**170
assert v.overlaps(alt)
assert lo <= QQ(alt.lower()) and QQ(alt.upper()) <= hi
R=v.parent()
assert v > (R.pi()/n).cos() and v < 1
q1=rational_decimal(quadrature[130][n]);q2=rational_decimal(quadrature[170][n])
difference=abs(q1-q2)
assert difference < QQ(1)/10**120
# Independent heuristic approximation is far inside the written interval.
assert lo < q1 < hi and lo < q2 < hi
assert abs(q2-QQ(v.mid()))<QQ(1)/10**130
if n==4:
assert v.overlaps(square)
assert lo <= QQ(square.lower()) and QQ(square.upper()) <= hi
# Relative error bounded by 2**(-bits), using exact rational comparisons.
bits=0
radius=QQ(v.rad())
lower=QQ(v.lower())
while radius*2**(bits+1) < lower:
bits+=1
worst_agreement=max(worst_agreement,difference)
rows.append({'n':n,'number':texts[n],'radius_upper':str(v.rad()),
'certified_relative_bits_at_least':bits,
'source_formula_and_serialization':'pass',
'quadrature_130':quadrature[130][n],
'quadrature_170':quadrature[170][n]})
output={'table':'T553','stored_readback':stored,'entries':len(rows),
'working_bits':numberdb.bits(100,losing=128),
'minimum_relative_accuracy_bits':min(r['certified_relative_bits_at_least'] for r in rows),
'serialization':'All Arb bounds and independent values lie inside decimal +/- one ulp.',
'quadrature_controls_absolute_errors':controls,
'quadrature_130_170_max_difference':str(RealBallField(80)(worst_agreement)),
'square_agm':'pass; bracket width < 1e-170; (1,1) control passed',
'geometric_disk_bounds':'pass on all 28 entries',
'measure_serialized':measure(texts),
'versions':{'sage':SAGE_VERSION,'numberdb':importlib.metadata.version('numberdb'),'mpmath':mp.__version__},
'policy_manifest':'agents/runs/20261027T162618Z-build-skills/manifest.json',
'skill_local_sha256':'e37efb7e2ededf6c1d7134c673f152f648f26e0267c556aebdf3ec65765d8b4c',
'skill_live_sha256':'e37efb7e2ededf6c1d7134c673f152f648f26e0267c556aebdf3ec65765d8b4c',
'rows':rows}
return output
if __name__=='__main__':
print(json.dumps(run(stored='--stored' in sys.argv),indent=2))