/machines/1RB0LC_1RC0RA_1RD0RF_0LE---_1LB1LA_1LD1RA/check_proof.py · raw
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 | """check_proof.py for #16 1RB0LC_1RC0RA_1RD0RF_0LE---_1LB1LA_1LD1RA (proof.md, stage informal_proof). Every section re-checks claims of proof.md by EXACT simulation of the machine (pure Python, bytearray tape) or by exact integer arithmetic; nothing is read from earlier output files. Exhaustive small boxes plus random large ones. Sections (proof.md section in brackets): A [1] rule table; TM5 of FractalType4.v is this table with states renamed (A..F -> B,C,D,E,A,F) B [3.1] shift rules (single block, exhaustive) and their n-fold forms (random n) C [3.3] staircase: P(a) (TM5's P, renamed) holds exactly for a in the level set S, for a <= AMAX; TM5's Inc1/Incs1 renamed; the 9-step start gadget after P(S) D [3.2] one-trip lemmas BounceE / BounceP with exact step formulas: next left-turn frame, exhaustive box + random E [4] soundness of the whole macro rule set (scripts/macro_sim3.py): from every frame of a small grammar box (and random larger frames) the exact run visits the next K macro frames in order, without halting F [7] initial segment: blank -> base hub 0^inf <A (10)^85 (011010)^7 (10)^46 0^inf in exactly 46,734 steps G [5] invariant H*c4 (scripts/inv4.py Hc4): from blank; random long orbits and random short seeds (narrow generators, supporting evidence only) H [5.3] G-step algebra: zipper families are swapped by B'(k) = 2 tau - B(k-1) (exhaustive small + random) I [6] halting: the only halting precursor (eat of an odd (10)-run) halts; negative controls of E are not met J [5.2] skeptic round 1 repairs: the counterexamples to H*c3 are outside H*c4; Hc4 is total; CP on orbits K [5.5] EXHAUSTIVE back-solved closure boxes (every zipper tail, both modes, clean/level/top): long E and long P (CP) right ends must close in one step (PASS required); short right ends are reported as OPEN (the short-regime clause Hs_K is a look-ahead and is not inductive: proof.md section 8, G1) L [4.4, 5.5, 8] skeptic round 2 (scripts/round2.py): the window start formula (exact), what follows it (exact where ruled; the unruled corners and the glued wall are OPEN); long boxes at S = 168; the short kinds on wider boxes (E1w, P1w, Pt1 OPEN; Et1, Eseg must close); the Reflect-into-top chain (OPEN). Leak counts are lower bounds. M [4.4] round 2: RightEndP with P = 2 at a wall = RightEndP to P = 0 + Absorb0 (exact, with a negative control) OPEN lines document known gaps (they are not counted as PASS or FAIL); SUMMARY lists them. usage: nice -n 10 .venv/bin/python -B check_proof.py [quick] (quick = smaller boxes)""" import sys, os, random, itertools, time, collections HERE = os.path.dirname(os.path.abspath(__file__)) SC = os.path.join(HERE, 'scripts') sys.path.insert(0, SC) sys.set_int_max_str_digits(0) QUICK = len(sys.argv) > 1 and sys.argv[1] == 'quick' TMS = '1RB0LC_1RC0RA_1RD0RF_0LE---_1LB1LA_1LD1RA' TM5 = '1RB0RE_1RC0RF_0LD---_1LA1LE_1RA0LB_1LC1RE' # verify/FractalType4.v Module TM5 def table(s): T = [] for row in s.split('_'): r = [] for j in range(2): x = row[3 * j:3 * j + 3] r.append(None if x == '---' else (int(x[0]), 1 if x[1] == 'R' else -1, 'ABCDEF'.index(x[2]))) T.append(r) return T T = table(TMS) RES = collections.OrderedDict() EVS1 = collections.Counter() # event names met in E1 (used by E2) def report(name, ok, detail='', open_=False): RES[name] = (ok, detail, open_) print('%-58s %s %s' % (name, ('OPEN' if ok else 'FAIL(open item changed)') if open_ else ('PASS' if ok else 'FAIL'), detail), flush=True) # ---------------------------------------------------------------- configurations def parse(s): """'0^inf (10)^3 <A (011010)^2 010 0^inf' -> (cells, head index, state); <S: head on the last cell of the left part; S>: head on the first cell of the right part""" cells = []; head = None; st = None for tk in s.split(): if tk == '0^inf': continue if tk[0] == '<': st = 'ABCDEF'.index(tk[1]); head = len(cells) - 1; continue if tk[-1] == '>': st = 'ABCDEF'.index(tk[0]); head = len(cells); continue if tk[0] == '(': w, n = tk[1:].split(')^') if ')^' in tk else (tk[1:-1], 1) cells += [int(c) for c in w] * int(n) else: cells += [int(c) for c in tk] return cells, head, st def key(t, p): a = t.find(1); b = t.rfind(1) a = min(a, p) if a >= 0 else p; b = max(b, p) return bytes(t[a:b + 1]), p - a def frame_key(s): cells, head, st = parse(s) pad = 8; t = bytearray(pad) + bytearray(cells) + bytearray(pad + 2) return key(t, head + pad) def visit_seq(start, targets, cap, first_only=False): """exact run from start; at every standard left-turn frame (A reads 0 after a left move, cell p-2 = 0) compare with the next target (trimmed tape + head offset). Returns ('ok', steps at each target) / ('halt', n) / ('cap', number matched) / ('miss', number matched) (first_only: the first standard frame must be the target).""" cells, head, st = parse(start) tk = [frame_key(x) for x in targets] pad = min(2 * len(cells) + 400 + cap // 40, 4 * 10 ** 6) t = bytearray(pad) + bytearray(cells) + bytearray(pad); p = pad + head lastL = any(x.startswith('<') for x in start.split()) lo = min(pad, p); hi = max(pad + len(cells), p) i = 0; n = 0; at = [] TT = T while n < cap: if st == 0 and lastL and t[p] == 0 and t[p - 2] == 0 and n > 0: w = t[lo:hi + 1]; a = w.find(1); b = w.rfind(1) a = min(a + lo, p) if a >= 0 else p; b = max(b + lo, p) if (p - a) == tk[i][1] and t[a:b + 1] == tk[i][0]: at.append(n); i += 1 if i == len(tk): return ('ok', at) elif first_only: return ('miss', i) tr = TT[st][t[p]] if tr is None: return ('halt', n) t[p] = tr[0]; p += tr[1]; st = tr[2]; n += 1; lastL = tr[1] < 0 if p < lo: lo = p if p < 3: return ('cap', i) elif p > hi: hi = p if p > len(t) - 3: return ('cap', i) return ('cap', i) # ---------------------------------------------------------------- A def sec_A(): T5 = table(TM5); ren = {0: 1, 1: 2, 2: 3, 3: 4, 4: 0, 5: 5} # TM5 A..F -> #16 B,C,D,E,A,F ok = True for s5 in range(6): for r in range(2): a, b = T5[s5][r], T[ren[s5]][r] if a is None or b is None: ok &= (a is None and b is None) else: ok &= (a[0], a[1], ren[a[2]]) == b report('A1 TM5 (FractalType4.v) = #16 under A..F -> B,C,D,E,A,F', ok) und = [(s, r) for s in range(6) for r in range(2) if T[s][r] is None] report('A2 one undefined transition, D1', und == [(3, 1)], str(und)) # A3: every halting run of length <= 3 from any state/window passes B reading 0, then C reading 0, then D reading 1 # (D is entered only by C0 and F0; F only by C1, which writes the 0 that F0 sends D back to; C by A1, which writes # the 0 that C0 sends D onto, or by B0). So the only halting pattern is B> 0 0 1. seqs = set(); n = 0 for st in range(6): for w in itertools.product([0, 1], repeat=7): t = list(w); p = 3; s_ = st; hist = [] for k in range(2): tr = T[s_][t[p]] if tr is None: break hist.append(('ABCDEF'[s_], t[p])); t[p] = tr[0]; p += tr[1]; s_ = tr[2] if len(hist) == 2 and T[s_][t[p]] is None: seqs.add(tuple(hist)); n += 1 ok = seqs == {(('B', 0), ('C', 0))} preds = sorted({('ABCDEF'[s_], r) for s_ in range(6) for r in range(2) if T[s_][r] and T[s_][r][2] == 3}) report('A3 halting needs B> 0 0 1 (D entered by C0/F0 only)', ok and preds == [('C', 0), ('F', 0)], 'D entered by %s; every 2-step history before D1 is %s (%d windows)' % (preds, sorted(seqs), n)) # ---------------------------------------------------------------- B def run_window(w, st, pos, nmax=10 ** 5): w = list(w); n = 0 while 0 <= pos < len(w): tr = T[st][w[pos]] if tr is None: return None w[pos] = tr[0]; pos += tr[1]; st = tr[2]; n += 1 if n > nmax: return None return ('R' if pos >= len(w) else 'L', st, w, n) SHIFTS = [ # (direction, state in, word, word out, state out, steps) proof.md 3.1 ('R', 'A', '01', '10', 'A', 2), ('R', 'B', '10', '01', 'B', 2), ('R', 'B', '011010', '101101', 'B', 6), ('L', 'A', '01', '10', 'A', 4), ('L', 'E', '110110', '011010', 'E', 14), ('L', 'A', '101101', '100110', 'A', 14), ] def sec_B(): ok = True; bad = [] for d, si, w, wo, so, ns in SHIFTS: wl = [int(c) for c in w]; s = 'ABCDEF'.index(si) r = run_window(wl, s, 0 if d == 'R' else len(wl) - 1) good = r is not None and r[0] == d and r[1] == 'ABCDEF'.index(so) and ''.join(map(str, r[2])) == wo and r[3] == ns ok &= good if not good: bad.append((d, si, w)) # n-fold form, random n, inside random context (context must not matter: window never left) for n in [1, 2, 3, 7, random.randint(8, 60)]: r = run_window(wl * n, s, 0 if d == 'R' else len(wl) * n - 1) good = r is not None and r[0] == d and ''.join(map(str, r[2])) == wo * n and r[3] == ns * n ok &= good if not good: bad.append((d, si, w, n)) report('B1 shift rules (6 rules, single block + n-fold)', ok, '%d rules %s' % (len(SHIFTS), bad[:2])) # B2 right turn: x B> 010 010 -->(5) x <A 101010, for any cell x (5 steps B0 C1 F0 D0 E1, D reads the 0 C1 wrote) ok = True for x in (0, 1): t = [x, 0, 1, 0, 0, 1, 0]; p = 1; st = 1 for k in range(5): tr = T[st][t[p]]; t[p] = tr[0]; p += tr[1]; st = tr[2] ok &= p == 0 and st == 0 and t == [x, 1, 0, 1, 0, 1, 0] report('B2 right turn x B> 010 010 -->(5) x <A 101010', ok) # ---------------------------------------------------------------- C def levels(n): S = [0] while S[-1] <= n: S.append(2 * S[-1] + (3 if S[-1] % 2 == 0 else 2)) return S def P_holds(a, ctx, cap=10 ** 7): """TM5's P a renamed: l (01)^a B> 0^inf -->* l <C 01 (010)^a 0^inf, with the run never reading l""" lc = list(ctx); pad = 4 t = [0] * pad + lc + [0, 1] * a + [0] * (3 * a + 60); lo = pad + len(lc); p = lo + 2 * a; st = 1; n = 0 while n < cap: tr = T[st][t[p]] if tr is None: return ('halt', n) t[p] = tr[0]; p += tr[1]; st = tr[2]; n += 1 if p < lo: if st == 2 and p == lo - 1 and t[lo:lo + 2 + 3 * a] == [0, 1] + [0, 1, 0] * a and not any(t[lo + 2 + 3 * a:]): return ('ok', n) return ('left', n) return ('cap', n) def S1(a, b, c, d): # TM5 S1 l a b c d = l (01)^a <A 1 (011010)^b (10)^c 0 (100)^d 0^inf; TM5 A = #16 B return '0^inf 1 (01)^%d <B 1 (011010)^%d (10)^%d 0 (100)^%d 0^inf' % (a, b, c, d) def sec_C(): AMAX = 60 if QUICK else 130 L = levels(AMAX); hold = [a for a in range(AMAX + 1) if P_holds(a, [1, 1, 0, 1])[0] == 'ok'] report('C1 P(a) holds exactly for a in S = {0,3,8,19,40,83,...}, a<=%d' % AMAX, hold == [x for x in L if x <= AMAX], str(hold)) ok = True for S in [x for x in levels(2000) if x <= 1400]: for ctx in ([], [1], [1, 0, 1], [0, 1, 1, 0, 1, 0]): ok &= P_holds(S, ctx, cap=10 ** 8)[0] == 'ok' report('C2 P(S) for S in levels <= 1400, 4 left contexts (l never read)', ok) # Inc1 renamed: S1 l (2+a) b c (2+d) -->* S1 l a (1+b) (2+c) d ok = True; cnt = 0 box = itertools.product(range(0, 4), range(0, 3), range(0, 3), range(0, 4)) if True else [] for a, b, c, d in box: r = visit_any(S1(2 + a, b, c, 2 + d), S1(a, 1 + b, 2 + c, d), 'C', 10 ** 5); ok &= r; cnt += 1 for _ in range(20 if QUICK else 60): a, b, c, d = [random.randint(0, 40) for _ in range(4)]; n = random.randint(1, 30) r = visit_any(S1(2 * n + a, b, c, 2 * n + d), S1(a, n + b, 2 * n + c, d), 'C', 10 ** 7); ok &= r; cnt += 1 report('C3 TM5 Inc1 / Incs1 renamed (box 4x3x3x4 + random n)', ok, '%d instances' % cnt) # start gadget: l (01)^m <C 01 (010)^S 0^inf -->(9) l (10)^(m-2) <A (10)(011010)(010)^(S-1) 0^inf, m >= 2 ok = True; cnt = 0 for S in [x for x in levels(500) if x >= 1 and x <= 400]: for m in list(range(2, 8)) + [random.randint(8, 300)]: st = '0^inf 1 (01)^%d <C 01 (010)^%d 0^inf' % (m, S) tg = '0^inf 1 0 (10)^%d <A (10) (011010) (010)^%d 0^inf' % (m - 2, S - 1) r = visit_seq(st, [tg], 50, first_only=True); ok &= r[0] == 'ok' and r[1] == [9]; cnt += 1 report('C4 start gadget after P(S): 9 steps to the fresh bouncer', ok, '%d instances' % cnt) def visit_any(start, target, st_letter, cap): """run until the configuration (tape key + head + state) equals target's (any state letter)""" c0, h0, s0 = parse(start); c1, h1, s1 = parse(target) pad = 400 + cap // 20; pad = min(pad, 2 * 10 ** 6) t = bytearray(pad) + bytearray(c0) + bytearray(pad); p = pad + h0; st = s0 t1 = bytearray(pad) + bytearray(c1) + bytearray(pad); k1 = key(t1, pad + h1) n = 0 while n < cap: tr = T[st][t[p]] if tr is None: return False t[p] = tr[0]; p += tr[1]; st = tr[2]; n += 1 if st == s1 and t[p] == t1[pad + h1] and key(t, p) == k1: return True return False # ---------------------------------------------------------------- D def ystr(Y): s = ' (10)^%d' % Y[0] if Y[0] else '' for i in range(1, len(Y), 2): s += ' (011010)^%d' % Y[i] + (' (10)^%d' % Y[i + 1] if Y[i + 1] else '') return s ZS = ['', ' (011010)^1 (10)^2 (010)^1', ' (10)^2 (010)^3', ' (011010)^2 (10)^4 (010)^2 (011010)^1 (10)^2 (010)^1'] XS = ['', ' (10)^2 (101)^2', ' (10)^5 (101)^3 (10)^4 (101)^4'] def bounceE(Y, d, Z): B = sum(Y[1::2]); A = sum(Y[0::2]) st = '0^inf <A' + ystr(Y) + ' (010)^%d' % (d + 2) + Z + ' 0^inf' Y2 = list(Y); Y2[0] += 2; Y2[-1] += 2 tg = '0^inf <A' + ystr(Y2) + (' (010)^%d' % d if d else '') + Z + ' 0^inf' return st, tg, 10 + 20 * B + 6 * A def bounceP(X, P, Y, d, Z): B = sum(Y[1::2]); Ap = sum(Y[2::2]) st = '0^inf' + X + ' (10)^%d <A' % (P + 2) + ystr(Y) + ' (010)^%d' % (d + 2) + Z + ' 0^inf' Y2 = list(Y); Y2[1] += 1; Y2[-1] += 2 tg = '0^inf' + X + ' (10)^%d <A' % P + ystr(Y2) + (' (010)^%d' % d if d else '') + Z + ' 0^inf' return st, tg, 22 + 20 * B + 6 * Ap def ys(nseg, vals, a0vals, akvals): for a0 in a0vals: for k in range(1, nseg + 1): for inner in itertools.product(vals, repeat=2 * k - 1): bs = inner[0::2]; ais = inner[1::2] for ak in akvals: Y = [a0] for j in range(k): Y += [bs[j], ais[j] if j < k - 1 else ak] yield Y def sec_D(): vals = [1, 2] if QUICK else [1, 2, 3] ok = True; cnt = 0; bad = [] for Y in ys(2, vals, [1, 2, 3, 4], [0, 1, 2, 3]): for d in [0, 1, 2, 3]: for Z in ZS[:3]: st, tg, ns = bounceE(Y, d, Z) r = visit_seq(st, [tg], ns + 5, first_only=True); g = r[0] == 'ok' and r[1] == [ns] ok &= g; cnt += 1 if not g and len(bad) < 3: bad.append((Y, d, Z, r)) for _ in range(30 if QUICK else 100): Y = [random.randint(1, 200)] for j in range(random.randint(1, 4)): Y += [random.randint(1, 200), 2 * random.randint(1, 100)] Y[-1] = random.randint(0, 200); d = random.randint(0, 300); Z = random.choice(ZS) st, tg, ns = bounceE(Y, d, Z) r = visit_seq(st, [tg], ns + 5, first_only=True); g = r[0] == 'ok' and r[1] == [ns]; ok &= g; cnt += 1 if not g and len(bad) < 3: bad.append((Y, d, Z, r)) report('D1 BounceE: next frame, steps 10+20B+6A', ok, '%d instances %s' % (cnt, bad[:1])) ok = True; cnt = 0; bad = [] for Y in ys(2, vals, [1], [0, 1, 2, 3]): for P in [2, 3, 4, 5]: for d in [0, 1, 2, 3]: for Z in ZS[:3]: for X in XS[:2]: st, tg, ns = bounceP(X, P, Y, d, Z) r = visit_seq(st, [tg], ns + 5, first_only=True); g = r[0] == 'ok' and r[1] == [ns] ok &= g; cnt += 1 if not g and len(bad) < 3: bad.append((X, P, Y, d, Z, r)) for _ in range(30 if QUICK else 100): Y = [1] for j in range(random.randint(1, 4)): Y += [random.randint(1, 200), 2 * random.randint(1, 100)] Y[-1] = random.randint(0, 200); d = random.randint(0, 300); Z = random.choice(ZS); X = random.choice(XS) P = random.randint(2, 300) st, tg, ns = bounceP(X, P, Y, d, Z) r = visit_seq(st, [tg], ns + 5, first_only=True); g = r[0] == 'ok' and r[1] == [ns]; ok &= g; cnt += 1 if not g and len(bad) < 3: bad.append((X, P, Y, d, Z, r)) report('D2 BounceP: next frame, steps 22+20B+6A\'', ok, '%d instances %s' % (cnt, bad[:1])) # ---------------------------------------------------------------- E import macro_sim3 as MS from corner_hybrid import mtostr def macro_targets(m0, K, maxev=400): """the next macro frames after m0 (K non-bounce events, every frame recorded)""" ev = []; out = []; m = m0; n = 0 for _ in range(maxev): m = MS.step(m, ev) out.append(m) if ev[-1] not in ('BounceP', 'BounceE'): n += 1 if n >= K: break return out, ev def standard(m): return (m.edge or m.P >= 2 or (m.P == 1 and not m.X)) and all(p >= 0 for p, q in m.X) def box_frames(quick): v = [1, 2] if quick else [1, 2, 3] Ys = list(ys(2, v, [1], [0, 1, 2, 4])) Zs = [[], [([1, 2], 1)], [([1, 2], 0)], [([2, 4], 2)], [([1, 2], 2), ([1, 2], 1)]] Xs = [[], [(2, 2)], [(3, 3)], [(4, 2)], [(1, 1)], [(2, 2), (5, 3)]] for X in Xs: for P in [1, 2, 3, 4, 5, 6]: for Y in Ys: for d in [0, 1, 2, 3, 4, 5]: for Z in Zs: yield MS.M(False, X, P, Y, d, Z) for a0 in [1, 2, 3, 5]: for Y in Ys: for d in [0, 1, 2, 3, 4]: for Z in Zs: Y2 = [a0] + Y[1:] yield MS.M(True, [], 0, Y2, d, Z) def check_macro(m0, K, cap): try: tg, ev = macro_targets(m0, K) except (MS.Unruled, ValueError, IndexError) as e: return 'unruled', str(e)[:30], None # outside every rule's domain tgs = [x for x in tg if standard(x)] if not tgs: return 'skip', None, None strs = [mtostr(x) for x in tgs] if sum(len(s) for s in strs) > 20000: return 'skip', None, None r = visit_seq(mtostr(m0), strs, cap) return r[0], tuple(e for e in ev if e not in ('BounceP', 'BounceE')), strs def sec_E(): K = 3; cnt = collections.Counter(); evs = collections.Counter(); bad = []; t0 = time.time() for m0 in box_frames(QUICK): if not m0.edge and m0.Y[0] != 1: continue r, ev, strs = check_macro(m0, K, 3 * 10 ** 6) cnt[r] += 1 if r == 'ok': for e in ev: evs[e] += 1 elif r not in ('unruled', 'skip') and len(bad) < 4: bad.append((repr(m0), r, ev)) ok = cnt['ok'] > 0 and all(k in ('ok', 'unruled', 'skip') for k in cnt) report('E1 macro rules sound on the small box (K=%d events)' % K, ok, '%s (%.0f s) %s' % (dict(cnt), time.time() - t0, bad[:2])) print(' event counts in E1:', dict(evs.most_common())) EVS1.update(evs) # random larger frames with walls / chunks, both modes, values up to 60 cnt = collections.Counter(); bad = []; evs2 = collections.Counter(); t0 = time.time(); n = 0 while n < (150 if QUICK else 600): edge = random.random() < 0.3 Y = [random.choice([1, 3, 5, 2 * random.randint(1, 30) + 1]) if edge else 1] for j in range(random.choice([1, 1, 2, 3])): Y += [random.randint(1, 30), 2 * random.randint(1, 15)] Y[-1] = random.randint(0, 40) X = [] if not edge: for j in range(random.choice([0, 0, 1, 2])): q = random.randint(1, 30); X.append((q % 2 + 2 * random.randint(1, 15), q)) Z = [] for j in range(random.choice([0, 0, 1, 2])): L = [random.randint(1, 10), 2 * random.randint(1, 8)] if random.random() < 0.3: L += [random.randint(1, 10), 2 * random.randint(1, 8)] Z.append((L, random.randint(1, 20))) m0 = MS.M(edge, X, 0 if edge else random.randint(2, 60), Y, random.randint(0, 60), Z) r, ev, strs = check_macro(m0, 3, 3 * 10 ** 7) if r == 'skip': continue n += 1; cnt[r] += 1 if r == 'ok': for e in ev: evs2[e] += 1 elif r != 'unruled' and len(bad) < 4: bad.append((repr(m0), r, ev)) for _ in range(60 if QUICK else 300): # rare families: EatChunkP (P large, d = 1), EatLast, V1 with d = 1 kind = random.choice(['eatP', 'eatlast', 'v1d1']) Y = [1, random.randint(1, 9), random.randint(0, 9)] if kind == 'eatP': L = [random.randint(1, 5), 2 * random.randint(1, 5)]; B, A = L m0 = MS.M(False, random.choice([[], [(4, 2)]]), 4 * B + 2 * A + 2 + random.randint(0, 9), Y, 1, [(L, random.randint(1, 9))]) elif kind == 'eatlast': L = [random.randint(1, 5), 2 * random.randint(1, 5) - 1]; B, A = L m0 = MS.M(False, [], 4 * B + 2 * A + 2 + random.randint(0, 9), Y, 1, [(L, 0)]) else: q = random.randint(1, 12); m0 = MS.M(False, [(q + 3 + random.randint(0, 9), q)], 3, Y, 3, []) r, ev, strs = check_macro(m0, 3, 3 * 10 ** 7) if r == 'skip': continue cnt[r] += 1 if r == 'ok': for e in ev: evs2[e] += 1 elif r != 'unruled' and len(bad) < 4: bad.append((repr(m0), r, ev)) ok = all(k in ('ok', 'unruled') for k in cnt) report('E2 macro rules sound on random frames (values <= 60)', ok, '%s (%.0f s) %s' % (dict(cnt), time.time() - t0, bad[:2])) print(' event counts in E2:', dict(evs2.most_common())) # negative controls: perturb the first target by one unit; the exact run must not visit it (same budget) random.seed(7); nn = 0; hit = 0 for m0 in box_frames(True): if nn >= (20 if QUICK else 60): break if not m0.edge and m0.Y[0] != 1: continue try: tg, ev = macro_targets(m0, 1) except (MS.Unruled, ValueError, IndexError): continue tgs = [x for x in tg if standard(x)] if not tgs or random.random() < 0.7: continue m1 = tgs[-1].copy(); m1.Y[-1] += 1 nn += 1; r = visit_seq(mtostr(m0), [mtostr(m1)], 2 * 10 ** 5); hit += r[0] == 'ok' report('E3 negative controls (target ak+1) not reached', hit == 0, '%d/%d reached' % (hit, nn)) # ---------------------------------------------------------------- F def sec_F(): target = '0^inf <A (10)^85 (011010)^7 (10)^46 0^inf' r = visit_seq('0^inf A> 0^inf', [target], 50000) # exactness: blank start has lastL False; first standard frame equal to the hub must be at 46,734 report('F1 blank -> base hub [85,7,46] at step 46,734', r[0] == 'ok' and r[1] == [46734], str(r)) # the macro orbit from the base hub against exact simulation: first right ends, in order m = MS.M(True, [], 0, [85, 7, 46], 0, []); ev = []; fr = [] while len(fr) < (40 if QUICK else 120): m = MS.step(m, ev) if standard(m): fr.append(mtostr(m)) if sum(len(x) for x in fr[-1:]) > 30000: break cap = 10 ** 7 if QUICK else 6 * 10 ** 7 r = visit_seq('0^inf <A (10)^85 (011010)^7 (10)^46 0^inf', fr, cap) got = len(r[1]) if r[0] == 'ok' else r[1] report('F2 macro orbit from the base hub = exact run, in order', r[0] in ('ok', 'cap') and got >= 25, '%d of %d macro frames met in order within %d steps (%s)' % (got, len(fr), cap, r[0])) # ---------------------------------------------------------------- G def sec_G(): os.environ.setdefault('LOOKK', '4') import seed_clause as SCL, hubinv_H, inv4 t0 = time.time() o = SCL.orbit((True, [], 0, [85, 7, 46]), 600 if QUICK else 2000) bad = [i for i, (x, e) in enumerate(o) if inv4.Hc4(x)] report('G1 H*c4 at every right end from blank (%d)' % len(o), not bad, '(%.0f s) %s' % (time.time() - t0, bad[:3])) for smax, seed in ((5459, 11), (1e30, 12)): random.seed(seed); n = 0; leaks = collections.Counter(); t0 = time.time(); nre = 0 N = 150 if QUICK else 600 while n < N: R = hubinv_H.rnd_R(random.choice(['Rc', 'Rt']), 0, smax) if R is None or hubinv_H.H(R) is not None: continue n += 1 try: oo = SCL.orbit(R, 20) except MS.Unruled as e: leaks['unruled ' + str(e)[:30]] += 1; continue for x, ev in oo[1:]: nre += 1; h = inv4.Hc4(x) if h: leaks[h] += 1; break report('G2 rnd_R long orbits (narrow generator), 20 trav., S<=%g' % smax, not leaks, '%d orbits, %d right ends, leaks %s (%.0f s)' % (N, nre, dict(leaks), time.time() - t0)) for smax, seed in ((5459, 13), (1e30, 14)): random.seed(seed); n = 0; leaks = collections.Counter(); t0 = time.time(); kinds = collections.Counter() N = 150 if QUICK else 600 while n < N: r = SCL.rnd_short(smax) if r is None: continue kind, R = r if inv4.Hc4(R): continue n += 1; kinds[kind] += 1 try: oo = SCL.orbit(R, 20) except MS.Unruled as e: leaks['unruled ' + str(e)[:30]] += 1; continue for x, ev in oo[1:]: h = inv4.Hc4(x) if h: leaks[h] += 1; break report('G3 rnd_short seeds in H*c4 (narrow generator), S<=%g' % smax, not leaks, '%d seeds %s, leaks %s (%.0f s)' % (N, dict(kinds), dict(leaks), time.time() - t0)) # ---------------------------------------------------------------- J def sec_J(): """skeptic round 1: counterexamples to H*c3 (all in H*c3, all outside H*c4); totality; CP on orbits""" import seed_clause as SCL, inv4 cases = [ # (R, clause of H*c4 that rejects it, what the skeptic found) ((True, [], 0, [9, 20, 24, 2, 24, 20, 39]), "H2t'", 'next right end [73,4,40,12,4,12,79] is a window'), ((True, [], 0, [35, 13, 30, 14, 18, 2, 40]), 'HL', 'gives a P-mode right end with walls'), ((True, [], 0, [79, 2, 40, 1, 40]), 'HL', 'unruled RightEndP P=2 with walls'), ((False, [], 5, [1, 27, 28, 15, 14, 1, 41]), 'CP', 'next E hub [257,2,104] has b1 even'), ((False, [], 1, [1, 41, 40, 1, 41]), 'CP', 'unruled V1 d=1 at the p=-1 wall'), ((False, [], 23, [1, 9, 8, 1, 9]), 'CP', 'unruled EatLast runs out of P')] ok = True; det = [] for R, cl, why in cases: h3 = SCL.Hc3(R); h4 = inv4.Hc4(R) good = h3 is None and h4 is not None and h4.startswith(cl) ok &= good; det.append('%s:%s' % (cl, 'ok' if good else (h3, h4))) report('J1 skeptic counterexamples: in H*c3, rejected by H*c4', ok, ' '.join(map(str, det))) # totality: Hc4 never raises on a small box of short right ends, incl. the E hub [12,2,2] (Hc3 raised TypeError) n = 0; err = []; old_err = 0 for ak in range(1, 23): for b1 in range(1, 9): for a in range(1, 25): for R in ((True, [], 0, [a, b1, ak]), (False, [], a, [1, b1, ak])): n += 1 try: inv4.Hc4(R) except Exception as e: err.append((R, type(e).__name__)) try: SCL.Hc3(R) except TypeError: old_err += 1 except Exception: pass report('J2 Hc4 is total (no exception) on a box of short right ends', not err and old_err > 0, '%d right ends, %d exceptions (Hc3 raised TypeError on %d of them)' % (n, len(err), old_err)) # round 2: fuzz with degenerate tuples (ak <= 0, segment-less [0], negative entries, walls, P <= 0) rs = random.getstate(); random.seed(11); err = []; cnt = collections.Counter() def rv(): return random.choice([0, 1, 2, 3, random.randrange(-1, 12), random.randrange(1, 400), 2 * random.randrange(1, 200)]) for i in range(10000 if QUICK else 60000): edge = random.random() < 0.5; k = random.choice([0, 0, 1, 1, 2, 3, 5]) Y = [rv() for _ in range(2 * k + 1)] X = [] if random.random() < 0.9 else [(rv(), rv())] P = 0 if edge else random.choice([0, 1, 2, 3, rv()]) try: h = inv4.Hc4((edge, X, P, Y)); cnt['member' if h is None else ('degenerate' if h.startswith('H0 degen') else 'rejected')] += 1 except Exception as e: err.append(((edge, X, P, Y), type(e).__name__)) random.setstate(rs) report('J2b Hc4 total on fuzzed tuples incl. degenerate ones', not err, '%s, %d exceptions %s' % (dict(cnt), len(err), err[:2])) c = inv4.cp_test(31, 100 if QUICK else 300, 5459) report('J3 CP: every long P-mode right end on orbits has P = 2B(3)-2tau+3', c['CP holds'] == c['long P-mode right ends'] > 0, '%d/%d (blank 1,500 right ends + rnd_R orbits x 40)' % (c['CP holds'], c['long P-mode right ends'])) # ---------------------------------------------------------------- K def sec_K(): """exhaustive back-solved boxes: every tail of the zipper at the given levels, every length up to MMAX pairs""" import inv4, io, contextlib def quiet(f, *a): buf = io.StringIO() with contextlib.redirect_stdout(buf): r = f(*a) return r t0 = time.time(); c, lk = quiet(inv4.box, 'E', [3, 8, 19, 40], 8) report('K1 long E hubs, S<=40, <=8 pairs: next right end in H*c4', c['members'] > 20000 and not lk, '%d members of %d candidates, next in H*c4 %d, leaks %d %s (%.0f s)' % (c['members'], c['candidates'], c['next in H*c4'], sum(lk.values()), dict(lk), time.time() - t0)) t0 = time.time(); c, lk = quiet(inv4.box, 'P', [3, 8, 19, 40], 6) report('K2 long P-mode right ends (P from CP), S<=40: next in H*c4', c['members'] > 15000 and not lk, '%d members of %d candidates, next in H*c4 %d (all next short: %d), leaks %d %s (%.0f s)' % (c['members'], c['candidates'], c['next in H*c4'], c['next short'], sum(lk.values()), dict(lk), time.time() - t0)) if not QUICK: t0 = time.time(); c, lk = quiet(inv4.box, 'E', [83], 8) report('K3 long E hubs, S=83, <=8 pairs: next right end in H*c4', c['members'] > 180000 and not lk, '%d members, next in H*c4 %d, leaks %d (%.0f s)' % (c['members'], c['next in H*c4'], sum(lk.values()), time.time() - t0)) if not QUICK: # one two-step leak at S = 83: long E -> long P -> window E hub [1485,15,335] (OPEN, proof.md section 8 G2) t0 = time.time(); c, lk = quiet(inv4.box, 'P', [83], 6) report('K6 long P-mode right ends (CP), S=83: next in H*c4', sum(lk.values()) == 1 and lk.get('next not in H*c4: H2 window') == 1, '%d members, next in H*c4 %d, leaks %d %s (%.0f s) -- the leak is P=31 [1,35,36,34,52,30,56,29,110,82,164] -> window hub [1485,15,335]' % ( c['members'], c['next in H*c4'], sum(lk.values()), dict(lk), time.time() - t0), open_=True) # short right ends: the look-ahead clause Hs_4 is not inductive (OPEN, proof.md section 8 G1) t0 = time.time(); leaks = collections.Counter(); mem = 0; ex = [] for ak in range(1, 41): for b1 in range(1, 21): for a in range(1, 81): R = (True, [], 0, [a, b1, ak]) if inv4.Hc4(R): continue mem += 1 o, err = inv4.succ(R) if err: leaks[err] += 1; ex.append(R); continue h = inv4.Hc4(o[1][0]) if h: leaks[h.split(':')[0]] += 1; ex.append(R) report('K4 short E hubs [a0<=80,b1<=20,ak<=40] in H*c4: next in H*c4', bool(leaks) and all(tuple(R[3]) in ((79, 12, 32), (77, 12, 34), (75, 12, 36)) for R in ex), '%d members, %d leak %s: %s -- Hs_4 is a look-ahead and not inductive (%.0f s)' % (mem, len(ex), dict(leaks), [R[3] for R in ex], time.time() - t0), open_=True) o = inv4.orbit((True, [], 0, [79, 12, 32]), 9) seq = [('E' if x[0] else 'P%d' % x[2]) + ('W' if x[1] else '') for x, ev in o] walls = [i for i, (x, ev) in enumerate(o) if x[1]] report('K5 [79,12,32]: short chain reaches a P-mode right end with walls', bool(walls), 'right ends %s; walls at index %s; outside H*c4 at %s' % (' '.join(seq), walls, [i for i, (x, ev) in enumerate(o) if inv4.Hc4(x)]), open_=True) # ---------------------------------------------------------------- L def sec_L(): """skeptic round 2: the window family, wider short boxes, multi-step chains (scripts/round2.py)""" import inv4, round2 as R2, io, contextlib def quiet(f, *a): buf = io.StringIO() with contextlib.redirect_stdout(buf): r = f(*a) return r # L1: the Clean start formula also holds for window right ends (exact) rng = random.Random(21); n = 0; bad = []; t0 = time.time(); dl = collections.Counter() for S in ([8, 19, 40] if QUICK else [8, 19, 40, 83]): Sn = 2 * S + (3 if S % 2 == 0 else 2) for ak in range(2 * S - 1, Sn - 1): for _ in range(3 if QUICK else 6): kind = rng.choice(['E1', 'E2', 'P1', 'P2']) b1 = rng.randint(1, 30); a1 = 2 * rng.randint(1, 30); b2 = rng.randint(1, 30) if kind[0] == 'E': Y = [2 * rng.randint(0, 60) + 1, b1] + ([a1, b2] if kind == 'E2' else []) + [ak] m0 = MS.M(True, [], 0, Y, 0, []); V = MS.hub_walls(Y, (Y[0] - 1, 2 * Y[1])) else: P = 2 * rng.randint(1, 60) + 1; Y = [1, b1] + ([a1, b2] if kind == 'P2' else []) + [ak] m0 = MS.M(False, [], P, Y, 0, []); V = MS.hub_walls(Y, (P - 2, 2 * Y[1] + 1)) tgt = MS.M(False, MS.normX(V), ak - S, [1, 1, 0], S - 1, []) r = visit_seq(mtostr(m0), [mtostr(tgt)], 3 * 10 ** 6) n += 1; dl[ak - 2 * S + 1] += 1 if r[0] != 'ok': bad.append((kind, Y, r)) report('L1 window right end: Clean start F_P(V, ak-S, [1,1,0], S-1)', not bad, '%d window right ends (S<=%d, delta counts %s), %d misses %s (%.0f s)' % (n, 40 if QUICK else 83, dict(dl), len(bad), bad[:2], time.time() - t0)) # L2: with the WindowStart rule, delta = 0 window right ends are ruled by the existing rules (exact, 3 events); # delta in {1, 2} stop at RightEndP P in {2,3} with walls or a V1 right end with walls rng = random.Random(22); cnt = collections.Counter(); bad = []; t0 = time.time(); why = collections.Counter() with R2.window_patch(): for S in ([8, 19, 40] if QUICK else [8, 19, 40, 83]): Sn = 2 * S + (3 if S % 2 == 0 else 2) for ak in range(2 * S - 1, Sn - 1): dlt = ak - 2 * S + 1 for _ in range(6 if QUICK else 15): Y = [2 * rng.randint(1, 60) + 1, rng.randint(1, 30)] + ([2 * rng.randint(1, 30), rng.randint(1, 30)] if rng.random() < 0.5 else []) + [ak] m0 = MS.M(True, [], 0, Y, 0, []) ch = R2.chain((True, [], 0, Y), 1) if ch[0][0] == 'UNRULED': cnt['delta %d unruled' % dlt] += 1; why['delta %d: %s' % (dlt, ch[0][1][:28])] += 1; continue cnt['delta %d ruled' % dlt] += 1 r = check_macro(m0, 3, 3 * 10 ** 6) if r[0] not in ('ok', 'skip', 'cap'): bad.append((Y, r[0], r[1])) cnt['exact ' + r[0]] += 1 report('L2 WindowStart + existing rules: exact (3 events) wherever ruled', not bad and cnt['exact ok'] > 0, '%s, %d exact misses %s (%.0f s)' % (dict(cnt), len(bad), bad[:2], time.time() - t0)) report('L2b WindowStart: the unruled cases (RightEndP P<=3 at a wall, V1 right end with walls)', len(why) > 0, '%s -- delta in {1,2} always, delta = 0 when a Push1End is followed by a V1 right end at the next wall, ' 'e.g. [25,6,28,13,79] (proof.md 4.4, 8 G2)' % dict(why), open_=True) # L3: the V1 right end with walls writes (101)^q 1 (101)^r: a left word outside the grammar ('111' never occurs in # a wall stack (10)^p (101)^q); exact run from the delta = 1 window hub [21,3,38] (S = 19) cells, head, st = parse('0^inf <A (10)^21 (011010)^3 (10)^38 0^inf') pad = 20000; t = bytearray(pad) + bytearray(cells) + bytearray(pad); p = pad + head; nst = 0; found = None; lastL = True while nst < 2 * 10 ** 6 and found is None: tr = T[st][t[p]] if tr is None: found = ('halt', nst); break t[p] = tr[0]; p += tr[1]; st = tr[2]; nst += 1 if st == 0 and tr[1] < 0 and t[p] == 0: left = bytes(t[max(0, p - 4000):p + 1]) if b'\x01\x01\x01' in left: found = ('glued wall', nst) report('L3 delta=1 window hub [21,3,38]: left word (101)^q 1 (101)^r appears', bool(found) and found[0] == 'glued wall', '%s -- a tape form outside the grammar of proof.md section 2' % (found,), open_=True) if QUICK: return # L4/L5: long boxes at S = 168 (one step) t0 = time.time(); c, lk = quiet(inv4.box, 'P', [168], 6) report('L4 long P box S=168 (<=6 pairs, CP): next in H*c4', True, '%d members, next in H*c4 %d, leaks %d %s (%.0f s) -- the window family (lower bound)' % ( c['members'], c['next in H*c4'], sum(lk.values()), dict(lk), time.time() - t0), open_=True) t0 = time.time(); c, lk = quiet(inv4.box, 'E', [168], 8) report('L5 long E box S=168 (<=8 pairs): next right end in H*c4 (one step)', c['members'] > 10 ** 6 and not lk, '%d members, next in H*c4 %d, leaks %d (%.0f s)' % (c['members'], c['next in H*c4'], sum(lk.values()), time.time() - t0)) ch = R2.chain((True, [], 0, [201, 36, 136, 52, 120, 56, 116, 57, 226, 138, 275]), 2) report('L5b two-step window leak from a long E member at S=168', inv4.Hc4((True, [], 0, [201, 36, 136, 52, 120, 56, 116, 57, 226, 138, 275])) is None and ch[0][2] is None and ch[1][2] == 'H2 window', '[201,36,136,52,120,56,116,57,226,138,275] -> P%d %s -> %s' % (ch[0][0][2], ch[0][0][3], ch[1][0][3]), open_=True) # L6: short kinds on wider boxes (the skeptic's round-2 boxes) for mode, expect_clean in (('Et1', True), ('Eseg', True), ('P1w', False), ('E1w', False), ('Pt1', False)): t0 = time.time(); c, lk, ex = quiet(R2.short_box, mode) det = '%d members of %d, next in H*c4 %d, leaks %d %s (%.0f s)' % (c['members'], c['candidates'], c['next in H*c4'], sum(lk.values()), dict(lk), time.time() - t0) if expect_clean: report('L6 short box %s: next in H*c4' % mode, c['members'] > 0 and not lk, det) else: report('L6 short box %s: next in H*c4' % mode, True, det + ' e.g. %s' % (str(list(ex.values())[:1])[:160]), open_=True) # L7: an H*c4 member reaches an unruled 'reflect not clean' (U24) within 4 traversals ch = R2.chain((True, [], 0, [255, 35, 3]), 6) report('L7 [255,35,3] (in H*c4) reaches an unruled event', inv4.Hc4((True, [], 0, [255, 35, 3])) is None and ch[-1][0] == 'UNRULED', ' -> '.join(('P%d ' % x[0][2] if not x[0][0] else 'E ') + str(x[0][3]) if x[0] != 'UNRULED' else 'UNRULED ' + x[1] for x in ch), open_=True) # ---------------------------------------------------------------- M def sec_M(): """skeptic round 2: one corner of the window family ruled -- RightEndP with P = 2 at a wall (row U4) is RightEndP to P = 0 followed by Absorb0 (scripts/round2.py corner_patch); exact for 2 events, plus a negative control""" import round2 as R2 def frames(n, seed): rng = random.Random(seed) for i in range(n): nw = rng.choice([1, 1, 2, 3]) X = [(2 * rng.randint(1, 15), 2 * rng.randint(1, 10)) for _ in range(nw)] Y = [1, rng.randint(1, 12)] + ([2 * rng.randint(1, 10), rng.randint(1, 10)] if rng.random() < 0.4 else []) + [rng.randint(1, 40)] yield MS.M(False, X, 2, Y, 1, []) c = collections.Counter(); bad = []; t0 = time.time() with R2.corner_patch(): for m0 in frames(100 if QUICK else 300, 5): r = check_macro(m0, 2, 4 * 10 ** 6); c[r[0]] += 1 if r[0] not in ('ok', 'unruled', 'skip', 'cap'): bad.append((m0.X, m0.Y, r[0])) report('M1 RightEndP P=2 at a wall = RightEndP to P=0 + Absorb0 (exact, 2 events)', not bad and c['ok'] > 0.7 * sum(c.values()), '%s, %d misses %s (%.0f s)' % (dict(c), len(bad), bad[:2], time.time() - t0)) orig = MS.step; hit = 0; n = 0 def wrong(s, ev): if not s.edge and s.d == 1 and not s.Z and s.P == 2 and s.X: s = s.copy(); s.Y[1] += 1; s.Y[-1] += 2; s.d = 0; s.P = 0; ev.append('Wrong'); MS.absorb(s, 0, ev, 'Absorb0') if not s.edge and s.P < 2: return MS.virtual(s, ev) return s return orig(s, ev) MS.step = wrong try: for m0 in frames(20 if QUICK else 40, 6): r = check_macro(m0, 2, 4 * 10 ** 6) if r[0] == 'unruled': continue n += 1; hit += r[0] == 'ok' finally: MS.step = orig report('M2 negative control (ak + 2 instead of ak + 1) never reached', hit == 0 and n > 0, '%d/%d reached' % (hit, n)) # how much of the window family this corner rule absorbs (macro level only) rng = random.Random(22); why = collections.Counter() with R2.window_patch(), R2.corner_patch(): for S in [8, 19, 40, 83]: Sn = 2 * S + (3 if S % 2 == 0 else 2) for ak in range(2 * S - 1, Sn - 1): for _ in range(15): Y = [2 * rng.randint(1, 60) + 1, rng.randint(1, 30)] + ([2 * rng.randint(1, 30), rng.randint(1, 30)] if rng.random() < 0.5 else []) + [ak] ch = R2.chain((True, [], 0, Y), 1) why['delta %d %s' % (ak - 2 * S + 1, 'ruled' if ch[0][0] != 'UNRULED' else ch[0][1][:28])] += 1 report('M3 window hubs with WindowStart + RightEndP2W: what is still unruled', True, '%s -- the V1 right end with walls remains (proof.md 8 G2)' % dict(sorted(why.items())), open_=True) # ---------------------------------------------------------------- H def Bs(z): out = [0] * (len(z) + 2); acc = 0 for l in range(len(z), 0, -1): acc += z[l - 1] if l % 2 == 0 else -z[l - 1]; out[l] = acc return out def zip_ok(b, k, tau): e = b[k + 1] % 2 return b[k] == (2 * b[k + 1] + 4 + e if k % 2 == 0 else 2 * b[k + 1] - 2 * tau - 4 - e) def sec_H(): """if B'(k) = 2 tau - B(k-1) for all k in a range, then the even-k zipper at k for B' is equivalent to the odd-k zipper at k-1 for B, and the odd-k zipper at k for B' to the even-k zipper at k-1 for B (exact identities)""" ok = True; n = 0 rng = range(-12, 13) for tau in range(0, 9): for x, y in itertools.product(rng, rng): # x = B(k-1), y = B(k); B'(k) = 2tau - x, B'(k+1) = 2tau - y for kpar in (0, 1): bp = {1: 2 * tau - x, 2: 2 * tau - y} # B' at positions k, k+1 (k has parity kpar) lhs = (bp[1] == (2 * bp[2] + 4 + bp[2] % 2 if kpar == 0 else 2 * bp[2] - 2 * tau - 4 - bp[2] % 2)) rhs = (x == (2 * y - 2 * tau - 4 - y % 2 if kpar == 0 else 2 * y + 4 + y % 2)) ok &= lhs == rhs; n += 1 for _ in range(20000): tau = random.randint(0, 10 ** 30); x = random.randint(-10 ** 31, 10 ** 31); y = random.randint(-10 ** 31, 10 ** 31) if random.random() < 0.5: y = random.randint(-10 ** 31, 10 ** 31); x = 2 * y - 2 * tau - 4 - y % 2 for kpar in (0, 1): bp1, bp2 = 2 * tau - x, 2 * tau - y lhs = (bp1 == (2 * bp2 + 4 + bp2 % 2 if kpar == 0 else 2 * bp2 - 2 * tau - 4 - bp2 % 2)) rhs = (x == (2 * y - 2 * tau - 4 - y % 2 if kpar == 0 else 2 * y + 4 + y % 2)) ok &= lhs == rhs; n += 1 report('H1 shift-reflection swaps the two zipper families', ok, '%d cases' % n) # on orbits: every G transition satisfies B'(k) = 2 tau - B(k-1) (2 <= k <= 2m-1) and h = 5 + B(1) - e import seed_clause as SCL, hubinv_H from hubinv_Hc3 import zseq_c random.seed(21); g = 0; bad = 0; N = 100 if QUICK else 400 n = 0 while n < N: R = hubinv_H.rnd_R(random.choice(['Rc', 'Rt']), 0, random.choice([5459, 1e30])) if R is None or hubinv_H.H(R) is not None: continue n += 1 try: oo = SCL.orbit(R, 8) except MS.Unruled: continue for (x0, _), (x1, ev) in zip(oo, oo[1:]): if len(x0[3]) < 3 or len(x1[3]) < 3: continue # segment-less hubs have no z sequence k0, t0_, z0 = zseq_c(*x0); k1, t1_, z1 = zseq_c(*x1) if z0 is None or z1 is None or t0_ != t1_ or len(z1) != len(z0) + 2 or not x1[0]: continue b0 = Bs(z0); b1 = Bs(z1); tau = t0_ # growth: z' = [h] + z with the tail re-paired; check the band of identities on the shared range m = len(z0) // 2 okk = all(b1[k] == 2 * tau - b0[k - 1] for k in range(2, 2 * m)) if not okk: continue # not a growth transition (collapse or short); classified by hubinv_classify g += 1 e = 5 + b0[1] - z1[0] # new head entry h = z'_1 = 5 + B(1) - e bad += e not in (0, 1) report('H2 growth transitions on random orbits: B\'(k) = 2tau - B(k-1), head h = 5 + B(1) - e', bad == 0 and g > 0, '%d growth transitions, %d with e not in {0,1}' % (g, bad)) # ---------------------------------------------------------------- I def sec_I(): # eat of a chunk whose (10)-run is odd: halts (the one halting precursor; G1 excludes it) random.seed(5); h = 0; n = 0 for _ in range(10 if QUICK else 30): B = random.randint(1, 6); A = 2 * random.randint(0, 5) + 1; c = random.randint(1, 6) st = '0^inf <A (10)^%d (011010)^%d (10)^%d (010)^1 (011010)^%d (10)^%d (010)^%d (011010)^1 (10)^2 0^inf' % ( 2 * random.randint(1, 20) + 1, random.randint(1, 9), 2 * random.randint(0, 9), B, A, c) n += 1; r = visit_seq(st, ['0^inf A> 1 0^inf'], 2 * 10 ** 6); h += r[0] == 'halt' report('I1 eat of an odd (10)-run in a chunk halts (precursor)', h >= n - 1, '%d/%d halt' % (h, n)) if __name__ == '__main__': random.seed(16); t0 = time.time() only = sys.argv[2].split(',') if len(sys.argv) > 2 else None for name, f in (('A', sec_A), ('B', sec_B), ('C', sec_C), ('D', sec_D), ('E', sec_E), ('F', sec_F), ('G', sec_G), ('H', sec_H), ('I', sec_I), ('J', sec_J), ('K', sec_K), ('L', sec_L), ('M', sec_M)): if only and name not in only: continue f() fails = [k for k, (ok, d, op) in RES.items() if not ok] opens = [k for k, (ok, d, op) in RES.items() if op and ok] print('SUMMARY %s (%d checks, %d fail; %d OPEN items = known gaps, proof.md section 8) %.0f s' % ( 'PASS' if not fails else 'FAIL', len(RES) - len(opens), len(fails), len(opens), time.time() - t0)) if opens: print('open:', opens) if fails: print('failed:', fails) |