Research source · python

check_pending_substitution.py

tools/research/check_pending_substitution.py

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

File fingerprint

SHA-256: bc9659d641d14771b9a0fefe608d95eedbed6713e048dab54fcaf4de91126fe2

"""Finite semantic/scheduling corroboration for assessment126.

Capsule tries are immutable. Python tuples model the established strict FIFO;
Python dict directories and integer clocks are semantic models, NOT native
instructions or timing evidence. Installer progress and reader replay are
counted explicitly in trie-bit/closure macrosteps. Independent set joins are
used only by the oracle. The written proof realizes directories/clocks locally.
"""
from dataclasses import dataclass
from itertools import product
import json
import random
from check_frozen_row_composition import B, view, close, lookup


def step(builder, bit):
    frames, root = builder
    value, left, right = view(root)
    return frames + ((value, int(bit), left if bit == '1' else right),), (right if bit == '1' else left)


def walk(root, word):
    builder = (), root
    for bit in word:
        builder = step(builder, bit)
    return builder


def cls(word):
    assert word
    return len(word).bit_length() - 1


@dataclass(frozen=True)
class RightRow:
    seen: object = B
    targets: tuple = ()  # (immutable spelling tuple, finite class offset)


def add_right(root, v, w, d, s):
    outer = walk(root, v)
    row = view(outer[1])[0] or RightRow()
    inner = walk(row.seen, w)
    offset = cls(w) - cls(v)
    if abs(offset) > s:
        return None
    if view(inner[1])[0]:
        return root
    if len(row.targets) == d:
        return None
    new = RightRow(close(inner, True), row.targets + ((tuple(w), offset),))
    return close(outer, new)


@dataclass(frozen=True)
class Bucket:
    committed: object = B
    pending: tuple = ()


class Installer:
    """One macrostep per inserted key bit or capsule closure."""
    def __init__(self, bucket):
        self.root = bucket.committed
        self.jobs = bucket.pending
        self.job = self.pos = self.steps = 0
        self.builder = (), self.root

    @property
    def done(self):
        return self.job == len(self.jobs)

    def tick(self):
        if self.done:
            return
        word = self.jobs[self.job]
        if self.pos < len(word):
            self.builder = step(self.builder, word[self.pos])
            self.pos += 1
        else:
            self.root = close(self.builder, True)
            self.job += 1
            self.pos = 0
            self.builder = (), self.root
        self.steps += 1

    def finish(self):
        while not self.done:
            self.tick()
        return Bucket(self.root, ())


STATS = {'serviced_batches': 0, 'discarded_partial_jobs': 0,
         'pending_answers': 0, 'reader_promotions': 0, 'max_pending': 0}


def service_for_name(index, word, d, s):
    """No new target pointers are passed here: they are revealed afterwards."""
    current = dict(index)
    start_cost = 0
    for j in range(s + 1):
        job = Installer(current.get(j, Bucket()))
        current[j] = job.finish()
        start_cost += job.steps
        STATS['serviced_batches'] += bool(job.steps)
    assert start_cost <= (s + 1) * d * (2 ** (s + 1))
    j, boundary = 0, 2
    next_bucket = s + 1
    worker = Installer(current.get(next_bucket, Bucket()))
    rate = d * (2 ** (s + 2) + 1)
    for length in range(2, len(word) + 1):
        for _ in range(rate):
            worker.tick()
        if length == boundary:
            assert worker.done, (length, next_bucket, worker.steps)
            current[next_bucket] = Bucket(worker.root, ())
            STATS['serviced_batches'] += bool(worker.steps)
            j += 1
            boundary *= 2
            next_bucket = j + s + 1
            worker = Installer(current.get(next_bucket, Bucket()))
    assert j == cls(word)
    if worker.steps and not worker.done:
        STATS['discarded_partial_jobs'] += 1
    # Even if speculative work finished early, no unpromoted bucket is changed.
    for bucket in range(max(0, j - s), j + s + 1):
        assert not current.get(bucket, Bucket()).pending
    return current, j


def add_left(root, frozen, u, v, d, s):
    outer = walk(root, u)
    index = view(outer[1])[0] or {}
    serviced, j = service_for_name(index, v, d, s)
    receipt = lookup(frozen, v) or RightRow()
    groups = {}
    for word, offset in receipt.targets:
        assert cls(word) == j + offset
        assert abs(offset) <= s
        groups.setdefault(j + offset, []).append(word)
    for bucket, words in groups.items():
        old = serviced.get(bucket, Bucket())
        assert not old.pending
        assert len(words) <= d
        serviced[bucket] = Bucket(old.committed, tuple(words))
        STATS['max_pending'] = max(STATS['max_pending'], len(words))
    return close(outer, serviced)


class Reader:
    def __init__(self, bucket):
        self.cursor = bucket.committed
        self.pending = [tuple(word) for word in bucket.pending]
        self.viable = [True] * len(self.pending)
        self.consumed = 0

    def feed(self, bit):
        _, left, right = view(self.cursor)
        self.cursor = right if bit == '1' else left
        for i, word in enumerate(self.pending):
            if self.viable[i]:
                if not word or word[0] != bit:
                    self.viable[i] = False
                else:
                    self.pending[i] = word[1:]
        self.consumed += 1

    def contains(self):
        pending = any(ok and not word for ok, word in zip(self.viable, self.pending))
        STATS['pending_answers'] += bool(pending and not view(self.cursor)[0])
        return bool(view(self.cursor)[0] or pending)


def index_contains(index, word):
    current = Reader(index.get(0, Bucket()))
    current.feed(word[0])
    prefix = (word[0],)
    queue = prefix
    ahead = Reader(index.get(1, Bucket()))
    j, boundary = 0, 2
    for length, bit in enumerate(word[1:], 2):
        prefix += (bit,)
        current.feed(bit)
        queue += (bit,)
        for _ in range(2):
            if queue:
                ahead.feed(queue[0])
                queue = queue[1:]
        if length == boundary:
            assert not queue and ahead.consumed == length
            current = ahead
            STATS['reader_promotions'] += 1
            j += 1
            boundary *= 2
            ahead = Reader(index.get(j + 1, Bucket()))
            queue = prefix
    assert current.consumed == len(word) and j == cls(word)
    return current.contains()


def answer(root, a, b):
    return not index_contains(lookup(root, a) or {}, b)


def main():
    names = ['0', '1']
    pairs = list(product(names, repeat=2))
    rels = [{edge for i, edge in enumerate(pairs) if mask >> i & 1} for mask in range(16)]
    exhaustive = 0
    for srel in rels:
        frozen = B
        for v, w in sorted(srel):
            frozen = add_right(frozen, v, w, 2, 0)
            assert frozen is not None
        for r in rels:
            root = B
            for u, v in sorted(r):
                root = add_left(root, frozen, u, v, 2, 0)
            expected = {(a, b) for a, v in r for z, b in srel if z == v}
            for a, b in product(names + ['00'], repeat=2):
                assert answer(root, a, b) == ((a, b) not in expected)
                exhaustive += 1
    rng = random.Random(126)
    words = ['0', '1', '00', '01', '10', '000', '111']
    words += ['0' * (n - 1) + '1' for n in [4, 7, 8, 15, 16, 31, 32, 65]]
    sources = ['0', '00', '1' * 97]
    snapshots = queries = checked = 0
    for trial in range(18):
        d, span = 1 + trial % 3, trial % 2
        frozen, srel = B, set()
        for _ in range(30):
            v, w = rng.choice(words), rng.choice(words)
            new = add_right(frozen, v, w, d, span)
            row = {b for a, b in srel if a == v}
            valid = abs(cls(v) - cls(w)) <= span and (w in row or len(row) < d)
            assert (new is not None) == valid
            checked += 1
            if valid:
                frozen = new
                srel.add((v, w))
        # Explicit long-then-short source variations with arbitrary row reuse.
        root, r, saved = B, set(), []
        for _ in range(28):
            u, v = rng.choice(sources), rng.choice(words)
            root = add_left(root, frozen, u, v, d, span)
            r.add((u, v))
            expected = {(a, b) for a, v in r for z, b in srel if z == v}
            saved.append((root, expected.copy()))
            snapshots += 1
        for old, expected in saved:
            for a, b in product(sources + ['101'], words):
                assert answer(old, a, b) == ((a, b) not in expected)
                queries += 1
    # Force a speculative long bucket installation to be discarded, while
    # short queries still see the exact earlier pending word.
    frozen = B
    for v in ['0' * 7, '0' * 4, '0' * 15, '0']:
        frozen = add_right(frozen, v, v[::-1], 1, 0)
    root = B
    for v in ['0' * 15, '0' * 7, '0' * 4, '0']:
        root = add_left(root, frozen, '0', v, 1, 0)
        assert not answer(root, '0', v[::-1])
    # Arbitrary equal-length permutations, not fixed streaming maps.
    permutation_queries = 0
    for n in range(1, 6):
        names = [''.join(x) for x in product('01', repeat=n)]
        targets = names.copy()
        rng.shuffle(targets)
        frozen, root = B, B
        for v, w in zip(names, targets):
            frozen = add_right(frozen, v, w, 1, 0)
        chosen = set(names[::2])
        for v in chosen:
            root = add_left(root, frozen, '0', v, 1, 0)
        expected = {w for v, w in zip(names, targets) if v in chosen}
        for w in names:
            assert answer(root, '0', w) == (w not in expected)
            permutation_queries += 1
    assert STATS['pending_answers'] and STATS['discarded_partial_jobs']
    print(json.dumps(dict(status='pass', exhaustive_queries=exhaustive,
        right_condition_checks=checked, retained_versions=snapshots,
        retained_queries=queries, arbitrary_permutation_queries=permutation_queries,
        scheduling=STATS, native_timing_evidence=False)))


if __name__ == '__main__':
    main()