back to table · edit · history · where entries came from · files · download
6966 bytes, as of the version from 2026-10-28 03:46 (current). Recorded here, not run.
"""Independent exact checks for T570 (sage -python checks.py).
The verifier reconstructs every even polynomial by interpolation at 21
half-integer Bessel orders. Its input is the elementary K recurrence, not
the product used in generate.py. K_(n+1/2)(z) = sqrt(pi/(2z))*exp(-z)*P_n(1/z),
where P_0=1, P_1=1+x and P_(n+1)=(2n+1)*x*P_n+P_(n-1).
Differentiating gives (1+x/2)*P_n+x^2*P_n'. Thus the coefficient of x^k
is b_k(n+1/2). Interpolation in t=nu^2 determines the degree <=20 polynomial.
Sources: DLMF 10.29.1 (with the modified cylinder-function convention),
10.39.2 and 10.49.12; NumberDB T116 and T199 fix the Bessel-polynomial
normalization. Local JSON snapshots of T116 and T569, when present, enable
cross-table readback checks. A snapshot T570.json enables stored-value checks.
No website writes occur. Run the same checks on all stored rows after filling.
"""
import numberdb.sage as numberdb
from sage.rings.rational_field import QQ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from math import factorial
from pathlib import Path
import json
import platform
import importlib.metadata
from check import exactness, measure, agrees_with, names_its_rings
V = PolynomialRing(QQ, 'v')
v = V.gen()
X = PolynomialRing(QQ, 'x')
x = X.gen()
T = PolynomialRing(QQ, 't')
t = T.gen()
MAX_K = 20
def elementary_polynomials():
polynomials = [X.one(), 1+x]
for n in range(1, MAX_K):
polynomials.append((2*n+1)*x*polynomials[-1]+polynomials[-2])
return polynomials
def interpolate(nodes, values):
result = T.zero()
for i, node in enumerate(nodes):
basis = T.one()
denominator = QQ.one()
for j, other in enumerate(nodes):
if j != i:
basis *= t-other
denominator *= node-other
result += (QQ(values[i])/denominator)*basis
return result
def independent_values():
# Positive controls run before the reconstruction they validate.
P = elementary_polynomials()
assert P[:4] == [X(1), 1+x, 1+3*x+3*x**2,
1+6*x+15*x**2+15*x**3]
D = [(1+x/QQ(2))*p+x**2*p.derivative() for p in P]
assert D[0] == 1+x/QQ(2)
assert D[1] == 1+QQ(3)/QQ(2)*x+QQ(3)/QQ(2)*x**2
nodes = [(QQ(n)+QQ(1)/QQ(2))**2 for n in range(MAX_K+1)]
for power in (0, 1, 2):
assert interpolate(nodes, [node**power for node in nodes]) == t**power
reconstructed = {}
for k in range(MAX_K+1):
polynomial = interpolate(nodes, [d[k] for d in D])
assert polynomial.degree() == k
reconstructed[k] = V(polynomial(v**2))
return reconstructed, P, D
def check_values(values, reconstructed, P, D):
assert list(values) == list(range(MAX_K+1)), 'wrong extent or row order'
assert not exactness(values)
assert not agrees_with(values, lambda k: reconstructed[k])
assert values[0] == 1 and values[1] == v**2/QQ(2)+QQ(3)/QQ(8)
A = [V.one()]
for k in range(1, MAX_K+1):
A.append((4*v**2-(2*k-1)**2)*A[-1]/QQ(8*k))
for k, value in values.items():
assert value.degree() == 2*k
assert value(-v) == value
assert value.leading_coefficient() == QQ(1)/QQ(2**k*factorial(k))
assert value == (A[k](v-1)+A[k](v+1))/QQ(2)
if k:
assert value == A[k]+(QQ(k)-QQ(1)/QQ(2))*A[k-1]
for j in range(1, k):
root = QQ(j)-QQ(1)/QQ(2)
assert value(root) == 0 and value(-root) == 0
for n in range(MAX_K+1):
assert value(QQ(n)+QQ(1)/QQ(2)) == D[n][k]
# These generate the full polynomial in x whenever n+1 <= MAX_K.
for n in range(MAX_K):
assert X([values[k](QQ(n)+QQ(1)/QQ(2))
for k in range(MAX_K+1)]) == D[n]
assert [values[k](QQ(1)/QQ(2)) for k in range(MAX_K+1)] == [QQ(1),QQ(1)/QQ(2)]+[QQ(0)]*(MAX_K-1)
return {'interpolated_polynomials':len(values),
'half_integer_specializations':len(values)*len(P),
'half_integer_derivative_polynomial_identities':MAX_K,
'degree_evenness_leading_coefficient':'pass',
'half_integer_roots':'pass',
'two_relations_with_a_k':'pass'}
def snapshot_values(path, ring):
doc = json.loads(path.read_text())
records = doc['Numbers']
if isinstance(records, dict):
return {int(k):ring(value['number'] if isinstance(value,dict) else value)
for k,value in records.items()}
return {int(entry['params']['k']):ring(entry['number']) for entry in records}
def main():
from generate import HankelDerivative
directory = Path(__file__).resolve().parent
reconstructed,P,D = independent_values()
generator = HankelDerivative()
assert not names_its_rings(str(directory/'generate.py'))
values = {int(p['k']):generator.value(p,100) for p in generator.enumerate()}
result = {'table':'T570','checks':check_values(values,reconstructed,P,D),
'measurement':measure(values)}
corrupted = dict(values)
corrupted[20] += QQ(1)/QQ(10**20)
try:
check_values(corrupted,reconstructed,P,D)
except AssertionError:
result['deliberate_corruption_rejected'] = True
else:
raise AssertionError('the independent verifier accepted corrupted data')
if (directory/'T116.json').exists():
stored_P = snapshot_values(directory/'T116.json',X)
assert all(stored_P[n] == P[n] for n in range(MAX_K+1))
result['stored_T116_matches'] = MAX_K+1
if (directory/'T569.json').exists():
stored_A = snapshot_values(directory/'T569.json',V)
assert all(values[k] == (stored_A[k](v-1)+stored_A[k](v+1))/QQ(2)
for k in range(MAX_K+1))
assert all(values[k] == stored_A[k]+(QQ(k)-QQ(1)/QQ(2))*stored_A[k-1]
for k in range(1,MAX_K+1))
result['stored_T569_relations'] = {'shift_identity':MAX_K+1,'derivative_identity':MAX_K}
if (directory/'T570.json').exists():
stored = snapshot_values(directory/'T570.json',V)
result['stored_T570_checks'] = check_values(stored,reconstructed,P,D)
assert stored == values
document=json.loads((directory/'T570.json').read_text())
namespace={}
exec(document['Programs']['program-sage']['code'],namespace)
assert namespace['values'] == list(stored.values())
result['stored_program_matches_all_entries'] = True
result['versions'] = {'python':platform.python_version()}
for package in ('numberdb','passagemath-standard','passagemath-symbolics'):
try:result['versions'][package]=importlib.metadata.version(package)
except importlib.metadata.PackageNotFoundError:pass
try:
from sage.version import version
result['versions']['sage'] = version
except ImportError:pass
print(json.dumps(result,indent=2))
print('VALUES_JSON '+json.dumps({str(k):str(value) for k,value in values.items()}))
if __name__ == '__main__':
main()