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.Mathlib.Data.Tree.Ranked.Preorder
public import Mathlib.Data.Fin.VecNotationThe two-symbol ranked alphabet
The alphabet of one nullary and one binary symbol, spelled by one bit each.
Its terms are the unlabelled binary trees, the initial algebra of
F X = 1 + X × X, and its preorder encoding is RankedAlphabet.spell at
this alphabet.
At width one every block is a single bit, so the validity scan carries no incomplete block and its state reduces to a pending count and a liveness verdict. This module names that counter form and gives it one bit at a time, which is the shape a recognizer over the encoding is stated against.
Main definitions
RankedAlphabet.Binary.binRanked — the alphabet.
RankedAlphabet.Binary.leaf, RankedAlphabet.Binary.node — the two forms
of its terms.
RankedAlphabet.Binary.depth, RankedAlphabet.Binary.ok — the validity
scan's pending count and its liveness verdict, read off a whole word.
Main statements
RankedAlphabet.Binary.buf_scanFinal_eq_nil — at width one no incomplete
block survives a step.
RankedAlphabet.Binary.depth_le_length — the pending count never exceeds
the word length, which is the bound Cobham.length_combSem_le asks for.
RankedAlphabet.Binary.valid_iff_ok_and_depth_eq_one — validity is the two
conditions on the counter form, the third holding of every word.
RankedAlphabet.Binary.ok_cons_false,
RankedAlphabet.Binary.ok_cons_true,
RankedAlphabet.Binary.depth_cons_false_of_ok,
RankedAlphabet.Binary.depth_cons_true_of_ok_of_two_le_depth — the counter
form one bit at a time.
Implementation notes
leafSym and nodeSym name the two indices rather than each use site
writing ⟨0, by decide⟩: a symbol index whose bound proof is still an
unassigned metavariable blocks arity from reducing, so the child family's
domain is then neither Fin 0 nor Fin 2 and the family does not elaborate.
Against a symbol index that is a pattern variable, a child index's bound is
ascribed rather than proved where it stands: the goal 0 < binRanked.arity ⟨1, h⟩ carries the free variable h, which decide refuses, and presents
the arity as an atom, which omega cannot unfold. show (0 : ℕ) < 2 replaces
it with the definitionally equal closed goal.
spell_leaf and spell_node have no consumer in this module: they are kept
as the alphabet's characteristic spelling equations, stating what the
preorder encoding is at this alphabet, and so belong to its public interface
rather than to internal machinery.
depth and ok are @[expose], as the declarations they project are: a
consuming module's rfl and decide reduce through them only if they unfold
across the module boundary. ok_cons_false and ok_cons_true are @[simp],
being unconditional rewrite rules on that form; the two depth cons-lemmas
are not, since neither ok w = true nor 2 ≤ depth w is a side condition
simp discharges here, so as simp rules they would be inert.
scanStep_of_not_live holds at any width — a failed scan absorbs whatever
the block layout — and is stated here because here is where it is used.
decide_length_eq_width proceeds by cases b rather than decide alone:
decide refuses a goal carrying a free variable, so the case analysis is what
closes b, even though [b].length is 1 either way.
code_leafSym and code_nodeSym are proved by decide rather than by rfl.
Nat.land, which Nat.testBit runs through, is not exposed, so a block does
not reduce during elaboration, while the kernel evaluates it.
Tags
binary tree, ranked alphabet, term algebra, preorder, scan
namespace RankedAlphabet.Binarypublic sectionThe alphabet of one nullary and one binary symbol, one bit to a block.
@[expose] def binRanked : RankedAlphabet := ⟨2, 1, Nat.one_pos, ⊢ 2 ≤ 2 ^ 1 All goals completed! 🐙, ![0, 2]⟩The nullary symbol.
The binary symbol.
The term with the nullary head symbol.
@[expose] def leaf : binRanked.Term :=
Term.mk binRanked leafSym fun d ↦ absurd (show d.val < 0 from d.isLt) (d:Fin (binRanked.arity leafSym)⊢ ¬↑d < 0 All goals completed! 🐙)
The term with the binary head symbol and children l and r.
@[expose] def node (l r : binRanked.Term) : binRanked.Term :=
Term.mk binRanked nodeSym fun d ↦ if d.val = 0 then l else r
The nullary symbol's block is the single false bit.
theorem code_leafSym : binRanked.code leafSym = [false] := ⊢ binRanked.code leafSym = [false] All goals completed! 🐙
The binary symbol's block is the single true bit.
theorem code_nodeSym : binRanked.code nodeSym = [true] := ⊢ binRanked.code nodeSym = [true] All goals completed! 🐙
The nullary term is spelled by the single false bit.
@[simp] theorem spell_leaf : binRanked.spell leaf = [false] := ⊢ binRanked.spell leaf = [false]
⊢ [false] ++ (List.ofFn fun d ↦ binRanked.spell (absurd ⋯ ⋯)).flatten = [false]
rfl All goals completed! 🐙
A binary term is spelled by a true bit and its children's spellings.
@[simp] theorem spell_node (l r : binRanked.Term) :
binRanked.spell (node l r) = true :: (binRanked.spell l ++ binRanked.spell r) := by l:binRanked.Termr:binRanked.Term⊢ binRanked.spell (node l r) = true :: (binRanked.spell l ++ binRanked.spell r)
rw [node, l:binRanked.Termr:binRanked.Term⊢ binRanked.spell (Term.mk binRanked nodeSym fun d ↦ if ↑d = 0 then l else r) =
true :: (binRanked.spell l ++ binRanked.spell r) spell_mk, l:binRanked.Termr:binRanked.Term⊢ binRanked.code nodeSym ++ (List.ofFn fun d ↦ binRanked.spell (if ↑d = 0 then l else r)).flatten =
true :: (binRanked.spell l ++ binRanked.spell r) code_nodeSym l:binRanked.Termr:binRanked.Term⊢ [true] ++ (List.ofFn fun d ↦ binRanked.spell (if ↑d = 0 then l else r)).flatten =
true :: (binRanked.spell l ++ binRanked.spell r)] l:binRanked.Termr:binRanked.Term⊢ [true] ++ (List.ofFn fun d ↦ binRanked.spell (if ↑d = 0 then l else r)).flatten =
true :: (binRanked.spell l ++ binRanked.spell r)
change [true] ++ (binRanked.spell l ++ (binRanked.spell r ++ [])) = _ l:binRanked.Termr:binRanked.Term⊢ [true] ++ (binRanked.spell l ++ (binRanked.spell r ++ [])) = true :: (binRanked.spell l ++ binRanked.spell r)
rw [List.append_nil l:binRanked.Termr:binRanked.Term⊢ [true] ++ (binRanked.spell l ++ binRanked.spell r) = true :: (binRanked.spell l ++ binRanked.spell r)] l:binRanked.Termr:binRanked.Term⊢ [true] ++ (binRanked.spell l ++ binRanked.spell r) = true :: (binRanked.spell l ++ binRanked.spell r)
rfl All goals completed! 🐙The count of pending subterms the validity scan leaves.
Whether the validity scan has not failed.
At width one every block completes as it is read, so no incomplete block survives a step.
theorem buf_scanFinal_eq_nil (w : List Bool) : (binRanked.scanFinal w).buf = [] := by w:List Bool⊢ (binRanked.scanFinal w).buf = []
have h : (binRanked.scanFinal w).buf.length < 1 := binRanked.length_buf_scanFinal_lt w w:List Boolh:(binRanked.scanFinal w).buf.length < 1⊢ (binRanked.scanFinal w).buf = []
exact List.eq_nil_of_length_eq_zero (by w:List Boolh:(binRanked.scanFinal w).buf.length < 1⊢ (binRanked.scanFinal w).buf.length = 0 omega All goals completed! 🐙)The pending count never exceeds the word length.
theorem depth_le_length (w : List Bool) : depth w ≤ w.length :=
binRanked.depth_scanFinal_le_length wValidity is the counter form's two conditions: at width one the third, that no incomplete block remains, holds of every word.
theorem valid_iff_ok_and_depth_eq_one (w : List Bool) :
binRanked.Valid w ↔ ok w = true ∧ depth w = 1 := by w:List Bool⊢ binRanked.Valid w ↔ ok w = true ∧ depth w = 1
rw [valid_iff_scanFinal w:List Bool⊢ (binRanked.scanFinal w).live = true ∧ (binRanked.scanFinal w).buf = [] ∧ (binRanked.scanFinal w).depth = 1 ↔
ok w = true ∧ depth w = 1] w:List Bool⊢ (binRanked.scanFinal w).live = true ∧ (binRanked.scanFinal w).buf = [] ∧ (binRanked.scanFinal w).depth = 1 ↔
ok w = true ∧ depth w = 1
exact ⟨fun h ↦ ⟨h.1, h.2.2⟩, fun h ↦ ⟨h.1, buf_scanFinal_eq_nil w, h.2⟩⟩ All goals completed! 🐙The block a bit completes has the alphabet's width.
theorem decide_length_eq_width (b : Bool) :
decide (([b] : List Bool).length = binRanked.width) = true := by b:Bool⊢ decide ([b].length = binRanked.width) = true cases b false ⊢ decide ([false].length = binRanked.width) = truetrue ⊢ decide ([true].length = binRanked.width) = true <;> false ⊢ decide ([false].length = binRanked.width) = truetrue ⊢ decide ([true].length = binRanked.width) = true decide All goals completed! 🐙The nullary symbol's block denotes arity zero.
theorem arOf_decodeBits_false : binRanked.arOf (decodeBits [false]) = some 0 := by ⊢ binRanked.arOf (decodeBits [false]) = some 0 decide All goals completed! 🐙The binary symbol's block denotes arity two.
theorem arOf_decodeBits_true : binRanked.arOf (decodeBits [true]) = some 2 := by ⊢ binRanked.arOf (decodeBits [true]) = some 2 decide All goals completed! 🐙A leaf bit read by a live scan carrying no incomplete block: its arity is zero, which every pending count admits.
theorem scanStep_false_of_live_of_buf_nil (s : Scan) (hl : s.live = true)
(hb : s.buf = []) : binRanked.scanStep false s = ⟨[], s.depth + 1, true⟩ := by s:Scanhl:s.live = truehb:s.buf = []⊢ binRanked.scanStep false s = { buf := [], depth := s.depth + 1, live := true }
rw [scanStep, s:Scanhl:s.live = truehb:s.buf = []⊢ (match s.live with
| false => s
| true =>
match decide ((false :: s.buf).length = binRanked.width) with
| false => { buf := false :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (false :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true } hl, s:Scanhl:s.live = truehb:s.buf = []⊢ (match true with
| false => s
| true =>
match decide ((false :: s.buf).length = binRanked.width) with
| false => { buf := false :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (false :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true } hb s:Scanhl:s.live = truehb:s.buf = []⊢ (match true with
| false => s
| true =>
match decide ([false].length = binRanked.width) with
| false => { buf := [false], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [false]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }] s:Scanhl:s.live = truehb:s.buf = []⊢ (match true with
| false => s
| true =>
match decide ([false].length = binRanked.width) with
| false => { buf := [false], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [false]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }
simp only [] s:Scanhl:s.live = truehb:s.buf = []⊢ (match decide ([false].length = binRanked.width) with
| false => { buf := [false], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [false]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }
rw [decide_length_eq_width s:Scanhl:s.live = truehb:s.buf = []⊢ (match true with
| false => { buf := [false], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [false]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }] s:Scanhl:s.live = truehb:s.buf = []⊢ (match true with
| false => { buf := [false], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [false]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }
simp only [] s:Scanhl:s.live = truehb:s.buf = []⊢ (match binRanked.arOf (decodeBits [false]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }
rw [arOf_decodeBits_false s:Scanhl:s.live = truehb:s.buf = []⊢ (match some 0 with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }] s:Scanhl:s.live = truehb:s.buf = []⊢ (match some 0 with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth + 1, live := true }
rfl All goals completed! 🐙A node bit read with two subterms pending pops both and pushes one.
theorem scanStep_true_of_live_of_buf_nil_of_two_le_depth (s : Scan) (hl : s.live = true)
(hb : s.buf = []) (h2 : 2 ≤ s.depth) :
binRanked.scanStep true s = ⟨[], s.depth - 2 + 1, true⟩ := by s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ binRanked.scanStep true s = { buf := [], depth := s.depth - 2 + 1, live := true }
rw [scanStep, s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match s.live with
| false => s
| true =>
match decide ((true :: s.buf).length = binRanked.width) with
| false => { buf := true :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (true :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true } hl, s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match true with
| false => s
| true =>
match decide ((true :: s.buf).length = binRanked.width) with
| false => { buf := true :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (true :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true } hb s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match true with
| false => s
| true =>
match decide ([true].length = binRanked.width) with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }] s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match true with
| false => s
| true =>
match decide ([true].length = binRanked.width) with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }
simp only [] s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match decide ([true].length = binRanked.width) with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }
rw [decide_length_eq_width s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match true with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }] s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match true with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }
simp only [] s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }
rw [arOf_decodeBits_true s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match some 2 with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }] s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match some 2 with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }
simp only [] s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match decide (2 ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - 2 + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }
rw [decide_eq_true h2 s:Scanhl:s.live = truehb:s.buf = []h2:2 ≤ s.depth⊢ (match true with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - 2 + 1, live := true }) =
{ buf := [], depth := s.depth - 2 + 1, live := true }] All goals completed! 🐙A node bit read with fewer than two subterms pending fails the scan.
theorem scanStep_true_of_live_of_buf_nil_of_depth_lt_two (s : Scan) (hl : s.live = true)
(hb : s.buf = []) (h2 : s.depth < 2) :
binRanked.scanStep true s = ⟨[], s.depth, false⟩ := by s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ binRanked.scanStep true s = { buf := [], depth := s.depth, live := false }
rw [scanStep, s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match s.live with
| false => s
| true =>
match decide ((true :: s.buf).length = binRanked.width) with
| false => { buf := true :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (true :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false } hl, s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match true with
| false => s
| true =>
match decide ((true :: s.buf).length = binRanked.width) with
| false => { buf := true :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (true :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false } hb s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match true with
| false => s
| true =>
match decide ([true].length = binRanked.width) with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }] s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match true with
| false => s
| true =>
match decide ([true].length = binRanked.width) with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }
simp only [] s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match decide ([true].length = binRanked.width) with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }
rw [decide_length_eq_width s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match true with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }] s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match true with
| false => { buf := [true], depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }
simp only [] s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match binRanked.arOf (decodeBits [true]) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }
rw [arOf_decodeBits_true s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match some 2 with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }] s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match some 2 with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }
simp only [] s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ (match decide (2 ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - 2 + 1, live := true }) =
{ buf := [], depth := s.depth, live := false }
rw [decide_eq_false (by s:Scanhl:s.live = truehb:s.buf = []h2:s.depth < 2⊢ ¬2 ≤ s.depth omega All goals completed! 🐙 : ¬ 2 ≤ s.depth)] All goals completed! 🐙A failed scan reads no further.
theorem scanStep_of_not_live (b : Bool) (s : Scan) (hl : s.live = false) :
binRanked.scanStep b s = s := by b:Bools:Scanhl:s.live = false⊢ binRanked.scanStep b s = s
rw [scanStep, b:Bools:Scanhl:s.live = false⊢ (match s.live with
| false => s
| true =>
match decide ((b :: s.buf).length = binRanked.width) with
| false => { buf := b :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (b :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
s hl b:Bools:Scanhl:s.live = false⊢ (match false with
| false => s
| true =>
match decide ((b :: s.buf).length = binRanked.width) with
| false => { buf := b :: s.buf, depth := s.depth, live := true }
| true =>
match binRanked.arOf (decodeBits (b :: s.buf)) with
| none => { buf := [], depth := s.depth, live := false }
| some r =>
match decide (r ≤ s.depth) with
| false => { buf := [], depth := s.depth, live := false }
| true => { buf := [], depth := s.depth - r + 1, live := true }) =
s] All goals completed! 🐙A leaf bit cannot fail.
@[simp] theorem ok_cons_false (w : List Bool) : ok (false :: w) = ok w := by w:List Bool⊢ ok (false :: w) = ok w
rw [ok, w:List Bool⊢ (binRanked.scanFinal (false :: w)).live = ok w ok, w:List Bool⊢ (binRanked.scanFinal (false :: w)).live = (binRanked.scanFinal w).live scanFinal_cons w:List Bool⊢ (binRanked.scanStep false (binRanked.scanFinal w)).live = (binRanked.scanFinal w).live] w:List Bool⊢ (binRanked.scanStep false (binRanked.scanFinal w)).live = (binRanked.scanFinal w).live
cases h : (binRanked.scanFinal w).live false w:List Boolh:(binRanked.scanFinal w).live = false⊢ (binRanked.scanStep false (binRanked.scanFinal w)).live = falsetrue w:List Boolh:(binRanked.scanFinal w).live = true⊢ (binRanked.scanStep false (binRanked.scanFinal w)).live = true
· false w:List Boolh:(binRanked.scanFinal w).live = false⊢ (binRanked.scanStep false (binRanked.scanFinal w)).live = false rw [scanStep_of_not_live false _ h, false w:List Boolh:(binRanked.scanFinal w).live = false⊢ (binRanked.scanFinal w).live = false h false w:List Boolh:(binRanked.scanFinal w).live = false⊢ false = false] All goals completed! 🐙
· true w:List Boolh:(binRanked.scanFinal w).live = true⊢ (binRanked.scanStep false (binRanked.scanFinal w)).live = true rw [scanStep_false_of_live_of_buf_nil _ h (buf_scanFinal_eq_nil w) true w:List Boolh:(binRanked.scanFinal w).live = true⊢ { buf := [], depth := (binRanked.scanFinal w).depth + 1, live := true }.live = true] All goals completed! 🐙A node bit fails when the scan has already failed, or when fewer than two subterms are pending.
@[simp] theorem ok_cons_true (w : List Bool) :
ok (true :: w) = (ok w && decide (2 ≤ depth w)) := by w:List Bool⊢ ok (true :: w) = (ok w && decide (2 ≤ depth w))
rw [ok, w:List Bool⊢ (binRanked.scanFinal (true :: w)).live = (ok w && decide (2 ≤ depth w)) ok, w:List Bool⊢ (binRanked.scanFinal (true :: w)).live = ((binRanked.scanFinal w).live && decide (2 ≤ depth w)) depth, w:List Bool⊢ (binRanked.scanFinal (true :: w)).live = ((binRanked.scanFinal w).live && decide (2 ≤ (binRanked.scanFinal w).depth)) scanFinal_cons w:List Bool⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live =
((binRanked.scanFinal w).live && decide (2 ≤ (binRanked.scanFinal w).depth))] w:List Bool⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live =
((binRanked.scanFinal w).live && decide (2 ≤ (binRanked.scanFinal w).depth))
cases h : (binRanked.scanFinal w).live false w:List Boolh:(binRanked.scanFinal w).live = false⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (false && decide (2 ≤ (binRanked.scanFinal w).depth))true w:List Boolh:(binRanked.scanFinal w).live = true⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (true && decide (2 ≤ (binRanked.scanFinal w).depth))
· false w:List Boolh:(binRanked.scanFinal w).live = false⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (false && decide (2 ≤ (binRanked.scanFinal w).depth)) rw [scanStep_of_not_live true _ h, false w:List Boolh:(binRanked.scanFinal w).live = false⊢ (binRanked.scanFinal w).live = (false && decide (2 ≤ (binRanked.scanFinal w).depth)) h, false w:List Boolh:(binRanked.scanFinal w).live = false⊢ false = (false && decide (2 ≤ (binRanked.scanFinal w).depth)) Bool.false_and false w:List Boolh:(binRanked.scanFinal w).live = false⊢ false = false] All goals completed! 🐙
· true w:List Boolh:(binRanked.scanFinal w).live = true⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (true && decide (2 ≤ (binRanked.scanFinal w).depth)) rcases Nat.lt_or_ge (binRanked.scanFinal w).depth 2 with h2 | h2 true.inl w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (true && decide (2 ≤ (binRanked.scanFinal w).depth))true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (true && decide (2 ≤ (binRanked.scanFinal w).depth))
· true.inl w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (true && decide (2 ≤ (binRanked.scanFinal w).depth)) rw [scanStep_true_of_live_of_buf_nil_of_depth_lt_two _ h (buf_scanFinal_eq_nil w) h2 true.inl w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ { buf := [], depth := (binRanked.scanFinal w).depth, live := false }.live =
(true && decide (2 ≤ (binRanked.scanFinal w).depth))] true.inl w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ { buf := [], depth := (binRanked.scanFinal w).depth, live := false }.live =
(true && decide (2 ≤ (binRanked.scanFinal w).depth))
dsimp only true.inl w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ false = (true && decide (2 ≤ (binRanked.scanFinal w).depth))
rw [decide_eq_false (by w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ ¬2 ≤ (binRanked.scanFinal w).depth omega All goals completed! 🐙 : ¬ 2 ≤ (binRanked.scanFinal w).depth), Bool.true_and true.inl w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth < 2⊢ false = false] All goals completed! 🐙
· true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ (binRanked.scanStep true (binRanked.scanFinal w)).live = (true && decide (2 ≤ (binRanked.scanFinal w).depth)) rw [scanStep_true_of_live_of_buf_nil_of_two_le_depth _ h (buf_scanFinal_eq_nil w) h2 true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ { buf := [], depth := (binRanked.scanFinal w).depth - 2 + 1, live := true }.live =
(true && decide (2 ≤ (binRanked.scanFinal w).depth))] true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ { buf := [], depth := (binRanked.scanFinal w).depth - 2 + 1, live := true }.live =
(true && decide (2 ≤ (binRanked.scanFinal w).depth))
dsimp only true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ true = (true && decide (2 ≤ (binRanked.scanFinal w).depth))
rw [decide_eq_true h2, true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ true = (true && true) Bool.true_and true.inr w:List Boolh:(binRanked.scanFinal w).live = trueh2:(binRanked.scanFinal w).depth ≥ 2⊢ true = true] All goals completed! 🐙A leaf bit raises the pending count by one, the scan being live before it.
theorem depth_cons_false_of_ok (w : List Bool) (h : ok w = true) :
depth (false :: w) = depth w + 1 := by w:List Boolh:ok w = true⊢ depth (false :: w) = depth w + 1
rw [depth, w:List Boolh:ok w = true⊢ (binRanked.scanFinal (false :: w)).depth = depth w + 1 depth, w:List Boolh:ok w = true⊢ (binRanked.scanFinal (false :: w)).depth = (binRanked.scanFinal w).depth + 1 scanFinal_cons, w:List Boolh:ok w = true⊢ (binRanked.scanStep false (binRanked.scanFinal w)).depth = (binRanked.scanFinal w).depth + 1
scanStep_false_of_live_of_buf_nil _ h (buf_scanFinal_eq_nil w) w:List Boolh:ok w = true⊢ { buf := [], depth := (binRanked.scanFinal w).depth + 1, live := true }.depth = (binRanked.scanFinal w).depth + 1] All goals completed! 🐙A node bit pops two pending subterms and pushes one, the scan being live before it and two subterms pending.
theorem depth_cons_true_of_ok_of_two_le_depth (w : List Bool) (h : ok w = true)
(h2 : 2 ≤ depth w) : depth (true :: w) = depth w - 1 := by w:List Boolh:ok w = trueh2:2 ≤ depth w⊢ depth (true :: w) = depth w - 1
simp only [depth] at h2 ⊢ w:List Boolh:ok w = trueh2:2 ≤ (binRanked.scanFinal w).depth⊢ (binRanked.scanFinal (true :: w)).depth = (binRanked.scanFinal w).depth - 1
rw [scanFinal_cons, w:List Boolh:ok w = trueh2:2 ≤ (binRanked.scanFinal w).depth⊢ (binRanked.scanStep true (binRanked.scanFinal w)).depth = (binRanked.scanFinal w).depth - 1
scanStep_true_of_live_of_buf_nil_of_two_le_depth _ h (buf_scanFinal_eq_nil w) h2 w:List Boolh:ok w = trueh2:2 ≤ (binRanked.scanFinal w).depth⊢ { buf := [], depth := (binRanked.scanFinal w).depth - 2 + 1, live := true }.depth = (binRanked.scanFinal w).depth - 1] w:List Boolh:ok w = trueh2:2 ≤ (binRanked.scanFinal w).depth⊢ { buf := [], depth := (binRanked.scanFinal w).depth - 2 + 1, live := true }.depth = (binRanked.scanFinal w).depth - 1
dsimp only w:List Boolh:ok w = trueh2:2 ≤ (binRanked.scanFinal w).depth⊢ (binRanked.scanFinal w).depth - 2 + 1 = (binRanked.scanFinal w).depth - 1
omega All goals completed! 🐙endend RankedAlphabet.Binary