repair_checks.py

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

4257 bytes, as of the version from 2026-10-30 06:50 (current). Recorded here, not run.

"""Check T616's n=1 wording repair and the optional program-scope finding.

Run with SageMath after downloading these T616 attachments to one directory:
repair_checks.py, document-before.json, generate-before.py, generate.py, solver.py.
Run: sage -python repair_checks.py
The script writes no table; JSON evidence is printed on stdout.
"""
import ast, hashlib, json, sys
from fractions import Fraction
from math import factorial
from pathlib import Path
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.real_arb import RealBallField
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.symbolic.ring import SR
from sage.symbolic.constants import pi
from sage.functions.trig import sin, cos
from sage.env import SAGE_VERSION
from generate import PolytropicInertia
from solver import inertia
base=Path(__file__).resolve().parent
doc=json.loads((base/'document-before.json').read_text())
x=SR.var('x')
theta=sin(x)/x
residual=(theta.diff(x,2)+2*theta.diff(x)/x+theta).expand()
assert residual==0
P=PolynomialRing(QQ,'z'); z=P.gen()
series=sum(QQ((-1)**k)/factorial(2*k+1)*z**(2*k) for k in range(8))
assert series[0]==1 and series[1]==0 and 2*series[2]==-QQ(1)/3
assert series.truncate(8)==1-z*z/6+z**4/120-z**6/5040
assert (z*series.derivative(2)+2*series.derivative()+z*series).truncate(14)==0
mass_primitive=sin(x)-x*cos(x)
moment_primitive=-x**3*cos(x)+3*x*x*sin(x)+6*x*cos(x)-6*sin(x)
assert (mass_primitive.diff(x)-x*sin(x)).expand()==0
assert (moment_primitive.diff(x)-x**3*sin(x)).expand()==0
mu=(mass_primitive(x=pi)-mass_primitive(x=0)).expand()
J=(moment_primitive(x=pi)-moment_primitive(x=0)).expand()
assert (mu-pi).expand()==0
assert (J-(pi**3-6*pi)).expand()==0
assert (2*J/(3*mu*pi**2)-(QQ(2)/3-4/pi**2)).expand()==0
B=RealBallField(512)
v=B(2)/3-4/B.pi()**2
assert v.is_finite()
f=Fraction(doc['Numbers']['1']['number'])
center=QQ(f.numerator)/f.denominator
unit=QQ(1)/10**100
assert center-unit < QQ(v.lower()) <= QQ(v.upper()) < center+unit
assert QQ(v.rad()) < QQ(1)/10**150
g=PolytropicInertia()
assert [p['n'] for p in g.enumerate()]==list(doc['Numbers'])
result=g.value({'n':'1'},digits=100)
assert result['number'].is_finite() and result['number'].overlaps(v)
assert result['comment'].startswith('The analytic profile')
assert g.value({'n':'0'},digits=100)['number']==QQ(2)/5
rejections={}
for name, f in [('generator',lambda:g.value({'n':'1/3'},digits=100)),('solver',lambda:inertia('1/3'))]:
    try:
        f()
    except ValueError as error:
        rejections[name]=str(error)
    else:
        raise AssertionError(name+' unexpectedly accepted n=1/3')
# A one-literal correction leaves all computation, selections and guards identical.
old=(base/'generate-before.py').read_text()
new=(base/'generate.py').read_text()
assert new==old.replace('The linear profile','The analytic profile')
assert ast.dump(ast.parse(new.replace('The analytic profile','The linear profile')))==ast.dump(ast.parse(old))
print(json.dumps({'table':'T616','skill_manifest':'agents/runs/20261030T032655Z-repair-skills/manifest.json','skill_sha256':{'local':'28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199','live':'28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199'},'sage':SAGE_VERSION,'python':sys.version.split()[0],'checks':{'lane_emden_residual':str(residual),'theta_at_center':'1','theta_prime_at_center':'0','theta_second_at_center':'-1/3','central_taylor':str(series),'mass_integral':str(mu),'moment_integral':str(J),'closed_form':'2/3-4/pi^2','arb_bits':512,'arb_value':str(v),'arb_radius':str(v.rad()),'stored_100_digit_interval_contains_arb_ball':True,'enumeration_matches_all_ten_entries':True,'generator_n0_exact':True,'generator_n1_comment_correct':True,'only_generator_change_is_comment_literal':True,'n_third_rejections':rejections},'limitations':'No numerical values or selected arguments changed. Rechecked n=0 and n=1; did not rerun the other eight ODE integrations. No general-rational solver was added. All pi uncertainty is propagated by Arb.','files':{name:hashlib.sha256((base/name).read_bytes()).hexdigest() for name in ('generate-before.py','generate.py','solver.py','document-before.json','repair_checks.py')}},indent=2))