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 Mathlib.Data.Nat.BinaryRec
public import Mathlib.Data.Nat.Notation
public import Mathlib.Tactic.ToDualset_option doc.verso trueA bitwise scanner for delta-prefixed leaf payloads
The finite control distinguishes tree tags, the unary part of a delta header, the two binary header fields, and raw payload bits. The pending-subtree counter is changed only by fork tags and completed leaf payloads.
Main definitions
-
Moderecords the current phase and its numeric counters. -
stepconsumes exactly one input bit. -
scanfolds the transition over the input.
Tags
Elias delta code, binary tree, streaming recognizer
@[expose] public sectionnamespace Geb.BitTree.Elias.ScannerHeader and payload phases, with remaining lengths and partial binary values.
inductive Mode where
| tree
| zeros (count : ℕ)
| size (remaining value : ℕ)
| length (remaining value : ℕ)
| payload (remaining : ℕ)
| done
| dead
deriving DecidableEq, Repr, InhabitedA phase and the number of pending subtrees.
abbrev State := Mode × ℕComplete one leaf, recognizing the final pending subtree.
Read one bit, including all phase changes that consume no additional input.
def step : State → Bool → State
| (.tree, n), true => (.tree, n + 1)
| (.tree, n), false => (.zeros 0, n)
| (.zeros z, n), false => (.zeros (z + 1), n)
| (.zeros z, n), true => if z = 0 then finish n else (.size z 1, n)
| (.size r v, n), b =>
if r = 1 then (.length (Nat.bit b v - 1) 1, n) else (.size (r - 1) (Nat.bit b v), n)
| (.length r v, n), b =>
if r = 1 then (.payload (Nat.bit b v - 1), n) else (.length (r - 1) (Nat.bit b v), n)
| (.payload r, n), _ => if r = 1 then finish n else (.payload (r - 1), n)
| (.done, n), _ => (.dead, n)
| (.dead, n), _ => (.dead, n)Scan from one pending root.
Accept exactly when the complete root ends at the end of input.
Positive pending counts and positive remaining lengths in the active phases.
def Active : State → Prop
| (.done, n) | (.dead, n) => n = 0
| (.tree, n) | (.zeros _, n) => 0 < n
| (.size r v, n) | (.length r v, n) => 0 < n ∧ 0 < r ∧ 0 < v
| (.payload r, n) => 0 < n ∧ 0 < rCompleting an active leaf preserves the scanner invariant.
theorem active_finish (n : ℕ) (hn : 0 < n) : Active (finish n) := n:ℕhn:0 < n⊢ Active (finish n)
n:ℕhn:0 < n⊢ Active (if n = 1 then (Mode.done, 0) else (Mode.tree, n - 1))
n:ℕhn:0 < nh✝:n = 1⊢ Active (Mode.done, 0)n:ℕhn:0 < nh✝:¬n = 1⊢ Active (Mode.tree, n - 1) n:ℕhn:0 < nh✝:n = 1⊢ Active (Mode.done, 0)n:ℕhn:0 < nh✝:¬n = 1⊢ Active (Mode.tree, n - 1) n:ℕhn:0 < nh✝:¬n = 1⊢ 0 < n - 1 n:ℕhn:0 < nh✝:¬n = 1⊢ 0 < n - 1 All goals completed! 🐙Consuming one bit preserves the invariant.
theorem active_step (s : State) (b : Bool) (h : Active s) : Active (step s b) := s:Stateb:Boolh:Active s⊢ Active (step s b)
b:Boolm:Moden:ℕh:Active (m, n)⊢ Active (step (m, n) b)
cases m with
b:Booln:ℕh:Active (Mode.tree, n)⊢ Active (step (Mode.tree, n) b)
b:Booln:ℕh:0 < n⊢ Active (step (Mode.tree, n) b)
n:ℕh:0 < n⊢ Active (step (Mode.tree, n) false)n:ℕh:0 < n⊢ Active (step (Mode.tree, n) true) n:ℕh:0 < n⊢ Active (step (Mode.tree, n) false)n:ℕh:0 < n⊢ Active (step (Mode.tree, n) true) n:ℕh:0 < n⊢ 0 < n + 1 n:ℕh:0 < n⊢ 0 < nn:ℕh:0 < n⊢ 0 < n + 1 All goals completed! 🐙
b:Booln:ℕz:ℕh:Active (Mode.zeros z, n)⊢ Active (step (Mode.zeros z, n) b)
cases b with
n:ℕz:ℕh:Active (Mode.zeros z, n)⊢ Active (step (Mode.zeros z, n) false) All goals completed! 🐙
n:ℕz:ℕh:Active (Mode.zeros z, n)⊢ Active (step (Mode.zeros z, n) true)
n:ℕz:ℕh:Active (Mode.zeros z, n)⊢ Active (if z = 0 then finish n else (Mode.size z 1, n))
n:ℕz:ℕh:Active (Mode.zeros z, n)h✝:z = 0⊢ Active (finish n)n:ℕz:ℕh:Active (Mode.zeros z, n)h✝:¬z = 0⊢ Active (Mode.size z 1, n)
n:ℕz:ℕh:Active (Mode.zeros z, n)h✝:z = 0⊢ Active (finish n) All goals completed! 🐙
n:ℕz:ℕh:Active (Mode.zeros z, n)h✝:¬z = 0⊢ Active (Mode.size z 1, n) exact ⟨h, n:ℕz:ℕh:Active (Mode.zeros z, n)h✝:¬z = 0⊢ 0 < z All goals completed! 🐙, n:ℕz:ℕh:Active (Mode.zeros z, n)h✝:¬z = 0⊢ 0 < 1 All goals completed! 🐙⟩
b:Booln:ℕr:ℕv:ℕh:Active (Mode.size r v, n)⊢ Active (step (Mode.size r v, n) b)
b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < v⊢ Active (step (Mode.size r v, n) b)
size b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b v⊢ Active (step (Mode.size r v, n) b)
change Active (if r = 1 then _ else _) size b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b v⊢ Active (if r = 1 then (Mode.length (Nat.bit b v - 1) 1, n) else (Mode.size (r - 1) (Nat.bit b v), n))
split size.isTrue b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ Active (Mode.length (Nat.bit b v - 1) 1, n)size.isFalse b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ Active (Mode.size (r - 1) (Nat.bit b v), n)
· size.isTrue b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ Active (Mode.length (Nat.bit b v - 1) 1, n) exact ⟨hn, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ 0 < Nat.bit b v - 1 omega All goals completed! 🐙, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ 0 < 1 decide All goals completed! 🐙⟩
· size.isFalse b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ Active (Mode.size (r - 1) (Nat.bit b v), n) exact ⟨hn, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ 0 < r - 1 omega All goals completed! 🐙, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ 0 < Nat.bit b v omega All goals completed! 🐙⟩
| length r v => length b:Booln:ℕr:ℕv:ℕh:Active (Mode.length r v, n)⊢ Active (step (Mode.length r v, n) b)
obtain ⟨hn, hr, hv⟩ := h length b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < v⊢ Active (step (Mode.length r v, n) b)
have hb : 2 ≤ Nat.bit b v := by s:Stateb:Boolh:Active s⊢ Active (step s b) rw [Nat.bit_val b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < v⊢ 2 ≤ 2 * v + b.toNat] b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < v⊢ 2 ≤ 2 * v + b.toNat; omega length b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b v⊢ Active (step (Mode.length r v, n) b)
change Active (if r = 1 then _ else _) length b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b v⊢ Active (if r = 1 then (Mode.payload (Nat.bit b v - 1), n) else (Mode.length (r - 1) (Nat.bit b v), n))
split length.isTrue b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ Active (Mode.payload (Nat.bit b v - 1), n)length.isFalse b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ Active (Mode.length (r - 1) (Nat.bit b v), n)
· length.isTrue b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ Active (Mode.payload (Nat.bit b v - 1), n) exact ⟨hn, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:r = 1⊢ 0 < Nat.bit b v - 1 omega All goals completed! 🐙⟩
· length.isFalse b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ Active (Mode.length (r - 1) (Nat.bit b v), n) exact ⟨hn, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ 0 < r - 1 omega All goals completed! 🐙, by b:Booln:ℕr:ℕv:ℕhn:0 < nhr:0 < rhv:0 < vhb:2 ≤ Nat.bit b vh✝:¬r = 1⊢ 0 < Nat.bit b v omega All goals completed! 🐙⟩
| payload r => payload b:Booln:ℕr:ℕh:Active (Mode.payload r, n)⊢ Active (step (Mode.payload r, n) b)
obtain ⟨hn, hr⟩ := h payload b:Booln:ℕr:ℕhn:0 < nhr:0 < r⊢ Active (step (Mode.payload r, n) b)
change Active (if r = 1 then _ else _) payload b:Booln:ℕr:ℕhn:0 < nhr:0 < r⊢ Active (if r = 1 then finish n else (Mode.payload (r - 1), n))
split payload.isTrue b:Booln:ℕr:ℕhn:0 < nhr:0 < rh✝:r = 1⊢ Active (finish n)payload.isFalse b:Booln:ℕr:ℕhn:0 < nhr:0 < rh✝:¬r = 1⊢ Active (Mode.payload (r - 1), n)
· payload.isTrue b:Booln:ℕr:ℕhn:0 < nhr:0 < rh✝:r = 1⊢ Active (finish n) exact active_finish n hn All goals completed! 🐙
· payload.isFalse b:Booln:ℕr:ℕhn:0 < nhr:0 < rh✝:¬r = 1⊢ Active (Mode.payload (r - 1), n) exact ⟨hn, by b:Booln:ℕr:ℕhn:0 < nhr:0 < rh✝:¬r = 1⊢ 0 < r - 1 omega All goals completed! 🐙⟩
| done => done b:Booln:ℕh:Active (Mode.done, n)⊢ Active (step (Mode.done, n) b) exact h All goals completed! 🐙
| dead => dead b:Booln:ℕh:Active (Mode.dead, n)⊢ Active (step (Mode.dead, n) b) exact h All goals completed! 🐙Every prefix of a scan satisfies the invariant.
theorem active_foldl (w : List Bool) : ∀ s, Active s → Active (w.foldl step s) :=
List.rec (fun _ h ↦ h) (fun b _ ih s h ↦ ih (step s b) (active_step s b h)) wThe scanner starts and remains in an active or terminal state.
theorem scan_active (w : List Bool) : Active (scan w) :=
active_foldl w (.tree, 1) (show 0 < 1 by All goals completed! 🐙 decide All goals completed! 🐙)An incomplete raw payload stays in the payload phase.
theorem foldl_payload_short (w : List Bool) : ∀ r n, w.length < r →
w.foldl step (.payload r, n) = (.payload (r - w.length), n) := by w:List Bool⊢ ∀ (r n : ℕ), w.length < r → List.foldl step (Mode.payload r, n) w = (Mode.payload (r - w.length), n)
refine List.rec ?_ ?_ w refine_1 w:List Bool⊢ ∀ (r n : ℕ), [].length < r → List.foldl step (Mode.payload r, n) [] = (Mode.payload (r - [].length), n)refine_2 w:List Bool⊢ ∀ (head : Bool) (tail : List Bool),
(∀ (r n : ℕ), tail.length < r → List.foldl step (Mode.payload r, n) tail = (Mode.payload (r - tail.length), n)) →
∀ (r n : ℕ),
(head :: tail).length < r →
List.foldl step (Mode.payload r, n) (head :: tail) = (Mode.payload (r - (head :: tail).length), n)
· refine_1 w:List Bool⊢ ∀ (r n : ℕ), [].length < r → List.foldl step (Mode.payload r, n) [] = (Mode.payload (r - [].length), n) intro r n _ refine_1 w:List Boolr:ℕn:ℕa✝:[].length < r⊢ List.foldl step (Mode.payload r, n) [] = (Mode.payload (r - [].length), n)
rfl All goals completed! 🐙
· refine_2 w:List Bool⊢ ∀ (head : Bool) (tail : List Bool),
(∀ (r n : ℕ), tail.length < r → List.foldl step (Mode.payload r, n) tail = (Mode.payload (r - tail.length), n)) →
∀ (r n : ℕ),
(head :: tail).length < r →
List.foldl step (Mode.payload r, n) (head :: tail) = (Mode.payload (r - (head :: tail).length), n) intro b bs ih r n h refine_2 w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < r⊢ List.foldl step (Mode.payload r, n) (b :: bs) = (Mode.payload (r - (b :: bs).length), n)
have hr : r ≠ 1 := by w:List Bool⊢ ∀ (r n : ℕ), w.length < r → List.foldl step (Mode.payload r, n) w = (Mode.payload (r - w.length), n) simp only [List.length_cons] at h w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:bs.length + 1 < r⊢ r ≠ 1; omega refine_2 w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < rhr:r ≠ 1⊢ List.foldl step (Mode.payload r, n) (b :: bs) = (Mode.payload (r - (b :: bs).length), n)
simp only [List.foldl_cons, step, ite_eq_right hr] refine_2 w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < rhr:r ≠ 1⊢ List.foldl step (Mode.payload (r - 1), n) bs = (Mode.payload (r - (b :: bs).length), n)
rw [ih (r - 1) n (by w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < rhr:r ≠ 1⊢ bs.length < r - 1 simp only [List.length_cons] at h w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:bs.length + 1 < rhr:r ≠ 1⊢ bs.length < r - 1; omega All goals completed! 🐙)] refine_2 w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < rhr:r ≠ 1⊢ (Mode.payload (r - 1 - bs.length), n) = (Mode.payload (r - (b :: bs).length), n)
congr 2 refine_2.e_fst w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < rhr:r ≠ 1⊢ r - 1 - bs.length = r - (b :: bs).length
simp only [List.length_cons] refine_2.e_fst w:List Boolb:Boolbs:List Boolih:∀ (r n : ℕ), bs.length < r → List.foldl step (Mode.payload r, n) bs = (Mode.payload (r - bs.length), n)r:ℕn:ℕh:(b :: bs).length < rhr:r ≠ 1⊢ r - 1 - bs.length = r - (bs.length + 1)
omega All goals completed! 🐙Consuming a complete nonempty raw payload completes one leaf.
theorem foldl_payload (w : List Bool) : ∀ n, w ≠ [] →
w.foldl step (.payload w.length, n) = finish n := by w:List Bool⊢ ∀ (n : ℕ), w ≠ [] → List.foldl step (Mode.payload w.length, n) w = finish n
refine List.rec ?_ ?_ w refine_1 w:List Bool⊢ ∀ (n : ℕ), [] ≠ [] → List.foldl step (Mode.payload [].length, n) [] = finish nrefine_2 w:List Bool⊢ ∀ (head : Bool) (tail : List Bool),
(∀ (n : ℕ), tail ≠ [] → List.foldl step (Mode.payload tail.length, n) tail = finish n) →
∀ (n : ℕ), head :: tail ≠ [] → List.foldl step (Mode.payload (head :: tail).length, n) (head :: tail) = finish n
· refine_1 w:List Bool⊢ ∀ (n : ℕ), [] ≠ [] → List.foldl step (Mode.payload [].length, n) [] = finish n intro n h refine_1 w:List Booln:ℕh:[] ≠ []⊢ List.foldl step (Mode.payload [].length, n) [] = finish n
exact (h rfl).elim All goals completed! 🐙
· refine_2 w:List Bool⊢ ∀ (head : Bool) (tail : List Bool),
(∀ (n : ℕ), tail ≠ [] → List.foldl step (Mode.payload tail.length, n) tail = finish n) →
∀ (n : ℕ), head :: tail ≠ [] → List.foldl step (Mode.payload (head :: tail).length, n) (head :: tail) = finish n intro b bs ih n _ refine_2 w:List Boolb:Boolbs:List Boolih:∀ (n : ℕ), bs ≠ [] → List.foldl step (Mode.payload bs.length, n) bs = finish nn:ℕa✝:b :: bs ≠ []⊢ List.foldl step (Mode.payload (b :: bs).length, n) (b :: bs) = finish n
cases bs with
| nil => refine_2.nil w:List Boolb:Booln:ℕih:∀ (n : ℕ), [] ≠ [] → List.foldl step (Mode.payload [].length, n) [] = finish na✝:[b] ≠ []⊢ List.foldl step (Mode.payload [b].length, n) [b] = finish n rfl All goals completed! 🐙
| cons c cs => refine_2.cons w:List Boolb:Booln:ℕc:Boolcs:List Boolih:∀ (n : ℕ), c :: cs ≠ [] → List.foldl step (Mode.payload (c :: cs).length, n) (c :: cs) = finish na✝:b :: c :: cs ≠ []⊢ List.foldl step (Mode.payload (b :: c :: cs).length, n) (b :: c :: cs) = finish n
simp only [List.length_cons, List.foldl_cons, step,
show cs.length + 1 + 1 ≠ 1 by omega, ↓reduceIte] refine_2.cons w:List Boolb:Booln:ℕc:Boolcs:List Boolih:∀ (n : ℕ), c :: cs ≠ [] → List.foldl step (Mode.payload (c :: cs).length, n) (c :: cs) = finish na✝:b :: c :: cs ≠ []⊢ List.foldl step (if cs.length + 1 + 1 - 1 = 1 then finish n else (Mode.payload (cs.length + 1 + 1 - 1 - 1), n)) cs =
finish n
exact ih n (by w:List Boolb:Booln:ℕc:Boolcs:List Boolih:∀ (n : ℕ), c :: cs ≠ [] → List.foldl step (Mode.payload (c :: cs).length, n) (c :: cs) = finish na✝:b :: c :: cs ≠ []⊢ c :: cs ≠ [] intro h w:List Boolb:Booln:ℕc:Boolcs:List Boolih:∀ (n : ℕ), c :: cs ≠ [] → List.foldl step (Mode.payload (c :: cs).length, n) (c :: cs) = finish na✝:b :: c :: cs ≠ []h:c :: cs = []⊢ False; cases h All goals completed! 🐙)A completed scanner with no further input remains completed.
theorem foldl_done (w : List Bool) (n : ℕ) :
(w.foldl step (.done, n)).1 = .done ↔ w = [] := by w:List Booln:ℕ⊢ (List.foldl step (Mode.done, n) w).fst = Mode.done ↔ w = []
have hd (bs : List Bool) : bs.foldl step (.dead, n) = (.dead, n) :=
List.rec rfl (fun _ _ ih ↦ ih) bs w:List Booln:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)⊢ (List.foldl step (Mode.done, n) w).fst = Mode.done ↔ w = []
cases w with
| nil => nil n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)⊢ (List.foldl step (Mode.done, n) []).fst = Mode.done ↔ [] = [] exact ⟨fun _ ↦ rfl, fun _ ↦ rfl⟩ All goals completed! 🐙
| cons b bs => cons n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ (List.foldl step (Mode.done, n) (b :: bs)).fst = Mode.done ↔ b :: bs = []
change (bs.foldl step (.dead, n)).1 = .done ↔ b :: bs = [] cons n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ (List.foldl step (Mode.dead, n) bs).fst = Mode.done ↔ b :: bs = []
rw [hd cons n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ (Mode.dead, n).fst = Mode.done ↔ b :: bs = []] cons n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ (Mode.dead, n).fst = Mode.done ↔ b :: bs = []
constructor cons.mp n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ (Mode.dead, n).fst = Mode.done → b :: bs = []cons.mpr n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ b :: bs = [] → (Mode.dead, n).fst = Mode.done <;> cons.mp n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ (Mode.dead, n).fst = Mode.done → b :: bs = []cons.mpr n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Bool⊢ b :: bs = [] → (Mode.dead, n).fst = Mode.done intro h cons.mpr n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Boolh:b :: bs = []⊢ (Mode.dead, n).fst = Mode.done <;> cons.mp n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Boolh:(Mode.dead, n).fst = Mode.done⊢ b :: bs = []cons.mpr n:ℕhd:∀ (bs : List Bool), List.foldl step (Mode.dead, n) bs = (Mode.dead, n)b:Boolbs:List Boolh:b :: bs = []⊢ (Mode.dead, n).fst = Mode.done cases h All goals completed! 🐙Acceptance after a declared payload supplies exactly that many raw bits and a suffix.
theorem payload_of_accept (w : List Bool) (m n : ℕ)
(h : (w.foldl step (if m = 0 then finish n else (.payload m, n))).1 = .done) :
∃ s rest, s.length = m ∧ w = s ++ rest ∧ (rest.foldl step (finish n)).1 = .done := by w:List Boolm:ℕn:ℕh:(List.foldl step (if m = 0 then finish n else (Mode.payload m, n)) w).fst = Mode.done⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
by_cases hm : m = 0 pos w:List Boolm:ℕn:ℕh:(List.foldl step (if m = 0 then finish n else (Mode.payload m, n)) w).fst = Mode.donehm:m = 0⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.doneneg w:List Boolm:ℕn:ℕh:(List.foldl step (if m = 0 then finish n else (Mode.payload m, n)) w).fst = Mode.donehm:¬m = 0⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
· pos w:List Boolm:ℕn:ℕh:(List.foldl step (if m = 0 then finish n else (Mode.payload m, n)) w).fst = Mode.donehm:m = 0⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done subst m pos w:List Booln:ℕh:(List.foldl step (if 0 = 0 then finish n else (Mode.payload 0, n)) w).fst = Mode.done⊢ ∃ s rest, s.length = 0 ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
exact ⟨[], w, rfl, rfl, h⟩ All goals completed! 🐙
· neg w:List Boolm:ℕn:ℕh:(List.foldl step (if m = 0 then finish n else (Mode.payload m, n)) w).fst = Mode.donehm:¬m = 0⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done rw [ite_eq_right hm neg w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done] at h neg w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
by_cases hl : m ≤ w.length pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.length⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.doneneg w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:¬m ≤ w.length⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
· pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.length⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done have hs : (w.take m).length = m := List.length_take_of_le hl pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = m⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
have hne : w.take m ≠ [] := by
intro he w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhe:List.take m w = []⊢ False
rw [he w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:[].length = mhe:List.take m w = []⊢ False] at hs w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:[].length = mhe:List.take m w = []⊢ False
exact hm hs.symm pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
refine ⟨w.take m, w.drop m, hs, (List.take_append_drop m w).symm, ?_⟩ pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done
have hf := foldl_payload (w.take m) n hne pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload (List.take m w).length, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done
rw [hs pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload m, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done] at hf pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload m, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done
rw [← List.take_append_drop m w, pos w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) (List.take m w ++ List.drop m w)).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload m, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done List.foldl_append, pos w:List Boolm:ℕn:ℕh:(List.foldl step (List.foldl step (Mode.payload m, n) (List.take m w)) (List.drop m w)).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload m, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done hf pos w:List Boolm:ℕn:ℕh:(List.foldl step (finish n) (List.drop m w)).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload m, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done] at h pos w:List Boolm:ℕn:ℕh:(List.foldl step (finish n) (List.drop m w)).fst = Mode.donehm:¬m = 0hl:m ≤ w.lengthhs:(List.take m w).length = mhne:List.take m w ≠ []hf:List.foldl step (Mode.payload m, n) (List.take m w) = finish n⊢ (List.foldl step (finish n) (List.drop m w)).fst = Mode.done
exact h All goals completed! 🐙
· neg w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:¬m ≤ w.length⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done rw [foldl_payload_short w m n (by w:List Boolm:ℕn:ℕh:(List.foldl step (Mode.payload m, n) w).fst = Mode.donehm:¬m = 0hl:¬m ≤ w.length⊢ w.length < m omega All goals completed! 🐙)] at h neg w:List Boolm:ℕn:ℕh:(Mode.payload (m - w.length), n).fst = Mode.donehm:¬m = 0hl:¬m ≤ w.length⊢ ∃ s rest, s.length = m ∧ w = s ++ rest ∧ (List.foldl step (finish n) rest).fst = Mode.done
cases h All goals completed! 🐙One input bit introduces at most one additional pending subtree.
theorem step_pending_le (s : State) (b : Bool) : (step s b).2 ≤ s.2 + 1 := by s:Stateb:Bool⊢ (step s b).snd ≤ s.snd + 1
have hf (n : ℕ) : (finish n).2 ≤ n + 1 := by
unfold finish s:Stateb:Booln:ℕ⊢ (if n = 1 then (Mode.done, 0) else (Mode.tree, n - 1)).snd ≤ n + 1
split isTrue s:Stateb:Booln:ℕh✝:n = 1⊢ (Mode.done, 0).snd ≤ n + 1isFalse s:Stateb:Booln:ℕh✝:¬n = 1⊢ (Mode.tree, n - 1).snd ≤ n + 1 <;> isTrue s:Stateb:Booln:ℕh✝:n = 1⊢ (Mode.done, 0).snd ≤ n + 1isFalse s:Stateb:Booln:ℕh✝:¬n = 1⊢ (Mode.tree, n - 1).snd ≤ n + 1 dsimp only isFalse s:Stateb:Booln:ℕh✝:¬n = 1⊢ n - 1 ≤ n + 1 <;> isTrue s:Stateb:Booln:ℕh✝:n = 1⊢ 0 ≤ n + 1isFalse s:Stateb:Booln:ℕh✝:¬n = 1⊢ n - 1 ≤ n + 1 omega s:Stateb:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1⊢ (step s b).snd ≤ s.snd + 1
rcases s with ⟨m, n⟩ b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1m:Moden:ℕ⊢ (step (m, n) b).snd ≤ (m, n).snd + 1
cases m tree b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.tree, n) b).snd ≤ (Mode.tree, n).snd + 1zeros b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕcount✝:ℕ⊢ (step (Mode.zeros count✝, n) b).snd ≤ (Mode.zeros count✝, n).snd + 1size b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.size remaining✝ value✝, n) b).snd ≤ (Mode.size remaining✝ value✝, n).snd + 1length b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.length remaining✝ value✝, n) b).snd ≤ (Mode.length remaining✝ value✝, n).snd + 1payload b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕ⊢ (step (Mode.payload remaining✝, n) b).snd ≤ (Mode.payload remaining✝, n).snd + 1done b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.done, n) b).snd ≤ (Mode.done, n).snd + 1dead b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.dead, n) b).snd ≤ (Mode.dead, n).snd + 1 <;> tree b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.tree, n) b).snd ≤ (Mode.tree, n).snd + 1zeros b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕcount✝:ℕ⊢ (step (Mode.zeros count✝, n) b).snd ≤ (Mode.zeros count✝, n).snd + 1size b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.size remaining✝ value✝, n) b).snd ≤ (Mode.size remaining✝ value✝, n).snd + 1length b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.length remaining✝ value✝, n) b).snd ≤ (Mode.length remaining✝ value✝, n).snd + 1payload b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕ⊢ (step (Mode.payload remaining✝, n) b).snd ≤ (Mode.payload remaining✝, n).snd + 1done b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.done, n) b).snd ≤ (Mode.done, n).snd + 1dead b:Boolhf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.dead, n) b).snd ≤ (Mode.dead, n).snd + 1 cases b dead.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.dead, n) false).snd ≤ (Mode.dead, n).snd + 1dead.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.dead, n) true).snd ≤ (Mode.dead, n).snd + 1 <;> tree.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.tree, n) false).snd ≤ (Mode.tree, n).snd + 1tree.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.tree, n) true).snd ≤ (Mode.tree, n).snd + 1zeros.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕcount✝:ℕ⊢ (step (Mode.zeros count✝, n) false).snd ≤ (Mode.zeros count✝, n).snd + 1zeros.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕcount✝:ℕ⊢ (step (Mode.zeros count✝, n) true).snd ≤ (Mode.zeros count✝, n).snd + 1size.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.size remaining✝ value✝, n) false).snd ≤ (Mode.size remaining✝ value✝, n).snd + 1size.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.size remaining✝ value✝, n) true).snd ≤ (Mode.size remaining✝ value✝, n).snd + 1length.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.length remaining✝ value✝, n) false).snd ≤ (Mode.length remaining✝ value✝, n).snd + 1length.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (step (Mode.length remaining✝ value✝, n) true).snd ≤ (Mode.length remaining✝ value✝, n).snd + 1payload.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕ⊢ (step (Mode.payload remaining✝, n) false).snd ≤ (Mode.payload remaining✝, n).snd + 1payload.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕ⊢ (step (Mode.payload remaining✝, n) true).snd ≤ (Mode.payload remaining✝, n).snd + 1done.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.done, n) false).snd ≤ (Mode.done, n).snd + 1done.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.done, n) true).snd ≤ (Mode.done, n).snd + 1dead.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.dead, n) false).snd ≤ (Mode.dead, n).snd + 1dead.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ (step (Mode.dead, n) true).snd ≤ (Mode.dead, n).snd + 1 simp only [step] dead.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1 <;> tree.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1tree.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n + 1 ≤ n + 1zeros.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕcount✝:ℕ⊢ n ≤ n + 1zeros.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕcount✝:ℕ⊢ (if count✝ = 0 then finish n else (Mode.size count✝ 1, n)).snd ≤ n + 1size.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (if remaining✝ = 1 then (Mode.length (Nat.bit false value✝ - 1) 1, n)
else (Mode.size (remaining✝ - 1) (Nat.bit false value✝), n)).snd ≤
n + 1size.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (if remaining✝ = 1 then (Mode.length (Nat.bit true value✝ - 1) 1, n)
else (Mode.size (remaining✝ - 1) (Nat.bit true value✝), n)).snd ≤
n + 1length.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (if remaining✝ = 1 then (Mode.payload (Nat.bit false value✝ - 1), n)
else (Mode.length (remaining✝ - 1) (Nat.bit false value✝), n)).snd ≤
n + 1length.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕvalue✝:ℕ⊢ (if remaining✝ = 1 then (Mode.payload (Nat.bit true value✝ - 1), n)
else (Mode.length (remaining✝ - 1) (Nat.bit true value✝), n)).snd ≤
n + 1payload.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕ⊢ (if remaining✝ = 1 then finish n else (Mode.payload (remaining✝ - 1), n)).snd ≤ n + 1payload.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕ⊢ (if remaining✝ = 1 then finish n else (Mode.payload (remaining✝ - 1), n)).snd ≤ n + 1done.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1done.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1dead.false hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1dead.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1
first | exact Nat.le_refl _ dead.true hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕ⊢ n ≤ n + 1 | exact Nat.le_succ _ All goals completed! 🐙 |
(split payload.true.isTrue hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕh✝:remaining✝ = 1⊢ (finish n).snd ≤ n + 1payload.true.isFalse hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕh✝:¬remaining✝ = 1⊢ (Mode.payload (remaining✝ - 1), n).snd ≤ n + 1 <;> payload.true.isTrue hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕh✝:remaining✝ = 1⊢ (finish n).snd ≤ n + 1payload.true.isFalse hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕh✝:¬remaining✝ = 1⊢ (Mode.payload (remaining✝ - 1), n).snd ≤ n + 1 first | exact hf n payload.true.isFalse hf:∀ (n : ℕ), (finish n).snd ≤ n + 1n:ℕremaining✝:ℕh✝:¬remaining✝ = 1⊢ (Mode.payload (remaining✝ - 1), n).snd ≤ n + 1 | exact Nat.le_succ _ All goals completed! 🐙)Pending subtrees are bounded by the initial count and the number of bits read.
theorem foldl_pending_le (w : List Bool) : ∀ s,
(w.foldl step s).2 ≤ s.2 + w.length := by w:List Bool⊢ ∀ (s : State), (List.foldl step s w).snd ≤ s.snd + w.length
refine List.rec ?_ ?_ w refine_1 w:List Bool⊢ ∀ (s : State), (List.foldl step s []).snd ≤ s.snd + [].lengthrefine_2 w:List Bool⊢ ∀ (head : Bool) (tail : List Bool),
(∀ (s : State), (List.foldl step s tail).snd ≤ s.snd + tail.length) →
∀ (s : State), (List.foldl step s (head :: tail)).snd ≤ s.snd + (head :: tail).length
· refine_1 w:List Bool⊢ ∀ (s : State), (List.foldl step s []).snd ≤ s.snd + [].length intro s refine_1 w:List Bools:State⊢ (List.foldl step s []).snd ≤ s.snd + [].length
exact Nat.le_refl _ All goals completed! 🐙
· refine_2 w:List Bool⊢ ∀ (head : Bool) (tail : List Bool),
(∀ (s : State), (List.foldl step s tail).snd ≤ s.snd + tail.length) →
∀ (s : State), (List.foldl step s (head :: tail)).snd ≤ s.snd + (head :: tail).length intro b bs ih s refine_2 w:List Boolb:Boolbs:List Boolih:∀ (s : State), (List.foldl step s bs).snd ≤ s.snd + bs.lengths:State⊢ (List.foldl step s (b :: bs)).snd ≤ s.snd + (b :: bs).length
have h := ih (step s b) refine_2 w:List Boolb:Boolbs:List Boolih:∀ (s : State), (List.foldl step s bs).snd ≤ s.snd + bs.lengths:Stateh:(List.foldl step (step s b) bs).snd ≤ (step s b).snd + bs.length⊢ (List.foldl step s (b :: bs)).snd ≤ s.snd + (b :: bs).length
have hb := step_pending_le s b refine_2 w:List Boolb:Boolbs:List Boolih:∀ (s : State), (List.foldl step s bs).snd ≤ s.snd + bs.lengths:Stateh:(List.foldl step (step s b) bs).snd ≤ (step s b).snd + bs.lengthhb:(step s b).snd ≤ s.snd + 1⊢ (List.foldl step s (b :: bs)).snd ≤ s.snd + (b :: bs).length
simp only [List.foldl_cons, List.length_cons] refine_2 w:List Boolb:Boolbs:List Boolih:∀ (s : State), (List.foldl step s bs).snd ≤ s.snd + bs.lengths:Stateh:(List.foldl step (step s b) bs).snd ≤ (step s b).snd + bs.lengthhb:(step s b).snd ≤ s.snd + 1⊢ (List.foldl step (step s b) bs).snd ≤ s.snd + (bs.length + 1)
omega All goals completed! 🐙The unary structural counter uses at most one plus the input length.
theorem scan_pending_le (w : List Bool) : (scan w).2 ≤ w.length + 1 := by w:List Bool⊢ (scan w).snd ≤ w.length + 1
have h := foldl_pending_le w (.tree, 1) w:List Boolh:(List.foldl step (Mode.tree, 1) w).snd ≤ (Mode.tree, 1).snd + w.length⊢ (scan w).snd ≤ w.length + 1
change (scan w).2 ≤ 1 + w.length at h w:List Boolh:(scan w).snd ≤ 1 + w.length⊢ (scan w).snd ≤ w.length + 1
omega All goals completed! 🐙end Geb.BitTree.Elias.Scanner