checks.py

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

8554 bytes, as of the version from 2026-10-28 22:35 (current). Recorded here, not run.

"""Independent counting and numerical checks for numberdb.org/T592.

Run: sage -python checks.py. Requires adjacent generate.py and the campaign's
unmodified check.py. Set CHECK_STORED=1 to check an authenticated database read.
The counting checks are independent of row transfer: direct subsets for small
rectangles and an edge-parity transfer for the zero-field specialization.
"""
import sys,os,json,time
from collections import defaultdict
from math import comb
import numberdb.sage as numberdb
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
from sage.rings.complex_interval_field import ComplexIntervalField
from sage.rings.complex_arb import ComplexBallField
from numberdb._write import to_text
from numberdb._compare import _claim, _complex_parts
from fractions import Fraction
from sage.rings.real_mpfi import RealIntervalField
import generate as g
import check


def edges(m,n):
    # Vertex order is column-major; independent from the generator's row masks.
    return [(r*n+c,(r+1)*n+c) for r in range(m-1) for c in range(n)] + [(r*n+c,r*n+c+1) for r in range(m) for c in range(n-1)]


def brute(m,n):
    es=edges(m,n);result=defaultdict(int)
    for mask in range(1 << (m*n)):
        d=sum(((mask>>u)^(mask>>v))&1 for u,v in es)
        result[(mask.bit_count(),d)] += 1
    return dict(result)


def even_counts(m,n):
    """Edge-subset expansion with parity states, forgetting finished vertices."""
    es=sorted((min(u,v),max(u,v)) for u,v in edges(m,n))
    last={v:i for i,e in enumerate(es) for v in e}
    dp={(0,0):1}
    for i,(u,v) in enumerate(es):
        nxt=defaultdict(int);flip=(1<<u)|(1<<v)
        forget=sum(1<<w for w in (u,v) if last[w]==i)
        for (parity,k),count in dp.items():
            if parity & forget == 0:
                nxt[(parity,k)] += count
            other=parity ^ flip
            if other & forget == 0:
                nxt[(other,k+1)] += count
        dp=nxt
    assert all(parity==0 for parity,k in dp)
    return {k:c for (parity,k),c in dp.items()}


def product_roots(values,cb):
    coefficients=[cb(1)]
    for value,mult in values:
        for _ in range(mult):
            nxt=[cb(0)]*(len(coefficients)+1)
            for k,c in enumerate(coefficients):
                nxt[k] -= value*c
                nxt[k+1] += c
            coefficients=nxt
    return coefficients


def exact_written_contains(text,raw):
    parts=_complex_parts(text) or (text,'0')
    cb=ComplexBallField(700);r=cb(raw)
    rf=RealIntervalField(700)
    for part,component in zip(parts,(r.real(),r.imag())):
        centre,radius=_claim(part)
        centre=QQ(Fraction(centre));radius=QQ(Fraction(radius))
        lo,hi=map(QQ,rf(component).endpoints())
        assert centre-radius <= lo <= hi <= centre+radius


def written_ball(text,cb):
    parts=_complex_parts(text) or (text,'0')
    rf=RealIntervalField(cb.prec())
    components=[]
    for part in parts:
        centre,radius=_claim(part)
        centre=QQ(Fraction(centre));radius=QQ(Fraction(radius))
        components.append(rf(centre-radius,centre+radius))
    return cb(components[0],components[1])


def run(stored=None):
    t0=time.time();report={'rectangles':[]};allvalues={};data={}; min_bits=None;max_rad=0
    # Known-answer control for the independent even-subgraph algorithm.
    assert even_counts(2,2)=={0:1,4:1}
    assert brute(2,2)=={(0,0):1,(1,2):4,(2,2):4,(2,4):2,(3,2):4,(4,0):1}
    print('Controls: C4 cut counts and even-subgraph counts passed',flush=True)
    B=PolynomialRing(QQ,'b');b=B.gen()
    cb=ComplexBallField(700)
    exact_written_contains('1.00 + i * 0.00', cb(1))
    try:
        exact_written_contains('1.00 + i * 0.00', cb(2))
    except AssertionError:
        pass
    else:
        raise AssertionError('Containment control accepted 2 as 1.00')
    for m in range(2,7):
        for n in range(m,7):
            N=m*n;E=2*N-m-n;c=g.counts(m,n)
            data[f'{m},{n}']=[[k,d,v] for (k,d),v in sorted(c.items())]
            assert sum(c.values())==2**N
            assert all(sum(v for (kk,d),v in c.items() if kk==k)==comb(N,k) for k in range(N+1))
            assert {(k,d):v for (k,d),v in c.items() if d==0}=={(0,0):1,(N,0):1}
            assert all(c.get((N-k,d),0)==v for (k,d),v in c.items())
            if N<=16:
                assert not check.agrees_with({(m,n):c},lambda _: brute(m,n))
            # Independent even-subgraph expansion over all fifteen geometries.
            ec=even_counts(m,n)
            assert sum(ec.values())==2**(E-N+1)
            high=QQ(2)**(N-E)*sum((ZZ(v)*(1-b)**k*(1+b)**(E-k) for k,v in ec.items()),B(0))
            low=sum((ZZ(v)*b**d for (k,d),v in c.items()),B(0))
            assert high==low
            p=g.field_polynomial(m,n)
            assert p(1)==g.F(low(g.BC)) and p(0)==1
            roots=g.root_data(m,n); vals=[]
            for j,(x,y,mult) in enumerate(roots,1):
                raw=g.enclosed_root(m,n,j,100)[0]
                entry=g.LeeYangZeros().value({'m':m,'n':n,'j':j},100)
                allvalues[f'{m},{n},{j}']=entry
                text=to_text(raw,100)
                if stored is not None:
                    text=stored[(m,n,j)]
                # Parse the intervals actually written, not their midpoints.
                exact_written_contains(text,raw)
                value=written_ball(text,cb)
                assert value.real().is_finite() and value.imag().is_finite()
                assert cb(raw) in value
                assert 0 in p.change_ring(cb)(value)
                assert 1 in (value*value.conjugate()).real()
                vals.append((value,mult))
                if raw != -1:
                    for part in (raw.real(),raw.imag()):
                        assert part.is_finite() and part.rad() < QQ(1)/10**120
                        # A conservative relative accuracy bound, computed from
                        # the enclosing interval with exact rational endpoints.
                        iv=RealIntervalField(part.parent().prec())(part)
                        lo,hi=map(QQ,iv.endpoints())
                        if lo != hi and lo*hi>0:
                            relative=(hi-lo)/min(abs(lo),abs(hi))
                            bits=0
                            while relative < QQ(1)/(ZZ(2)**bits): bits+=1
                            min_bits=bits-1 if min_bits is None else min(min_bits,bits-1)
            assert sum(e for _,e in vals)==N
            assert all((roots[k][0],roots[k][1]) < (roots[k+1][0],roots[k+1][1]) for k in range(len(roots)-1))
            assert all(any(v.conjugate().overlaps(w) and e==f for w,f in vals) for v,e in vals)
            recon=product_roots(vals,cb)
            assert len(recon)==len(p.list())
            assert all(cb(exact) in enclosure for enclosure,exact in zip(recon,p.list()))
            assert all(enclosure.real().is_finite() and enclosure.imag().is_finite() and enclosure.real().rad() < QQ(1)/10**75 and enclosure.imag().rad() < QQ(1)/10**75 for enclosure in recon)
            report['rectangles'].append({'m':m,'n':n,'degree':N,'distinct_roots':len(roots),'multiplicities':[int(e) for _,_,e in roots],'brute_force':N<=16,'even_subgraph_check':True,'reconstruction':True})
            print('PASS',m,n,'roots',len(roots),'seconds',round(time.time()-t0,2),flush=True)
    assert not check.exactness(allvalues)
    assert not check.names_its_rings(g.__file__)
    report['minimum_relative_accuracy_bits']=min_bits
    report['minimum_relative_decimal_digits']=int(min_bits*0.301029995663981)
    report['measure_raw_balls']=check.measure(allvalues)
    written={k:{**v,'number':to_text(v['number'],100)} for k,v in allvalues.items()}
    report['measure_serialized']=check.measure(written)
    report['seconds']=time.time()-t0
    report['skill_manifest']='agents/runs/20261028T215936Z-build-skills/manifest.json'
    report['skill_sha256']='28ecbeeccb0c5e5d6eb541b5a5b0f88aec47b154374d909085116d34f5629199'
    print('REPORT_JSON '+json.dumps(report),flush=True)
    print('COUNT_DATA_JSON '+json.dumps(data),flush=True)
    print('VALUES_JSON '+json.dumps(written),flush=True)
    return report

if __name__=='__main__':
    stored=None
    if '--stored' in sys.argv:
        from numberdb._generate import _current_entries
        entries=_current_entries('T592',None)
        stored={tuple(map(int,key.split(','))): value for key,value in entries.items()}
        assert len(stored)==245
    run(stored)