Research source · python
check_gap_hole_exports.py
tools/research/check_gap_hole_exports.py
240 lines. Source is displayed for inspection; it is not executed by this page.
File fingerprint
SHA-256: 87e01c019e8dae9dce0c29af9826ef1a2d54e73da8f0d2da7e5c720e39146f4d
#!/usr/bin/env python3
"""Independent persistent gap-list audit for arbitrary bounded-hole reuse.
Unary cells and list capsules are explicit immutable records. Tuple FIFOs and
run-head numerals stand for the separately proved strict queue/counter. No
loop in view/close follows a capsule tip; terminal commits are bounded. Sets
and integer decoding occur only in the independent assertions/test harness.
"""
from dataclasses import dataclass, replace
from itertools import product, combinations
from random import Random
import json
from check_single_hole_reuse import inc, decode
from check_colored_hole_reuse import Receipt, select, query
@dataclass(frozen=True, eq=False)
class Unit:
tail: object = None
def length(p):
result = 0
while p is not None:
result += 1
p = p.tail
return result
@dataclass(frozen=True, eq=False)
class Payload:
gap: object
ruler: object
numeral: tuple
@dataclass(frozen=True, eq=False)
class Node:
payload: Payload
tail: object = None
@dataclass(frozen=True, eq=False)
class Cap:
frames: tuple
tip: Node | None
def close(frames, tip):
assert tip is None or isinstance(tip, Node)
return Cap(frames, tip) if frames else tip
def view(root):
if root is None or isinstance(root, Node):
return root
assert isinstance(root, Cap) and root.frames
# One FIFO front/dequeue and one capsule; no recursive normalization.
return Node(root.frames[0], close(root.frames[1:], root.tip))
@dataclass(frozen=True, eq=False)
class Row:
maximum: object = None
gaps: object = None
root: object = None
def record(old, word):
"""The algorithm depends on arriving symbols and local empty tests only."""
assert word
frames = ()
head = view(old.root)
successor = view(head.tail) if head is not None else None
remaining = head.payload.gap if head is not None else None
merge = successor.payload.gap if successor is not None else None
elapsed = ruler = None
numeral = ()
old_maximum = old.maximum
gaps = old.gaps
passed = False
extension = None
extensions = deletions = prefix_frames = 0
for symbol in word:
assert symbol in '01'
if passed:
assert head is not None
frames += (head.payload,)
prefix_frames += 1
head = successor
successor = view(head.tail) if head is not None else None
remaining = head.payload.gap if head is not None else None
merge = successor.payload.gap if successor is not None else None
elapsed = None
passed = False
if extension is not None:
frames += (extension,)
prefix_frames += 1
gaps = Unit(gaps)
extensions += 1
elapsed = None
extension = None
ruler = Unit(ruler)
numeral = inc(numeral)
if old_maximum is not None:
old_maximum = old_maximum.tail
beyond = False
else:
beyond = True
elapsed = Unit(elapsed)
if head is not None:
assert not beyond and remaining is not None
remaining = remaining.tail
if successor is not None:
merge = Unit(merge)
passed = remaining is None
elif beyond:
extension = Payload(elapsed, ruler, numeral)
# Only these bounded actions occur after the final target bit.
if beyond:
new = Row(ruler, gaps, close(frames, None))
elif passed:
assert gaps is not None
tip = None if successor is None else Node(
replace(successor.payload, gap=merge), successor.tail)
new = Row(old.maximum, gaps.tail, close(frames, tip))
deletions = 1
else:
new = old
assert prefix_frames <= len(word)
return new, (extensions, deletions, prefix_frames)
def inspect(row, occupied):
"""Independent oracle; never called by record or the native algorithm."""
h = max(occupied, default=0)
assert length(row.maximum) == h
expected = sorted(set(range(1, h+1))-set(occupied))
found, cursor, previous = [], row.root, 0
while cursor is not None:
node = view(cursor)
value = length(node.payload.ruler)
assert decode(node.payload.numeral) == value
assert length(node.payload.gap) == value-previous > 0
found.append(value)
cursor, previous = node.tail, value
assert found == expected
assert length(row.gaps) == len(expected)
return tuple(found)
def main():
rng = Random(18457)
records = branches = merges = extensions = saved_queries = 0
# Every short insertion ordering, duplicates included; earlier roots retained.
for sequence in product(range(1, 7), repeat=4):
row, occupied = Row(), set()
history = [(row, frozenset())]
for n in sequence:
row, stats = record(row, '0'*n)
occupied.add(n)
inspect(row, occupied)
records += 1; extensions += stats[0]; merges += stats[1]
history.append((row, frozenset(occupied)))
for old, old_set in history:
inspect(old, old_set)
n = rng.randrange(1, 10)
fork, _ = record(old, '1'*n)
inspect(fork, old_set | {n})
inspect(old, old_set)
branches += 1
for _ in range(100):
rows, sets = [Row() for _ in range(4)], [set() for _ in range(4)]
retained = []
for _ in range(100):
u, n = rng.randrange(4), rng.randrange(1, 90)
old = rows[u]
rows[u], stats = record(old, ''.join(rng.choice('01') for _ in range(n)))
sets[u].add(n)
inspect(rows[u], sets[u])
retained.append((rows[u], frozenset(sets[u])))
records += 1; extensions += stats[0]; merges += stats[1]
for old, old_set in rng.sample(retained, 10):
inspect(old, old_set)
n = rng.randrange(1, 110)
fork, _ = record(old, '0'*n)
inspect(fork, old_set | {n})
inspect(old, old_set)
branches += 1
# Very late short deletion followed immediately by a one-bit query export.
row, _ = record(Row(), '0'*80)
occupied = {80}
for n in range(3, 80):
if n != 63:
row, _ = record(row, '0'*n); occupied.add(n)
assert inspect(row, occupied) == (1, 2, 63)
old = row
row, _ = record(row, '0'); occupied.add(1)
assert inspect(row, occupied) == (2, 63)
assert inspect(old, occupied-{1}) == (1, 2, 63)
# End-to-end producer exports into the independently audited reuse kernel.
literal_records = 0
for bound in (1, 2, 3, 4):
for _ in range(35):
h = rng.randrange(3, 8)
table, right_rows = {}, []
for v in range(8):
holes = set(rng.sample(range(1, h), rng.randrange(min(bound, h-1)+1)))
name = bin(v+2)[2:]
table[name] = holes
right_rows += [(name, format(x, f'0{n}b'))
for n in range(1, h+1) if n not in holes for x in range(1 << n)]
rng.shuffle(right_rows)
stores, widths = {}, {}
for name, word in right_rows:
stores[name], _ = record(stores.get(name, Row()), word)
widths.setdefault(name, set()).add(len(word))
literal_records += 1
exports = {name: inspect(stores[name], widths[name]) for name in table}
assert all(set(exports[name]) == table[name] for name in table)
states, selected = [Receipt() for _ in range(3)], [[] for _ in range(3)]
snapshots = []
for _ in range(30):
u, name = rng.randrange(3), rng.choice(tuple(table))
states[u] = select(states[u], name, exports[name], bound)
selected[u].append(table[name])
missing = frozenset(set.intersection(*selected[u]))
snapshots.append((states[u], missing))
for old, missing in snapshots:
saved_queries += query(old, h, h+2, missing, bound)
print(json.dumps(dict(status='passed', insertion_records=records,
persistent_branch_checks=branches, hole_deletions=merges,
confirmed_new_holes=extensions, literal_records=literal_records,
composed_query_prefix_answers=saved_queries,
late_short_deletion='passed', nonrecursive_capsule_view='asserted'), indent=2))
if __name__ == '__main__':
main()