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 Cslib.Computability.Machines.Turing.MultiTape.Deterministic
public import Geb.Prototypes.Computability.BitTree.Scannerset_option doc.verso trueA binary-counter machine for trees with bitstring leaves
The machine reads the input from left to right. Its first two work tapes hold the number of forks plus one and the number of completed leaves in binary. Their heads remain aligned. The third head records the number of unequal bit positions, so equality is detected at its marked origin without scanning the binary representations. Each carry changes this number by one at each bit flip.
Main definitions
-
machineis the three-work-tape machine. -
digitreads a binary digit, including the tagged origin digits. -
flippedflips a digit while preserving the origin tag. -
modeStateembeds scanner modes into finite machine control. -
startCfg,consumeCfgandreturnCfgdescribe phase boundaries. -
HeadBoundbounds all work-head positions.
Implementation notes
The alphabet has four symbols. Symbols zero and one are ordinary digits; symbols two and three tag the least significant position. A blank is read as zero. The third tape has one marker, at its origin. Input movement occurs only when consuming a bit; carry and return transitions leave the input head fixed.
Tags
Turing machine, binary counter, bitstring, tree
@[expose] public sectionnamespace Geb.BitTree.BinaryMachineopen Turing MultiTapeTMEmbed input and output booleans into the machine alphabet.
def boolEmb : Bool ↪ Fin 4 where
toFun b := if b then 1 else 0
inj' a b := a:Boolb:Bool⊢ (fun b ↦ if b = true then 1 else 0) a = (fun b ↦ if b = true then 1 else 0) b → a = b b:Bool⊢ (fun b ↦ if b = true then 1 else 0) false = (fun b ↦ if b = true then 1 else 0) b → false = bb:Bool⊢ (fun b ↦ if b = true then 1 else 0) true = (fun b ↦ if b = true then 1 else 0) b → true = b b:Bool⊢ (fun b ↦ if b = true then 1 else 0) false = (fun b ↦ if b = true then 1 else 0) b → false = bb:Bool⊢ (fun b ↦ if b = true then 1 else 0) true = (fun b ↦ if b = true then 1 else 0) b → true = b ⊢ (fun b ↦ if b = true then 1 else 0) true = (fun b ↦ if b = true then 1 else 0) false → true = false⊢ (fun b ↦ if b = true then 1 else 0) true = (fun b ↦ if b = true then 1 else 0) true → true = true ⊢ (fun b ↦ if b = true then 1 else 0) false = (fun b ↦ if b = true then 1 else 0) false → false = false⊢ (fun b ↦ if b = true then 1 else 0) false = (fun b ↦ if b = true then 1 else 0) true → false = true⊢ (fun b ↦ if b = true then 1 else 0) true = (fun b ↦ if b = true then 1 else 0) false → true = false⊢ (fun b ↦ if b = true then 1 else 0) true = (fun b ↦ if b = true then 1 else 0) true → true = true All goals completed! 🐙Read a digit, with a blank representing zero.
def digit (s : Option (Fin 4)) : Bool := s == some 1 || s == some 3Detect a tagged least significant digit.
def origin (s : Option (Fin 4)) : Bool := s == some 2 || s == some 3Flip one digit, preserving its origin tag.
def flipped (s : Option (Fin 4)) : Fin 4 :=
if origin s then (if digit s then 2 else 3) else (if digit s then 0 else 1)Reading a flipped digit gives the boolean complement.
theorem digit_flipped (s : Option (Fin 4)) : digit (some (flipped s)) = !digit s := s:Option (Fin 4)⊢ digit (some (flipped s)) = !digit s
s:Option (Fin 4)⊢ digit (some (if origin s = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = !digit s
s:Option (Fin 4)⊢ digit (some (if false = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = !digit ss:Option (Fin 4)⊢ digit (some (if true = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = !digit s s:Option (Fin 4)⊢ digit (some (if false = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = !digit ss:Option (Fin 4)⊢ digit (some (if true = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = !digit s s:Option (Fin 4)⊢ digit (some (if true = true then if false = true then 2 else 3 else if false = true then 0 else 1)) = !falses:Option (Fin 4)⊢ digit (some (if true = true then if true = true then 2 else 3 else if true = true then 0 else 1)) = !true s:Option (Fin 4)⊢ digit (some (if false = true then if false = true then 2 else 3 else if false = true then 0 else 1)) = !falses:Option (Fin 4)⊢ digit (some (if false = true then if true = true then 2 else 3 else if true = true then 0 else 1)) = !trues:Option (Fin 4)⊢ digit (some (if true = true then if false = true then 2 else 3 else if false = true then 0 else 1)) = !falses:Option (Fin 4)⊢ digit (some (if true = true then if true = true then 2 else 3 else if true = true then 0 else 1)) = !true All goals completed! 🐙Flipping a digit preserves its origin tag.
theorem origin_flipped (s : Option (Fin 4)) : origin (some (flipped s)) = origin s := s:Option (Fin 4)⊢ origin (some (flipped s)) = origin s
s:Option (Fin 4)⊢ origin (some (if origin s = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = origin s
s:Option (Fin 4)⊢ origin (some (if false = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = falses:Option (Fin 4)⊢ origin (some (if true = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = true s:Option (Fin 4)⊢ origin (some (if false = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = falses:Option (Fin 4)⊢ origin (some (if true = true then if digit s = true then 2 else 3 else if digit s = true then 0 else 1)) = true s:Option (Fin 4)⊢ origin (some (if true = true then if false = true then 2 else 3 else if false = true then 0 else 1)) = trues:Option (Fin 4)⊢ origin (some (if true = true then if true = true then 2 else 3 else if true = true then 0 else 1)) = true s:Option (Fin 4)⊢ origin (some (if false = true then if false = true then 2 else 3 else if false = true then 0 else 1)) = falses:Option (Fin 4)⊢ origin (some (if false = true then if true = true then 2 else 3 else if true = true then 0 else 1)) = falses:Option (Fin 4)⊢ origin (some (if true = true then if false = true then 2 else 3 else if false = true then 0 else 1)) = trues:Option (Fin 4)⊢ origin (some (if true = true then if true = true then 2 else 3 else if true = true then 0 else 1)) = true All goals completed! 🐙The mismatch count rises when two equal digits become different.
Write both origin digits and the mismatch tape's origin marker.
def stInit : Fin 10 := 0Enter scanning after initialization.
def stStart : Fin 10 := 1Expect a tree constructor.
def stTree : Fin 10 := 2Expect a string continuation or terminator.
def stString : Fin 10 := 3Consume one payload bit.
def stBit : Fin 10 := 4The complete tree has ended; only end of input is accepted.
def stDone : Fin 10 := 5A malformed prefix has been found.
def stDead : Fin 10 := 6Increment the number of forks plus one.
def stCarryFork : Fin 10 := 7Increment the number of completed leaves.
def stCarryLeaf : Fin 10 := 8Return both binary heads to their origins.
def stReturn : Fin 10 := 9A transition consuming one input symbol without changing work tapes.
def consume (q : Fin 10) : TransitionOut 3 (Fin 4) (Fin 10) where
inputMove := 1
workActions _ := (none, 0)
outS := none
q' := some qEmit one boolean and halt.
def finish (b : Bool) : TransitionOut 3 (Fin 4) (Fin 10) where
inputMove := 0
workActions _ := (none, 0)
outS := some (boolEmb b)
q' := noneFlip the selected counter's current bit and maintain the mismatch count. Carry transitions move both binary heads right; the first zero ends the carry.
def carry (leaf : Bool) (work : Fin 3 → Option (Fin 4)) :
TransitionOut 3 (Fin 4) (Fin 10) :=
let selected : Fin 3 := if leaf then 1 else 0
{ inputMove := 0
workActions := fun i ↦
if i = 2 then (none, mismatchMove (work 0) (work 1))
else (if i = selected then some (some (flipped (work i))) else none, 1)
outS := none
q' := some (if digit (work selected) then
(if leaf then stCarryLeaf else stCarryFork) else stReturn) }A three-work-tape recognizer whose counters are incremented monotonically.
def machine : MultiTapeTM 3 (Fin 4) (Fin 10) where
q₀ := stInit
tr q input work :=
if q = stInit then
{ inputMove := 0
workActions := fun i ↦
if i = 0 then (some (some 3), 0)
else if i = 1 then (some (some 2), 0)
else (some (some 0), 1)
outS := none
q' := some stStart }
else if q = stStart then
{ inputMove := 0, workActions := fun _ ↦ (none, 0),
outS := none, q' := some stTree }
else if q = stCarryFork then carry false work
else if q = stCarryLeaf then carry true work
else if q = stReturn then
if origin (work 0) then
{ inputMove := 0, workActions := fun _ ↦ (none, 0), outS := none,
q' := some (if work 2 == some 0 then stDone else stTree) }
else
{ inputMove := 0,
workActions := fun i ↦ (none, if i = 2 then 0 else -1),
outS := none, q' := some stReturn }
else
match input with
| none => finish (q == stDone)
| some b =>
if q = stTree then consume (if b == 0 then stString else stCarryFork)
else if q = stString then consume (if b == 0 then stCarryLeaf else stBit)
else if q = stBit then consume stString
else consume stDeadEvery input transition is stationary or moves right.
theorem inputMove_ne_neg (q : Fin 10) (input : Option (Fin 4))
(work : Fin 3 → Option (Fin 4)) : (machine.tr q input work).inputMove ≠ -1 := q:Fin 10input:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ (machine.tr q input work).inputMove ≠ -1
q:Fin 10work:Fin 3 → Option (Fin 4)⊢ (machine.tr q none work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ (machine.tr q (some val✝) work).inputMove ≠ -1 q:Fin 10work:Fin 3 → Option (Fin 4)⊢ (machine.tr q none work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ (machine.tr q (some val✝) work).inputMove ≠ -1 q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ (if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else
if q = stTree then consume (if (val✝ == 0) = true then stString else stCarryFork)
else
if q = stString then consume (if (val✝ == 0) = true then stCarryLeaf else stBit)
else if q = stBit then consume stString else consume stDead).inputMove ≠
-1 q:Fin 10work:Fin 3 → Option (Fin 4)⊢ (if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else finish (q == stDone)).inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ (if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else
if q = stTree then consume (if (val✝ == 0) = true then stString else stCarryFork)
else
if q = stString then consume (if (val✝ == 0) = true then stCarryLeaf else stBit)
else if q = stBit then consume stString else consume stDead).inputMove ≠
-1 q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝:q = stInit⊢ { inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝¹:¬q = stInith✝:q = stStart⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝²:¬q = stInith✝¹:¬q = stStarth✝:q = stCarryFork⊢ (carry false work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝³:¬q = stInith✝²:¬q = stStarth✝¹:¬q = stCarryForkh✝:q = stCarryLeaf⊢ (carry true work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:(work 2 == some 0) = true⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:¬(work 2 == some 0) = true⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁵:¬q = stInith✝⁴:¬q = stStarth✝³:¬q = stCarryForkh✝²:¬q = stCarryLeafh✝¹:q = stReturnh✝:¬origin (work 0) = true⊢ { inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:(val✝ == 0) = true⊢ (consume stString).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:¬(val✝ == 0) = true⊢ (consume stCarryFork).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:(val✝ == 0) = true⊢ (consume stCarryLeaf).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:¬(val✝ == 0) = true⊢ (consume stBit).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:q = stBit⊢ (consume stString).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:¬q = stBit⊢ (consume stDead).inputMove ≠ -1 q:Fin 10work:Fin 3 → Option (Fin 4)h✝:q = stInit⊢ { inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)h✝¹:¬q = stInith✝:q = stStart⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)h✝²:¬q = stInith✝¹:¬q = stStarth✝:q = stCarryFork⊢ (carry false work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)h✝³:¬q = stInith✝²:¬q = stStarth✝¹:¬q = stCarryForkh✝:q = stCarryLeaf⊢ (carry true work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:(work 2 == some 0) = true⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:¬(work 2 == some 0) = true⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁵:¬q = stInith✝⁴:¬q = stStarth✝³:¬q = stCarryForkh✝²:¬q = stCarryLeafh✝¹:q = stReturnh✝:¬origin (work 0) = true⊢ { inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁴:¬q = stInith✝³:¬q = stStarth✝²:¬q = stCarryForkh✝¹:¬q = stCarryLeafh✝:¬q = stReturn⊢ (finish (q == stDone)).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝:q = stInit⊢ { inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝¹:¬q = stInith✝:q = stStart⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝²:¬q = stInith✝¹:¬q = stStarth✝:q = stCarryFork⊢ (carry false work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝³:¬q = stInith✝²:¬q = stStarth✝¹:¬q = stCarryForkh✝:q = stCarryLeaf⊢ (carry true work).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:(work 2 == some 0) = true⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:¬(work 2 == some 0) = true⊢ { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁵:¬q = stInith✝⁴:¬q = stStarth✝³:¬q = stCarryForkh✝²:¬q = stCarryLeafh✝¹:q = stReturnh✝:¬origin (work 0) = true⊢ { inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.inputMove ≠
-1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:(val✝ == 0) = true⊢ (consume stString).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:¬(val✝ == 0) = true⊢ (consume stCarryFork).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:(val✝ == 0) = true⊢ (consume stCarryLeaf).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:¬(val✝ == 0) = true⊢ (consume stBit).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:q = stBit⊢ (consume stString).inputMove ≠ -1q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:¬q = stBit⊢ (consume stDead).inputMove ≠ -1 first
| exact (q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:¬q = stBit⊢ 0 ≠ -1 All goals completed! 🐙 : (0 : SignType) ≠ -1)
| exact (q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:¬q = stBit⊢ 1 ≠ -1 All goals completed! 🐙 : (1 : SignType) ≠ -1)All transitions move the two binary heads by the same displacement.
theorem binaryHeads_move_eq (q : Fin 10) (input : Option (Fin 4))
(work : Fin 3 → Option (Fin 4)) :
((machine.tr q input work).workActions 0).2 =
((machine.tr q input work).workActions 1).2 := q:Fin 10input:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ ((machine.tr q input work).workActions 0).2 = ((machine.tr q input work).workActions 1).2
q:Fin 10work:Fin 3 → Option (Fin 4)⊢ ((machine.tr q none work).workActions 0).2 = ((machine.tr q none work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ ((machine.tr q (some val✝) work).workActions 0).2 = ((machine.tr q (some val✝) work).workActions 1).2 q:Fin 10work:Fin 3 → Option (Fin 4)⊢ ((machine.tr q none work).workActions 0).2 = ((machine.tr q none work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ ((machine.tr q (some val✝) work).workActions 0).2 = ((machine.tr q (some val✝) work).workActions 1).2 q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ ((if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else
if q = stTree then consume (if (val✝ == 0) = true then stString else stCarryFork)
else
if q = stString then consume (if (val✝ == 0) = true then stCarryLeaf else stBit)
else if q = stBit then consume stString else consume stDead).workActions
0).2 =
((if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else
if q = stTree then consume (if (val✝ == 0) = true then stString else stCarryFork)
else
if q = stString then consume (if (val✝ == 0) = true then stCarryLeaf else stBit)
else if q = stBit then consume stString else consume stDead).workActions
1).2 q:Fin 10work:Fin 3 → Option (Fin 4)⊢ ((if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else finish (q == stDone)).workActions
0).2 =
((if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else finish (q == stDone)).workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4⊢ ((if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else
if q = stTree then consume (if (val✝ == 0) = true then stString else stCarryFork)
else
if q = stString then consume (if (val✝ == 0) = true then stCarryLeaf else stBit)
else if q = stBit then consume stString else consume stDead).workActions
0).2 =
((if q = stInit then
{ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }
else
if q = stStart then { inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }
else
if q = stCarryFork then carry false work
else
if q = stCarryLeaf then carry true work
else
if q = stReturn then
if origin (work 0) = true then
{ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none,
q' := some (if (work 2 == some 0) = true then stDone else stTree) }
else
{ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }
else
if q = stTree then consume (if (val✝ == 0) = true then stString else stCarryFork)
else
if q = stString then consume (if (val✝ == 0) = true then stCarryLeaf else stBit)
else if q = stBit then consume stString else consume stDead).workActions
1).2 q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝:q = stInit⊢ ({ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.workActions
0).2 =
({ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝¹:¬q = stInith✝:q = stStart⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝²:¬q = stInith✝¹:¬q = stStarth✝:q = stCarryFork⊢ ((carry false work).workActions 0).2 = ((carry false work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝³:¬q = stInith✝²:¬q = stStarth✝¹:¬q = stCarryForkh✝:q = stCarryLeaf⊢ ((carry true work).workActions 0).2 = ((carry true work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:(work 2 == some 0) = true⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:¬(work 2 == some 0) = true⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁵:¬q = stInith✝⁴:¬q = stStarth✝³:¬q = stCarryForkh✝²:¬q = stCarryLeafh✝¹:q = stReturnh✝:¬origin (work 0) = true⊢ ({ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.workActions
0).2 =
({ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:(val✝ == 0) = true⊢ ((consume stString).workActions 0).2 = ((consume stString).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:¬(val✝ == 0) = true⊢ ((consume stCarryFork).workActions 0).2 = ((consume stCarryFork).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:(val✝ == 0) = true⊢ ((consume stCarryLeaf).workActions 0).2 = ((consume stCarryLeaf).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:¬(val✝ == 0) = true⊢ ((consume stBit).workActions 0).2 = ((consume stBit).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:q = stBit⊢ ((consume stString).workActions 0).2 = ((consume stString).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:¬q = stBit⊢ ((consume stDead).workActions 0).2 = ((consume stDead).workActions 1).2 q:Fin 10work:Fin 3 → Option (Fin 4)h✝:q = stInit⊢ ({ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.workActions
0).2 =
({ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝¹:¬q = stInith✝:q = stStart⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝²:¬q = stInith✝¹:¬q = stStarth✝:q = stCarryFork⊢ ((carry false work).workActions 0).2 = ((carry false work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝³:¬q = stInith✝²:¬q = stStarth✝¹:¬q = stCarryForkh✝:q = stCarryLeaf⊢ ((carry true work).workActions 0).2 = ((carry true work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:(work 2 == some 0) = true⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:¬(work 2 == some 0) = true⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁵:¬q = stInith✝⁴:¬q = stStarth✝³:¬q = stCarryForkh✝²:¬q = stCarryLeafh✝¹:q = stReturnh✝:¬origin (work 0) = true⊢ ({ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.workActions
0).2 =
({ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)h✝⁴:¬q = stInith✝³:¬q = stStarth✝²:¬q = stCarryForkh✝¹:¬q = stCarryLeafh✝:¬q = stReturn⊢ ((finish (q == stDone)).workActions 0).2 = ((finish (q == stDone)).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝:q = stInit⊢ ({ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.workActions
0).2 =
({ inputMove := 0,
workActions := fun i ↦
if i = 0 then (some (some 3), 0) else if i = 1 then (some (some 2), 0) else (some (some 0), 1),
outS := none, q' := some stStart }.workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝¹:¬q = stInith✝:q = stStart⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝²:¬q = stInith✝¹:¬q = stStarth✝:q = stCarryFork⊢ ((carry false work).workActions 0).2 = ((carry false work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝³:¬q = stInith✝²:¬q = stStarth✝¹:¬q = stCarryForkh✝:q = stCarryLeaf⊢ ((carry true work).workActions 0).2 = ((carry true work).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:(work 2 == some 0) = true⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stDone }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:q = stReturnh✝¹:origin (work 0) = trueh✝:¬(work 2 == some 0) = true⊢ ({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 0).2 =
({ inputMove := 0, workActions := fun x ↦ (none, 0), outS := none, q' := some stTree }.workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁵:¬q = stInith✝⁴:¬q = stStarth✝³:¬q = stCarryForkh✝²:¬q = stCarryLeafh✝¹:q = stReturnh✝:¬origin (work 0) = true⊢ ({ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.workActions
0).2 =
({ inputMove := 0, workActions := fun i ↦ (none, if i = 2 then 0 else -1), outS := none,
q' := some stReturn }.workActions
1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:(val✝ == 0) = true⊢ ((consume stString).workActions 0).2 = ((consume stString).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁶:¬q = stInith✝⁵:¬q = stStarth✝⁴:¬q = stCarryForkh✝³:¬q = stCarryLeafh✝²:¬q = stReturnh✝¹:q = stTreeh✝:¬(val✝ == 0) = true⊢ ((consume stCarryFork).workActions 0).2 = ((consume stCarryFork).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:(val✝ == 0) = true⊢ ((consume stCarryLeaf).workActions 0).2 = ((consume stCarryLeaf).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:q = stStringh✝:¬(val✝ == 0) = true⊢ ((consume stBit).workActions 0).2 = ((consume stBit).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:q = stBit⊢ ((consume stString).workActions 0).2 = ((consume stString).workActions 1).2q:Fin 10work:Fin 3 → Option (Fin 4)val✝:Fin 4h✝⁷:¬q = stInith✝⁶:¬q = stStarth✝⁵:¬q = stCarryForkh✝⁴:¬q = stCarryLeafh✝³:¬q = stReturnh✝²:¬q = stTreeh✝¹:¬q = stStringh✝:¬q = stBit⊢ ((consume stDead).workActions 0).2 = ((consume stDead).workActions 1).2 All goals completed! 🐙A stationary or right-moving displacement cannot lower an input position.
theorem le_moveInputPos {n : ℕ} (p : Fin (n + 2)) (d : SignType) (h : d ≠ -1) :
p.val ≤ (moveInputPos p d).val := n:ℕp:Fin (n + 2)d:SignTypeh:d ≠ -1⊢ ↑p ≤ ↑(moveInputPos p d)
cases d with
n:ℕp:Fin (n + 2)h:SignType.neg ≠ -1⊢ ↑p ≤ ↑(moveInputPos p SignType.neg) All goals completed! 🐙
n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1⊢ ↑p ≤ ↑(moveInputPos p SignType.zero)
n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1⊢ ↑p ≤
↑(have p_1 := (↑↑p + ↑SignType.zero).toNat;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)
zero n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑p⊢ ↑p ≤
↑(have p_1 := (↑↑p + ↑SignType.zero).toNat;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)
rw [hz zero n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑p⊢ ↑p ≤
↑(have p_1 := ↑p;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)] zero n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑p⊢ ↑p ≤
↑(have p_1 := ↑p;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)
dsimp only zero n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑p⊢ ↑p ≤ ↑(if h : ↑p < n + 2 then ⟨↑p, h⟩ else ⟨n + 1, ⋯⟩)
split zero.isTrue n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑ph✝:↑p < n + 2⊢ ↑p ≤ ↑⟨↑p, h✝⟩zero.isFalse n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑ph✝:¬↑p < n + 2⊢ ↑p ≤ ↑⟨n + 1, ⋯⟩
· zero.isTrue n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑ph✝:↑p < n + 2⊢ ↑p ≤ ↑⟨↑p, h✝⟩ exact Nat.le_refl _ All goals completed! 🐙
· zero.isFalse n:ℕp:Fin (n + 2)h:SignType.zero ≠ -1hz:(↑↑p + ↑SignType.zero).toNat = ↑ph✝:¬↑p < n + 2⊢ ↑p ≤ ↑⟨n + 1, ⋯⟩ exact Nat.le_of_lt_succ p.isLt All goals completed! 🐙
| pos => pos n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1⊢ ↑p ≤ ↑(moveInputPos p SignType.pos)
unfold moveInputPos pos n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1⊢ ↑p ≤
↑(have p_1 := (↑↑p + ↑SignType.pos).toNat;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)
have hz : ((p.val : ℤ) + (SignType.pos.cast : ℤ)).toNat = p.val + 1 := by n:ℕp:Fin (n + 2)d:SignTypeh:d ≠ -1⊢ ↑p ≤ ↑(moveInputPos p d)
change ((p.val : ℤ) + 1).toNat = p.val + 1 n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1⊢ (↑↑p + 1).toNat = ↑p + 1
omega pos n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1⊢ ↑p ≤
↑(have p_1 := (↑↑p + ↑SignType.pos).toNat;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)
rw [hz pos n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1⊢ ↑p ≤
↑(have p_1 := ↑p + 1;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)] pos n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1⊢ ↑p ≤
↑(have p_1 := ↑p + 1;
if h : p_1 < n + 2 then ⟨p_1, h⟩ else ⟨n + 1, ⋯⟩)
dsimp only pos n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1⊢ ↑p ≤ ↑(if h : ↑p + 1 < n + 2 then ⟨↑p + 1, h⟩ else ⟨n + 1, ⋯⟩)
split pos.isTrue n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1h✝:↑p + 1 < n + 2⊢ ↑p ≤ ↑⟨↑p + 1, h✝⟩pos.isFalse n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1h✝:¬↑p + 1 < n + 2⊢ ↑p ≤ ↑⟨n + 1, ⋯⟩
· pos.isTrue n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1h✝:↑p + 1 < n + 2⊢ ↑p ≤ ↑⟨↑p + 1, h✝⟩ exact Nat.le_succ _ All goals completed! 🐙
· pos.isFalse n:ℕp:Fin (n + 2)h:SignType.pos ≠ -1hz:(↑↑p + ↑SignType.pos).toNat = ↑p + 1h✝:¬↑p + 1 < n + 2⊢ ↑p ≤ ↑⟨n + 1, ⋯⟩ exact Nat.le_of_lt_succ p.isLt All goals completed! 🐙The initialized configuration has counter values one and zero.
def startCfg (input : List (Fin 4)) : Cfg 3 (Fin 4) (Fin 10) input where
state := some stTree
inputPos := 1
workTapes i z := if z = 0 then some (if i = 0 then 3 else if i = 1 then 2 else 0)
else none
workTapePos i := if i = 2 then 1 else 0The digits read at nonnegative positions of a work tape.
def digits {input : List (Fin 4)} (cfg : Cfg 3 (Fin 4) (Fin 10) input)
(i : Fin 3) (j : ℕ) : Bool := digit (cfg.workTapes i j)Both carry states resolve to the common carry transition.
theorem tr_carry (leaf : Bool) (input : Option (Fin 4))
(work : Fin 3 → Option (Fin 4)) :
machine.tr (if leaf then stCarryLeaf else stCarryFork) input work = carry leaf work := by leaf:Boolinput:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ machine.tr (if leaf = true then stCarryLeaf else stCarryFork) input work = carry leaf work
cases leaf false input:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ machine.tr (if false = true then stCarryLeaf else stCarryFork) input work = carry false worktrue input:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ machine.tr (if true = true then stCarryLeaf else stCarryFork) input work = carry true work <;> false input:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ machine.tr (if false = true then stCarryLeaf else stCarryFork) input work = carry false worktrue input:Option (Fin 4)work:Fin 3 → Option (Fin 4)⊢ machine.tr (if true = true then stCarryLeaf else stCarryFork) input work = carry true work rfl All goals completed! 🐙A return configuration with the binary heads at a specified nonnegative position.
def returnCfg {input : List (Fin 4)} (cfg : Cfg 3 (Fin 4) (Fin 10) input)
(p : ℕ) : Cfg 3 (Fin 4) (Fin 10) input where
state := some stReturn
inputPos := cfg.inputPos
workTapes := cfg.workTapes
workTapePos i := if i = 2 then cfg.workTapePos 2 else pThe configuration reached when the return's final state change has completed.
def returnedCfg {input : List (Fin 4)} (cfg : Cfg 3 (Fin 4) (Fin 10) input) :
Cfg 3 (Fin 4) (Fin 10) input :=
{ returnCfg cfg 0 with
state := some (if cfg.workTapes 2 (cfg.workTapePos 2) == some 0 then stDone else stTree) }A configuration already in the return state equals its return normal form.
theorem returnCfg_self {input : List (Fin 4)}
(cfg : Cfg 3 (Fin 4) (Fin 10) input) (p : ℕ)
(hq : cfg.state = some stReturn)
(hp0 : cfg.workTapePos 0 = p) (hp1 : cfg.workTapePos 1 = p) :
returnCfg cfg p = cfg := by input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputp:ℕhq:cfg.state = some stReturnhp0:cfg.workTapePos 0 = ↑php1:cfg.workTapePos 1 = ↑p⊢ returnCfg cfg p = cfg
refine Cfg.ext hq.symm rfl rfl ?_ input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputp:ℕhq:cfg.state = some stReturnhp0:cfg.workTapePos 0 = ↑php1:cfg.workTapePos 1 = ↑p⊢ (returnCfg cfg p).workTapePos = cfg.workTapePos
funext i input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputp:ℕhq:cfg.state = some stReturnhp0:cfg.workTapePos 0 = ↑php1:cfg.workTapePos 1 = ↑pi:Fin 3⊢ (returnCfg cfg p).workTapePos i = cfg.workTapePos i
exact Fin.cases hp0.symm (Fin.cases hp1.symm (Fin.cases rfl (fun i ↦ Fin.elim0 i))) i All goals completed! 🐙The finite machine state corresponding to a scanner mode.
def modeState : Mode → Fin 10
| .tree => stTree
| .string => stString
| .bit => stBit
| .done => stDone
| .dead => stDeadThe state entered by consuming one bit, before any counter update.
def postReadState : Mode → Bool → Fin 10
| .tree, false => stString
| .tree, true => stCarryFork
| .string, false => stCarryLeaf
| .string, true => stBit
| .bit, _ => stString
| .done, _ => stDead
| .dead, _ => stDeadReading a bit selects the grammar transition without modifying work tapes.
theorem tr_read (m : Mode) (b : Bool) (work : Fin 3 → Option (Fin 4)) :
machine.tr (modeState m) (some (boolEmb b)) work = consume (postReadState m b) := by m:Modeb:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState m) (some (boolEmb b)) work = consume (postReadState m b)
cases m tree b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.tree) (some (boolEmb b)) work = consume (postReadState Mode.tree b)string b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.string) (some (boolEmb b)) work = consume (postReadState Mode.string b)bit b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.bit) (some (boolEmb b)) work = consume (postReadState Mode.bit b)done b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.done) (some (boolEmb b)) work = consume (postReadState Mode.done b)dead b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) (some (boolEmb b)) work = consume (postReadState Mode.dead b) <;> tree b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.tree) (some (boolEmb b)) work = consume (postReadState Mode.tree b)string b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.string) (some (boolEmb b)) work = consume (postReadState Mode.string b)bit b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.bit) (some (boolEmb b)) work = consume (postReadState Mode.bit b)done b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.done) (some (boolEmb b)) work = consume (postReadState Mode.done b)dead b:Boolwork:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) (some (boolEmb b)) work = consume (postReadState Mode.dead b) cases b dead.false work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) (some (boolEmb false)) work = consume (postReadState Mode.dead false)dead.true work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) (some (boolEmb true)) work = consume (postReadState Mode.dead true) <;> tree.false work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.tree) (some (boolEmb false)) work = consume (postReadState Mode.tree false)tree.true work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.tree) (some (boolEmb true)) work = consume (postReadState Mode.tree true)string.false work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.string) (some (boolEmb false)) work = consume (postReadState Mode.string false)string.true work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.string) (some (boolEmb true)) work = consume (postReadState Mode.string true)bit.false work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.bit) (some (boolEmb false)) work = consume (postReadState Mode.bit false)bit.true work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.bit) (some (boolEmb true)) work = consume (postReadState Mode.bit true)done.false work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.done) (some (boolEmb false)) work = consume (postReadState Mode.done false)done.true work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.done) (some (boolEmb true)) work = consume (postReadState Mode.done true)dead.false work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) (some (boolEmb false)) work = consume (postReadState Mode.dead false)dead.true work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) (some (boolEmb true)) work = consume (postReadState Mode.dead true) rfl All goals completed! 🐙Reading a bit changes the input position and finite control only.
def consumeCfg {input : List (Fin 4)} (cfg : Cfg 3 (Fin 4) (Fin 10) input) (q : Fin 10) :
Cfg 3 (Fin 4) (Fin 10) input :=
{ cfg with state := some q, inputPos := moveInputPos cfg.inputPos 1 }The input position advances by one when it is not the right end marker.
theorem consumeCfg_inputPos {input : List (Fin 4)} (cfg : Cfg 3 (Fin 4) (Fin 10) input)
(q : Fin 10) (h : cfg.inputPos.val < input.length + 1) :
(consumeCfg cfg q).inputPos.val = cfg.inputPos.val + 1 := by input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1⊢ ↑(consumeCfg cfg q).inputPos = ↑cfg.inputPos + 1
change (moveInputPos cfg.inputPos SignType.pos).val = _ input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1⊢ ↑(moveInputPos cfg.inputPos SignType.pos) = ↑cfg.inputPos + 1
unfold moveInputPos input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1⊢ ↑(have p := (↑↑cfg.inputPos + ↑SignType.pos).toNat;
if h : p < input.length + 2 then ⟨p, h⟩ else ⟨input.length + 1, ⋯⟩) =
↑cfg.inputPos + 1
have hz : ((cfg.inputPos.val : ℤ) + (SignType.pos.cast : ℤ)).toNat =
cfg.inputPos.val + 1 := by input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1⊢ ↑(consumeCfg cfg q).inputPos = ↑cfg.inputPos + 1
change ((cfg.inputPos.val : ℤ) + 1).toNat = cfg.inputPos.val + 1 input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1⊢ (↑↑cfg.inputPos + 1).toNat = ↑cfg.inputPos + 1
omega input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1⊢ ↑(have p := (↑↑cfg.inputPos + ↑SignType.pos).toNat;
if h : p < input.length + 2 then ⟨p, h⟩ else ⟨input.length + 1, ⋯⟩) =
↑cfg.inputPos + 1
rw [hz input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1⊢ ↑(have p := ↑cfg.inputPos + 1;
if h : p < input.length + 2 then ⟨p, h⟩ else ⟨input.length + 1, ⋯⟩) =
↑cfg.inputPos + 1] input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1⊢ ↑(have p := ↑cfg.inputPos + 1;
if h : p < input.length + 2 then ⟨p, h⟩ else ⟨input.length + 1, ⋯⟩) =
↑cfg.inputPos + 1
dsimp only input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1⊢ ↑(if h : ↑cfg.inputPos + 1 < input.length + 2 then ⟨↑cfg.inputPos + 1, h⟩ else ⟨input.length + 1, ⋯⟩) =
↑cfg.inputPos + 1
split isTrue input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1h✝:↑cfg.inputPos + 1 < input.length + 2⊢ ↑⟨↑cfg.inputPos + 1, h✝⟩ = ↑cfg.inputPos + 1isFalse input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1h✝:¬↑cfg.inputPos + 1 < input.length + 2⊢ ↑⟨input.length + 1, ⋯⟩ = ↑cfg.inputPos + 1
· isTrue input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1h✝:↑cfg.inputPos + 1 < input.length + 2⊢ ↑⟨↑cfg.inputPos + 1, h✝⟩ = ↑cfg.inputPos + 1 rfl All goals completed! 🐙
· isFalse input:List (Fin 4)cfg:Cfg 3 (Fin 4) (Fin 10) inputq:Fin 10h:↑cfg.inputPos < input.length + 1hz:(↑↑cfg.inputPos + ↑SignType.pos).toNat = ↑cfg.inputPos + 1h✝:¬↑cfg.inputPos + 1 < input.length + 2⊢ ↑⟨input.length + 1, ⋯⟩ = ↑cfg.inputPos + 1 omega All goals completed! 🐙The right end marker emits the accepting-mode test and halts.
theorem tr_end (m : Mode) (work : Fin 3 → Option (Fin 4)) :
machine.tr (modeState m) none work = finish (decide (m = .done)) := by m:Modework:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState m) none work = finish (decide (m = Mode.done))
cases m tree work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.tree) none work = finish (decide (Mode.tree = Mode.done))string work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.string) none work = finish (decide (Mode.string = Mode.done))bit work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.bit) none work = finish (decide (Mode.bit = Mode.done))done work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.done) none work = finish (decide (Mode.done = Mode.done))dead work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) none work = finish (decide (Mode.dead = Mode.done)) <;> tree work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.tree) none work = finish (decide (Mode.tree = Mode.done))string work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.string) none work = finish (decide (Mode.string = Mode.done))bit work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.bit) none work = finish (decide (Mode.bit = Mode.done))done work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.done) none work = finish (decide (Mode.done = Mode.done))dead work:Fin 3 → Option (Fin 4)⊢ machine.tr (modeState Mode.dead) none work = finish (decide (Mode.dead = Mode.done)) rfl All goals completed! 🐙Every work head lies in the nonnegative interval bounded by the chosen width.
def HeadBound {input : List (Fin 4)} (width : ℕ) (cfg : Cfg 3 (Fin 4) (Fin 10) input) :
Prop := ∀ i, 0 ≤ cfg.workTapePos i ∧ cfg.workTapePos i ≤ (width : ℤ)end Geb.BitTree.BinaryMachine