/machines/1RB0RA_1LC0LD_1LE1LD_0LB0RE_1RF0LA_---0RA/validate_rules.py · raw
#!/usr/bin/env python3
"""Observe-stage rule validation for 1RB0RA_1LC0LD_1LE1LD_0LB0RE_1RF0LA_---0RA.
Each rule is simulated from concrete configurations (random small/large parameters, random
left/right contexts) and compared cell-for-cell (state, head, trimmed tape) with the predicted
configuration. Exact step counts where given; OP/OQ: target = the next left-edge E record.
Writes validation.json next to this file.  Run: python3 -B validate_rules.py"""
import sys, random, json, os
sys.path.insert(0, "[local working file]")
import sim
TM = '1RB0RA_1LC0LD_1LE1LD_0LB0RE_1RF0LA_---0RA'
M = sim.parse(TM)
random.seed(20261010)

def key(c):
    t = c.trimmed(); return (t.tape, t.head, t.state)

def word(maxlen=8):
    return ' '.join(random.choice('01') for _ in range(random.randint(0, maxlen)))

def ctx():
    return '0^inf 1 ' + word(), word() + ' 1 0^inf'

def nval(i, lo, hi):
    if i < 6: return lo + i % 3              # small, incl. the minimum
    if i < 20: return random.randint(lo, lo + 30)
    return random.randint(lo, hi)            # large

def exact(frm, to, steps, n, ranges, use_r=True):
    ok = 0
    for i in range(n):
        v = {k: nval(i, lo, hi) for k, (lo, hi) in ranges.items()}
        l, r = ctx()
        if not use_r: r = '0^inf'
        a = sim.Config.parse(frm.format(l=l, r=r), **v)
        b = sim.Config.parse(to.format(l=l, r=r), **v)
        s = sim.Simulator(M, a); s.run(eval(steps, {}, v))
        if not s.halted and key(s.snapshot()) == key(b): ok += 1
    return {"instances": n, "passed": ok}

def next_Erec(cfg, cap):
    for ev in sim.events(M, cfg, max_steps=cap, on_record=True, on_halt=True, snapshot=True):
        if 'halt' in ev.kinds: return None
        if ev.side == 'L' and ev.state == 'E': return ev.config
    return None

def X(gaps): return ' '.join('(110)^%d 111110' % g for g in gaps)
def P(g, G, Mm): return '0^inf <E 110 111110 %s (110)^%d 00 (110)^%d 0^inf' % (X(g), G, Mm)
def Q(g, G, Mm): return '0^inf <E 110 11110 111110 %s (110)^%d 00 (110)^%d 0^inf' % (X(g), G, Mm)

def overflow(which, n):
    ok = 0
    for i in range(n):
        nd = i % 4 if i < 8 else random.choice([0, 1, 1, 2, 2, 3, 4, 5])
        gaps = [random.choice([1, 1, 2, 3, 4, 7, 10, 17]) if random.random() < 0.7 else random.randint(1, 60)
                for _ in range(nd)]
        f = 1 + nd
        G = random.choice([0, 1, 2]) if i % 5 == 0 else random.randint(0, 400)
        Mm = random.choice([0, 1]) if i % 7 == 0 else random.randint(0, 400)
        if which == 'OP': a, b = P(gaps, G + 2**f, Mm), Q(gaps, G, Mm + 2**f)
        else:             a, b = Q(gaps, G + 2**(f+2), Mm), P([1] + gaps, G, Mm + 2**(f+2))
        c = next_Erec(sim.Config.parse(a), 10**9)
        if c is not None and key(c) == key(sim.Config.parse(b)): ok += 1
    return {"instances": n, "passed": ok}

res = {}
res['R1'] = exact('{l} A> (011)^n {r}', '{l} (010)^n A> {r}', '5*n', 60, {'n': (0, 3000)})
res['R2'] = exact('{l} (010)^n <B {r}', '{l} <B (011)^n {r}', '3*n', 60, {'n': (0, 3000)})
res['R3'] = exact('{l} A> 011 00 011 {r}', '{l} <B 00 011 011 {r}', '11', 60, {})
res['R4'] = exact('{l} 010 A> 0^inf', '{l} <B 00 011 0^inf', '6', 60, {}, use_r=False)
res['L0'] = exact('{l} 0 <E 11 (011)^(a+1) 00 (011)^b 0^inf', '{l} 1 <E 11 (011)^a 00 (011)^(b+1) 0^inf',
                  '8*a+16', 60, {'a': (0, 2000), 'b': (0, 2000)}, use_r=False)
res['OP'] = overflow('OP', 120)
res['OQ'] = overflow('OQ', 120)
json.dump(res, open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'validation.json'), 'w'), indent=1)
print(json.dumps(res))