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.Steps
public import Cslib.Computability.Machines.Turing.MultiTape.TapeLemmasset_option doc.verso trueTime and space bounds for the single-pass bitstring-tree recognizer
The unary-counter machine takes one transition per input bit, two initialization transitions and a final output transition. Its visited work cells lie between zero and one plus the input length.
Main statements
-
computableInTimeAndSpace_validBoolpackages the recognizer in CSLib's finite-alphabet, finite-state machine complexity predicate.
Implementation notes
The space bound counts visited work cells, including blank cells. It excludes the read-only input tape, as specified by CSLib. The bound is for this unary implementation and is not a lower bound on recognition space.
Tags
binary tree, bitstring, time complexity, space complexity, Turing machine
@[expose] public sectionnamespace Geb.BitTreeopen Turing MultiTapeTMopen Geb.TreeScanner (boolEmb step_of_state)The final output transition leaves the work head in place.
theorem end_workTapePos (w : List Bool) (s : State) (i : Fin 1) :
(unaryScanner.step (scanCfg w w.length (w:List Bools:Statei:Fin 1⊢ w.length ≤ w.length All goals completed! 🐙) s)).workTapePos i = s.2 := w:List Bools:Statei:Fin 1⊢ (MultiTapeTM.step (scanCfg w w.length ⋯ s)).workTapePos i = ↑s.2
w:List Bools:Statei:Fin 1⊢ { state := (unaryScanner.tr (modeState s.1) none (scanCfg w w.length ⋯ s).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ s).inputPos
(unaryScanner.tr (modeState s.1) none (scanCfg w w.length ⋯ s).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState s.1) none (scanCfg w w.length ⋯ s).workTapeSymbols).workActions i).1 with
| none => (scanCfg w w.length ⋯ s).workTapes i
| some s_1 =>
Function.update ((scanCfg w w.length ⋯ s).workTapes i) ((scanCfg w w.length ⋯ s).workTapePos i) s_1,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ s).workTapePos i +
↑((unaryScanner.tr (modeState s.1) none (scanCfg w w.length ⋯ s).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑s.2
rcases s with ⟨m, n⟩ w:List Booli:Fin 1m:Moden:ℕ⊢ { state := (unaryScanner.tr (modeState (m, n).1) none (scanCfg w w.length ⋯ (m, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (m, n)).inputPos
(unaryScanner.tr (modeState (m, n).1) none (scanCfg w w.length ⋯ (m, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (m, n).1) none (scanCfg w w.length ⋯ (m, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (m, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (m, n)).workTapes i) ((scanCfg w w.length ⋯ (m, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (m, n)).workTapePos i +
↑((unaryScanner.tr (modeState (m, n).1) none (scanCfg w w.length ⋯ (m, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(m, n).2
cases m tree w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.tree, n).1) none (scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.tree, n)).inputPos
(unaryScanner.tr (modeState (Mode.tree, n).1) none
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.tree, n).1) none
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.tree, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.tree, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.tree, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.tree, n).1) none
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.tree, n).2string w:List Booli:Fin 1n:ℕ⊢ {
state :=
(unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.string, n)).inputPos
(unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.string, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.string, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.string, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.string, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.string, n).2bit w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.bit, n).1) none (scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.bit, n)).inputPos
(unaryScanner.tr (modeState (Mode.bit, n).1) none
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.bit, n).1) none
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.bit, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.bit, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.bit, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.bit, n).1) none
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.bit, n).2done w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.done, n).1) none (scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.done, n)).inputPos
(unaryScanner.tr (modeState (Mode.done, n).1) none
(scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.done, n).1) none
(scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.done, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.done, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.done, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.done, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.done, n).1) none
(scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.done, n).2dead w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.dead, n).1) none (scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.dead, n)).inputPos
(unaryScanner.tr (modeState (Mode.dead, n).1) none
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.dead, n).1) none
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.dead, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.dead, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.dead, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.dead, n).1) none
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.dead, n).2 <;> tree w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.tree, n).1) none (scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.tree, n)).inputPos
(unaryScanner.tr (modeState (Mode.tree, n).1) none
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.tree, n).1) none
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.tree, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.tree, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.tree, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.tree, n).1) none
(scanCfg w w.length ⋯ (Mode.tree, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.tree, n).2string w:List Booli:Fin 1n:ℕ⊢ {
state :=
(unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.string, n)).inputPos
(unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.string, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.string, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.string, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.string, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.string, n).1) none
(scanCfg w w.length ⋯ (Mode.string, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.string, n).2bit w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.bit, n).1) none (scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.bit, n)).inputPos
(unaryScanner.tr (modeState (Mode.bit, n).1) none
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.bit, n).1) none
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.bit, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.bit, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.bit, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.bit, n).1) none
(scanCfg w w.length ⋯ (Mode.bit, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.bit, n).2done w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.done, n).1) none (scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.done, n)).inputPos
(unaryScanner.tr (modeState (Mode.done, n).1) none
(scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.done, n).1) none
(scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.done, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.done, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.done, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.done, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.done, n).1) none
(scanCfg w w.length ⋯ (Mode.done, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.done, n).2dead w:List Booli:Fin 1n:ℕ⊢ { state := (unaryScanner.tr (modeState (Mode.dead, n).1) none (scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).q',
inputPos :=
moveInputPos (scanCfg w w.length ⋯ (Mode.dead, n)).inputPos
(unaryScanner.tr (modeState (Mode.dead, n).1) none
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).inputMove,
workTapes := fun i ↦
match (motive := Option (Option (Fin 2)) → ℤ → Option (Fin 2))
((unaryScanner.tr (modeState (Mode.dead, n).1) none
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).workActions
i).1 with
| none => (scanCfg w w.length ⋯ (Mode.dead, n)).workTapes i
| some s =>
Function.update ((scanCfg w w.length ⋯ (Mode.dead, n)).workTapes i)
((scanCfg w w.length ⋯ (Mode.dead, n)).workTapePos i) s,
workTapePos := fun i ↦
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapePos i +
↑((unaryScanner.tr (modeState (Mode.dead, n).1) none
(scanCfg w w.length ⋯ (Mode.dead, n)).workTapeSymbols).workActions
i).2 }.workTapePos
i =
↑(Mode.dead, n).2 simp [unaryScanner, modeState, scanCfg] All goals completed! 🐙Every visited work-head position is between zero and the input length plus one.
theorem workTapePos_bounds (w : List Bool) (t : ℕ) (ht : t ≤ w.length + 3) (i : Fin 1) :
0 ≤ (unaryScanner.configs (unaryScanner.initCfg (w.map boolEmb)) t).workTapePos i ∧
(unaryScanner.configs (unaryScanner.initCfg (w.map boolEmb)) t).workTapePos i ≤
(w.length + 1 : ℕ) := by w:List Boolt:ℕht:t ≤ w.length + 3i:Fin 1⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1)
rcases t with _ | t zero w:List Booli:Fin 1ht:0 ≤ w.length + 3⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i ≤ ↑(w.length + 1)succ w:List Booli:Fin 1t:ℕht:t + 1 ≤ w.length + 3⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1)).workTapePos i ≤ ↑(w.length + 1)
· zero w:List Booli:Fin 1ht:0 ≤ w.length + 3⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i ≤ ↑(w.length + 1) simp zero w:List Booli:Fin 1ht:0 ≤ w.length + 3⊢ 0 ≤ ↑w.length + 1
omega All goals completed! 🐙
rcases t with _ | t succ.zero w:List Booli:Fin 1ht:0 + 1 ≤ w.length + 3⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i ≤ ↑(w.length + 1)succ.succ w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ≤ ↑(w.length + 1)
· succ.zero w:List Booli:Fin 1ht:0 + 1 ≤ w.length + 3⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i ≤ ↑(w.length + 1) rw [show unaryScanner.configs (unaryScanner.initCfg (w.map boolEmb)) 1 =
plantCfg w by w:List Boolt:ℕht:t ≤ w.length + 3i:Fin 1⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1) exact init_step w All goals completed! 🐙] succ.zero w:List Booli:Fin 1ht:0 + 1 ≤ w.length + 3⊢ 0 ≤ (plantCfg w).workTapePos i ∧ (plantCfg w).workTapePos i ≤ ↑(w.length + 1)
simp [plantCfg] All goals completed! 🐙
by_cases h : t ≤ w.length pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.length⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ≤ ↑(w.length + 1)neg w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:¬t ≤ w.length⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ≤ ↑(w.length + 1)
· pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.length⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ≤ ↑(w.length + 1) rw [(configs_scan w t h).1 pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.length⊢ 0 ≤ (scanCfg w t h (scan (List.take t w))).workTapePos i ∧
(scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1)] pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.length⊢ 0 ≤ (scanCfg w t h (scan (List.take t w))).workTapePos i ∧
(scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1)
change 0 ≤ ((scan (w.take t)).2 : ℤ) ∧ _ pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.length⊢ 0 ≤ ↑(scan (List.take t w)).2 ∧ (scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1)
have hc := scan_counter_le (w.take t) pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ (List.take t w).length + 1⊢ 0 ≤ ↑(scan (List.take t w)).2 ∧ (scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1)
simp only [List.length_take] at hc pos w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ min t w.length + 1⊢ 0 ≤ ↑(scan (List.take t w)).2 ∧ (scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1)
constructor pos.left w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ min t w.length + 1⊢ 0 ≤ ↑(scan (List.take t w)).2pos.right w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ min t w.length + 1⊢ (scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1)
· pos.left w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ min t w.length + 1⊢ 0 ≤ ↑(scan (List.take t w)).2 exact Int.natCast_nonneg _ All goals completed! 🐙
· pos.right w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ min t w.length + 1⊢ (scanCfg w t h (scan (List.take t w))).workTapePos i ≤ ↑(w.length + 1) simp only [scanCfg] pos.right w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:t ≤ w.lengthhc:(scan (List.take t w)).2 ≤ min t w.length + 1⊢ ↑(scan (List.take t w)).2 ≤ ↑(w.length + 1)
omega All goals completed! 🐙
· neg w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:¬t ≤ w.length⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ≤ ↑(w.length + 1) have he : t = w.length + 1 := by w:List Boolt:ℕht:t ≤ w.length + 3i:Fin 1⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1) omega neg w:List Booli:Fin 1t:ℕht:t + 1 + 1 ≤ w.length + 3h:¬t ≤ w.lengthhe:t = w.length + 1⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (t + 1 + 1)).workTapePos i ≤ ↑(w.length + 1)
subst t neg w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.length⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) (w.length + 1 + 1 + 1)).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) (w.length + 1 + 1 + 1)).workTapePos i ≤ ↑(w.length + 1)
rw [show w.length + 1 + 1 + 1 = (w.length + 2) + 1 by w:List Boolt:ℕht:t ≤ w.length + 3i:Fin 1⊢ 0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∧
(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1) omega All goals completed! 🐙,
configs_succ_eq_step', neg w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.length⊢ 0 ≤ (MultiTapeTM.step (configs (initCfg (List.map (⇑boolEmb) w)) (w.length + 2))).workTapePos i ∧
(MultiTapeTM.step (configs (initCfg (List.map (⇑boolEmb) w)) (w.length + 2))).workTapePos i ≤ ↑(w.length + 1) (configs_scan w w.length (by w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.length⊢ w.length ≤ w.length omega All goals completed! 🐙)).1, end_workTapePos neg w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.length⊢ 0 ≤ ↑(scan (List.take w.length w)).2 ∧ ↑(scan (List.take w.length w)).2 ≤ ↑(w.length + 1)] neg w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.length⊢ 0 ≤ ↑(scan (List.take w.length w)).2 ∧ ↑(scan (List.take w.length w)).2 ≤ ↑(w.length + 1)
have hc := scan_counter_le w neg w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.lengthhc:(scan w).2 ≤ w.length + 1⊢ 0 ≤ ↑(scan (List.take w.length w)).2 ∧ ↑(scan (List.take w.length w)).2 ≤ ↑(w.length + 1)
simp only [List.take_length] neg w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.lengthhc:(scan w).2 ≤ w.length + 1⊢ 0 ≤ ↑(scan w).2 ∧ ↑(scan w).2 ≤ ↑(w.length + 1)
exact ⟨Int.natCast_nonneg _, by w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 ≤ w.length + 3h:¬w.length + 1 ≤ w.lengthhc:(scan w).2 ≤ w.length + 1⊢ ↑(scan w).2 ≤ ↑(w.length + 1) exact_mod_cast hc All goals completed! 🐙⟩The unary machine visits at most the input length plus two work cells.
theorem spaceUsed_le (w : List Bool) :
unaryScanner.spaceUsed (unaryScanner.initCfg (w.map boolEmb)) (w.length + 3) ≤
w.length + 2 := by w:List Bool⊢ spaceUsed (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) ≤ w.length + 2
have hsub (i : Fin 1) :
unaryScanner.visitedByTapeHead (unaryScanner.initCfg (w.map boolEmb))
(w.length + 3) i ⊆ (Finset.range (w.length + 2)).image (fun n : ℕ ↦ (n : ℤ)) := by
intro z hz w:List Booli:Fin 1z:ℤhz:z ∈ visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i⊢ z ∈ Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))
obtain ⟨t, ht, rfl⟩ := unaryScanner.mem_visitedByTapeHead.mp hz w:List Booli:Fin 1t:ℕht:t < w.length + 3 + 1hz:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i⊢ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈ Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))
obtain ⟨hlo, hhi⟩ := workTapePos_bounds w t (by w:List Booli:Fin 1t:ℕht:t < w.length + 3 + 1hz:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i⊢ t ≤ w.length + 3 omega All goals completed! 🐙) i w:List Booli:Fin 1t:ℕht:t < w.length + 3 + 1hz:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) ihlo:0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos ihhi:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1)⊢ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈ Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))
apply Finset.mem_image.mpr w:List Booli:Fin 1t:ℕht:t < w.length + 3 + 1hz:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) ihlo:0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos ihhi:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1)⊢ ∃ a ∈ Finset.range (w.length + 2), ↑a = (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i
refine ⟨_, Finset.mem_range.mpr ?_, Int.toNat_of_nonneg hlo⟩ w:List Booli:Fin 1t:ℕht:t < w.length + 3 + 1hz:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ∈
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) ihlo:0 ≤ (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos ihhi:(configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i ≤ ↑(w.length + 1)⊢ ((configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i).toNat < w.length + 2
omega w:List Boolhsub:∀ (i : Fin 1),
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i ⊆
Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))⊢ spaceUsed (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) ≤ w.length + 2
change ∑ i : Fin 1, _ ≤ _ w:List Boolhsub:∀ (i : Fin 1),
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i ⊆
Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))⊢ ∑ i, spaceUsedByTape (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i ≤ w.length + 2
simp only [Finset.univ_unique, Finset.sum_singleton] w:List Boolhsub:∀ (i : Fin 1),
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i ⊆
Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))⊢ spaceUsedByTape (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) default ≤ w.length + 2
exact (Finset.card_le_card (hsub 0)).trans
(Finset.card_image_le.trans (by w:List Boolhsub:∀ (i : Fin 1),
visitedByTapeHead (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) i ⊆
Finset.image (fun n ↦ ↑n) (Finset.range (w.length + 2))⊢ (Finset.range (w.length + 2)).card ≤ w.length + 2 simp All goals completed! 🐙))The unified recognizer runs in input length plus three steps and input length plus two cells.
theorem computableInTimeAndSpace_validBool :
ComputableInTimeAndSpace (fun w : List Bool ↦ [validBool w])
(fun n ↦ n + 3) (fun n ↦ n + 2) := by ⊢ ComputableInTimeAndSpace (fun w ↦ [validBool w]) (fun n ↦ n + 3) fun n ↦ n + 2
refine ⟨1, 2, 7, boolEmb, unaryScanner, fun w ↦ ?_⟩ w:List Bool⊢ ∃ t' ≤ (fun n ↦ n + 3) w.length,
∃ s' ≤ (fun n ↦ n + 2) w.length,
unaryScanner.ComputesInTimeAndSpace (List.map (⇑boolEmb) w) (List.map (⇑boolEmb) ((fun w ↦ [validBool w]) w)) t' s'
exact ⟨w.length + 3, le_refl _,
unaryScanner.spaceUsed (unaryScanner.initCfg (w.map boolEmb)) (w.length + 3),
spaceUsed_le w, halts_at w, outputString_eq w, rfl⟩ All goals completed! 🐙end Geb.BitTree