back to table · edit · history · where entries came from · files · download
4095 bytes, as of the version from 2026-10-25 06:53 (current). Recorded here, not run.
"""Reproduce and check the eight measured rows of numberdb.org/T476.
Run with SageMath and numberdb installed:
sage -python repair_checks.py < api-key-file
For a public table, run without redirected input. No writes are performed.
This reproduces a transcription, not the Monte Carlo simulations. SOURCE
is independently read from Table III (page 15) of arXiv:1004.4983v3.
EARLIER uses Table 1 (page 6) of arXiv:cond-mat/0201180 and equations
(45)-(46) (page 22) of arXiv:hep-lat/9701007. All arithmetic is exact.
The printed uncertainties remain measurements, not proven bounds.
"""
import json
import re
import sys
from importlib.metadata import version
import numberdb.sage as numberdb
# Sage rational coercion inspects this module even for exact arithmetic.
import sage.rings.real_mpfr
from sage.rings.rational_field import QQ
from sage.version import version as sage_version
SOURCE = {
'U0': '0.536(2)', 'U2': '4.713(7)', 'Uxi': '1.939(5)',
'Qxi-minus': '1.020(5)', 'Q-plus': '0.01899(10)',
'Q-minus': '0.00487(2)', 'u-star': '14.08(5)', 'Qc': '0.3293(2)',
}
EARLIER = {
'U0': '0.532(3)', 'U2': '4.76(2)', 'Uxi': '1.956(7)',
'Qxi-minus': '1.017(7)', 'Q-plus': '0.01880(8)',
'Q-minus': '0.00472(5)', 'u-star': '14.3(1)', 'Qc': '0.3315(10)',
}
def decimal(text):
whole, frac = text.split('.')
return QQ(int(whole + frac)) / QQ(10 ** len(frac))
def published(text):
match = re.fullmatch(r'(\d+\.\d+)\((\d+)\)', text)
assert match, text
centre, error = match.groups()
return decimal(centre), QQ(int(error)) / QQ(10 ** len(centre.split('.')[1]))
def stored(text):
centre, radius = text.split(' +/- ')
return decimal(centre), decimal(radius)
def generate_rows():
"""Yield the exact printed centre and radius, with the source's precision."""
for name, text in SOURCE.items():
centre, error = re.fullmatch(r'(\d+\.\d+)\((\d+)\)', text).groups()
places = len(centre.split('.')[1])
radius = '0.' + error.zfill(places)
yield name, centre + ' +/- ' + radius
def disjoint(a, b):
return abs(a[0] - b[0]) > a[1] + b[1]
def check(document):
# Known positive and negative controls establish the parsing and comparison.
assert published('0.01899(10)') == (QQ(1899)/100000, QQ(1)/10000)
assert stored('0.01899 +/- 0.00010') == published('0.01899(10)')
assert not disjoint((QQ(1), QQ(1)/10), (QQ(1), QQ(1)/20))
assert disjoint((QQ(1), QQ(1)/10), (QQ(2), QQ(1)/20))
assert published('0.01899(10)') != stored('0.01899 +/- 0.00001')
assert list(document['Numbers']) == list(SOURCE)
assert document['Data properties']['rigour'] == 'measured'
results = {}
for name, number in generate_rows():
entry = document['Numbers'][name]
now = stored(entry['number'])
assert now == published(SOURCE[name]) == stored(number), name
assert 'CITE{Hasenbusch2010}' in entry['comment'], name
earlier = published(EARLIER[name])
distance_squared = (now[0] - earlier[0])**2 / (now[1]**2 + earlier[1]**2)
assert distance_squared < 9, name
results[name] = {
'source_transcription_matches': True,
'reproduced_number': number,
'earlier_source': ('CaselleHasenbusch1997' if name in ('Qxi-minus', 'u-star') else 'Campostrini2002'),
'quoted_intervals_disjoint': bool(disjoint(now, earlier)),
'separation_squared_in_combined_error_units': str(distance_squared),
}
actual = {name for name, row in results.items() if row['quoted_intervals_disjoint']}
assert actual == {'U2', 'Uxi', 'Q-plus', 'Q-minus', 'u-star', 'Qc'}
return {'tid': 'T476', 'checked': len(results), 'all_match': True,
'controls_passed': True, 'comparisons': results,
'versions': {'sage': sage_version, 'numberdb': version('numberdb')}}
if __name__ == '__main__':
key = sys.stdin.read().strip() if not sys.stdin.isatty() else ''
if key:
numberdb.configure(api_key=key)
print(json.dumps(check(numberdb.table('T476')), indent=2))