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.Scanner public import Geb.Prototypes.Computability.TreeScanner.Machine
set_option doc.verso true

A single-pass machine for binary trees with bitstring leaves

The input head advances once per bit. The work head stores the number of pending subtrees; a marker at cell one detects completion of the last leaf. Two initial steps position the work head and install the marker.

Main definitions

  • unaryScanner implements the fused structural and payload scan.

  • scanCfg describes a configuration after a prefix has been consumed.

Tags

binary tree, bitstring, Turing machine, recognizer

@[expose] public sectionnamespace Geb.BitTreeopen Turing MultiTapeTMopen Geb.TreeScanner (boolEmb)

The scanner modes occupy the last five machine states.

def modeState : Mode Fin 7 | .tree => 2 | .string => 3 | .bit => 4 | .done => 5 | .dead => 6

Consume one input bit, moving the counter head by the given displacement.

def consume (q : Fin 7) (d : SignType) : TransitionOut 1 (Fin 2) (Fin 7) where inputMove := 1 workActions _ := (none, d) outS := none q' := some q

A fused recognizer with one work tape and a unary pending-subtree counter.

def unaryScanner : MultiTapeTM 1 (Fin 2) (Fin 7) where q₀ := 0 tr q input work := if q = 0 then { inputMove := 0, workActions := fun _ (none, 1), outS := none, q' := some 1 } else if q = 1 then { inputMove := 0, workActions := fun _ (some (some 0), 0), outS := none, q' := some 2 } else match input with | none => { inputMove := 0, workActions := fun _ (none, 0), outS := some (boolEmb (q == 5)), q' := none } | some b => if q = 2 then if b = 0 then consume 3 0 else consume 2 1 else if q = 3 then if b = 0 then consume (if work 0 = some 0 then 5 else 2) (-1) else consume 4 0 else if q = 4 then consume 3 0 else consume 6 0

The configuration between the two initialization steps.

def plantCfg (w : List Bool) : Cfg 1 (Fin 2) (Fin 7) (w.map boolEmb) where state := some 1 inputPos := 1 workTapes _ _ := none workTapePos _ := 1

A configuration at a prefix boundary, with its pure scanner state.

def scanCfg (w : List Bool) (t : ) (h : t w.length) (s : State) : Cfg 1 (Fin 2) (Fin 7) (w.map boolEmb) where state := some (modeState s.1) inputPos := t + 1, w:List Boolt:h:t w.lengths:Statet + 1 < (List.map (⇑boolEmb) w).length + 2 w:List Boolt:h:t w.lengths:Statet + 1 < w.length + 2; All goals completed! 🐙 workTapes _ z := if z = 1 then some 0 else none workTapePos _ := s.2

Fork tags increment the counter; string terminators decrement it.

def counterMove (m : Mode) (b : Bool) : SignType := match m, b with | .tree, true => 1 | .string, false => -1 | _, _ => 0

The transition table implements the pure scanner's finite control.

theorem tr_scan (m : Mode) (n : ) (b : Bool) : unaryScanner.tr (modeState m) (some (boolEmb b)) (fun _ if n = 1 then some 0 else none) = consume (modeState (step (m, n) b).1) (counterMove m b) := m:Moden:b:Bool(unaryScanner.tr (modeState m) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (m, n) b).1) (counterMove m b) m:Moden:b:Boolhf:boolEmb false = 0(unaryScanner.tr (modeState m) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (m, n) b).1) (counterMove m b) m:Moden:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState m) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (m, n) b).1) (counterMove m b) n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) b).1) (counterMove Mode.tree b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) b).1) (counterMove Mode.string b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) b).1) (counterMove Mode.bit b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) b).1) (counterMove Mode.done b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) b).1) (counterMove Mode.dead b) n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) b).1) (counterMove Mode.tree b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) b).1) (counterMove Mode.string b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) b).1) (counterMove Mode.bit b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) b).1) (counterMove Mode.done b)n:b:Boolhf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb b)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) b).1) (counterMove Mode.dead b) n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) false).1) (counterMove Mode.dead false)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) true).1) (counterMove Mode.dead true) n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) false).1) (counterMove Mode.tree false)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) true).1) (counterMove Mode.tree true)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) false).1) (counterMove Mode.string false)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) true).1) (counterMove Mode.string true)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) false).1) (counterMove Mode.bit false)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) true).1) (counterMove Mode.bit true)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) false).1) (counterMove Mode.done false)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) true).1) (counterMove Mode.done true)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) false).1) (counterMove Mode.dead false)n:hf:boolEmb false = 0ht:boolEmb true = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) true).1) (counterMove Mode.dead true) n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) true).1) (counterMove Mode.dead true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) true).1) (counterMove Mode.dead true) n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) false).1) (counterMove Mode.tree false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) false).1) (counterMove Mode.tree false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) true).1) (counterMove Mode.tree true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.tree) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.tree, n) true).1) (counterMove Mode.tree true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) false).1) (counterMove Mode.string false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) false).1) (counterMove Mode.string false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) true).1) (counterMove Mode.string true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.string) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.string, n) true).1) (counterMove Mode.string true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) false).1) (counterMove Mode.bit false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) false).1) (counterMove Mode.bit false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) true).1) (counterMove Mode.bit true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.bit) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.bit, n) true).1) (counterMove Mode.bit true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) false).1) (counterMove Mode.done false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) false).1) (counterMove Mode.done false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) true).1) (counterMove Mode.done true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.done) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.done, n) true).1) (counterMove Mode.done true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) false).1) (counterMove Mode.dead false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb false)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) false).1) (counterMove Mode.dead false)n:hf:boolEmb false = 0ht:boolEmb true = 1h:n = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) true).1) (counterMove Mode.dead true)n:hf:boolEmb false = 0ht:boolEmb true = 1h:¬n = 1(unaryScanner.tr (modeState Mode.dead) (some (boolEmb true)) fun x if n = 1 then some 0 else none) = consume (modeState (step (Mode.dead, n) true).1) (counterMove Mode.dead true) All goals completed! 🐙

The head displacement agrees with the natural-number counter on live states.

theorem counterMove_add (m : Mode) (n : ) (b : Bool) (h : m = .string 0 < n) : (n : ) + (counterMove m b : ) = ((step (m, n) b).2 : ) := m:Moden:b:Boolh:m = Mode.string 0 < nn + (counterMove m b) = (step (m, n) b).2 n:b:Boolh:Mode.tree = Mode.string 0 < nn + (counterMove Mode.tree b) = (step (Mode.tree, n) b).2n:b:Boolh:Mode.string = Mode.string 0 < nn + (counterMove Mode.string b) = (step (Mode.string, n) b).2n:b:Boolh:Mode.bit = Mode.string 0 < nn + (counterMove Mode.bit b) = (step (Mode.bit, n) b).2n:b:Boolh:Mode.done = Mode.string 0 < nn + (counterMove Mode.done b) = (step (Mode.done, n) b).2n:b:Boolh:Mode.dead = Mode.string 0 < nn + (counterMove Mode.dead b) = (step (Mode.dead, n) b).2 n:b:Boolh:Mode.tree = Mode.string 0 < nn + (counterMove Mode.tree b) = (step (Mode.tree, n) b).2n:b:Boolh:Mode.string = Mode.string 0 < nn + (counterMove Mode.string b) = (step (Mode.string, n) b).2n:b:Boolh:Mode.bit = Mode.string 0 < nn + (counterMove Mode.bit b) = (step (Mode.bit, n) b).2n:b:Boolh:Mode.done = Mode.string 0 < nn + (counterMove Mode.done b) = (step (Mode.done, n) b).2n:b:Boolh:Mode.dead = Mode.string 0 < nn + (counterMove Mode.dead b) = (step (Mode.dead, n) b).2 n:h:Mode.dead = Mode.string 0 < nn + (counterMove Mode.dead false) = (step (Mode.dead, n) false).2n:h:Mode.dead = Mode.string 0 < nn + (counterMove Mode.dead true) = (step (Mode.dead, n) true).2 n:h:Mode.tree = Mode.string 0 < nn + (counterMove Mode.tree false) = (step (Mode.tree, n) false).2n:h:Mode.tree = Mode.string 0 < nn + (counterMove Mode.tree true) = (step (Mode.tree, n) true).2n:h:Mode.string = Mode.string 0 < nn + (counterMove Mode.string false) = (step (Mode.string, n) false).2n:h:Mode.string = Mode.string 0 < nn + (counterMove Mode.string true) = (step (Mode.string, n) true).2n:h:Mode.bit = Mode.string 0 < nn + (counterMove Mode.bit false) = (step (Mode.bit, n) false).2n:h:Mode.bit = Mode.string 0 < nn + (counterMove Mode.bit true) = (step (Mode.bit, n) true).2n:h:Mode.done = Mode.string 0 < nn + (counterMove Mode.done false) = (step (Mode.done, n) false).2n:h:Mode.done = Mode.string 0 < nn + (counterMove Mode.done true) = (step (Mode.done, n) true).2n:h:Mode.dead = Mode.string 0 < nn + (counterMove Mode.dead false) = (step (Mode.dead, n) false).2n:h:Mode.dead = Mode.string 0 < nn + (counterMove Mode.dead true) = (step (Mode.dead, n) true).2 try All goals completed! 🐙 n:h:Mode.string = Mode.string 0 < nn - 1 = (finish n).2 n:h:Mode.string = Mode.string 0 < nn - 1 = (if n = 1 then (Mode.done, 0) else (Mode.tree, n - 1)).2 n:h:Mode.string = Mode.string 0 < nhn:n = 1n - 1 = (Mode.done, 0).2n:h:Mode.string = Mode.string 0 < nhn:¬n = 1n - 1 = (Mode.tree, n - 1).2 n:h:Mode.string = Mode.string 0 < nhn:n = 1n - 1 = (Mode.done, 0).2 h:Mode.string = Mode.string 0 < 11 - 1 = (Mode.done, 0).2 All goals completed! 🐙 n:h:Mode.string = Mode.string 0 < nhn:¬n = 1n - 1 = (Mode.tree, n - 1).2 n:h:Mode.string = Mode.string 0 < nhn:¬n = 1n - 1 = (n - 1) n:h:Mode.string = Mode.string 0 < nhn:¬n = 1hp:0 < nn - 1 = (n - 1) All goals completed! 🐙

A transition increases the pending count by at most one.

theorem step_counter_le (s : State) (b : Bool) : (step s b).2 s.2 + 1 := s:Stateb:Bool(step s b).2 s.2 + 1 b:Boolm:Moden:(step (m, n) b).2 (m, n).2 + 1 b:Booln:(step (Mode.tree, n) b).2 (Mode.tree, n).2 + 1b:Booln:(step (Mode.string, n) b).2 (Mode.string, n).2 + 1b:Booln:(step (Mode.bit, n) b).2 (Mode.bit, n).2 + 1b:Booln:(step (Mode.done, n) b).2 (Mode.done, n).2 + 1b:Booln:(step (Mode.dead, n) b).2 (Mode.dead, n).2 + 1 b:Booln:(step (Mode.tree, n) b).2 (Mode.tree, n).2 + 1b:Booln:(step (Mode.string, n) b).2 (Mode.string, n).2 + 1b:Booln:(step (Mode.bit, n) b).2 (Mode.bit, n).2 + 1b:Booln:(step (Mode.done, n) b).2 (Mode.done, n).2 + 1b:Booln:(step (Mode.dead, n) b).2 (Mode.dead, n).2 + 1 n:(step (Mode.dead, n) false).2 (Mode.dead, n).2 + 1n:(step (Mode.dead, n) true).2 (Mode.dead, n).2 + 1 n:(step (Mode.tree, n) false).2 (Mode.tree, n).2 + 1n:(step (Mode.tree, n) true).2 (Mode.tree, n).2 + 1n:(step (Mode.string, n) false).2 (Mode.string, n).2 + 1n:(step (Mode.string, n) true).2 (Mode.string, n).2 + 1n:(step (Mode.bit, n) false).2 (Mode.bit, n).2 + 1n:(step (Mode.bit, n) true).2 (Mode.bit, n).2 + 1n:(step (Mode.done, n) false).2 (Mode.done, n).2 + 1n:(step (Mode.done, n) true).2 (Mode.done, n).2 + 1n:(step (Mode.dead, n) false).2 (Mode.dead, n).2 + 1n:(step (Mode.dead, n) true).2 (Mode.dead, n).2 + 1 first | All goals completed! 🐙 | n:(step (Mode.string, n) false).2 (Mode.string, n).2 + 1 | (n:(finish n).2 n + 1; n:(if n = 1 then (Mode.done, 0) else (Mode.tree, n - 1)).2 n + 1; n:h✝:n = 1(Mode.done, 0).2 n + 1n:h✝:¬n = 1(Mode.tree, n - 1).2 n + 1 n:h✝:n = 1(Mode.done, 0).2 n + 1n:h✝:¬n = 1(Mode.tree, n - 1).2 n + 1 n:h✝:¬n = 1n - 1 n + 1 n:h✝:n = 10 n + 1n:h✝:¬n = 1n - 1 n + 1 All goals completed! 🐙)

A scan's pending count is bounded by its initial count plus its input length.

theorem foldl_counter_le (w : List Bool) : s : State, (w.foldl step s).2 s.2 + w.length := w:List Bool (s : State), (List.foldl step s w).2 s.2 + w.length w:List Bool (s : State), (List.foldl step s []).2 s.2 + [].lengthw:List Bool (head : Bool) (tail : List Bool), (∀ (s : State), (List.foldl step s tail).2 s.2 + tail.length) (s : State), (List.foldl step s (head :: tail)).2 s.2 + (head :: tail).length w:List Bool (s : State), (List.foldl step s []).2 s.2 + [].length w:List Bools:State(List.foldl step s []).2 s.2 + [].length All goals completed! 🐙 w:List Bool (head : Bool) (tail : List Bool), (∀ (s : State), (List.foldl step s tail).2 s.2 + tail.length) (s : State), (List.foldl step s (head :: tail)).2 s.2 + (head :: tail).length w:List Boolb:Boolbs:List Boolih: (s : State), (List.foldl step s bs).2 s.2 + bs.lengths:State(List.foldl step s (b :: bs)).2 s.2 + (b :: bs).length w:List Boolb:Boolbs:List Boolih: (s : State), (List.foldl step s bs).2 s.2 + bs.lengths:Stateh:(List.foldl step (step s b) bs).2 (step s b).2 + bs.length(List.foldl step s (b :: bs)).2 s.2 + (b :: bs).length w:List Boolb:Boolbs:List Boolih: (s : State), (List.foldl step s bs).2 s.2 + bs.lengths:Stateh:(List.foldl step (step s b) bs).2 (step s b).2 + bs.lengthhstep:(step s b).2 s.2 + 1(List.foldl step s (b :: bs)).2 s.2 + (b :: bs).length w:List Boolb:Boolbs:List Boolih: (s : State), (List.foldl step s bs).2 s.2 + bs.lengths:Stateh:(List.foldl step (step s b) bs).2 (step s b).2 + bs.lengthhstep:(step s b).2 s.2 + 1(List.foldl step (step s b) bs).2 s.2 + (bs.length + 1) All goals completed! 🐙

There are at most one plus the input length pending subtrees.

theorem scan_counter_le (w : List Bool) : (scan w).2 w.length + 1 := w:List Bool(scan w).2 w.length + 1 All goals completed! 🐙

Extending the scanned prefix applies one pure transition.

theorem scan_take_succ (w : List Bool) (t : ) (h : t < w.length) : scan (w.take (t + 1)) = step (scan (w.take t)) w[t] := w:List Boolt:h:t < w.lengthscan (List.take (t + 1) w) = step (scan (List.take t w)) w[t] All goals completed! 🐙
end Geb.BitTree