Documentation

Complexitylib.Models.TuringMachine.UTM.Internal.BodyLoop

Body machine: the match-loop induction #

The final piece of the body correctness: from cmpQ f at the start of the entry region, the machine walks the takeField segment split exactly as machFind does (BodyLookup.lean) — per segment either the full key-and-value scan succeeds (cmpQcmpScopyQ'copyActappRewScr), or the first failure point diverts to the uniform mismatch path (skipSegsegCheckmmScrrewindSt) and the loop resumes at the next segment; an empty next segment sends the machine to the default path (dfScr) with the sanitized default moves applied (trick 4).

matchLoop packages both outcomes against machFind:

Corner (empty first segment). machFind/parseEntries treat a region that starts with as an exhausted table. The machine, started at cmpQ on such a region, instead steps past the empty segment (cmpQskipSegsegCheck at the next cell) — it only recognizes the table terminator as a read by segCheck. On R = □ :: s :: … with s ≠ □ the two genuinely diverge: the machine goes on to scan the segments after the empty one while machFind returns none. matchLoop therefore carries the hypothesis that an empty head segment is a real terminator (R = □ :: s :: … → s = □). Every region the loop actually sees satisfies it: canonical descriptions (TMDesc.syms) have entry regions of the form entry □ ⋯ □ □ (head symbol is an entry bit) or (empty table), and the loop re-enters cmpQ only through segCheck, which has just read the next region's head symbol and found it non-.

theorem Complexity.TM.UTMBody.matchLoop (f : VFlags) (v0 v1 v2 : Γ) (stSyms : List Γw) (hst_nb : sstSyms, s Γw.blank) (R : List Γw) (pos : ) (c : Cfg 6 bodyTM.Q) :
(∀ (s : Γw) (rest : List Γw), R = Γw.blank :: s :: rests = Γw.blank)c.state = BodyQ.cmpQ f(∀ (j : ), (c.work dsT).cells (pos + j) = (R[j]?.getD Γw.blank).toΓ)(c.work dsT).head = pos1 pos(∀ (j : ), 1 j(c.work dsT).cells j Γ.start)(c.work stT).HoldsExact stSyms(c.work stT).head = 1(c.work scT).HoldsExact [](c.work scT).head = 1(c.work vIn).read = v0(c.work vWk).read = v1(c.work vOut).read = v2(c.work vIn).read Γ.start(c.work vWk).read Γ.start(c.work vOut).read Γ.startc.input.read Γ.startc.output.read Γ.start(∀ (seg : List Γw), machFind stSyms.length stSyms (keyCells f v0 v1 v2) R = some seg∃ (c' : Cfg 6 bodyTM.Q), t ≤ (R.length + 2) * (4 * stSyms.length + 60), bodyTM.reachesIn t c c' c'.state = BodyQ.appRewScr f (c'.work scT).HoldsExact (List.take (stSyms.length + 10) (List.drop (stSyms.length + 6) seg)) (c'.work scT).head = stSyms.length + 10 + 1 c'.work stT = c.work stT (c'.work dsT).cells = (c.work dsT).cells 1 (c'.work dsT).head (c'.work dsT).head pos + R.length + 1 c'.work vIn = c.work vIn c'.work vWk = c.work vWk c'.work vOut = c.work vOut c'.input = c.input c'.output = c.output) (machFind stSyms.length stSyms (keyCells f v0 v1 v2) R = none∃ (c' : Cfg 6 bodyTM.Q), t ≤ (R.length + 2) * (4 * stSyms.length + 60), bodyTM.reachesIn t c c' c'.state = BodyQ.dfScr c'.work vIn = (c.work vIn).writeAndMove (readBackWrite v0).toΓ (if f.1 = true then Dir3.right else Dir3.stay) c'.work vWk = (c.work vWk).writeAndMove (readBackWrite v1).toΓ (if f.2.1 = true then Dir3.right else Dir3.stay) c'.work vOut = (c.work vOut).writeAndMove (readBackWrite v2).toΓ (if f.2.2 = true then Dir3.right else Dir3.stay) (c'.work stT).cells = (c.work stT).cells 1 (c'.work stT).head (c'.work stT).head stSyms.length + 1 (c'.work dsT).cells = (c.work dsT).cells 1 (c'.work dsT).head (c'.work dsT).head pos + R.length + 1 (c'.work scT).cells 0 = Γ.start (∀ (j : ), 1 j(c'.work scT).cells j Γ.start) 1 (c'.work scT).head (c'.work scT).head stSyms.length + 11 (∀ (j : ), (c'.work scT).head j1 j(c'.work scT).cells j = Γ.blank) c'.input = c.input c'.output = c.output)

The match-loop induction (design appendix 2, machine side): from cmpQ f at the start of the entry region suffix R (desc cells at pos + j hold R's symbols, blank-padded; an empty head segment of R, if any, is a real terminator — see the module docstring), with the state tape holding stSyms at head 1, a clean scratch tape, and the three virtual tapes stationary with live reads v0/v1/v2:

  • if machFind accepts a segment seg, the machine reaches appRewScr f with seg's value slice (the w + 10 cells after its key) on the scratch tape, the state tape restored, desc cells unchanged, and the virtual tapes untouched;
  • if machFind rejects (none), the machine reaches dfScr having applied the sanitized default moves (trick 4) to the three virtual tapes, with state and desc cells unchanged and the scratch confined (-free, blank at and beyond its head, head ≤ w + 11) — the shape defaultTail consumes;

in either case within (|R| + 2)·(4·|stSyms| + 60) steps.