Imports
CLRS Section 34.4 - Canonical bounded-stack semantics
This module connects pure Boolean stack primitives to canonical bounded-stack codes and lists over the original machine alphabet.
Main results:
-
StackBits.Representspackages a canonical bounded-stack code, its exact Boolean encoding, and its decoded machine-alphabet list. -
pushStackBits_represents,peekStackBits_represents, andpopStackBits_representsgive list-level semantics to the pure stack primitives. -
evalBundle_stack_representsprojects a successfully decoded complete tableau row to the semantic representation of each machine stack.
Current gaps:
-
Circuit allocation and recursive statement semantics are supplied by the downstream
StackCircuitsandStatementCircuitslayers;TransitionCircuitssupplies finite-label dispatch and local correctness. -
Fresh row allocation and exact boundary constraints are supplied downstream; polynomial bounds and verified whole-tableau assembly remain.
namespace CLRS.Chapter34.Turing.CookLevinnoncomputable sectionCanonical Boolean encodings
Project a bounded stack code to one-hot Boolean height and cell bundles.
def encodeBoundedStackBits {tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(code : BoundedStack (reachableAlphabet tm k).card W) : StackBits tm W k where
height := encodeOneHot code.height
cell i := encodeOneHot (code.cells i)The height projection selects exactly the bounded code's height.
@[simp] theorem encodeBoundedStackBits_height
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(code : BoundedStack (reachableAlphabet tm k).card W)
(height : Fin (W + 1)) :
(encodeBoundedStackBits code).height height =
encodeOneHot code.height height := rflEvery cell projection selects exactly the bounded code's symbol code.
@[simp] theorem encodeBoundedStackBits_cell
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(code : BoundedStack (reachableAlphabet tm k).card W) (cell : Fin W)
(symbol : Fin ((reachableAlphabet tm k).card + 1)) :
(encodeBoundedStackBits code).cell cell symbol =
encodeOneHot (code.cells cell) symbol := rflEvery projected bounded stack is raw one-hot decodable.
theorem encodeBoundedStackBits_rawDecodable
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(code : BoundedStack (reachableAlphabet tm k).card W) :
(encodeBoundedStackBits code).RawDecodable := by
refine ⟨oneHot_encodeOneHot code.height, ?_⟩
intro i
exact oneHot_encodeOneHot (code.cells i)Representation relation
namespace StackBitsnamespace RepresentsProof-carrying data witnessing that one Boolean stack represents one machine-alphabet list.
Canonical finite stack code underlying the Boolean bundle.
The finite code has an active nonblank prefix and blank suffix.
The Boolean bundle is exactly the one-hot projection of the code.
Proof-indexed decoding returns the represented original-alphabet list.
structure Witness {tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(stack : StackBits tm W k) (xs : List (tm.Γ k)) where code : BoundedStack (reachableAlphabet tm k).card W valid : code.Valid bits_eq : stack = encodeBoundedStackBits code decode_eq : decodeBoundedStack tm k code valid = xsend RepresentsA Boolean stack represents a machine-alphabet list when there is proof-carrying data showing that it is exactly the one-hot projection of a valid bounded-stack code whose proof-indexed decoding is that list.
def Represents {tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(stack : StackBits tm W k) (xs : List (tm.Γ k)) : Prop :=
Nonempty (Represents.Witness stack xs)namespace RepresentsEvery semantically represented stack is independently one-hot decodable.
theorem rawDecodable {tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
{stack : StackBits tm W k} {xs : List (tm.Γ k)}
(hrep : stack.Represents xs) : stack.RawDecodable := by
rcases hrep with ⟨⟨code, _, hbits, _⟩⟩
rw [hbits]
exact encodeBoundedStackBits_rawDecodable codeEncoding a supported list that fits the fixed width gives its canonical Boolean representation.
theorem of_encode {tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(xs : List (tm.Γ k))
(halphabet : ∀ a, a ∈ xs → a ∈ reachableAlphabet tm k)
(hheight : xs.length ≤ W) :
(encodeBoundedStackBits
(encodeBoundedStack tm k xs halphabet hheight)).Represents xs := by
exact ⟨
{ code := encodeBoundedStack tm k xs halphabet hheight
valid := encodeBoundedStack_valid tm k xs halphabet hheight
bits_eq := rfl
decode_eq := decodeBoundedStack_encode tm k xs halphabet hheight }⟩Every semantic representation normalizes to an encoding of its represented list, for suitable support and width proofs.
theorem eq_encode {tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
{stack : StackBits tm W k} {xs : List (tm.Γ k)}
(hrep : stack.Represents xs) :
∃ (halphabet : ∀ a, a ∈ xs → a ∈ reachableAlphabet tm k)
(hheight : xs.length ≤ W),
stack = encodeBoundedStackBits
(encodeBoundedStack tm k xs halphabet hheight) := by
rcases hrep with ⟨⟨code, hvalid, hbits, hdecode⟩⟩
subst xs
let halphabet : ∀ a,
a ∈ decodeBoundedStack tm k code hvalid →
a ∈ reachableAlphabet tm k := by
intro a ha
simp only [decodeBoundedStack, List.mem_ofFn] at ha
rcases ha with ⟨i, rfl⟩
exact (alphabetEquivFin tm k).symm
⟨(code.cells (code.activeIndex i)).val,
(hvalid (code.activeIndex i)).mpr i.isLt⟩ |>.property
let hheight : (decodeBoundedStack tm k code hvalid).length ≤ W := by
rw [decodeBoundedStack_length]
exact Nat.le_of_lt_succ code.height.isLt
refine ⟨halphabet, hheight, ?_⟩
have hcode := encodeBoundedStack_decode tm k code hvalid
rw [hbits]
exact congrArg encodeBoundedStackBits hcode.symmend Representsend StackBitsA represented stack has room for one more symbol exactly when its decoded list is strictly shorter than the fixed width, including width zero.
theorem represents_hasCapacity_iff
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
{stack : StackBits tm W k} {xs : List (tm.Γ k)}
(hrep : stack.Represents xs) :
stack.HasCapacity ↔ xs.length < W := by
rcases hrep.eq_encode with ⟨halphabet, hheight, hbits⟩
rw [hbits]
simp [StackBits.HasCapacity, encodeBoundedStackBits, encodeBoundedStack,
encodeOneHot, Fin.ext_iff]
omegaprivate theorem encodeAlphabetSymbol_eq_encodeHeadCode
{tm : _root_.Turing.FinTM2} {k : tm.K}
(symbol : SupportedSymbol tm k) :
encodeAlphabetSymbol tm k symbol.val symbol.property =
encodeHeadCode (some symbol) := by
apply Fin.ext
rflList semantics of pure stack operations
Peeking a represented stack decodes exactly to the list head, with an empty
list producing the well-formed inner none.
theorem peekStackBits_represents
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
{stack : StackBits tm W k} {xs : List (tm.Γ k)}
(hrep : stack.Represents xs) :
decodeHeadValue? (peekStackBits W stack) = some xs.head? := by
rcases hrep.eq_encode with ⟨halphabet, hheight, hbits⟩
rw [hbits]
cases W with
| zero =>
have hnil : xs = [] := List.eq_nil_of_length_eq_zero (by omega)
subst xs
simp
| succ W =>
cases xs with
| nil =>
simp [peekStackBits, encodeBoundedStackBits, encodeBoundedStack]
change decodeHeadValue? (encodeHeadBits (tm := tm) (k := k) none) =
some none
simp
| cons symbol tail =>
let supported : SupportedSymbol tm k :=
⟨symbol, halphabet symbol (by simp)⟩
have hcell :
(encodeBoundedStackBits
(encodeBoundedStack tm k (symbol :: tail) halphabet hheight)).cell 0 =
encodeHeadBits (some supported) := by
funext code
simp only [encodeBoundedStackBits, encodeBoundedStack]
rw [dif_pos (by simp)]
change encodeOneHot (encodeAlphabetSymbol tm k symbol _) code =
encodeOneHot (encodeHeadCode (some supported)) code
rw [encodeAlphabetSymbol_eq_encodeHeadCode supported]
rw [peekStackBits_of_pos, hcell]
simp [supported]Popping an exactly encoded bounded stack produces the exact canonical encoding of its list tail.
theorem popStackBits_encodeBoundedStackBits
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(xs : List (tm.Γ k))
(halphabet : ∀ a, a ∈ xs → a ∈ reachableAlphabet tm k)
(hheight : xs.length ≤ W)
(htailAlphabet : ∀ a, a ∈ xs.tail → a ∈ reachableAlphabet tm k)
(htailHeight : xs.tail.length ≤ W) :
(popStackBits W
(encodeBoundedStackBits
(encodeBoundedStack tm k xs halphabet hheight))).stack =
encodeBoundedStackBits
(encodeBoundedStack tm k xs.tail htailAlphabet htailHeight) := by
cases W with
| zero =>
have hnil : xs = [] := List.eq_nil_of_length_eq_zero (by omega)
subst xs
simp
| succ W =>
have htailLe : xs.tail.length ≤ W := by
cases xs with
| nil => simp
| cons symbol tail =>
simp only [List.tail_cons]
simp only [List.length_cons] at hheight
omega
apply StackBundle.ext
· funext i
by_cases hizero : i = 0
· subst i
rw [popStackBits_height_zero]
cases xs with
| nil =>
simp [encodeBoundedStackBits, encodeBoundedStack, encodeOneHot]
| cons symbol tail =>
cases tail with
| nil =>
simp [encodeBoundedStackBits, encodeBoundedStack, encodeOneHot]
| cons next rest =>
simp [encodeBoundedStackBits, encodeBoundedStack, encodeOneHot,
Fin.ext_iff]
· obtain ⟨j, rfl⟩ := Fin.eq_succ_of_ne_zero hizero
rw [popStackBits_height_succ]
cases xs with
| nil =>
split <;>
simp [encodeBoundedStackBits, encodeBoundedStack, encodeOneHot]
| cons symbol tail =>
split
next hnext =>
change encodeOneHot
((encodeBoundedStack tm k (symbol :: tail) halphabet
hheight).height)
⟨j.val + 2, hnext⟩ =
encodeOneHot
((encodeBoundedStack tm k tail htailAlphabet
htailHeight).height) j.succ
have hequiv :
(⟨j.val + 2, hnext⟩ : Fin (W + 2)) =
(encodeBoundedStack tm k (symbol :: tail) halphabet
hheight).height ↔
j.succ =
(encodeBoundedStack tm k tail htailAlphabet
htailHeight).height := by
simp [encodeBoundedStack, Fin.ext_iff]
by_cases hselected :
j.succ =
(encodeBoundedStack tm k tail htailAlphabet
htailHeight).height
· have hold := hequiv.mpr hselected
simp [encodeOneHot, hold, hselected]
· have hold :
(⟨j.val + 2, hnext⟩ : Fin (W + 2)) ≠
(encodeBoundedStack tm k (symbol :: tail) halphabet
hheight).height :=
fun heq => hselected (hequiv.mp heq)
simp [encodeOneHot, hold, hselected]
next hnext =>
simp only [List.tail_cons] at htailLe
have hnotSelected :
j.succ ≠
(encodeBoundedStack tm k tail htailAlphabet
htailHeight).height := by
intro heq
have hval := congrArg Fin.val heq
simp only [Fin.val_succ, encodeBoundedStack] at hval
omega
change false = encodeOneHot
((encodeBoundedStack tm k tail htailAlphabet
htailHeight).height) j.succ
simp [encodeOneHot, hnotSelected]
· funext i code
by_cases hnext : i.val + 1 < W + 1
· rw [popStackBits_cell_of_next _ i hnext]
change encodeOneHot
((encodeBoundedStack tm k xs halphabet hheight).cells
⟨i.val + 1, hnext⟩) code =
encodeOneHot
((encodeBoundedStack tm k xs.tail htailAlphabet htailHeight).cells i)
code
cases xs with
| nil => simp [encodeBoundedStack]
| cons symbol tail =>
by_cases hactive : i.val < tail.length
· simp [encodeBoundedStack, hactive]
· simp [encodeBoundedStack, hactive]
· have hilast : i = Fin.last W := by
apply Fin.ext
simp only [Fin.val_last]
omega
subst i
rw [popStackBits_cell_last]
have hinactive : ¬ (Fin.last W).val < xs.tail.length := by
simpa using Nat.not_lt_of_ge htailLe
have hinactive' : ¬ W < xs.length - 1 := by
simpa only [Fin.val_last, List.length_tail] using hinactive
have hcell :
(encodeBoundedStack tm k xs.tail htailAlphabet
htailHeight).cells (Fin.last W) =
encodeHeadCode (tm := tm) (k := k) none := by
apply Fin.ext
simp [encodeBoundedStack, hinactive', encodeHeadCode]
change encodeHeadBits (tm := tm) (k := k) none code =
encodeOneHot
((encodeBoundedStack tm k xs.tail htailAlphabet
htailHeight).cells (Fin.last W)) code
rw [hcell]
rflPopping a represented stack represents its list tail and returns the old list head; popping an empty stack is stable.
theorem popStackBits_represents
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
{stack : StackBits tm W k} {xs : List (tm.Γ k)}
(hrep : stack.Represents xs) :
(popStackBits W stack).stack.Represents xs.tail ∧
decodeHeadValue? (popStackBits W stack).head = some xs.head? := by
rcases hrep.eq_encode with ⟨halphabet, hheight, hbits⟩
let htailAlphabet : ∀ a, a ∈ xs.tail →
a ∈ reachableAlphabet tm k := by
intro a ha
exact halphabet a (List.mem_of_mem_tail ha)
let htailHeight : xs.tail.length ≤ W := by
cases xs with
| nil => simp
| cons symbol tail =>
simp only [List.tail_cons]
simp only [List.length_cons] at hheight
omega
constructor
· rw [hbits]
rw [popStackBits_encodeBoundedStackBits xs halphabet hheight
htailAlphabet htailHeight]
exact StackBits.Represents.of_encode xs.tail htailAlphabet htailHeight
· rw [popStackBits_head]
exact peekStackBits_represents hrepPushing an exactly encoded supported symbol into a nonfull bounded stack produces the exact canonical encoding of list cons.
theorem pushStackBits_encodeBoundedStackBits
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
(symbol : SupportedSymbol tm k) (xs : List (tm.Γ k))
(halphabet : ∀ a, a ∈ xs → a ∈ reachableAlphabet tm k)
(hheight : xs.length ≤ W) (hroom : xs.length < W)
(hconsAlphabet : ∀ a, a ∈ symbol.val :: xs →
a ∈ reachableAlphabet tm k)
(hconsHeight : (symbol.val :: xs).length ≤ W) :
pushStackBits (encodeSymbolBits symbol) W
(encodeBoundedStackBits
(encodeBoundedStack tm k xs halphabet hheight)) =
encodeBoundedStackBits
(encodeBoundedStack tm k (symbol.val :: xs) hconsAlphabet
hconsHeight) := by
cases W with
| zero => omega
| succ W =>
apply StackBundle.ext
· funext i
by_cases hizero : i = 0
· subst i
simp [pushStackBits, encodeBoundedStackBits, encodeBoundedStack,
encodeOneHot, Fin.ext_iff]
· obtain ⟨j, rfl⟩ := Fin.eq_succ_of_ne_zero hizero
rw [pushStackBits_height_succ]
simp [encodeBoundedStackBits, encodeBoundedStack, encodeOneHot,
Fin.ext_iff]
· funext i code
by_cases hizero : i = 0
· subst i
rw [pushStackBits_cell_zero_encodeSymbol]
change encodeHeadBits (some symbol) code =
encodeOneHot
((encodeBoundedStack tm k (symbol.val :: xs) hconsAlphabet
hconsHeight).cells 0) code
have hcell :
(encodeBoundedStack tm k (symbol.val :: xs) hconsAlphabet
hconsHeight).cells 0 = encodeHeadCode (some symbol) := by
simp only [encodeBoundedStack]
rw [dif_pos (by simp)]
exact encodeAlphabetSymbol_eq_encodeHeadCode symbol
rw [hcell]
rfl
· obtain ⟨j, rfl⟩ := Fin.eq_succ_of_ne_zero hizero
rw [pushStackBits_cell_succ]
change encodeOneHot
((encodeBoundedStack tm k xs halphabet hheight).cells
j.castSucc) code =
encodeOneHot
((encodeBoundedStack tm k (symbol.val :: xs) hconsAlphabet
hconsHeight).cells j.succ) code
by_cases hactive : j.val < xs.length
· simp [encodeBoundedStack, hactive]
· simp [encodeBoundedStack, hactive]Pushing a supported symbol into a represented stack with capacity represents consing that symbol onto the list.
theorem pushStackBits_represents
{tm : _root_.Turing.FinTM2} {W : Nat} {k : tm.K}
{stack : StackBits tm W k} {xs : List (tm.Γ k)}
(hrep : stack.Represents xs) (symbol : SupportedSymbol tm k)
(hcapacity : stack.HasCapacity) :
(pushStackBits (encodeSymbolBits symbol) W stack).Represents
(symbol.val :: xs) := by
rcases hrep.eq_encode with ⟨halphabet, hheight, hbits⟩
have hroom : xs.length < W :=
(represents_hasCapacity_iff hrep).mp hcapacity
let hconsAlphabet : ∀ a, a ∈ symbol.val :: xs →
a ∈ reachableAlphabet tm k := by
intro a ha
simp only [List.mem_cons] at ha
rcases ha with rfl | ha
· exact symbol.property
· exact halphabet a ha
let hconsHeight : (symbol.val :: xs).length ≤ W := by
simp only [List.length_cons]
omega
rw [hbits]
rw [pushStackBits_encodeBoundedStackBits symbol xs halphabet hheight hroom
hconsAlphabet hconsHeight]
exact StackBits.Represents.of_encode (symbol.val :: xs) hconsAlphabet
hconsHeightComplete-row projections
Projecting one stack from a canonically encoded raw row is exactly the one-hot projection of that row's bounded stack code.
theorem encodeRawCfgBits_stack
{tm : _root_.Turing.FinTM2} {H : Nat}
(code : BoundedCfg tm H) (k : tm.K) :
(encodeRawCfgBits code).stack k =
encodeBoundedStackBits (code.stack k) := by
apply StackBundle.ext
· funext height
rfl
· funext cell symbol
rflIf a complete row bundle evaluates and canonically decodes to a machine configuration, each evaluated stack represents the corresponding machine stack list.
theorem evalBundle_stack_represents
{tm : _root_.Turing.FinTM2} {H : Nat}
(base : CircuitBuilder) (inputs : Nat → Bool)
(wires : CfgWires tm H) (hvalid : wires.ValidIn base)
{c : tm.Cfg} (hdecoded : evalBundle base inputs wires hvalid = some c)
(k : tm.K) :
StackBits.Represents ((evalCfgBits base inputs wires).stack k) (c.stk k) := by
unfold evalBundle evalRawBundle at hdecoded
cases hraw : decodeRawCfg? (evalCfgBits base inputs wires) with
| none => simp [hraw] at hdecoded
| some code =>
simp only [hraw, Option.bind_some] at hdecoded
unfold decodeCfg? at hdecoded
split at hdecoded
next hcodeValid =>
have hc : decodeCfg tm code hcodeValid = c := Option.some.inj hdecoded
have hbits : evalCfgBits base inputs wires = encodeRawCfgBits code :=
(decodeRawCfg_eq_some_iff (evalCfgBits base inputs wires) code).mp hraw
refine ⟨
{ code := code.stack k
valid := hcodeValid.2 k
bits_eq := ?_
decode_eq := ?_ }⟩
· rw [hbits, encodeRawCfgBits_stack]
· rw [← hc]
rfl
next hnotValid => contradictionendend CLRS.Chapter34.Turing.CookLevin