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.Encoding public import Geb.Prototypes.Computability.BitTree.Elias.Code
set_option doc.verso true

Binary trees with length-prefixed leaf payloads

The tree shape retains one tag per node. Leaf payloads are preceded by their lengths, so payload bits are stored without escaping.

Main definitions

  • lengths lists the payload lengths in left-to-right leaf order.

  • encode uses one tag per node and a delta length header per leaf.

  • decode reads a complete tree; validBool tests whether it succeeds.

Main statements

  • length_encode counts node tags, raw payload bits and length headers.

  • readTree_encode_append proves the fuel-bounded parser's prefix roundtrip.

  • validBool_iff_existsUnique characterizes the recognized language.

Tags

binary tree, bitstring, length prefix, encoding

@[expose] public sectionnamespace Geb.BitTree.Elias

Payload lengths in left-to-right leaf order.

def lengths : Tree List := WType.elim (List ) fun x match x with | some s, _ => [s.length] | none, f => f false ++ f true
@[simp] theorem lengths_leaf (s : List Bool) : lengths (leaf s) = [s.length] := rfl@[simp] theorem lengths_fork (l r : Tree) : lengths (fork l r) = lengths l ++ lengths r := rfl

There is one payload length per leaf.

theorem length_lengths (t : Tree) : (lengths t).length = (counts t).2.1 := tree_ind (P := fun t (lengths t).length = (counts t).2.1) (fun _ rfl) (fun l r hl hr t:Treel:Treer:Treehl:(lengths l).length = (counts l).2.1hr:(lengths r).length = (counts r).2.1(lengths (fork l r)).length = (counts (fork l r)).2.1 t:Treel:Treer:Treehl:(lengths l).length = (counts l).2.1hr:(lengths r).length = (counts r).2.1(counts l).2.1 + (counts r).2.1 = (counts (fork l r)).2.1 All goals completed! 🐙) t

The sum of the lengths is the total number of payload bits.

theorem sum_lengths (t : Tree) : (lengths t).sum = (counts t).2.2 := tree_ind (P := fun t (lengths t).sum = (counts t).2.2) (fun _ Nat.add_zero _) (fun l r hl hr t:Treel:Treer:Treehl:(lengths l).sum = (counts l).2.2hr:(lengths r).sum = (counts r).2.2(lengths (fork l r)).sum = (counts (fork l r)).2.2 t:Treel:Treer:Treehl:(lengths l).sum = (counts l).2.2hr:(lengths r).sum = (counts r).2.2(counts l).2.2 + (counts r).2.2 = (counts (fork l r)).2.2 All goals completed! 🐙) t

Read a payload of the specified length, rejecting truncated input.

def readPayload (n : ) (w : List Bool) : Option (List Bool × List Bool) := if n w.length then some (w.take n, w.drop n) else none

Reading a payload preserves the unconsumed suffix.

theorem readPayload_append (s rest : List Bool) : readPayload s.length (s ++ rest) = some (s, rest) := s:List Boolrest:List BoolreadPayload s.length (s ++ rest) = some (s, rest) All goals completed! 🐙

A successful payload read gives its length and the exact input decomposition.

theorem readPayload_eq_some {n : } {w s rest : List Bool} (h : readPayload n w = some (s, rest)) : s.length = n w = s ++ rest := n:w:List Bools:List Boolrest:List Boolh:readPayload n w = some (s, rest)s.length = n w = s ++ rest n:w:List Bools:List Boolrest:List Boolh:(if n w.length then some (List.take n w, List.drop n w) else none) = some (s, rest)s.length = n w = s ++ rest n:w:List Bools:List Boolrest:List Boolh✝:n w.lengthh:some (List.take n w, List.drop n w) = some (s, rest)s.length = n w = s ++ restn:w:List Bools:List Boolrest:List Boolh✝:¬n w.lengthh:none = some (s, rest)s.length = n w = s ++ rest next hn n:w:List Bools:List Boolrest:List Boolhn:n w.lengthh:some (List.take n w, List.drop n w) = some (s, rest)s.length = n w = s ++ rest n:w:List Boolhn:n w.length(List.take n w).length = n w = List.take n w ++ List.drop n w All goals completed! 🐙 next n:w:List Bools:List Boolrest:List Boolh✝:¬n w.lengthh:none = some (s, rest)s.length = n w = s ++ rest All goals completed! 🐙

Preorder tree tags with a delta-coded length followed by each leaf's raw payload.

def encode : Tree List Bool := WType.elim (List Bool) fun x match x with | some s, _ => false :: (encodeNat s.length ++ s) | none, f => true :: (f false ++ f true)
@[simp] theorem encode_leaf (s : List Bool) : encode (leaf s) = false :: (encodeNat s.length ++ s) := rfl@[simp] theorem encode_fork (l r : Tree) : encode (fork l r) = true :: (encode l ++ encode r) := rfl

The exact representation length separates node tags, raw bits and length headers.

theorem length_encode (t : Tree) : (encode t).length = 2 * (counts t).1 + 1 + (counts t).2.2 + ((lengths t).map fun n (encodeNat n).length).sum := tree_ind (P := fun t (encode t).length = 2 * (counts t).1 + 1 + (counts t).2.2 + ((lengths t).map fun n (encodeNat n).length).sum) (fun s t:Trees:List Bool(encode (leaf s)).length = 2 * (counts (leaf s)).1 + 1 + (counts (leaf s)).2.2 + (List.map (fun n (encodeNat n).length) (lengths (leaf s))).sum t:Trees:List Bool(encodeNat s.length).length + s.length + 1 = 2 * 0 + 1 + s.length + ((encodeNat s.length).length + 0) All goals completed! 🐙) (fun l r hl hr t:Treel:Treer:Treehl:(encode l).length = 2 * (counts l).1 + 1 + (counts l).2.2 + (List.map (fun n (encodeNat n).length) (lengths l)).sumhr:(encode r).length = 2 * (counts r).1 + 1 + (counts r).2.2 + (List.map (fun n (encodeNat n).length) (lengths r)).sum(encode (fork l r)).length = 2 * (counts (fork l r)).1 + 1 + (counts (fork l r)).2.2 + (List.map (fun n (encodeNat n).length) (lengths (fork l r))).sum t:Treel:Treer:Treehl:(encode l).length = 2 * (counts l).1 + 1 + (counts l).2.2 + (List.map (fun n (encodeNat n).length) (lengths l)).sumhr:(encode r).length = 2 * (counts r).1 + 1 + (counts r).2.2 + (List.map (fun n (encodeNat n).length) (lengths r)).sum(encode l).length + (encode r).length + 1 = 2 * ((counts l).1 + (counts r).1 + 1) + 1 + ((counts l).2.2 + (counts r).2.2) + ((List.map (fun n (encodeNat n).length) (lengths l)).sum + (List.map (fun n (encodeNat n).length) (lengths r)).sum) All goals completed! 🐙) t

The total header cost is logarithmic in each shifted payload length.

theorem length_encode_le (t : Tree) : (encode t).length 2 * (counts t).1 + 1 + (counts t).2.2 + 3 * ((lengths t).map fun n (n + 1).size).sum := tree_ind (P := fun t (encode t).length 2 * (counts t).1 + 1 + (counts t).2.2 + 3 * ((lengths t).map fun n (n + 1).size).sum) (fun s t:Trees:List Bool(encode (leaf s)).length 2 * (counts (leaf s)).1 + 1 + (counts (leaf s)).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths (leaf s))).sum t:Trees:List Boolh:(encodeNat s.length).length 3 * (s.length + 1).size(encode (leaf s)).length 2 * (counts (leaf s)).1 + 1 + (counts (leaf s)).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths (leaf s))).sum t:Trees:List Boolh:(encodeNat s.length).length 3 * (s.length + 1).size(encodeNat s.length).length + s.length + 1 2 * 0 + 1 + s.length + 3 * ((s.length + 1).size + 0) All goals completed! 🐙) (fun l r hl hr t:Treel:Treer:Treehl:(encode l).length 2 * (counts l).1 + 1 + (counts l).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths l)).sumhr:(encode r).length 2 * (counts r).1 + 1 + (counts r).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths r)).sum(encode (fork l r)).length 2 * (counts (fork l r)).1 + 1 + (counts (fork l r)).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths (fork l r))).sum t:Treel:Treer:Treehl:(encode l).length 2 * (counts l).1 + 1 + (counts l).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths l)).sumhr:(encode r).length 2 * (counts r).1 + 1 + (counts r).2.2 + 3 * (List.map (fun n (n + 1).size) (lengths r)).sum(encode l).length + (encode r).length + 1 2 * ((counts l).1 + (counts r).1 + 1) + 1 + ((counts l).2.2 + (counts r).2.2) + 3 * ((List.map (fun n (n + 1).size) (lengths l)).sum + (List.map (fun n (n + 1).size) (lengths r)).sum) All goals completed! 🐙) t

There is enough input length to bound every recursive descent in the tree parser.

theorem forks_lt_length_encode (t : Tree) : (counts t).1 < (encode t).length := t:Tree(counts t).1 < (encode t).length t:Tree(counts t).1 < 2 * (counts t).1 + 1 + (counts t).2.2 + (List.map (fun n (encodeNat n).length) (lengths t)).sum All goals completed! 🐙

One tree-parser layer: a leaf payload or two recursively read children.

def readTreeStep (readChild : List Bool Option (Tree × List Bool)) (w : List Bool) : Option (Tree × List Bool) := match w with | [] => none | false :: suffix => (readNat suffix).bind fun p (readPayload p.1 p.2).map fun q (leaf q.1, q.2) | true :: suffix => (readChild suffix).bind fun p (readChild p.2).map fun q (fork p.1 q.1, q.2)

A fuel-bounded tree parser, with the bound controlling recursive tree descent.

def readTree : List Bool Option (Tree × List Bool) := Nat.rec (fun _ none) fun _ readChild readTreeStep readChild

The parser's successor-fuel equation.

theorem readTree_succ (fuel : ) (w : List Bool) : readTree (fuel + 1) w = readTreeStep (readTree fuel) w := rfl

A bound larger than the number of forks suffices for every encoded tree.

theorem readTree_encode_append (t : Tree) : fuel, (counts t).1 + 1 fuel rest, readTree fuel (encode t ++ rest) = some (t, rest) := tree_ind (P := fun t fuel, (counts t).1 + 1 fuel rest, readTree fuel (encode t ++ rest) = some (t, rest)) (fun s fuel hf rest t:Trees:List Boolfuel:hf:(counts (leaf s)).1 + 1 fuelrest:List BoolreadTree fuel (encode (leaf s) ++ rest) = some (leaf s, rest) cases fuel with t:Trees:List Boolrest:List Boolhf:(counts (leaf s)).1 + 1 0readTree 0 (encode (leaf s) ++ rest) = some (leaf s, rest) t:Trees:List Boolrest:List Boolhf:(counts (leaf s)).1 + 1 0False t:Trees:List Boolrest:List Boolhf:(counts (leaf s)).1 + 1 0hh:0 + 1 0False All goals completed! 🐙 t:Trees:List Boolrest:List Boolfuel:hf:(counts (leaf s)).1 + 1 fuel + 1readTree (fuel + 1) (encode (leaf s) ++ rest) = some (leaf s, rest) All goals completed! 🐙) (fun l r hl hr fuel hf rest t:Treel:Treer:Treehl: (fuel : ), (counts l).1 + 1 fuel (rest : List Bool), readTree fuel (encode l ++ rest) = some (l, rest)hr: (fuel : ), (counts r).1 + 1 fuel (rest : List Bool), readTree fuel (encode r ++ rest) = some (r, rest)fuel:hf:(counts (fork l r)).1 + 1 fuelrest:List BoolreadTree fuel (encode (fork l r) ++ rest) = some (fork l r, rest) cases fuel with t:Treel:Treer:Treehl: (fuel : ), (counts l).1 + 1 fuel (rest : List Bool), readTree fuel (encode l ++ rest) = some (l, rest)hr: (fuel : ), (counts r).1 + 1 fuel (rest : List Bool), readTree fuel (encode r ++ rest) = some (r, rest)rest:List Boolhf:(counts (fork l r)).1 + 1 0readTree 0 (encode (fork l r) ++ rest) = some (fork l r, rest) t:Treel:Treer:Treehl: (fuel : ), (counts l).1 + 1 fuel (rest : List Bool), readTree fuel (encode l ++ rest) = some (l, rest)hr: (fuel : ), (counts r).1 + 1 fuel (rest : List Bool), readTree fuel (encode r ++ rest) = some (r, rest)rest:List Boolhf:(counts (fork l r)).1 + 1 0False; All goals completed! 🐙 t:Treel:Treer:Treehl: (fuel : ), (counts l).1 + 1 fuel (rest : List Bool), readTree fuel (encode l ++ rest) = some (l, rest)hr: (fuel : ), (counts r).1 + 1 fuel (rest : List Bool), readTree fuel (encode r ++ rest) = some (r, rest)rest:List Boolfuel:hf:(counts (fork l r)).1 + 1 fuel + 1readTree (fuel + 1) (encode (fork l r) ++ rest) = some (fork l r, rest) t:Treel:Treer:Treehl: (fuel : ), (counts l).1 + 1 fuel (rest : List Bool), readTree fuel (encode l ++ rest) = some (l, rest)hr: (fuel : ), (counts r).1 + 1 fuel (rest : List Bool), readTree fuel (encode r ++ rest) = some (r, rest)rest:List Boolfuel:hf:((counts l).1 + (counts r).1 + 1, (counts l).2.1 + (counts r).2.1, (counts l).2.2 + (counts r).2.2).1 + 1 fuel + 1readTree (fuel + 1) (encode (fork l r) ++ rest) = some (fork l r, rest) t:Treel:Treer:Treehl: (fuel : ), (counts l).1 + 1 fuel (rest : List Bool), readTree fuel (encode l ++ rest) = some (l, rest)hr: (fuel : ), (counts r).1 + 1 fuel (rest : List Bool), readTree fuel (encode r ++ rest) = some (r, rest)rest:List Boolfuel:hf:((counts l).1 + (counts r).1 + 1, (counts l).2.1 + (counts r).2.1, (counts l).2.2 + (counts r).2.2).1 + 1 fuel + 1((readTree fuel (encode l ++ (encode r ++ rest))).bind fun p Option.map (fun q (fork p.1 q.1, q.2)) (readTree fuel p.2)) = some (fork l r, rest) All goals completed! 🐙) t

Every successful tree parse consumes exactly the canonical encoding of its result.

theorem readTree_eq_some (fuel : ) : w t rest, readTree fuel w = some (t, rest) w = encode t ++ rest := Nat.rec (fun w t rest h fuel:w:List Boolt:Treerest:List Boolh:readTree Nat.zero w = some (t, rest)w = encode t ++ rest All goals completed! 🐙) (fun fuel ih w t rest h fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restw:List Boolt:Treerest:List Boolh:readTree fuel.succ w = some (t, rest)w = encode t ++ rest cases w with fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolh:readTree fuel.succ [] = some (t, rest)[] = encode t ++ rest All goals completed! 🐙 fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolb:Boolsuffix:List Boolh:readTree fuel.succ (b :: suffix) = some (t, rest)b :: suffix = encode t ++ rest cases b with fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)false :: suffix = encode t ++ rest cases hn : readNat suffix with fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)hn:readNat suffix = nonefalse :: suffix = encode t ++ rest All goals completed! 🐙 fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)p: × List Boolhn:readNat suffix = some pfalse :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)false :: suffix = encode t ++ rest cases hp : readPayload n input with fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)hp:readPayload n input = nonefalse :: suffix = encode t ++ rest All goals completed! 🐙 fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)p:List Bool × List Boolhp:readPayload n input = some pfalse :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)bs:List Booltail:List Boolhp:readPayload n input = some (bs, tail)false :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)bs:List Booltail:List Boolhp:readPayload n input = some (bs, tail)he:(leaf bs, tail) = (t, rest)false :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)bs:List Booltail:List Boolhp:readPayload n input = some (bs, tail)he:(leaf bs, tail) = (t, rest)ht:leaf bs = thr:tail = restfalse :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (false :: suffix) = some (t, rest)n:input:List Boolhn:readNat suffix = some (n, input)bs:List Booltail:List Boolhp:readPayload n input = some (bs, tail)he:(leaf bs, tail) = (t, rest)ht:leaf bs = thr:tail = resthlen:bs.length = nhinput:input = bs ++ tailfalse :: suffix = encode t ++ rest All goals completed! 🐙 fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)true :: suffix = encode t ++ rest cases hl : readTree fuel suffix with fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)hl:readTree fuel suffix = nonetrue :: suffix = encode t ++ rest All goals completed! 🐙 fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)p:Tree × List Boolhl:readTree fuel suffix = some ptrue :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)l:Treemiddle:List Boolhl:readTree fuel suffix = some (l, middle)true :: suffix = encode t ++ rest cases hr : readTree fuel middle with fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)l:Treemiddle:List Boolhl:readTree fuel suffix = some (l, middle)hr:readTree fuel middle = nonetrue :: suffix = encode t ++ rest All goals completed! 🐙 fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)l:Treemiddle:List Boolhl:readTree fuel suffix = some (l, middle)p:Tree × List Boolhr:readTree fuel middle = some ptrue :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)l:Treemiddle:List Boolhl:readTree fuel suffix = some (l, middle)r:Treetail:List Boolhr:readTree fuel middle = some (r, tail)true :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)l:Treemiddle:List Boolhl:readTree fuel suffix = some (l, middle)r:Treetail:List Boolhr:readTree fuel middle = some (r, tail)he:(fork l r, tail) = (t, rest)true :: suffix = encode t ++ rest fuel✝:fuel:ih: (w : List Bool) (t : Tree) (rest : List Bool), readTree fuel w = some (t, rest) w = encode t ++ restt:Treerest:List Boolsuffix:List Boolh:readTree fuel.succ (true :: suffix) = some (t, rest)l:Treemiddle:List Boolhl:readTree fuel suffix = some (l, middle)r:Treetail:List Boolhr:readTree fuel middle = some (r, tail)he:(fork l r, tail) = (t, rest)ht:fork l r = ths:tail = resttrue :: suffix = encode t ++ rest All goals completed! 🐙) fuel

Decode exactly one complete tree, rejecting trailing or incomplete input.

def decode (w : List Bool) : Option Tree := match readTree w.length w with | some (t, []) => some t | _ => none

The input length supplies enough parser fuel for every encoded tree.

@[simp] theorem decode_encode (t : Tree) : decode (encode t) = some t := t:Treedecode (encode t) = some t t:Treeh:readTree (encode t).length (encode t ++ []) = some (t, [])decode (encode t) = some t t:Treeh:readTree (encode t).length (encode t) = some (t, [])decode (encode t) = some t All goals completed! 🐙

Successful complete decoding identifies the whole input as the resulting tree's encoding.

theorem decode_eq_some (w : List Bool) (t : Tree) (h : decode w = some t) : encode t = w := w:List Boolt:Treeh:decode w = some tencode t = w cases hp : readTree w.length w with w:List Boolt:Treeh:decode w = some thp:readTree w.length w = noneencode t = w All goals completed! 🐙 w:List Boolt:Treeh:decode w = some tp:Tree × List Boolhp:readTree w.length w = some pencode t = w w:List Boolt:Treeh:decode w = some tt':Treerest:List Boolhp:readTree w.length w = some (t', rest)encode t = w cases rest with w:List Boolt:Treeh:decode w = some tt':Treehp:readTree w.length w = some (t', [])encode t = w w:List Boolt:Treeh:decode w = some tt':Treehp:readTree w.length w = some (t', [])he:t' = tencode t = w w:List Boolt:Treeh:decode w = some tt':Treehp:readTree w.length w = some (t, [])he:t' = tencode t = w All goals completed! 🐙 w:List Boolt:Treeh:decode w = some tt':Treehead✝:Booltail✝:List Boolhp:readTree w.length w = some (t', head✝ :: tail✝)encode t = w All goals completed! 🐙

The length-prefixed tree encoding is injective.

theorem encode_injective : Function.Injective encode := Function.Injective encode t:Treet':Treeh:encode t = encode t't = t' t:Treet':Treeh:encode t = encode t'he:decode (encode t) = decode (encode t')t = t' t:Treet':Treeh:encode t = encode t'he:some t = some t't = t' All goals completed! 🐙

The complete decoder decides membership in the encoded-tree language.

def validBool (w : List Bool) : Bool := (decode w).isSome

Every encoded tree is accepted by the complete decoder.

@[simp] theorem validBool_encode (t : Tree) : validBool (encode t) = true := t:TreevalidBool (encode t) = true t:Tree(some t).isSome = true All goals completed! 🐙

Acceptance is exactly existence of an encoded tree.

theorem validBool_iff (w : List Bool) : validBool w = true t, encode t = w := w:List BoolvalidBool w = true t, encode t = w w:List BoolvalidBool w = true t, encode t = ww:List Bool(∃ t, encode t = w) validBool w = true w:List BoolvalidBool w = true t, encode t = w w:List Boolh:validBool w = true t, encode t = w cases hd : decode w with w:List Boolh:validBool w = truehd:decode w = none t, encode t = w All goals completed! 🐙 w:List Boolh:validBool w = truet:Treehd:decode w = some t t, encode t = w All goals completed! 🐙 w:List Bool(∃ t, encode t = w) validBool w = true t:TreevalidBool (encode t) = true All goals completed! 🐙

Every accepted word represents exactly one tree of bitstrings.

theorem validBool_iff_existsUnique (w : List Bool) : validBool w = true ∃! t, encode t = w := w:List BoolvalidBool w = true ∃! t, encode t = w w:List Bool(∃ t, encode t = w) ∃! t, encode t = w w:List Bool(∃ t, encode t = w) ∃! t, encode t = ww:List Bool(∃! t, encode t = w) t, encode t = w w:List Bool(∃ t, encode t = w) ∃! t, encode t = w w:List Boolt:Treeht:encode t = w∃! t, encode t = w All goals completed! 🐙 w:List Bool(∃! t, encode t = w) t, encode t = w w:List Boolt:Treeht:encode t = wright✝: (y : Tree), (fun t encode t = w) y y = t t, encode t = w All goals completed! 🐙
end Geb.BitTree.Elias