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.TapeLemmas
set_option doc.verso true

Time 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_validBool packages 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 1w.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 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 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).2w: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).2w: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).2w: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).2w: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 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).2w: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).2w: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).2w: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).2w: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 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 : ) := w:List Boolt:ht:t w.length + 3i:Fin 10 (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i (configs (initCfg (List.map (⇑boolEmb) w)) t).workTapePos i (w.length + 1) w:List Booli:Fin 1ht:0 w.length + 30 (configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i (configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i (w.length + 1)w:List Booli:Fin 1t:ht:t + 1 w.length + 30 (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1)).workTapePos i (configs (initCfg (List.map (⇑boolEmb) w)) (t + 1)).workTapePos i (w.length + 1) w:List Booli:Fin 1ht:0 w.length + 30 (configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i (configs (initCfg (List.map (⇑boolEmb) w)) 0).workTapePos i (w.length + 1) w:List Booli:Fin 1ht:0 w.length + 30 w.length + 1 All goals completed! 🐙 w:List Booli:Fin 1ht:0 + 1 w.length + 30 (configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i (configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i (w.length + 1)w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 30 (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) w:List Booli:Fin 1ht:0 + 1 w.length + 30 (configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i (configs (initCfg (List.map (⇑boolEmb) w)) (0 + 1)).workTapePos i (w.length + 1) w:List Booli:Fin 1ht:0 + 1 w.length + 30 (plantCfg w).workTapePos i (plantCfg w).workTapePos i (w.length + 1) All goals completed! 🐙 w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:t w.length0 (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)w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:¬t w.length0 (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) w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:t w.length0 (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) w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:t w.length0 (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) w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:t w.length0 (scan (List.take t w)).2 (scanCfg w t h (scan (List.take t w))).workTapePos i (w.length + 1) 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 + 10 (scan (List.take t w)).2 (scanCfg w t h (scan (List.take t w))).workTapePos i (w.length + 1) 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 + 10 (scan (List.take t w)).2 (scanCfg w t h (scan (List.take t w))).workTapePos i (w.length + 1) 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 + 10 (scan (List.take t w)).2w: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) 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 + 10 (scan (List.take t w)).2 All goals completed! 🐙 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) 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) All goals completed! 🐙 w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:¬t w.length0 (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) w:List Booli:Fin 1t:ht:t + 1 + 1 w.length + 3h:¬t w.lengthhe:t = w.length + 10 (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) w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 w.length + 3h:¬w.length + 1 w.length0 (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) w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 w.length + 3h:¬w.length + 1 w.length0 (scan (List.take w.length w)).2 (scan (List.take w.length w)).2 (w.length + 1) w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 w.length + 3h:¬w.length + 1 w.lengthhc:(scan w).2 w.length + 10 (scan (List.take w.length w)).2 (scan (List.take w.length w)).2 (w.length + 1) w:List Booli:Fin 1ht:w.length + 1 + 1 + 1 w.length + 3h:¬w.length + 1 w.lengthhc:(scan w).2 w.length + 10 (scan w).2 (scan w).2 (w.length + 1) exact Int.natCast_nonneg _, 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) 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 := w:List BoolspaceUsed (initCfg (List.map (⇑boolEmb) w)) (w.length + 3) w.length + 2 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 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 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 (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 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) := ComputableInTimeAndSpace (fun w [validBool w]) (fun n n + 3) fun n n + 2 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' All goals completed! 🐙
end Geb.BitTree