/machines/1RB---_1LC1RE_1LD0LC_1LE1LC_1RF0RE_1RA0RB/validate_cycle.py · raw
"""Validate the cycle rule X(a, R) -> X(a + d, R') (two left records later) for random a, machine #14.

X(a, R) := 0^inf <C 1^6 0 (00011000011)^2 (00011)^2 (10001)^3 10 (00011)^6 (10001)^8 (11000)^12 1 (11000)^18
           (01100)^27 0^2 (11000)^41 (01100)^61 (00110)^92 (00011)^138 (10001)^206 (11000)^a R 0^inf
The right barrier R runs through a 4-cycle; observed (1e9 run): d = 8, 8, 4, 12.
usage: python3 validate_cycle.py SEED N
"""
import json
import random
import sys

sys.path.insert(0, "[local working file]")
import compress as C  # noqa: E402
import sim  # noqa: E402

TM = "1RB---_1LC1RE_1LD0LC_1LE1LC_1RF0RE_1RA0RB"
M = sim.parse(TM)
PREFIX = ("0^inf <C 1^6 0 00011000011^2 00011^2 10001^3 10 00011^6 10001^8 11000^12 1 11000^18 01100^27 0^2 "
          "11000^41 01100^61 00110^92 00011^138 10001^206 11000^")
PAT = C.CConfig.parse(PREFIX + "a r")
# observed consecutive barrier states at X records (861M .. 968M) and the observed increment
CHAIN = [("0 0001^4 0^23 1", "10001^4 1 0^15 1 0^23 1", 4),
         ("10001^4 1 0^15 1 0^23 1", "0 0001^3 0^27 1", 12),
         ("0 0001^3 0^27 1", "0 0001^2 0^31 1", 8),
         ("0 0001^2 0^31 1", "0 0001^9", 8)]


def rest_of(cfg, a):
    t = C.compress(cfg).text()
    key = "10001^206 11000^%d " % a
    i = t.find(key)
    return t[i + len(key):].replace(" 0^inf", "") if i >= 0 else None


def one(a, R):
    cfg = sim.Config.parse(PREFIX + "%d %s 0^inf" % (a, R))
    nL = 0
    for ev in sim.events(M, cfg, 10**9, on_record=True, snapshot=True):
        if ev.side == "L" and ev.state == "C":
            nL += 1
            if nL == 2:
                snap = ev.config
                mt = PAT.match(snap)
                if not mt:
                    return None, None, ev.step
                return mt["a"], rest_of(snap, mt["a"]), ev.step
    return None, None, None


if __name__ == "__main__":
    rng = random.Random(int(sys.argv[1]))
    n = int(sys.argv[2])
    out = []
    tot = kept = 0
    for R, R2, d in CHAIN:
        inst = ok = exact = 0
        ds = []
        for _ in range(n):
            a = rng.randint(60, 300)
            a2, r2, steps = one(a, R)
            inst += 1
            ok += a2 is not None          # prefix (all frozen levels) reproduced two left records later
            exact += (a2 == a + d and r2 == R2)
            if a2 is not None:
                ds.append(a2 - a)
        tot += inst
        kept += ok
        out.append({"R": R, "instances": inst, "prefix_kept": ok, "observed_successor": exact, "d=a'-a": sorted(ds)})
    out.append({"rule": "X(a, R) -->+ X(a', R') (prefix kept, left edge -8)", "instances": tot, "passed": kept})
    print(json.dumps(out))