back to table · edit · history · where entries came from · files · download
6948 bytes, as of the version from 2026-10-26 21:14. Recorded here, not run.
"""Independent checks for T528; run `sage -python checks.py` beside generate.py.
Checks do not fill, offer, review or publish a table. Set NUMBERDB_API_KEY
(or pipe a key with NUMBERDB_KEY_FROM_STDIN=1) to also check the private draft.
The source of the independent coefficient calculation is Janson (2007),
equations (62)--(65), from the generating function for graph enumeration.
"""
import os
import sys
import json
from math import factorial, comb
from fractions import Fraction
from itertools import combinations
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from numberdb._write import to_text
from numberdb._generate import _stored_entries
from check import exactness, measure, agrees_with, names_its_rings
from generate import WrightConstants, rational_factor, k_coefficients
def graph_coefficients(limit):
# E(z)=sum e_r z^r; C(z)=log E(z). Implement E*C'=E' exactly.
e = [QQ(factorial(6*r)) / (QQ(2)**(5*r) * QQ(3)**(2*r)
* QQ(factorial(3*r)) * QQ(factorial(2*r))) for r in range(limit+1)]
c = [QQ(0)]
for r in range(1, limit+1):
c.append(e[r] - sum((j*c[j]*e[r-j] for j in range(1,r)), QQ(0))/QQ(r))
return e,c
def independent_factor(k,c):
# Equation (34), simplified independently using Gamma(3*k/2).
if k == 0:
return QQ(1)/4
if k % 2 == 0:
m=k//2
return c[k] / (QQ(2)**(3*m) * QQ(factorial(3*m-1)))
m=(k-1)//2
return c[k] * QQ(2)**(3*m+1)*QQ(factorial(3*m+1))/QQ(factorial(6*m+2))
def decimal_interval(text):
# Exact endpoints of NumberDB's one-unit-in-the-last-place convention.
mantissa,_,exponent=text.lower().partition('e')
exponent=int(exponent or 0)
places=len(mantissa.partition('.')[2])
ulp=QQ(10)**(exponent-places)
center=QQ(Fraction(text).numerator)/QQ(Fraction(text).denominator)
return center-ulp,center+ulp
def contained(text,ball):
lo,hi=decimal_interval(text)
R=ball.parent()
assert ball.is_finite() and ball.accuracy() >= 450
assert R(lo) < ball and ball < R(hi), (text,str(ball))
def small_graph_controls():
# Independently count labelled simple graphs by all edge subsets through n=5.
counts={}
for n in range(2,6):
edges=list(combinations(range(n),2)); by_edges={}
for mask in range(1 << len(edges)):
neighbours=[set() for _ in range(n)]
m=0
for j,(a,b) in enumerate(edges):
if mask & (1<<j):
neighbours[a].add(b);neighbours[b].add(a);m+=1
reached={0}; frontier=[0]
while frontier:
for v in neighbours[frontier.pop()]-reached:
reached.add(v);frontier.append(v)
if len(reached)==n:by_edges[m]=by_edges.get(m,0)+1
assert by_edges.get(n-1,0)==n**(n-2) # Cayley control first.
if n>=3:
unicyclic=QQ(factorial(n-1))/2*sum((QQ(n)**j/QQ(factorial(j)) for j in range(n-2)),QQ(0))
assert by_edges[n]==unicyclic
counts[str(n)]=by_edges
return counts
def main():
if os.environ.get('NUMBERDB_KEY_FROM_STDIN')=='1':
key=sys.stdin.read().strip()
if '=' in key and key.split('=',1)[0].isupper():key=key.split('=',1)[1].strip().strip('\'"')
os.environ['NUMBERDB_API_KEY']=key
controls=small_graph_controls()
e,c=graph_coefficients(11)
assert e[1]==QQ(5)/24 and e[2]==QQ(385)/1152 and c[1]==QQ(5)/24
assert independent_factor(0,c)==QQ(1)/4
assert independent_factor(1,c)==QQ(5)/24
assert independent_factor(2,c)==QQ(5)/256
assert independent_factor(3,c)==QQ(221)/24192
factors={k:rational_factor(k) for k in range(12)}
assert not agrees_with(factors,lambda k:independent_factor(k,c))
# Check the displayed sigma recurrence across every required coefficient.
K=k_coefficients(12);sigma={k:QQ(2)**(k+1)*K[k+1] for k in range(-1,12)}
for k in range(-1,11):
assert sigma[k+1]==QQ(3*k+2)/2*sigma[k]+sum((sigma[j]*sigma[k-j] for j in range(k+1)),QQ(0))
gen=WrightConstants();values={int(p['k']):gen.value(p,100) for p in gen.enumerate()}
assert not exactness(values) and not names_its_rings(__file__.replace('checks.py','generate.py'))
R=RealBallField(640);sqrt2pi=(2*R.pi()).sqrt()
rows=[]
for k,value in values.items():
text=to_text(value,digits=100)
independent=R(independent_factor(k,c))*(sqrt2pi if k%2==0 else 1)
if k%2:
assert text==str(independent_factor(k,c)) and value in QQ
else:
contained(text,value);contained(text,independent)
# Direct Gamma form avoids both parity simplifications.
general=R(2)**(QQ(1-3*k)/2)*R.pi().sqrt()*R(sigma[k])/R(QQ(3*k)/2+1).gamma()
assert general.is_finite() and general.accuracy()>600
contained(text,general)
# Check the public Programs formula at every index, including rational rows.
program_value=R(2)**(QQ(3-k)/2)*R.pi().sqrt()*R(K[k+1])/R(QQ(3*k+2)/2).gamma()
assert program_value.is_finite() and program_value.accuracy()>600
assert program_value.overlaps(independent)
rows.append({'k':k,'factor':str(factors[k]),'number':text,
'accuracy_bits':None if k%2 else int(value.accuracy()),
'radius':None if k%2 else str(value.rad())})
result={'controls':controls,'rows':rows,'measure_written':measure({r['k']:r['number'] for r in rows}),
'independent_coefficients':'12/12 exact matches','sigma_recurrence':'all required indices',
'manifest':'agents/runs/20261026T210447Z-build-skills/manifest.json',
'skill_sha256':'b4d51ded0d52cfe3dcc0859de0845c3879b0c2363273ba7e809a7e06ded40b18'}
if os.environ.get('NUMBERDB_API_KEY'):
doc=numberdb.table('T528')
records=_stored_entries(doc)
assert len(records)==12 and list(records)==[str(k) for k in range(12)]
for identity,text in records.items():
k=int(identity)
if k%2:assert QQ(text)==independent_factor(k,c)
else:contained(text,R(independent_factor(k,c))*sqrt2pi)
verification=gen.verify(sample=None)
assert verification.ok
result['stored_independent_checks']='12/12';result['verify']=str(verification)
excursion=_stored_entries(numberdb.table('T523'))
assert len(excursion)==12 and set(excursion)=={str(n) for n in range(1,13)}
for identity,text in excursion.items():
n=int(identity);k=n-1
expected=R(independent_factor(k,c))*factorial(n)*(sqrt2pi if k%2==0 else 1)
if k%2:assert QQ(text)==independent_factor(k,c)*factorial(n)
else:contained(text,expected)
result['stored_excursion_moment_identity']='12/12 at authenticated draft T523'
print(json.dumps(result,indent=2))
if __name__=='__main__':main()