Research source · python
check_learned_spine_profiles.py
tools/research/check_learned_spine_profiles.py
194 lines. Source is displayed for inspection; it is not executed by this page.
File fingerprint
SHA-256: 07fdd80cea64702b63a86ac35f41662f298cdfb4ccc4f2478a1c2107b752cae1
#!/usr/bin/env python3
"""Finite transition model for theorem 67's learned-spine factorization.
Reuses the maintained theorem-66 producer and consumer transition models.
Python tuples, strings, dictionaries and integers are semantic containers, not
claims of native unit-cost primitives. Native compilation and all-length rates
are proved in learned-spine-profile-reuse.md. The independent checker imports
neither this file nor the inherited model.
"""
from dataclasses import dataclass, replace
from itertools import product
from random import Random
import json
import check_mixed_budget_producer as base
@dataclass(frozen=True)
class Row:
words: frozenset = frozenset()
slots: tuple = ()
profiles: tuple = ()
pending: tuple = ()
active: object = None
def step(row, r):
if row.active is None:
if not row.pending:
return row
lane, n = row.pending[0]
p = row.profiles[lane]
assert p.active is None and not p.queue
profiles = row.profiles[:lane] + (replace(p, queue=(n,)),) + row.profiles[lane+1:]
return replace(row, profiles=profiles, active=lane, pending=row.pending[1:])
lane = row.active
p = base.producer_step(row.profiles[lane], r)
profiles = row.profiles[:lane] + (p,) + row.profiles[lane+1:]
return replace(row, profiles=profiles,
active=None if p.active is None and not p.queue else lane)
def guide_word(guides, word, K):
# Actual one-bit-delayed parent construction, no endpoint LCP oracle.
previous, parent = None, []
cursors = [0 for _ in guides]
mismatch = [False for _ in guides]
extension = [False for _ in guides]
for bit in word:
if previous is not None:
parent.append(previous)
for lane, guide in enumerate(guides):
pos = cursors[lane]
if pos == len(guide):
extension[lane] = True
else:
mismatch[lane] |= guide[pos] != previous
cursors[lane] += 1
previous = bit
assert previous is not None
parent = ''.join(parent)
compatible = [i for i, bad in enumerate(mismatch) if not bad]
if not compatible:
if len(guides) == K:
return None
return guides + (parent,), len(guides), parent
lane = compatible[0]
if extension[lane]:
guides = guides[:lane] + (parent,) + guides[lane+1:]
return guides, lane, parent
def insert(guides, row, word, K, r, counts):
for _ in word:
for _ in range(64):
before = row
row = step(row, r)
counts['producer_service_steps'] += before != row
result = guide_word(guides, word, K)
if result is None:
return None
guides, choice, parent = result
slots = dict(row.slots)
first = parent not in slots
if first:
slots[parent] = choice
else:
assert slots[parent] == choice # Stable least-compatible invariant.
lane = slots[parent]
p = row.profiles[lane]
profiles = row.profiles[:lane] + (replace(p, seen=p.seen | {(len(word), 0)}),) + row.profiles[lane+1:]
row = replace(row, words=row.words | {word}, slots=tuple(slots.items()),
profiles=profiles,
pending=row.pending + (((lane, len(word)),) if first else ()))
counts['records'] += 1
return guides, row
def closed(row):
return all(w[:-1] + ('1' if w[-1] == '0' else '0') in row.words for w in row.words)
def read_content(guides, word, lane_bits):
previous, cursors, failed = None, [0]*len(guides), [False]*len(guides)
answers = []
for n, bit in enumerate(word, 1):
if previous is not None:
for lane, guide in enumerate(guides):
pos = cursors[lane]
if pos == len(guide):
failed[lane] = True
else:
failed[lane] |= guide[pos] != previous
cursors[lane] += 1
answers.append(any(not failed[lane] and lane_bits[lane][n-1]
for lane in range(len(guides))))
previous = bit
return answers
def main():
rng = Random(20467)
counts = dict(histories=0, records=0, producer_service_steps=0,
closure_boundaries=0, budget_passes=0, retained_versions=0,
consumer_releases=0, query_prefixes=0, negative_prefixes=0,
overflow_cases=0)
for trial in range(180):
K = 1 + trial % 3
r = 0 if trial % 11 == 0 else 4
# Long shared prefix and distinct final branches; all rows remain sparse.
stem = ''.join(rng.choice('01') for _ in range(trial % 9))
branches = ('00', '01', '1')[:K]
spines = tuple(stem + b + ''.join(rng.choice('01') for _ in range(12)) for b in branches)
records = []
row_count = 2 + trial % 7
for name in range(row_count):
for _ in range(2 + trial % 5):
g = rng.choice(spines)
n = rng.randrange(1, len(g)+2)
parent = g[:n-1]
records.extend(((name, parent+'0'), (name, parent+'1')))
records += rng.sample(records, min(8, len(records)))
rng.shuffle(records)
rows = {name: Row(profiles=tuple(base.Producer() for _ in range(K))) for name in range(row_count)}
guides, saved = (), []
for name, word in records:
old = rows[name]
out = insert(guides, old, word, K, r, counts)
assert out is not None
guides, rows[name] = out
saved.append((old, old.words, old.profiles))
if closed(rows[name]):
assert rows[name].active is None and not rows[name].pending
for p in rows[name].profiles:
base.check_quiet(p, r)
counts['closure_boundaries'] += 1
assert all(closed(row) for row in rows.values())
for old, words, profiles in saved:
assert old.words == words and old.profiles == profiles
counts['retained_versions'] += 1
if any(p.bad for row in rows.values() for p in row.profiles):
counts['histories'] += 1
continue
counts['budget_passes'] += 1
workers = tuple(base.Worker() for _ in range(K))
selected, literal = set(), set()
# Deliberately give no pre-query service: this is stronger than paying
# each real intermediate name. No delimiter drain is permitted.
for name in list(rows) + list(rows)[:2]:
if name not in selected:
workers = tuple(base.release(w, p.trees) for w, p in zip(workers, rows[name].profiles))
selected.add(name)
literal.update(rows[name].words)
counts['consumer_releases'] += 1
length = max(max(map(len, literal)), max(map(len, guides))) + 2
lane_bits = tuple(base.query(w, length, 1024*max(1,16*r+16)) for w in workers)
tests = set(literal)
tests.update(''.join(rng.choice('01') for _ in range(length)) for _ in range(20))
tests.update(g+'00' for g in guides)
for word in tests:
ans = read_content(guides, word, lane_bits)
for n, actual in enumerate(ans, 1):
expected = word[:n] in literal
assert actual == expected
counts['query_prefixes'] += 1
counts['negative_prefixes'] += not expected
counts['histories'] += 1
assert guide_word(('0','1'), '001', 2) is not None
assert guide_word(('00','01'), '10', 2) is None
counts['overflow_cases'] += 1
print(json.dumps(counts, sort_keys=True))
if __name__ == '__main__':
main()