Encoding converters for the Cook-Levin reduction
From w # y to the canonical pair encoding
InductiveStacks of the converter to the canonical pair encoding#✓fully proved
The converter has four stacks: the input stack, whose symbols are left-tagged bits, right-tagged bits and the separator (the input is the bits of a first bit list tagged left, a separator, then the bits of a second bit list tagged right); the output stack, holding bits; and two stashes, holding the bits of the first and of the second list.
inductive Stk | inp | out | fst | snd
deriving DecidableEq
Used by 7
DefinitionStack alphabets of the separator-to-canonical converter#✓fully proved
The input stack of the converter from the separator form of a pair to its canonical encoding has the verifier's alphabet, and each of its other three stacks (the output and the two stashes) has the alphabet of bits.
@[reducible] def Γ : Stk → Type
| .inp => Verifier.G
| _ => Bool
inductive Stk | inp | out | fst | snd
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:44
abbrev G := Bool ⊕ Option Bool
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:67
Uses 2 · Used by 6
InductiveLabels of the converter to the canonical pair encoding#✓fully proved
The machine that turns the separated form of a pair \((x, w)\) of bit lists (the bits of \(x\) tagged left, a separator, then the bits of \(w\) tagged right) into the canonical encoding of the pair has five labels: reading the first part, reading the second part, emitting the second part, writing the separator, and emitting the first part.
inductive Lab | readFst | readSnd | emitSnd | sep | emitFst
deriving DecidableEq
AbbreviationStates of the converter to the canonical pair encoding#✓fully proved
A state of the converter is either empty or one symbol of the verifier's input alphabet, that is, a left-tagged bit, a right-tagged bit or the separator.
The state holds the last symbol popped; bits popped from the stashes are stored as left-tagged bits.
abbrev St := Option Verifier.G
abbrev G := Bool ⊕ Option Bool
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:67
Uses 1 · Used by 8
DefinitionLeft-tagged state test#✓fully proved
For a state \(s\) of the pair-to-canonical converter (either empty or a symbol of the verifier alphabet), the test is true exactly when \(s\) is a left-tagged bit \(\mathrm{inl}\,b\) for some bit \(b\), and false when \(s\) is empty, the separator \(\mathrm{inr}(\mathrm{none})\) or a right-tagged bit.
def isFst : St → Bool
| some (.inl _) => true
| _ => false
abbrev St := Option Verifier.G
CSLibExt/Computability/Complexity/EncodingConverters.lean:65
Uses 2 · Used by 2
DefinitionRight-tagged state test#✓fully proved
For a state \(s\) of the pair-to-canonical converter (either empty or a symbol of the verifier alphabet), the test is true exactly when \(s\) is a right-tagged bit \(\mathrm{inr}(\mathrm{some}\,b)\) for some bit \(b\), and false when \(s\) is empty, the separator \(\mathrm{inr}(\mathrm{none})\) or a left-tagged bit.
def isSnd : St → Bool
| some (.inr (some _)) => true
| _ => false
abbrev St := Option Verifier.G
CSLibExt/Computability/Complexity/EncodingConverters.lean:65
Uses 2 · Used by 2
DefinitionBit carried by a converter state#✓fully proved
For a state \(s\) of the pair-to-canonical converter (either empty or a symbol of the verifier alphabet), the bit of \(s\) is \(b\) when \(s\) is a left-tagged bit \(\mathrm{inl}\,b\) or a right-tagged bit \(\mathrm{inr}(\mathrm{some}\,b)\), and \(\mathrm{false}\) when \(s\) is empty or the separator \(\mathrm{inr}(\mathrm{none})\).
def bit : St → Bool
| some (.inl b) => b
| some (.inr (some b)) => b
| _ => false
abbrev St := Option Verifier.G
CSLibExt/Computability/Complexity/EncodingConverters.lean:65
Uses 2 · Used by 2
DefinitionProgram of the converter to the canonical pair encoding#✓fully proved
The machine has an input stack of symbols, each a left-tagged bit, a right-tagged bit or the separator, and three stacks of bits: the output and two stashes. Its program first pops input symbols and pushes the bit of each left-tagged one onto the first stash, until the input is empty or the symbol popped is not a left-tagged bit. It then pops input symbols and pushes the bit of each right-tagged one onto the second stash, until the input is empty or the symbol popped is not a right-tagged bit. Next it pops each bit \(b\) of the second stash and pushes false, \(b\), true onto the output, and then pushes a single false. Finally it pops each bit \(b\) of the first stash and pushes false, true, \(b\), true, true, true onto the output, and halts when the first stash is empty.
Each output block is pushed in reverse, so that it reads true, \(b\), false (respectively true, true, true, \(b\), true, false) from the top.
Cslib.Complexity.DenseSAT.ToCanonical.prog · 21 lines
def prog : Lab → TM2.Stmt Γ Lab St
| .readFst =>
.pop .inp (fun _ o => o) <| .branch isFst
(.push .fst bit <| .goto fun _ => .readFst)
(.goto fun _ => .readSnd)
| .readSnd =>
.pop .inp (fun _ o => o) <| .branch isSnd
(.push .snd bit <| .goto fun _ => .readSnd)
(.goto fun _ => .emitSnd)
| .emitSnd =>
.pop .snd (fun _ o => o.map Sum.inl) <| .branch isFst
(.push .out (fun _ => false) <| .push .out bit <| .push .out (fun _ => true) <|
.goto fun _ => .emitSnd)
(.goto fun _ => .sep)
| .sep => .push .out (fun _ => false) <| .goto fun _ => .emitFst
| .emitFst =>
.pop .fst (fun _ o => o.map Sum.inl) <| .branch isFst
(.push .out (fun _ => false) <| .push .out (fun _ => true) <| .push .out bit <|
.push .out (fun _ => true) <| .push .out (fun _ => true) <|
.push .out (fun _ => true) <| .goto fun _ => .emitFst)
.halt
inductive Lab | readFst | readSnd | emitSnd | sep | emitFst
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:57
@[reducible] def Γ : Stk → Type
| .inp => Verifier.G
| _ => Bool
CSLibExt/Computability/Complexity/EncodingConverters.lean:52
abbrev St := Option Verifier.G
CSLibExt/Computability/Complexity/EncodingConverters.lean:65
def isFst : St → Bool
| some (.inl _) => true
| _ => false
CSLibExt/Computability/Complexity/EncodingConverters.lean:68
def bit : St → Bool
| some (.inl b) => b
| some (.inr (some b)) => b
| _ => false
CSLibExt/Computability/Complexity/EncodingConverters.lean:78
def isSnd : St → Bool
| some (.inr (some _)) => true
| _ => false
CSLibExt/Computability/Complexity/EncodingConverters.lean:73
Uses 8 · Used by 4
DefinitionMachine converting the separator form of a pair to its canonical encoding#✓fully proved
The multi-stack Turing machine with the four stacks of the converter to the canonical pair encoding (input, output and two stashes), whose input stack holds symbols of the verifier's alphabet (left-tagged bits, right-tagged bits and the separator) and whose other stacks hold bits, reading its input from the input stack and leaving its output on the output stack, with the five labels of that converter and start label \(\mathrm{readFst}\), the converter's states (empty or one verifier symbol) as internal states, initially empty, and the program of the converter to the canonical pair encoding. It pops input symbols, pushing the bit of each left-tagged one onto the first stash, until the input is empty or the symbol popped is not a left-tagged bit. It then pops input symbols, pushing the bit of each right-tagged one onto the second stash, until the input is empty or the symbol popped is not a right-tagged bit. Next it pops each bit \(b\) of the second stash and pushes a block reading true, \(b\), false from the top onto the output, pushes a single false, pops each bit \(b\) of the first stash and pushes a block reading true, true, true, \(b\), true, false from the top, and halts when the first stash is empty.
def tm : FinTM2 where
K := Stk
k₀ := .inp
k₁ := .out
Γ := Γ
Λ := Lab
main := .readFst
σ := St
initialState := none
Γk₀Fin := (inferInstance : Fintype Verifier.G)
m := prog
inductive Stk | inp | out | fst | snd
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:44
@[reducible] def Γ : Stk → Type
| .inp => Verifier.G
| _ => Bool
CSLibExt/Computability/Complexity/EncodingConverters.lean:52
inductive Lab | readFst | readSnd | emitSnd | sep | emitFst
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:57
abbrev St := Option Verifier.G
CSLibExt/Computability/Complexity/EncodingConverters.lean:65
abbrev G := Bool ⊕ Option Bool
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:67
def prog : Lab → TM2.Stmt Γ Lab St
| .readFst =>
.pop .inp (fun _ o => o) <| .branch isFst
(.push .fst bit <| .goto fun _ => .readFst)
(.goto fun _ => .readSnd)
| .readSnd =>
.pop .inp (fun _ o => o) <| .branch isSnd
(.push .snd bit <| .goto fun _ => .readSnd)
(.goto fun _ => .emitSnd)
| .emitSnd =>
.pop .snd (fun _ o => o.map Sum.inl) <| .branch isFst
(.push .out (fun _ => false) <| .push .out bit <| .push .out (fun _ => true) <|
⋯
CSLibExt/Computability/Complexity/EncodingConverters.lean:84
Uses 6 · Used by 1
DefinitionStack contents of the converter to the canonical pair encoding#✓fully proved
Given a list \(i\) of input symbols and bit lists \(o\), \(a\) and \(b\), this is the contents of the four stacks of the converter with \(i\) on the input stack, \(o\) on the output stack, \(a\) on the first stash and \(b\) on the second stash.
def stk (i : List Verifier.G) (o a b : List Bool) : ∀ k, List (Γ k)
| .inp => i
| .out => o
| .fst => a
| .snd => b
abbrev G := Bool ⊕ Option Bool
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:67
@[reducible] def Γ : Stk → Type
| .inp => Verifier.G
| _ => Bool
CSLibExt/Computability/Complexity/EncodingConverters.lean:52
AbbreviationRuns of the converter to the canonical pair encoding#✓fully proved
For a natural number \(n\) and configurations \(c\) and \(d\) of the converter, this is the proposition that \(n\) steps of its program lead from \(c\) to \(d\): applying the step function \(n\) times to \(c\) is defined at every step (no configuration before the last one is halted) and gives \(d\).
abbrev Run (n : ℕ) (c d : TM2.Cfg Γ Lab St) : Prop := TM2Program.Run prog n c d
@[reducible] def Γ : Stk → Type
| .inp => Verifier.G
| _ => Bool
CSLibExt/Computability/Complexity/EncodingConverters.lean:52
inductive Lab | readFst | readSnd | emitSnd | sep | emitFst
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:57
abbrev St := Option Verifier.G
CSLibExt/Computability/Complexity/EncodingConverters.lean:65
def Run (n : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
(flip bind (TM2.step M))^[n] (some c) = some d
MathlibExt/Computability/TuringMachine/Program.lean:84
def prog : Lab → TM2.Stmt Γ Lab St
| .readFst =>
.pop .inp (fun _ o => o) <| .branch isFst
(.push .fst bit <| .goto fun _ => .readFst)
(.goto fun _ => .readSnd)
| .readSnd =>
.pop .inp (fun _ o => o) <| .branch isSnd
(.push .snd bit <| .goto fun _ => .readSnd)
(.goto fun _ => .emitSnd)
| .emitSnd =>
.pop .snd (fun _ o => o.map Sum.inl) <| .branch isFst
(.push .out (fun _ => false) <| .push .out bit <| .push .out (fun _ => true) <|
⋯
CSLibExt/Computability/Complexity/EncodingConverters.lean:84
Uses 6 · Used by 1
TheoremRun of the pair-to-canonical converter#✓fully proved
Let \(x\) and \(w\) be bit lists, write \(x \# w\) for the verifier input of the pair \((x, w)\), and read \(1\) for true and \(0\) for false. Let \(\mathrm{encFst}(x)\) replace each bit \(b\) of \(x\) by \(1, 1, 1, b, 1, 0\) and \(\mathrm{encSnd}(w)\) replace each bit \(b\) of \(w\) by \(1, b, 0\). The program of the pair-to-canonical converter goes in exactly \(2|x| + 2|w| + 5\) steps from the configuration at label \(\mathrm{readFst}\) with empty state, \(x \# w\) on the input stack and the output stack and both stashes empty, to the halted configuration with empty state, empty input stack and stashes, and output stack reading \(\mathrm{encFst}(x)\), then \(0\), then \(\mathrm{encSnd}(w)\) from the top.
theorem convert_run (x w : List Bool) :
Run (2 * x.length + 2 * w.length + 5)
⟨some .readFst, none, stk (Verifier.pairEncode (x, w)) [] [] []⟩
⟨none, none, stk [] (encFst x ++ false :: encSnd w) [] []⟩
abbrev Run (n : ℕ) (c d : TM2.Cfg Γ Lab St) : Prop := TM2Program.Run prog n c d
CSLibExt/Computability/Complexity/EncodingConverters.lean:140
def stk (i : List Verifier.G) (o a b : List Bool) : ∀ k, List (Γ k)
| .inp => i
| .out => o
| .fst => a
| .snd => b
CSLibExt/Computability/Complexity/EncodingConverters.lean:120
def pairEncode (p : List Bool × List Bool) : List G :=
p.1.map Sum.inl ++ Sum.inr none :: p.2.map fun b => Sum.inr (some b)
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:71
def encFst (x : List Bool) : List Bool := x.flatMap fun b => [true, true, true, b, true, false]
CSLibExt/Computability/Complexity/PairEncodingConverter.lean:45
def encSnd (w : List Bool) : List Bool := w.flatMap fun b => [true, b, false]
CSLibExt/Computability/Complexity/PairEncodingConverter.lean:48
Uses 16 · Used by 1
DefinitionCanonical bit-list decoder#✓fully proved
This is a multi-stack Turing machine over the alphabet \(\mathrm{Bool}\), with time bound \(n + 2\), such that for every bit list \(x\), started on the canonical bitstring encoding of \(x\), it halts within \(n + 2\) steps, where \(n\) is the length of that encoding, with \(x\) on its output stack and all other stacks empty. So the identity on bit lists is computable in polynomial time from the canonical encoding to the raw bits.
Cslib.Complexity.DenseSAT.ToCanonical.computable · 19 lines
noncomputable def computable :
TM2ComputableInPolyTime Verifier.pairEncode
(BitstringEncoding.toEncoding (α := List Bool × List Bool)).encode id where
tm := tm
inputAlphabet := Equiv.refl Verifier.G
outputAlphabet := Equiv.refl Bool
time := Polynomial.C 2 * Polynomial.X + Polynomial.C 3
outputsFun := fun p => by
obtain ⟨x, w⟩ := p
unfold TM2OutputsInTime
refine { steps := 2 * x.length + 2 * w.length + 5, evals_in_steps := ?_, steps_le_m := ?_ }
· change (flip bind (TM2.step prog))^[_] (some (initList tm _)) =
Option.map (haltList tm) (some _)
erw [List.map_id, List.map_id, id, bitEncode_pair_eq, initList_tm, Option.map_some,
haltList_tm]
exact convert_run x w
· simp only [Verifier.pairEncode, List.length_append, List.length_cons, List.length_map,
Polynomial.eval_add, Polynomial.eval_mul, Polynomial.eval_X, Polynomial.eval_C]
omega
def pairEncode (p : List Bool × List Bool) : List G :=
p.1.map Sum.inl ++ Sum.inr none :: p.2.map fun b => Sum.inr (some b)
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:71
class BitstringEncoding α extends Computability.Encoding α Bool
MathlibExt/Computability/Complexity.lean:48
def tm : FinTM2 where
K := Stk
k₀ := .inp
k₁ := .out
Γ := Γ
Λ := Lab
main := .readFst
σ := St
initialState := none
Γk₀Fin := (inferInstance : Fintype Verifier.G)
m := prog
CSLibExt/Computability/Complexity/EncodingConverters.lean:107
abbrev G := Bool ⊕ Option Bool
CSLibExt/Computability/Complexity/DenseSATVerifier.lean:67
Uses 21 · Used by 3
Bit lists: canonical encoding to raw bits and back
InductiveStacks of the bit-list converters#✓fully proved
The two bit-list converters use three stacks: the input stack, the output stack and one stash.
inductive BStk | inp | out | stash
deriving DecidableEq
Used by 9
InductiveLabels of the bit-list converters#✓fully proved
The two bit-list converters have two program labels, \(\mathrm{read}\) and \(\mathrm{emit}\).
inductive BLab | read | emit
deriving DecidableEq
Used by 8
DefinitionStack contents of the bit-list converters#✓fully proved
For bit lists \(i\), \(o\) and \(a\), this assigns contents to the three stacks of the bit-list converters: \(i\) to the input stack, \(o\) to the output stack and \(a\) to the stash. Every stack alphabet is \(\mathrm{Bool}\).
def bstk (i o a : List Bool) : BStk → List Bool
| .inp => i
| .out => o
| .stash => a
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
Uses 1 · Used by 2
DefinitionProgram of the bit-list decoder#✓fully proved
The program of the machine that decodes the canonical encoding of a bit list acts on the three stacks of the bit-list converters, all over bits, with an optional bit as internal state. At label \(\mathrm{read}\) it pops a symbol from the input stack into the state (which becomes empty if the input is empty). If that symbol is true, it pops a second symbol \(b\) into the state, pops and discards a third, pushes \(b\) onto the stash (false if the input ran out before \(b\)) and returns to \(\mathrm{read}\); otherwise it goes to \(\mathrm{emit}\). At label \(\mathrm{emit}\) it pops a bit from the stash, pushes it onto the output and returns to \(\mathrm{emit}\), and it halts when the stash is empty.
def prog : BLab → TM2.Stmt (fun _ : BStk => Bool) BLab (Option Bool)
| .read =>
.pop .inp (fun _ o => o) <| .branch (fun s => s == some true)
(.pop .inp (fun _ o => o) <| .pop .inp (fun s _ => s) <|
.push .stash (fun s => s.getD false) <| .goto fun _ => .read)
(.goto fun _ => .emit)
| .emit =>
.pop .stash (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .out (fun s => s.getD false) <| .goto fun _ => .emit)
.halt
inductive BLab | read | emit
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:275
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
DefinitionMachine decoding the canonical encoding of a bit list#✓fully proved
The multi-stack Turing machine with the three stacks of the bit-list converters (input, output and a stash), all over bits, reading its input from the input stack and leaving its output on the output stack, with the two labels \(\mathrm{read}\) and \(\mathrm{emit}\) and start label \(\mathrm{read}\), an optional bit as internal state, initially empty, and the program of the bit-list decoder. It repeatedly pops an input symbol; while that symbol is true, it pops two more and pushes the first of them onto the stash (false if the input ran out before it). Then it moves the stash, bit by bit, onto the output, and halts.
def tm : FinTM2 where
K := BStk
k₀ := .inp
k₁ := .out
Γ := fun _ => Bool
Λ := BLab
main := .read
σ := Option Bool
initialState := none
Γk₀Fin := (inferInstance : Fintype Bool)
m := prog
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
inductive BLab | read | emit
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:275
def prog : BLab → TM2.Stmt (fun _ : BStk => Bool) BLab (Option Bool)
| .read =>
.pop .inp (fun _ o => o) <| .branch (fun s => s == some true)
(.pop .inp (fun _ o => o) <| .pop .inp (fun s _ => s) <|
.push .stash (fun s => s.getD false) <| .goto fun _ => .read)
(.goto fun _ => .emit)
| .emit =>
.pop .stash (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .out (fun s => s.getD false) <| .goto fun _ => .emit)
.halt
CSLibExt/Computability/Complexity/EncodingConverters.lean:301
Uses 3 · Used by 1
AbbreviationRuns of the bit-list decoder#✓fully proved
For a natural number \(n\) and configurations \(c\) and \(d\) of the machine decoding the canonical encoding of a bit list (each an optional label, an optional bit as internal state and the contents of the three bit stacks), this is the proposition that \(n\) steps of its program lead from \(c\) to \(d\): applying the step function \(n\) times to \(c\) is defined at every step (no configuration before the last one is halted) and gives \(d\).
abbrev Run (n : ℕ) (c d : TM2.Cfg (fun _ : BStk => Bool) BLab (Option Bool)) : Prop :=
TM2Program.Run prog n c d
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
inductive BLab | read | emit
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:275
def Run (n : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
(flip bind (TM2.step M))^[n] (some c) = some d
MathlibExt/Computability/TuringMachine/Program.lean:84
def prog : BLab → TM2.Stmt (fun _ : BStk => Bool) BLab (Option Bool)
| .read =>
.pop .inp (fun _ o => o) <| .branch (fun s => s == some true)
(.pop .inp (fun _ o => o) <| .pop .inp (fun s _ => s) <|
.push .stash (fun s => s.getD false) <| .goto fun _ => .read)
(.goto fun _ => .emit)
| .emit =>
.pop .stash (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .out (fun s => s.getD false) <| .goto fun _ => .emit)
.halt
CSLibExt/Computability/Complexity/EncodingConverters.lean:301
Uses 4 · Used by 1
DefinitionPolynomial-time decoder of the canonical bit-list encoding#✓fully proved
This is a multi-stack Turing machine whose input and output alphabets are the bits, together with the polynomial time bound \(t(n) = n + 2\), such that for every bit list \(x\), whose canonical bitstring encoding has length \(n\), the machine started with that encoding on its input stack and all other stacks empty halts within \(t(n)\) steps with \(x\) on its output stack, all other stacks empty and its internal state back to the initial one. So the identity on bit lists is computable in polynomial time from the canonical encoding to the raw bits.
The canonical encoding writes each bit \(b\) of \(x\) as the three bits true, \(b\), false.
Cslib.Complexity.DenseSAT.DecodeBits.computable · 25 lines
noncomputable def computable :
TM2ComputableInPolyTime (BitstringEncoding.toEncoding (α := List Bool)).encode
(fun l : List Bool => l) id where
tm := tm
inputAlphabet := Equiv.refl Bool
outputAlphabet := Equiv.refl Bool
time := Polynomial.X + Polynomial.C 2
outputsFun := fun x => by
unfold TM2OutputsInTime
refine { steps := 2 * x.length + 2, evals_in_steps := ?_, steps_le_m := ?_ }
· change (flip bind (TM2.step prog))^[_] (some (initList tm _)) =
Option.map (haltList tm) (some _)
have h := (read_run x [] [] none).trans (emit_run (x.reverse ++ []) [] none)
simp only [List.append_nil, List.reverse_reverse, List.length_reverse] at h
have hx : (BitstringEncoding.toEncoding (α := List Bool)).encode x = encSnd x :=
bitEncode_list x
erw [List.map_id, List.map_id, id, hx, initList_tm, Option.map_some, haltList_tm]
exact h.of_eq (by omega)
· change 2 * x.length + 2 ≤ (Polynomial.X + Polynomial.C 2).eval
(BitstringEncoding.bitEncode x).length
rw [bitEncode_list]
simp only [encSnd, List.length_flatMap, List.length_cons, List.length_nil,
Polynomial.eval_add, Polynomial.eval_X, Polynomial.eval_C, List.map_const',
List.sum_replicate, smul_eq_mul]
omega
class BitstringEncoding α extends Computability.Encoding α Bool
MathlibExt/Computability/Complexity.lean:48
def tm : FinTM2 where
K := BStk
k₀ := .inp
k₁ := .out
Γ := fun _ => Bool
Λ := BLab
main := .read
σ := Option Bool
initialState := none
Γk₀Fin := (inferInstance : Fintype Bool)
m := prog
CSLibExt/Computability/Complexity/EncodingConverters.lean:313
Uses 17 · Used by 6
DefinitionProgram of the bit-list encoder#✓fully proved
The program of the machine that writes the canonical encoding of a bit list acts on the three stacks of the bit-list converters, all over bits, with an optional bit as internal state. At label \(\mathrm{read}\) it pops a bit from the input stack, pushes it onto the stash and returns to \(\mathrm{read}\); when the input is empty it goes to \(\mathrm{emit}\). At label \(\mathrm{emit}\) it pops a bit \(b\) from the stash, pushes false, \(b\) and true onto the output, so that the output then reads true, \(b\), false from the top, and returns to \(\mathrm{emit}\); it halts when the stash is empty.
def prog : BLab → TM2.Stmt (fun _ : BStk => Bool) BLab (Option Bool)
| .read =>
.pop .inp (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .stash (fun s => s.getD false) <| .goto fun _ => .read)
(.goto fun _ => .emit)
| .emit =>
.pop .stash (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .out (fun _ => false) <| .push .out (fun s => s.getD false) <|
.push .out (fun _ => true) <| .goto fun _ => .emit)
.halt
inductive BLab | read | emit
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:275
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
DefinitionMachine writing the canonical encoding of a bit list#✓fully proved
The multi-stack Turing machine with the three stacks of the bit-list converters (input, output and a stash), all over bits, reading its input from the input stack and leaving its output on the output stack, with the two labels \(\mathrm{read}\) and \(\mathrm{emit}\) and start label \(\mathrm{read}\), an optional bit as internal state, initially empty, and the program of the bit-list encoder. It moves the input, bit by bit, onto the stash. Then it pops the stash bit by bit, pushing for each bit \(b\) the three bits false, \(b\), true onto the output, so that each block reads true, \(b\), false from the top, and halts.
def tm : FinTM2 where
K := BStk
k₀ := .inp
k₁ := .out
Γ := fun _ => Bool
Λ := BLab
main := .read
σ := Option Bool
initialState := none
Γk₀Fin := (inferInstance : Fintype Bool)
m := prog
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
inductive BLab | read | emit
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:275
def prog : BLab → TM2.Stmt (fun _ : BStk => Bool) BLab (Option Bool)
| .read =>
.pop .inp (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .stash (fun s => s.getD false) <| .goto fun _ => .read)
(.goto fun _ => .emit)
| .emit =>
.pop .stash (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .out (fun _ => false) <| .push .out (fun s => s.getD false) <|
.push .out (fun _ => true) <| .goto fun _ => .emit)
.halt
CSLibExt/Computability/Complexity/EncodingConverters.lean:404
Uses 3 · Used by 1
AbbreviationRuns of the bit-list encoder#✓fully proved
For a natural number \(n\) and configurations \(c\) and \(d\) of the machine writing the canonical encoding of a bit list (each an optional label, an optional bit as internal state and the contents of the three bit stacks), this is the proposition that \(n\) steps of its program lead from \(c\) to \(d\): applying the step function \(n\) times to \(c\) is defined at every step (no configuration before the last one is halted) and gives \(d\).
abbrev Run (n : ℕ) (c d : TM2.Cfg (fun _ : BStk => Bool) BLab (Option Bool)) : Prop :=
TM2Program.Run prog n c d
inductive BStk | inp | out | stash
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:267
inductive BLab | read | emit
deriving DecidableEq
CSLibExt/Computability/Complexity/EncodingConverters.lean:275
def Run (n : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
(flip bind (TM2.step M))^[n] (some c) = some d
MathlibExt/Computability/TuringMachine/Program.lean:84
def prog : BLab → TM2.Stmt (fun _ : BStk => Bool) BLab (Option Bool)
| .read =>
.pop .inp (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .stash (fun s => s.getD false) <| .goto fun _ => .read)
(.goto fun _ => .emit)
| .emit =>
.pop .stash (fun _ o => o) <| .branch (fun s => s.isSome)
(.push .out (fun _ => false) <| .push .out (fun s => s.getD false) <|
.push .out (fun _ => true) <| .goto fun _ => .emit)
.halt
CSLibExt/Computability/Complexity/EncodingConverters.lean:404
Uses 4 · Used by 1
DefinitionPolynomial-time encoder to the canonical bit-list encoding#✓fully proved
This is a multi-stack Turing machine whose input and output alphabets are the bits, together with the polynomial time bound \(t(n) = 2n + 2\), such that for every bit list \(x\) of length \(n\), the machine started with \(x\) on its input stack and all other stacks empty halts within \(t(n)\) steps with the canonical bitstring encoding of \(x\) on its output stack, all other stacks empty and its internal state back to the initial one. So the identity on bit lists is computable in polynomial time from the raw bits to the canonical encoding.
The canonical encoding writes each bit \(b\) of \(x\) as the three bits true, \(b\), false.
Cslib.Complexity.DenseSAT.EncodeBits.computable · 20 lines
noncomputable def computable :
TM2ComputableInPolyTime (fun l : List Bool => l)
(BitstringEncoding.toEncoding (α := List Bool)).encode id where
tm := tm
inputAlphabet := Equiv.refl Bool
outputAlphabet := Equiv.refl Bool
time := Polynomial.C 2 * Polynomial.X + Polynomial.C 2
outputsFun := fun x => by
unfold TM2OutputsInTime
refine { steps := 2 * x.length + 2, evals_in_steps := ?_, steps_le_m := ?_ }
· change (flip bind (TM2.step prog))^[_] (some (initList tm _)) =
Option.map (haltList tm) (some _)
have h := (read_run x [] [] none).trans (emit_run (x.reverse ++ []) [] none)
simp only [List.append_nil, List.reverse_reverse, List.length_reverse] at h
have hx : (BitstringEncoding.toEncoding (α := List Bool)).encode x = encSnd x :=
bitEncode_list x
erw [List.map_id, List.map_id, id, hx, initList_tm, Option.map_some, haltList_tm]
exact h.of_eq (by omega)
· simp only [Polynomial.eval_add, Polynomial.eval_mul, Polynomial.eval_X, Polynomial.eval_C]
omega
class BitstringEncoding α extends Computability.Encoding α Bool
MathlibExt/Computability/Complexity.lean:48
def tm : FinTM2 where
K := BStk
k₀ := .inp
k₁ := .out
Γ := fun _ => Bool
Λ := BLab
main := .read
σ := Option Bool
initialState := none
Γk₀Fin := (inferInstance : Fintype Bool)
m := prog
CSLibExt/Computability/Complexity/EncodingConverters.lean:416
Uses 17 · Used by 5
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.