Research source · python
check_scale_sparse_band_reuse.py
tools/research/check_scale_sparse_band_reuse.py
312 lines. Source is displayed for inspection; it is not executed by this page.
File fingerprint
SHA-256: 0b2c75560b4834f09d7a8ab78b2e03ec448eee27708a4d752083ea3afe46f4cf
#!/usr/bin/env python3
"""Finite audit of scale-sparse band production and reuse.
Tuple deques and integer clock flags model inherited native primitives.
They are not measurements of Python/native complexity. Producer width events
stand for the separately proved distinct-width dictionary; complete binary
levels are checked independently below. Persistent unit cursors, delimiter
updates and resumable consumer insertion are explicit. Calls to digits(n) at
a delimiter stand for inherited numerals already prepared during the word;
this model does not audit their construction. Complete-level cases check
count/set semantics, not the inherited capacity-counter implementation.
"""
from dataclasses import dataclass, replace
from random import Random
from collections import deque
import json
import check_banded_interval_reuse as base
from check_banded_interval_reuse import Link, units, digits, Bucket, Worker, Reader
def size(s):
n = 0
while s is not None:
n += 1
s = s.tail
return n
def pop(s):
assert s is not None
return s.tail
def delta(s, d):
return Link(None, s) if d == 1 else pop(s) if d == -1 else s
def over(s, bound):
# At most bound+1 observations; bound is a fixed machine parameter.
for _ in range(bound+1):
if s is None:
return False
s = s.tail
return True
@dataclass(frozen=True)
class Record:
flag: str = 'EMPTY'
missing: object = None
runs: object = None
low: object = None
high: object = None
low_offset: object = None
high_offset: object = None
@dataclass(frozen=True)
class Row:
bands: tuple = ()
groups: tuple = ()
bad_groups: object = None
bad_runs: object = None
widths: frozenset = frozenset() # Imported dictionary, not worker lookup.
def produce(row, n, r):
assert n > 0
P, S, GP, GS = (), row.bands, (), row.groups
prefix = offset = lc = hc = None
j = 0
for position in range(1, n+1):
prefix = Link(None, prefix)
if position & (position-1) == 0: # Inherited native counter flag.
if j:
P, S = P+(S[0],), S[1:]
j += 1
if not S:
S = (Record(missing=prefix),)
if j & (j-1) == 0:
if j > 1:
GP, GS = GP+(GS[0],), GS[1:]
if not GS:
GS = (None,)
offset, lc, hc = None, S[0].low_offset, S[0].high_offset
else:
offset = Link(None, offset)
lc = None if lc is None else lc.tail
hc = None if hc is None else hc.tail
old = rec = S[0]
first = n not in row.widths
if first:
missing = pop(old.missing)
pred = n-1 in row.widths and n & (n-1) != 0
succ = n+1 in row.widths and n & (n+1) != 0
runs = delta(old.runs, 1-int(pred)-int(succ))
rec = replace(old, missing=missing, runs=runs,
flag='FULL' if missing is None else 'PARTIAL')
if old.flag == 'EMPTY' or lc is not None:
rec = replace(rec, low=digits(n), low_offset=offset)
if old.flag == 'EMPTY' or hc is None:
rec = replace(rec, high=digits(n), high_offset=offset)
d = int(rec.flag == 'PARTIAL')-int(old.flag == 'PARTIAL')
group = delta(GS[0], d)
bad_groups = delta(row.bad_groups, int(over(group,r))-int(over(GS[0],r)))
bad_runs = delta(row.bad_runs, int(over(rec.runs,1))-int(over(old.runs,1)))
return Row(P+(rec,)+S[1:], GP+(group,)+GS[1:], bad_groups,
bad_runs, row.widths | {n})
def number(p):
n, weight = 0, 1
while p is not None:
n += p.head*weight
p, weight = p.tail, weight*2
return n
def audit_row(row, r):
counts = [0]*len(row.groups)
bad_runs = 0
for j, rec in enumerate(row.bands, 1):
a, z = 1 << (j-1), (1 << j)-1
points = sorted(row.widths & set(range(a,z+1)))
flag = 'EMPTY' if not points else 'FULL' if len(points)==a else 'PARTIAL'
assert rec.flag == flag
assert size(rec.missing) == a-len(points)
runs = sum(x-1 not in points for x in points)
assert size(rec.runs) == runs
bad_runs += runs > 1
counts[j.bit_length()-1] += flag == 'PARTIAL'
if points:
assert number(rec.low) == points[0] and number(rec.high) == points[-1]
assert size(rec.low_offset) == points[0]-a
assert size(rec.high_offset) == points[-1]-a
assert [size(g) for g in row.groups] == counts
assert size(row.bad_groups) == sum(c > r for c in counts)
assert size(row.bad_runs) == bad_runs
return bad_runs == 0 and all(c <= r for c in counts)
@dataclass(frozen=True)
class Cursor:
records: tuple
def release(w, row):
seq = w.prefix+w.suffix
b = seq[0] if seq else Bucket()
b = replace(b, jobs=Link(Cursor(row.bands), b.jobs))
return Worker((), (b,)+seq[1:])
def service(w):
if not w.suffix:
return w
b = w.suffix[0]
if b.insertion is not None:
ins = base.insert_step(b.insertion)
if ins.phase == 'done':
new = replace(b, tree=ins.result, insertion=None, continuation=None)
return base.finish(w, new, b.continuation)
return Worker(w.prefix, (replace(b, insertion=ins),)+w.suffix[1:])
if b.jobs is None:
return Worker(w.prefix+(b,), w.suffix[1:])
job = b.jobs.head
rec, tail = job.records[0], job.records[1:]
cont = Cursor(tail) if tail else None
new = replace(b, jobs=b.jobs.tail)
if rec.flag == 'EMPTY':
return base.finish(w, new, cont)
if rec.flag == 'FULL' or b.tree is True:
return base.finish(w, replace(new, tree=True), cont)
ins = base.start_insert(b.tree,b.height,rec.low,rec.high)
return Worker(w.prefix,(replace(new,insertion=ins,continuation=cont),)+w.suffix[1:])
def drain(w,k):
steps = 0
while len(w.prefix)<k and w.suffix:
w = service(w)
steps += 1
assert steps < 1000000
return steps
def query(w,count,r):
ready, pending = w.prefix, Worker((),w.suffix)
reader, output, answers = Reader(), deque(), []
for _ in range(count):
for _ in range(1024*256*(r+1)):
if not pending.suffix:
break
pending = service(pending)
if pending.prefix:
ready += pending.prefix
pending = Worker((),pending.suffix)
for _ in range(1024):
if reader.stack is None:
if not ready:
break
b, ready = ready[0], ready[1:]
reader = replace(reader,stack=Link((b.tree,b.height)))
reader = base.read_step(reader)
if reader.emission is not None:
output.append(reader.emission)
if output:
answers.append(output.popleft())
else:
assert not ready and not pending.suffix and reader.stack is None
answers.append(False)
return answers
def valid_row(rng,r,max_j=7):
points, partial = [], {}
for j in range(1,max_j+1):
a,z = 1 << (j-1),(1 << j)-1
group = j.bit_length()
kind = rng.randrange(3)
if kind == 0:
continue
if kind == 1 or partial.get(group,0) >= r:
lo,hi = a,z
else:
lo = rng.randrange(a,z+1)
hi = rng.randrange(lo,z+1)
if (lo,hi)!=(a,z):
partial[group] = partial.get(group,0)+1
points.extend(range(lo,hi+1))
if not points:
points = [1]
rng.shuffle(points)
row = Row()
for n in points:
row = produce(row,n,r)
assert audit_row(row,r)
return row
def main():
rng = Random(199)
producer_steps = retained = releases = prefixes = inequalities = 0
# Arbitrary order, duplicates, temporary invalidity, and repair.
for r in range(4):
for trial in range(35):
row, versions = Row(), []
order = list(range(1,64)) + [rng.randrange(1,64) for _ in range(30)]
rng.shuffle(order)
for n in order:
if rng.randrange(8)==0:
versions.append(row)
row = produce(row,n,r)
audit_row(row,r)
producer_steps += 1
assert audit_row(row,r)
for old in versions:
audit_row(old,r)
retained += 1
# Independent complete-level semantics, including duplicates.
level_cases = 0
for mask in range(1 << 6):
words = ['0','1','00','01','10','11']
selected = {w for i,w in enumerate(words) if mask >> i & 1}
counts = {n:sum(len(w)==n for w in selected) for n in (1,2)}
gate = all(c in (0,1 << n) for n,c in counts.items())
direct = all({w for w in words if len(w)==len(v)} <= selected for v in selected)
assert gate == direct
assert selected | selected == selected
level_cases += 1
# Generalized consumer with interrupted releases and retained query forks.
for r in range(4):
for trial in range(15):
w, covered, versions = Worker(), set(), []
for _ in range(9):
row = valid_row(rng,r)
for _ in range(rng.randrange(40)):
w = service(w)
k = rng.randrange(1,9)
before = drain(w,k)
new = release(w,row)
assert drain(new,k) <= before+256*(r+1)*k
versions.append((w,frozenset(covered)))
w = new
covered.update(row.widths)
out = query(w,140,r)
assert out == [n in covered for n in range(1,141)]
prefixes += len(out)
releases += 1
for old,points in versions[::3]:
assert query(old,140,r) == [n in points for n in range(1,141)]
prefixes += 140
retained += 1
# Unbounded-family witness at increasingly many scales (finite samples).
for t in range(1,12):
js = [1 << a for a in range(1,t+1)]
for k in js:
assert sum(j+1 for j in js if j<=k) < 4*k
for r in range(4):
for k in range(4,513):
c = 256*(r+1)
C,q,Q = c*k,64*c,1024*c
B = C+sum((1<<d)*(C-q*d) for d in range(1,(C-1)//q+1))
assert B < Q*(1 << (k-4))
inequalities += 1
print(json.dumps(dict(producer_updates=producer_steps,retained_forks=retained,
complete_level_cases=level_cases,releases_and_envelope_checks=releases,
query_prefixes=prefixes,deadline_inequalities=inequalities)))
if __name__ == '__main__':
main()