Imports
/- Copyright (c) 2026 Terence Rokop. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Terence Rokop -/ module public import Geb.Prototypes.Computability.BitTree.BinaryMachine.Machine public import Geb.Prototypes.Computability.BitTree.BinaryMachine.Difference public import Geb.Prototypes.Computability.BitTree.Counter public import Mathlib.Data.Nat.Bitwise
set_option doc.verso true

Representation invariants for binary counters

The representation relation records digit values, origin markers and the mismatch count. It permits either blank cells or explicit zero digits beyond the represented number. The fixed width bounds both binary counters throughout a complete execution.

Main definitions

  • bitsAt extends a natural number's digits by zero.

  • Represents describes configurations at scan boundaries.

Tags

Turing machine, binary representation, simulation

@[expose] public sectionnamespace Geb.BitTree.BinaryMachineopen Turing MultiTapeTM

A natural number's little-endian bit sequence, extended by zero.

def bitsAt (n j : ) : Bool := (n.bits[j]?).getD false

The zero-extended list representation agrees with bit testing.

theorem bitsAt_eq_testBit (n j : ) : bitsAt n j = n.testBit j := n:j:bitsAt n j = n.testBit j n:j:bitsAt n j = n.bits[j]?.getD default All goals completed! 🐙

Zero-extended binary representations determine their natural numbers.

theorem bitsAt_injective {a b : } (h : bitsAt a = bitsAt b) : a = b := a:b:h:bitsAt a = bitsAt ba = b a:b:h:bitsAt a = bitsAt b (i : ), a.testBit i = b.testBit i a:b:h:bitsAt a = bitsAt bi:a.testBit i = b.testBit i All goals completed! 🐙

All digits beyond the binary size are zero.

theorem bitsAt_of_size_le (n j : ) (h : n.size j) : bitsAt n j = false := n:j:h:n.size jbitsAt n j = false n:j:h:n.size jhl:n.bits.length jbitsAt n j = false All goals completed! 🐙

Scan-boundary configurations represent two bounded binary counters.

Finite control at the scan boundary.

The fork counter is read at its least significant digit.

The leaf counter is read at its least significant digit.

Digit representation of the fork counter.

Digit representation of the leaf counter.

Only the origin is tagged on the first binary tape.

The mismatch tape contains only its origin marker.

The third head counts unequal digit positions.

The fork counter fits within the fixed width.

The leaf counter fits within the fixed width.

structure Represents {input : List (Fin 4)} (width : ) (cfg : Cfg 3 (Fin 4) (Fin 10) input) (q : Fin 10) (a b : ) : Prop where state : cfg.state = some q forkPos : cfg.workTapePos 0 = 0 leafPos : cfg.workTapePos 1 = 0 forkDigits : digits cfg 0 = bitsAt a leafDigits : digits cfg 1 = bitsAt b originTag : z, origin (cfg.workTapes 0 z) = decide (z = 0) marker : z, cfg.workTapes 2 z = if z = 0 then some 0 else none mismatchPos : cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b) : ) forkSize : a.size width leafSize : b.size width

The mismatch head is at the origin exactly when the two counters are equal.

theorem Represents.mismatchPos_eq_zero_iff {input : List (Fin 4)} {width a b : } {cfg : Cfg 3 (Fin 4) (Fin 10) input} {q : Fin 10} (h : Represents width cfg q a b) : cfg.workTapePos 2 = 0 a = b := input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bcfg.workTapePos 2 = 0 a = b input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bcfg.workTapePos 2 = 0 a = b input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bcfg.workTapePos 2 = 0 a = binput:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt ba = b cfg.workTapePos 2 = 0 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bcfg.workTapePos 2 = 0 a = b input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bhz:cfg.workTapePos 2 = 0a = b input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bhz:cfg.workTapePos 2 = 0hc:mismatchCount width (bitsAt a) (bitsAt b) = 0a = b All goals completed! 🐙 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt ba = b cfg.workTapePos 2 = 0 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bhab:a = bcfg.workTapePos 2 = 0 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bhab:a = bhc:mismatchCount width (bitsAt a) (bitsAt b) = 0cfg.workTapePos 2 = 0 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bhe:mismatchCount width (bitsAt a) (bitsAt b) = 0 bitsAt a = bitsAt bhab:a = bhc:mismatchCount width (bitsAt a) (bitsAt b) = 00 = 0 All goals completed! 🐙

The initial counters differ only at their least significant digit.

theorem mismatchCount_one_zero (width : ) (hw : 1 width) : mismatchCount width (bitsAt 1) (bitsAt 0) = 1 := width:hw:1 widthmismatchCount width (bitsAt 1) (bitsAt 0) = 1 cases width with hw:1 0mismatchCount 0 (bitsAt 1) (bitsAt 0) = 1 All goals completed! 🐙 width:hw:1 width + 1mismatchCount (width + 1) (bitsAt 1) (bitsAt 0) = 1 width:hw:1 width + 1mismatchCount (Nat.zero + 1) (bitsAt 1) (bitsAt 0) = 1width:hw:1 width + 1 (n : ), mismatchCount (n + 1) (bitsAt 1) (bitsAt 0) = 1 mismatchCount (n.succ + 1) (bitsAt 1) (bitsAt 0) = 1 width:hw:1 width + 1mismatchCount (Nat.zero + 1) (bitsAt 1) (bitsAt 0) = 1 All goals completed! 🐙 width:hw:1 width + 1 (n : ), mismatchCount (n + 1) (bitsAt 1) (bitsAt 0) = 1 mismatchCount (n.succ + 1) (bitsAt 1) (bitsAt 0) = 1 width:hw:1 width + 1k:ih:mismatchCount (k + 1) (bitsAt 1) (bitsAt 0) = 1mismatchCount (k.succ + 1) (bitsAt 1) (bitsAt 0) = 1 width:hw:1 width + 1k:ih:mismatchCount (k + 1) (bitsAt 1) (bitsAt 0) = 1(1 + if bitsAt 1 (k + 1) = bitsAt 0 (k + 1) then 0 else 1) = 1 width:hw:1 width + 1k:ih:mismatchCount (k + 1) (bitsAt 1) (bitsAt 0) = 1h1:bitsAt 1 (k + 1) = false(1 + if bitsAt 1 (k + 1) = bitsAt 0 (k + 1) then 0 else 1) = 1 width:hw:1 width + 1k:ih:mismatchCount (k + 1) (bitsAt 1) (bitsAt 0) = 1h1:bitsAt 1 (k + 1) = falseh0:bitsAt 0 (k + 1) = false(1 + if bitsAt 1 (k + 1) = bitsAt 0 (k + 1) then 0 else 1) = 1 width:hw:1 width + 1k:ih:mismatchCount (k + 1) (bitsAt 1) (bitsAt 0) = 1h1:bitsAt 1 (k + 1) = falseh0:bitsAt 0 (k + 1) = false(1 + if false = false then 0 else 1) = 1 All goals completed! 🐙

Initialization establishes the boundary representation with one pending root.

theorem represents_startCfg (input : List (Fin 4)) (width : ) (hw : 1 width) : Represents width (startCfg input) stTree 1 0 := input:List (Fin 4)width:hw:1 widthRepresents width (startCfg input) stTree 1 0 input:List (Fin 4)width:hw:1 widthdigits (startCfg input) 0 = bitsAt 1input:List (Fin 4)width:hw:1 widthdigits (startCfg input) 1 = bitsAt 0input:List (Fin 4)width:hw:1 width (z : ), origin ((startCfg input).workTapes 0 z) = decide (z = 0)input:List (Fin 4)width:hw:1 width (z : ), (startCfg input).workTapes 2 z = if z = 0 then some 0 else noneinput:List (Fin 4)width:hw:1 width(startCfg input).workTapePos 2 = (mismatchCount width (bitsAt 1) (bitsAt 0))input:List (Fin 4)width:hw:1 widthNat.size 1 widthinput:List (Fin 4)width:hw:1 widthNat.size 0 width input:List (Fin 4)width:hw:1 widthdigits (startCfg input) 0 = bitsAt 1 input:List (Fin 4)width:hw:1 widthj:digits (startCfg input) 0 j = bitsAt 1 j input:List (Fin 4)width:hw:1 widthj:digit (if j = 0 then some 3 else none) = [true][j]?.getD false cases j with input:List (Fin 4)width:hw:1 widthdigit (if 0 = 0 then some 3 else none) = [true][0]?.getD false All goals completed! 🐙 input:List (Fin 4)width:hw:1 widthj:digit (if (j + 1) = 0 then some 3 else none) = [true][j + 1]?.getD false input:List (Fin 4)width:hw:1 widthj:digit none = [true][j + 1]?.getD false All goals completed! 🐙 input:List (Fin 4)width:hw:1 widthdigits (startCfg input) 1 = bitsAt 0 input:List (Fin 4)width:hw:1 widthj:digits (startCfg input) 1 j = bitsAt 0 j input:List (Fin 4)width:hw:1 widthj:digit (if j = 0 then some 2 else none) = false input:List (Fin 4)width:hw:1 widthj:h✝:j = 0digit (some 2) = falseinput:List (Fin 4)width:hw:1 widthj:h✝:¬j = 0digit none = false input:List (Fin 4)width:hw:1 widthj:h✝:j = 0digit (some 2) = falseinput:List (Fin 4)width:hw:1 widthj:h✝:¬j = 0digit none = false All goals completed! 🐙 input:List (Fin 4)width:hw:1 width (z : ), origin ((startCfg input).workTapes 0 z) = decide (z = 0) input:List (Fin 4)width:hw:1 widthz:origin ((startCfg input).workTapes 0 z) = decide (z = 0) input:List (Fin 4)width:hw:1 widthz:origin (if z = 0 then some 3 else none) = decide (z = 0) input:List (Fin 4)width:hw:1 widthz:hz:z = 0origin (some 3) = decide (z = 0)input:List (Fin 4)width:hw:1 widthz:hz:¬z = 0origin none = decide (z = 0) input:List (Fin 4)width:hw:1 widthz:hz:z = 0origin (some 3) = decide (z = 0) input:List (Fin 4)width:hw:1 widthz:hz:z = 0origin (some 3) = true All goals completed! 🐙 input:List (Fin 4)width:hw:1 widthz:hz:¬z = 0origin none = decide (z = 0) input:List (Fin 4)width:hw:1 widthz:hz:¬z = 0origin none = false All goals completed! 🐙 input:List (Fin 4)width:hw:1 width (z : ), (startCfg input).workTapes 2 z = if z = 0 then some 0 else none input:List (Fin 4)width:hw:1 widthz:(startCfg input).workTapes 2 z = if z = 0 then some 0 else none All goals completed! 🐙 input:List (Fin 4)width:hw:1 width(startCfg input).workTapePos 2 = (mismatchCount width (bitsAt 1) (bitsAt 0)) input:List (Fin 4)width:hw:1 width1 = (mismatchCount width (bitsAt 1) (bitsAt 0)) input:List (Fin 4)width:hw:1 width1 = 1 All goals completed! 🐙 input:List (Fin 4)width:hw:1 widthNat.size 1 width All goals completed! 🐙 input:List (Fin 4)width:hw:1 widthNat.size 0 width All goals completed! 🐙

The representation invariant is preserved by a pure input transition.

theorem Represents.consume {input : List (Fin 4)} {width a b : } {cfg : Cfg 3 (Fin 4) (Fin 10) input} {q : Fin 10} (h : Represents width cfg q a b) (q' : Fin 10) : Represents width (consumeCfg cfg q') q' a b := { h with state := rfl }

A scan-boundary representation bounds all three heads.

theorem Represents.headBound {input : List (Fin 4)} {width a b : } {cfg : Cfg 3 (Fin 4) (Fin 10) input} {q : Fin 10} (h : Represents width cfg q a b) : HeadBound width cfg := input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bHeadBound width cfg input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos i cfg.workTapePos i width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos 0 cfg.workTapePos 0 widthinput:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos (Fin.succ 0) cfg.workTapePos (Fin.succ 0) widthinput:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos (Fin.succ 0).succ cfg.workTapePos (Fin.succ 0).succ width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos 0 cfg.workTapePos 0 width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos 0 cfg.workTapePos 0 width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 0 0 width All goals completed! 🐙 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos (Fin.succ 0) cfg.workTapePos (Fin.succ 0) width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos 1 cfg.workTapePos 1 width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 0 0 width All goals completed! 🐙 input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos (Fin.succ 0).succ cfg.workTapePos (Fin.succ 0).succ width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 cfg.workTapePos 2 cfg.workTapePos 2 width input:List (Fin 4)width:a:b:cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:Represents width cfg q a bi:Fin 30 (mismatchCount width (bitsAt a) (bitsAt b)) (mismatchCount width (bitsAt a) (bitsAt b)) width All goals completed! 🐙

Returning reconstructs the boundary representation and tests counter equality.

theorem returnedCfg_represents {input : List (Fin 4)} (cfg : Cfg 3 (Fin 4) (Fin 10) input) (width a b : ) (hd0 : digits cfg 0 = bitsAt a) (hd1 : digits cfg 1 = bitsAt b) (ho : z, origin (cfg.workTapes 0 z) = decide (z = 0)) (hmark : z, cfg.workTapes 2 z = if z = 0 then some 0 else none) (hm : cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b) : )) (ha : a.size width) (hb : b.size width) : Represents width (returnedCfg cfg) (if a = b then stDone else stTree) a b := input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputwidth:a:b:hd0:digits cfg 0 = bitsAt ahd1:digits cfg 1 = bitsAt bho: (z : ), origin (cfg.workTapes 0 z) = decide (z = 0)hmark: (z : ), cfg.workTapes 2 z = if z = 0 then some 0 else nonehm:cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b))ha:a.size widthhb:b.size widthRepresents width (returnedCfg cfg) (if a = b then stDone else stTree) a b input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputwidth:a:b:hd0:digits cfg 0 = bitsAt ahd1:digits cfg 1 = bitsAt bho: (z : ), origin (cfg.workTapes 0 z) = decide (z = 0)hmark: (z : ), cfg.workTapes 2 z = if z = 0 then some 0 else nonehm:cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b))ha:a.size widthhb:b.size widthhr:Represents width (returnedCfg cfg) (if (cfg.workTapes 2 (cfg.workTapePos 2) == some 0) = true then stDone else stTree) a bRepresents width (returnedCfg cfg) (if a = b then stDone else stTree) a b input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputwidth:a:b:hd0:digits cfg 0 = bitsAt ahd1:digits cfg 1 = bitsAt bho: (z : ), origin (cfg.workTapes 0 z) = decide (z = 0)hmark: (z : ), cfg.workTapes 2 z = if z = 0 then some 0 else nonehm:cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b))ha:a.size widthhb:b.size widthhr:Represents width (returnedCfg cfg) (if (cfg.workTapes 2 (cfg.workTapePos 2) == some 0) = true then stDone else stTree) a bhe:cfg.workTapePos 2 = 0 a = bRepresents width (returnedCfg cfg) (if a = b then stDone else stTree) a b input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputwidth:a:b:hd0:digits cfg 0 = bitsAt ahd1:digits cfg 1 = bitsAt bho: (z : ), origin (cfg.workTapes 0 z) = decide (z = 0)hmark: (z : ), cfg.workTapes 2 z = if z = 0 then some 0 else nonehm:cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b))ha:a.size widthhb:b.size widthhr:Represents width (returnedCfg cfg) (if (cfg.workTapes 2 (cfg.workTapePos 2) == some 0) = true then stDone else stTree) a bhe:cfg.workTapePos 2 = 0 a = bhs:(if (cfg.workTapes 2 (cfg.workTapePos 2) == some 0) = true then stDone else stTree) = if a = b then stDone else stTreeRepresents width (returnedCfg cfg) (if a = b then stDone else stTree) a b input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputwidth:a:b:hd0:digits cfg 0 = bitsAt ahd1:digits cfg 1 = bitsAt bho: (z : ), origin (cfg.workTapes 0 z) = decide (z = 0)hmark: (z : ), cfg.workTapes 2 z = if z = 0 then some 0 else nonehm:cfg.workTapePos 2 = (mismatchCount width (bitsAt a) (bitsAt b))ha:a.size widthhb:b.size widthhr:Represents width (returnedCfg cfg) (if a = b then stDone else stTree) a bhe:cfg.workTapePos 2 = 0 a = bhs:(if (cfg.workTapes 2 (cfg.workTapePos 2) == some 0) = true then stDone else stTree) = if a = b then stDone else stTreeRepresents width (returnedCfg cfg) (if a = b then stDone else stTree) a b All goals completed! 🐙
end Geb.BitTree.BinaryMachine