Research source · python

check_learned_row_keys.py

tools/research/check_learned_row_keys.py

136 lines. Source is displayed for inspection; it is not executed by this page.

File fingerprint

SHA-256: ac61731bb97ad38af0662c737760f441f8ae3634ad0c38d8755d69bd4deb67c9

"""Finite semantic audit for learned row-key palettes; not native timing evidence."""
from dataclasses import dataclass, replace
from itertools import product, permutations
import json, random
import check_row_typed_composition as base
from check_rectangle_deficit import key, count, frame_count
from check_frozen_row_composition import B, lookup, insert
import check_pending_substitution as n

@dataclass(frozen=True)
class Learned:
    state: object
    palette: object = B

def initial(r): return Learned(base.initial(r))

def step(old, v, w, f, r, K, d=2, s=1):
    a,z=f(v),key(w)
    if not a or not z: return None
    branch=lookup(old.palette,a) or B
    code=lookup(branch,z)
    meta=lookup(old.state.keys,z)
    slots=meta.row_slots if meta else 0
    if code is None:
        if slots==r: return None
        c=slots; slots+=1
    else: c=code-1
    st=base.step(old.state,v,w,lambda _v,_z:c,r,K,d,s)
    if st is None: return None
    meta=replace(lookup(st.keys,z),row_slots=slots)
    st=replace(st,keys=insert(st.keys,z,meta))
    return Learned(st,insert(old.palette,a,insert(branch,z,c+1)))

stats=dict(sequences=0,prefixes=0,retained_versions=0,queries=0)

def oracle(seq,f,r,K,d=2,s=1):
    palettes={}; rows={}; cells={}; targets={}
    for v,w in seq:
        a,z=f(v),key(w)
        if not a or not z or abs(n.cls(v)-n.cls(z))>s:return None
        rows.setdefault(v,set()).add(z)
        if len(rows[v])>d:return None
        p=palettes.setdefault(z,[])
        if a not in p:p.append(a)
        if len(p)>r:return None
        c=p.index(a)
        cells.setdefault((z,c),set()).add((v,w))
        targets.setdefault(z,set()).add(w)
    rectangular=all(es==set(product({v for v,w in es},{w for v,w in es})) for es in cells.values())
    diversity=all(len({frozenset(v for v,t in seq if t==w) for w in ws})<=K for ws in targets.values())
    return palettes,cells,targets,rectangular and diversity

def inspect(st,seq,f,r,K,d=2,s=1):
    data=oracle(seq,f,r,K,d,s);assert data is not None
    palettes,cells,targets,ok=data
    incomplete=excess=0
    for z,p in palettes.items():
        meta=lookup(st.state.keys,z)
        assert meta.row_slots==len(p)
        for c,a in enumerate(p):assert lookup(lookup(st.palette,a),z)==c+1
        hist=[0]*(1<<r)
        for w in targets[z]:
            mask=sum(1<<c for c in range(r) if any(t==w for v,t in cells.get((z,c),set())))
            assert lookup(st.state.masks,w)==mask
            hist[mask]+=1
        assert [count(x) for x in meta.population]==hist
        assert meta.occupied==sum(bool(x) for x in hist)
        excess+=meta.occupied>K
        for c in range(r):
            es=cells.get((z,c),set());vc=len({v for v,w in es});tc=len({w for v,w in es})
            cell=meta.cells[c];debt=vc*tc-len(es)
            assert count(cell.predecessors)==vc and count(cell.targets)==tc
            assert frame_count(cell.deficit)==debt
            incomplete+=bool(debt)
    assert count(st.state.unfinished)==incomplete and count(st.state.excessive)==excess
    assert (not incomplete and not excess)==ok
    return ok

def check(seq,f,r=2,K=2,d=2,s=1,query=True):
    stats['sequences']+=1
    st=initial(r);versions=[st]
    for i,(v,w) in enumerate(seq):
        st=step(st,v,w,f,r,K,d,s)
        if st is None:
            assert oracle(seq,f,r,K,d,s) is None
            return None
        inspect(st,seq[:i+1],f,r,K,d,s);stats['prefixes']+=1
        versions.append(st)
    for i,old in enumerate(versions):
        inspect(old,seq[:i],f,r,K,d,s);stats['retained_versions']+=1
    ok=inspect(st,seq,f,r,K,d,s)
    if ok and query:
        roots=(B,)*r;left=set()
        for i,v in enumerate(sorted({v for v,w in seq})):
            u=str(i%2);left.add((u,v))
            roots=tuple(n.add_left(roots[c],st.state.lanes[c],u,v,d,s) for c in range(r))
            for u,w in product(('0','1'),sorted({w for v,w in seq})+['0001']):
                mask=lookup(st.state.masks,w) or 0;z=key(w)
                got=bool(mask) and z is not None and any(mask&(1<<c) and n.index_contains(lookup(roots[c],u) or {},z) for c in range(r))
                want=any((u,v) in left and t==w for v,t in seq)
                assert bool(got)==want;stats['queries']+=1
    return st

def main():
    rng=random.Random(137)
    edges=list(product(['10','010','11'],['10','010','0010']))
    for bits in range(1<<len(edges)):
        seq=[e for i,e in enumerate(edges) if bits>>i&1]
        mixed=seq[:];rng.shuffle(mixed)
        if mixed:mixed.append(mixed[0])
        for order in (seq,list(reversed(seq)),mixed):check(order,key)
    # All orders of a genuine two-row rectangle with equal streamed row keys.
    for seq in permutations(list(product(['10','010'],['10','010','0010']))):
        st=check(list(seq),key,K=1);assert st.state.unfinished is None
    # Slots are per target key, not global and not allocated per raw row.
    pool=list(product(['10','010','11','011'],['10','010','11','011']))
    for _ in range(300):check([rng.choice(pool) for _ in range(rng.randrange(1,25))],key)
    families=[]
    for m in (2,3,5,9):
        a='0'*m;b='1'*m;z='0'*(2*m+1)
        A=['0'*j+'1'+a for j in range(m+1)]
        Bv=['0'*j+'1'+b for j in range(m+1)]
        T=['0'*j+'1'+z for j in range(6)]
        seq=list(product(A,T[:3]))+list(product(Bv,T[3:]))
        rng.shuffle(seq)
        st=check(seq,key,d=1);assert st.state.unfinished is None
        assert lookup(st.state.keys,z).row_slots==2
        families.append({'rows':len(A)+len(Bv),'learned_keys':2,'targets':len(T)})
    # Same learned key is not permission to erase distinct neighborhoods.
    bad=check([('10','10'),('010','010')],key)
    assert bad.state.unfinished is not None
    assert check([('10','10'),('11','10'),('100','10')],key) is None
    assert check([('000','10')],key) is None
    print(json.dumps({**stats,'growing_families':families,'native_timing_evidence':False},indent=2))

if __name__=='__main__':main()