The summing loop of the SUBSET-SUM verifier to Binary addition of framed numbers in quadratic time
TheoremThe summing loop of the SUBSET-SUM verifier#✓fully proved
Let \(N\) be a natural number and \(t\) a list of symbols. Write \(\langle m \rangle\) for the canonical binary code of a natural number \(m\), least significant bit first, and put a bit list on a stack as the list of its name-bit symbols. Let \(n\) and \(s\) be natural numbers, \(r\) and \(w\) bit lists and \(v\) a Boolean, with \(|r| \le n\) and \(|\langle s \rangle| + |r| \le N\). Start the SUBSET-SUM verifier at the label \(\mathsf{next}\) with internal state \(v\), with \(r\) on \(X\), \(w\) on \(W\), \(t\) on \(T\), \(\langle s \rangle\) on \(A\), and the stacks \(B\), \(P\) and \(Q\) empty. Then for some internal state \(v'\) and stack contents \(S'\) it runs within \(|r| \cdot (2N + 6) + 1\) steps to the configuration with internal state \(v'\), stacks \(S'\) and label \(\mathsf{fmove}\) if parsing the number blocks of \(r\) with fuel \(n\) succeeds, and label \(\mathsf{no}\) if it fails. Moreover, if that parsing gives the list of numbers \(a\), and \(\sigma\) is \(s\) plus the sum of the numbers of \(a\) chosen by the mask \(w\), then \(|\langle \sigma \rangle| \le N\), and for some list of symbols \(w'\) the stacks \(S'\) hold nothing on \(X\), \(w'\) on \(W\), \(t\) on \(T\), \(\langle \sigma \rangle\) on \(A\), and nothing on \(B\), \(P\) and \(Q\).
theorem loop_run (N : ℕ) (t : List Sym) : ∀ (n : ℕ) (r w : List Bool) (s : ℕ) (v : Bool),
r.length ≤ n → (encodeNat s).length + r.length ≤ N →
∃ v' S', RunLe prog (r.length * (2 * N + 6) + 1)
⟨some .next, v, st (r.map .bit) (w.map .bit) t ((encodeNat s).map .bit) []⟩
⟨some (if (numsAux n r).isSome then .fmove else .no), v', S'⟩ ∧
∀ as, numsAux n r = some as → (encodeNat (s + (pick as w).sum)).length ≤ N ∧
∃ w', S' = st [] w' t ((encodeNat (s + (pick as w).sum)).map .bit) []
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
def RunLe (M : Λ → TM2.Stmt Γ Λ σ) (B : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
∃ n, n ≤ B ∧ Run M n c d
MathlibExt/Computability/TuringMachine/Program.lean:901
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .tgt z => rdS z (.goto fun _ => .next) fun b =>
.push .T (fun _ => .bit b) <| .goto fun _ => .tgt (!b)
| .next => nextS
| .add c z => rdS z (.goto fun _ => .fin c) (addS c)
| .skip z => rdS z (.goto fun _ => .next) fun b => .goto fun _ => .skip (!b)
| .fin c => finS c
| .back => moveB .B .A Sym.bit? Sym.bit .back .next
| .fmove => moveB .A .B Sym.bit? Sym.bit .fmove .cmp
| .cmp => cmpB .B .T .P .Q Sym.bit? Sym.bit? Sym.bit Sym.bit .cmp .yes .no
| .yes => .halt
| .no => .halt
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:357
def st (x w t a b : List Sym) : K → List Sym
| .X => x
| .W => w
| .T => t
| .A => a
| .B => b
| .P => []
| .Q => []
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:376
def numsAux : ℕ → List Bool → Option (List ℕ)
| _, [] => some []
| 0, _ :: _ => none
| n + 1, b :: l => match decodeNatPrefix (b :: l) with
| some (a, r) => (numsAux n r).map (a :: ·)
| none => none
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:79
def pick : List ℕ → List Bool → List ℕ
| [], _ => []
| a :: as, w => if w.headD false then a :: pick as w.tail else pick as w.tail
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:178
Uses 30 · Used by 2
TheoremCubic bound on the verifier's phase costs#✓fully proved
For natural numbers \(X\), \(W\), \(P\), \(R\) and \(S\) with \(P + R \le X\) and \(S \le X\), \(P + 1 + (R(2X + 6) + 1) + (S + 1) + (S + 1) \le 16 (X + W + 1)^3\).
theorem cost_le (X W P R S : ℕ) (hP : P + R ≤ X) (hS : S ≤ X) :
P + 1 + (R * (2 * X + 6) + 1) + (S + 1) + (S + 1) ≤ 16 * (X + W + 1) ^ 3
Used by 1
TheoremThe SUBSET-SUM verifier machine#✓fully proved
Let \(x\) and \(w\) be lists of bits and \(v\) a Boolean, and let \(S\) assign stack contents with the bits of \(x\) on \(X\), the bits of \(w\) on \(W\) and every other stack empty. Started at the start label with internal state \(v\) and stacks \(S\), the verifier program reaches, within \(16(|x| + |w| + 1)^3\) steps, a configuration with label \(\mathsf{yes}\) if the SUBSET-SUM check accepts \((x, w)\), and with label \(\mathsf{no}\) otherwise.
theorem run (x w : List Bool) (v : Bool) (St : ∀ _ : K, List Sym)
(hX : St .X = x.map Sym.bit) (hW : St .W = w.map Sym.bit)
(h0 : ∀ k, k ≠ .X → k ≠ .W → St k = []) :
∃ v' S', RunLe prog (16 * (x.length + w.length + 1) ^ 3) ⟨some start, v, St⟩
⟨some (if ssCheck x w then .yes else .no), v', S'⟩
inductive K | X | W | T | A | B | P | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:299
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
def RunLe (M : Λ → TM2.Stmt Γ Λ σ) (B : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
∃ n, n ≤ B ∧ Run M n c d
MathlibExt/Computability/TuringMachine/Program.lean:901
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .tgt z => rdS z (.goto fun _ => .next) fun b =>
.push .T (fun _ => .bit b) <| .goto fun _ => .tgt (!b)
| .next => nextS
| .add c z => rdS z (.goto fun _ => .fin c) (addS c)
| .skip z => rdS z (.goto fun _ => .next) fun b => .goto fun _ => .skip (!b)
| .fin c => finS c
| .back => moveB .B .A Sym.bit? Sym.bit .back .next
| .fmove => moveB .A .B Sym.bit? Sym.bit .fmove .cmp
| .cmp => cmpB .B .T .P .Q Sym.bit? Sym.bit? Sym.bit Sym.bit .cmp .yes .no
| .yes => .halt
| .no => .halt
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:357
def start : Lab := .tgt false
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:371
def ssCheck (x w : List Bool) : Bool :=
match decodeSS x with
| some (as, t) => (pick as w).sum == t
| none => false
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:183
Uses 27 · Used by 1
AbbreviationThe SUBSET-SUM verifier machine as a host component#✓fully proved
The multi-stack Turing machine that checks SUBSET-SUM certificates, packaged as a host component: it has seven stacks, each holding symbols of the SAT verifier alphabet, its labels and its program are those of the machine, and the list of its stacks names each of the seven stacks exactly once.
abbrev ssVerifyComp : Host.Comp where
K := SSVerify.K
Γ := fun _ => SatVerifier.Sym
finΓ := fun _ => SatVerifier.Sym.instFintype
L := SSVerify.Lab
prog := SSVerify.prog
ks := [.X, .W, .T, .A, .B, .P, .Q]
ks_nodup := by decide
mem_ks k := by cases k <;> decide
structure Comp where
/-- Stack indices. -/
K : Type
/-- Decidable equality of stack indices. -/
[decK : DecidableEq K]
/-- Finitely many stacks. -/
[finK : Fintype K]
/-- Stack alphabets. -/
Γ : K → Type
/-- Finite alphabets. -/
[finΓ : ∀ k, Fintype (Γ k)]
/-- Labels. -/
⋯
CSLibExt/Computability/Complexity/Host.lean:53
inductive K | X | W | T | A | B | P | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:299
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
instance Sym.instFintype : Fintype Sym where
elems := ⟨↑[Sym.bit false, .bit true, .lit false, .lit true, .cl, .val false, .val true, .dead],
by decide⟩
complete := fun x => by rcases x with b | b | _ | b | _ <;> (try cases b) <;> decide
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:155
inductive Lab
| tgt (z : Bool) | next | add (c z : Bool) | skip (z : Bool) | fin (c : Bool) | back | fmove
| cmp | yes | no
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:310
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .tgt z => rdS z (.goto fun _ => .next) fun b =>
.push .T (fun _ => .bit b) <| .goto fun _ => .tgt (!b)
| .next => nextS
| .add c z => rdS z (.goto fun _ => .fin c) (addS c)
| .skip z => rdS z (.goto fun _ => .next) fun b => .goto fun _ => .skip (!b)
| .fin c => finS c
| .back => moveB .B .A Sym.bit? Sym.bit .back .next
| .fmove => moveB .A .B Sym.bit? Sym.bit .fmove .cmp
| .cmp => cmpB .B .T .P .Q Sym.bit? Sym.bit? Sym.bit Sym.bit .cmp .yes .no
| .yes => .halt
| .no => .halt
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:357
Uses 5 · Used by 1
TheoremSUBSET-SUM is in NP#✓fully proved
SUBSET-SUM is the decision problem on bit strings that accepts \(x\) exactly when \(x\) encodes a target \(t\) followed by natural numbers \(a_1, \dots, a_n\) (each written in binary and delimited) such that some, possibly empty, sublist of \(a_1, \dots, a_n\) sums to \(t\). This decision problem belongs to NP: there are a polynomial \(p\) with natural-number coefficients and a polynomial-time computable verifier \(R\) such that SUBSET-SUM accepts \(x\) exactly when \(R(x, w)\) holds for some bit string \(w\) with \(|w| \le p(|x|)\).
theorem subsetSumDec_mem_NP : subsetSumDec ∈ NP
noncomputable def subsetSumDec : MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
decide (∃ as t, encodeSS as t = x ∧ ∃ l : List ℕ, l.Sublist as ∧ l.sum = t)
CSLibExt/Computability/Complexity/Karp/SubsetSum.lean:48
def NP : DecisionComplexityClass :=
{ L | ∃ (p : Polynomial ℕ), ∃ R : (List Bool × List Bool) → Bool,
IsPolyTime R ∧
∀ x, L x ↔ ∃ w : List Bool, w.length ≤ p.eval x.length ∧ R (x, w) }
MathlibExt/Computability/Complexity.lean:200
Uses 26 · Used by 2
AbbreviationThe VERTEX-COVER to SUBSET-SUM machine as a host component#✓fully proved
The multi-stack Turing machine that computes the VERTEX-COVER to SUBSET-SUM reduction on bit strings, packaged as a host component: its fifteen stacks (the output stack holds booleans, every other stack holds symbols of the SAT verifier alphabet), its labels and its program are those of the machine, and the list of its stacks names each of the fifteen stacks exactly once.
abbrev emitSSComp : Host.Comp where
K := EmitSS.K
Γ := EmitSS.Γ
L := EmitSS.Lab
prog := EmitSS.prog
ks := [.X, .O, .A, .H, .N, .M, .C, .S1, .S2, .Y, .Z, .T, .L, .R, .Rt]
ks_nodup := by decide
mem_ks k := by cases k <;> decide
structure Comp where
/-- Stack indices. -/
K : Type
/-- Decidable equality of stack indices. -/
[decK : DecidableEq K]
/-- Finitely many stacks. -/
[finK : Fintype K]
/-- Stack alphabets. -/
Γ : K → Type
/-- Finite alphabets. -/
[finΓ : ∀ k, Fintype (Γ k)]
/-- Labels. -/
⋯
CSLibExt/Computability/Complexity/Host.lean:53
inductive K | X | O | A | H | N | M | C | S1 | S2 | Y | Z | T | L | R | Rt
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumEmit.lean:55
@[reducible] def Γ : K → Type
| .O => Bool
| _ => Sym
CSLibExt/Computability/Complexity/Karp/SubsetSumEmit.lean:64
inductive Lab
| rdK | rdN | mv | tri | triC | triC2 | cmp | rc (o : Ordering) | rcB (o : Ordering)
| eg | egX | egR | egR2 | egY | vinit | vtx | pr | rend | rmv | vend | vchk | rs
| hv | hv0 | hv1 | hvB | tem0 | tsk | tem | bad | done
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumEmit.lean:71
def prog : Lab → TM2.Stmt Γ Lab Bool
| .rdK => .peek .X (fun _ o => o.isNone) <| .branch id (.goto fun _ => .bad) <|
.pop .X (fun _ o => isT o) <| .branch id
(.push .A (fun _ => U) (.goto fun _ => .rdK)) (.goto fun _ => .rdN)
| .rdN => .peek .X (fun _ o => o.isNone) <| .branch id (.goto fun _ => .bad) <|
.pop .X (fun _ o => isT o) <| .branch id
(.push .N (fun _ => U) <| .push .L (fun _ => .val false) <| .goto fun _ => .rdN)
(.goto fun _ => .mv)
| .mv => .peek .X (fun _ o => o.isNone) <| .branch id (.goto fun _ => .tri) <|
.pop .X (fun _ o => isT o) <| .push .Y (fun s => .val s) <|
.push .T (fun _ => .bit false) <| .push .T (fun s => .bit s) <|
.push .C (fun _ => U) <| .goto fun _ => .mv
⋯
CSLibExt/Computability/Complexity/Karp/SubsetSumEmit.lean:110
Uses 6 · Used by 1
TheoremThe VERTEX-COVER to SUBSET-SUM reduction is polynomial-time#✓fully proved
The reduction map on bit strings, which sends the encoding of a VERTEX-COVER instance \((k, G)\) to the encoding of the SUBSET-SUM instance built from it (one base-4 number for each vertex and for each pair of vertices of \(G\), and a target) and every other bit string to the instance with no numbers and target \(1\), is computable in polynomial time.
theorem isPolyTime_reduceSS : IsPolyTime reduceSS
def IsPolyTime {α β : Type} [BitstringEncoding α] [BitstringEncoding β]
(f : α → β) : Prop :=
IsPolyTimeWithEncoding (BitstringEncoding.toEncoding (α := α))
(BitstringEncoding.toEncoding (α := β)) f
MathlibExt/Computability/Complexity.lean:186
def reduceSS (x : List Bool) : List Bool :=
match decodeKG x with
| some (k, n, bits) =>
if bits.length = (pairs n).length then encodeSS (ssNums n bits) (ssTarget k n bits)
else noSS
| none => noSS
CSLibExt/Computability/Complexity/Karp/SubsetSum.lean:80
Uses 22 · Used by 1
TheoremSUBSET-SUM is NP-hard#✓fully proved
Let SUBSET-SUM be the decision problem on bit strings that accepts exactly the strings encoding a target \(t\) followed by natural numbers \(a_1, \dots, a_n\) (each written in binary and delimited) such that some, possibly empty, sublist of \(a_1, \dots, a_n\) sums to \(t\). Every decision problem \(L\) in NP reduces to SUBSET-SUM by a polynomial-time many-one reduction: there is a polynomial-time computable map \(f\) on bit strings such that, for every bit string \(x\), \(L\) accepts \(x\) exactly when SUBSET-SUM accepts \(f(x)\).
theorem subsetSumDec_npHard : ∀ L : DecisionProblem, L ∈ NP → PolyManyOneRed L subsetSumDec
abbrev DecisionProblem := List Bool → Bool
MathlibExt/Computability/Complexity.lean:170
def NP : DecisionComplexityClass :=
{ L | ∃ (p : Polynomial ℕ), ∃ R : (List Bool × List Bool) → Bool,
IsPolyTime R ∧
∀ x, L x ↔ ∃ w : List Bool, w.length ≤ p.eval x.length ∧ R (x, w) }
MathlibExt/Computability/Complexity.lean:200
def PolyManyOneRed (L₁ L₂ : MetaMathlibExt.ComplexityTheory.DecisionProblem) : Prop :=
∃ reduce : List Bool → List Bool,
MetaMathlibExt.ComplexityTheory.IsPolyTime reduce ∧ ∀ x, L₁ x = L₂ (reduce x)
CSLibExt/Computability/CookLevin.lean:396
noncomputable def subsetSumDec : MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
decide (∃ as t, encodeSS as t = x ∧ ∃ l : List ℕ, l.Sublist as ∧ l.sum = t)
CSLibExt/Computability/Complexity/Karp/SubsetSum.lean:48
Uses 32 · Used by 2
k) is NP-hard · Reading a unary length prefix · Bitstring encodings · Decoding function of a bitstring encoding · Decoding inverts bitstring encoding · Encoding function of a bitstring encoding · Self-delimiting form of a bitstring · Parsing one self-delimiting block · Parsing a list of booleans into self-delimiting blocks · Bounded parsing of self-delimiting blocks · Polynomial-time computable functionsTheoremSUBSET-SUM is NP-complete#✓fully proved
Let SUBSET-SUM be the decision problem on bit strings that accepts exactly the strings encoding a target \(t\) followed by natural numbers \(a_1, \dots, a_n\) (each written in binary and delimited) such that some, possibly empty, sublist of \(a_1, \dots, a_n\) sums to \(t\). Then SUBSET-SUM belongs to NP, and every decision problem \(L\) in NP reduces to SUBSET-SUM by a polynomial-time many-one reduction: there is a polynomial-time computable map \(f\) on bit strings such that, for every bit string \(x\), \(L\) accepts \(x\) exactly when SUBSET-SUM accepts \(f(x)\).
theorem subsetSumDec_npComplete :
subsetSumDec ∈ NP ∧ ∀ L : DecisionProblem, L ∈ NP → PolyManyOneRed L subsetSumDec
noncomputable def subsetSumDec : MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
decide (∃ as t, encodeSS as t = x ∧ ∃ l : List ℕ, l.Sublist as ∧ l.sum = t)
CSLibExt/Computability/Complexity/Karp/SubsetSum.lean:48
def NP : DecisionComplexityClass :=
{ L | ∃ (p : Polynomial ℕ), ∃ R : (List Bool × List Bool) → Bool,
IsPolyTime R ∧
∀ x, L x ↔ ∃ w : List Bool, w.length ≤ p.eval x.length ∧ R (x, w) }
MathlibExt/Computability/Complexity.lean:200
abbrev DecisionProblem := List Bool → Bool
MathlibExt/Computability/Complexity.lean:170
def PolyManyOneRed (L₁ L₂ : MetaMathlibExt.ComplexityTheory.DecisionProblem) : Prop :=
∃ reduce : List Bool → List Bool,
MetaMathlibExt.ComplexityTheory.IsPolyTime reduce ∧ ∀ x, L₁ x = L₂ (reduce x)
CSLibExt/Computability/CookLevin.lean:396
Uses 7
TheoremSUBSET-SUM verifier computes the mask-selected sum#✓fully proved
On canonical delimited encodeNat blocks, the existing component
leaves the selected sum at a halt label. Normalize raw payloads first:
malformed blocks can instead reject early, leaving only a partial sum.
The cost uses framed bit length, never numeric magnitudes. The mask is
consumed; copy it before reuse in another component.
theorem sum_component_run (as : List ℕ) (w : List Bool) (v : Bool) :
let r := as.flatMap fun a =>
BitstringEncoding.delimit (Computability.encodeNat a)
let bits := Computability.encodeNat (SSVerify.pick as w).sum
∃ v' w', RunLe SSVerify.prog
(r.length * (2 * r.length + 6) + r.length + 3)
⟨some .next, v, SSVerify.st (r.map .bit) (w.map .bit) [] [] []⟩
⟨some (if bits = [] then .yes else .no), v',
SSVerify.st [] w' [] [] (bits.map .bit).reverse⟩
def delimit : List Bool → List Bool
| [] => [false]
| b :: l => true :: b :: delimit l
MathlibExt/Computability/Complexity.lean:68
def pick : List ℕ → List Bool → List ℕ
| [], _ => []
| a :: as, w => if w.headD false then a :: pick as w.tail else pick as w.tail
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:178
def RunLe (M : Λ → TM2.Stmt Γ Λ σ) (B : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
∃ n, n ≤ B ∧ Run M n c d
MathlibExt/Computability/TuringMachine/Program.lean:901
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .tgt z => rdS z (.goto fun _ => .next) fun b =>
.push .T (fun _ => .bit b) <| .goto fun _ => .tgt (!b)
| .next => nextS
| .add c z => rdS z (.goto fun _ => .fin c) (addS c)
| .skip z => rdS z (.goto fun _ => .next) fun b => .goto fun _ => .skip (!b)
| .fin c => finS c
| .back => moveB .B .A Sym.bit? Sym.bit .back .next
| .fmove => moveB .A .B Sym.bit? Sym.bit .fmove .cmp
| .cmp => cmpB .B .T .P .Q Sym.bit? Sym.bit? Sym.bit Sym.bit .cmp .yes .no
| .yes => .halt
| .no => .halt
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:357
def st (x w t a b : List Sym) : K → List Sym
| .X => x
| .W => w
| .T => t
| .A => a
| .B => b
| .P => []
| .Q => []
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:376
Uses 22 · Used by 2
TheoremA long enough all-true mask selects the whole list#✓fully proved
A mask long enough to select every item gives the original list.
theorem pick_all (as : List ℕ) (n : ℕ) (h : as.length ≤ n) :
SSVerify.pick as (List.replicate n true) = as
def pick : List ℕ → List Bool → List ℕ
| [], _ => []
| a :: as, w => if w.headD false then a :: pick as w.tail else pick as w.tail
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:178
Uses 1 · Used by 2
TheoremEmbedded SUBSET-SUM summing component reaches the mapped label#✓fully proved
Reach the common mapped label after summing canonical encodeNat
blocks; unembedded stacks remain intact. The input agreement requires
prior normalization. A raw parse-failure exit can expose a partial sum.
This is only a reachability guarantee: hφ does not make the endpoint
fresh, distinct from mapped live labels, or a halt of the host. Callers
must establish their intended label separation and the code run next.
The embedded mask is consumed; each later sum needs its own saved copy.
Cslib.Complexity.SSVerifierSum.sum_embed · 15 lines
theorem sum_embed {K Λ : Type} [DecidableEq K] {Γ : K → Type}
(E : SEmb (fun _ : SSVerify.K => Sym) Γ)
(φ : SSVerify.Lab → Λ) (M : Λ → TM2.Stmt Γ Λ Bool)
(hM : Embeds E φ SSVerify.prog M) (hφ : φ .yes = φ .no)
(as : List ℕ) (w : List Bool) (v : Bool) (S : ∀ k, List (Γ k))
(hS : Agree E (SSVerify.st
((as.flatMap fun a => BitstringEncoding.delimit
(Computability.encodeNat a)).map .bit) (w.map .bit) [] [] []) S) :
let n := (as.flatMap fun a => BitstringEncoding.delimit
(Computability.encodeNat a)).length
∃ v' w' S', RunLe M (n * (2 * n + 6) + n + 3)
⟨some (φ .next), v, S⟩ ⟨some (φ .yes), v', S'⟩ ∧
Agree E (SSVerify.st [] w' [] []
((Computability.encodeNat (SSVerify.pick as w).sum).map
.bit).reverse) S' ∧ Frame E S S'
structure SEmb {K K' : Type} (Γ : K → Type) (Γ' : K' → Type) where
/-- The stack renaming. -/
e : K → K'
/-- Distinct sub-machine stacks go to distinct host stacks. -/
inj : Injective e
/-- The alphabet of each sub-machine stack, identified with its host stack's. -/
ι : ∀ k, Γ k ≃ Γ' (e k)
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:51
inductive K | X | W | T | A | B | P | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:299
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
inductive Lab
| tgt (z : Bool) | next | add (c z : Bool) | skip (z : Bool) | fin (c : Bool) | back | fmove
| cmp | yes | no
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:310
def Embeds (M : Λ → TM2.Stmt Γ Λ σ) (M' : Λ' → TM2.Stmt Γ' Λ' σ) : Prop :=
∀ l, M' (φ l) = mapS E φ (M l) ∨ M l = .halt
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:76
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .tgt z => rdS z (.goto fun _ => .next) fun b =>
.push .T (fun _ => .bit b) <| .goto fun _ => .tgt (!b)
| .next => nextS
| .add c z => rdS z (.goto fun _ => .fin c) (addS c)
| .skip z => rdS z (.goto fun _ => .next) fun b => .goto fun _ => .skip (!b)
| .fin c => finS c
| .back => moveB .B .A Sym.bit? Sym.bit .back .next
| .fmove => moveB .A .B Sym.bit? Sym.bit .fmove .cmp
| .cmp => cmpB .B .T .P .Q Sym.bit? Sym.bit? Sym.bit Sym.bit .cmp .yes .no
| .yes => .halt
| .no => .halt
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:357
def Agree (S : ∀ k, List (Γ k)) (S' : ∀ k', List (Γ' k')) : Prop :=
∀ k, S' (E.e k) = (S k).map (E.ι k)
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:80
def st (x w t a b : List Sym) : K → List Sym
| .X => x
| .W => w
| .T => t
| .A => a
| .B => b
| .P => []
| .Q => []
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:376
def delimit : List Bool → List Bool
| [] => [false]
| b :: l => true :: b :: delimit l
MathlibExt/Computability/Complexity.lean:68
def RunLe (M : Λ → TM2.Stmt Γ Λ σ) (B : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
∃ n, n ≤ B ∧ Run M n c d
MathlibExt/Computability/TuringMachine/Program.lean:901
def pick : List ℕ → List Bool → List ℕ
| [], _ => []
| a :: as, w => if w.headD false then a :: pick as w.tail else pick as w.tail
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:178
def Frame (S' S'' : ∀ k', List (Γ' k')) : Prop :=
∀ k', (∀ k, E.e k ≠ k') → S'' k' = S' k'
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:84
Uses 14 · Used by 2
DefinitionFramed input of two natural numbers#✓fully proved
Two canonical Nat blocks in the existing list framing.
def pairInput (m n : ℕ) : List Bool :=
delimit (encodeNat m) ++ delimit (encodeNat n)
def delimit : List Bool → List Bool
| [] => [false]
| b :: l => true :: b :: delimit l
MathlibExt/Computability/Complexity.lean:68
Uses 1 · Used by 3
AbbreviationLabels of the binary addition machine#✓fully proved
Original verifier labels plus initialization, clear, reverse, and halt.
abbrev Lab := SSVerify.Lab ⊕ Fin 4
inductive Lab
| tgt (z : Bool) | next | add (c z : Bool) | skip (z : Bool) | fin (c : Bool) | back | fmove
| cmp | yes | no
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:310
Uses 1 · Used by 5
DefinitionIdentity embedding of the verifier stacks#✓fully proved
Reuse all original verifier stacks without re-encoding symbols.
def identity : SEmb (fun _ : SSVerify.K => Sym)
(fun _ : SSVerify.K => Sym) where
e := id
inj := injective_id
ι _ := Equiv.refl _
structure SEmb {K K' : Type} (Γ : K → Type) (Γ' : K' → Type) where
/-- The stack renaming. -/
e : K → K'
/-- Distinct sub-machine stacks go to distinct host stacks. -/
inj : Injective e
/-- The alphabet of each sub-machine stack, identified with its host stack's. -/
ι : ∀ k, Γ k ≃ Γ' (e k)
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:51
inductive K | X | W | T | A | B | P | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:299
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
ι : ∀ k, Γ k ≃ Γ' (e k)
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:57
Uses 3 · Used by 2
DefinitionRedirection of the verifier's halt labels#✓fully proved
Redirect the two halt labels, leaving every live label distinct.
def redirect : SSVerify.Lab → Lab
| .yes | .no => .inr 1
| l => .inl l
inductive Lab
| tgt (z : Bool) | next | add (c z : Bool) | skip (z : Bool) | fin (c : Bool) | back | fmove
| cmp | yes | no
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:310
abbrev Lab := SSVerify.Lab ⊕ Fin 4
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:65
TheoremOnly halt labels are redirected to the cleanup label#✓fully proved
The cleanup continuation cannot alias any live verifier label.
@[simp] theorem redirect_eq_clear_iff (l : SSVerify.Lab) :
redirect l = .inr 1 ↔ l = .yes ∨ l = .no
inductive Lab
| tgt (z : Bool) | next | add (c z : Bool) | skip (z : Bool) | fin (c : Bool) | back | fmove
| cmp | yes | no
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:310
def redirect : SSVerify.Lab → Lab
| .yes | .no => .inr 1
| l => .inl l
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:75
DefinitionBinary addition program built on the SUBSET-SUM machine#✓fully proved
Run the existing sum machine, then clear the mask and restore LSB order. Only the original halt labels are redirected to a continuation.
def prog : Lab → TM2.Stmt (fun _ : SSVerify.K => Sym) Lab Bool
| .inl l => mapS identity redirect (SSVerify.prog l)
| .inr i =>
if i = 0 then
.push .W (fun _ => .bit true) <|
.push .W (fun _ => .bit true) <| .goto fun _ => .inl .next
else if i = 1 then
cleanS [.W] (.inr 1) (.inr 2)
else if i = 2 then
moveB .B .A Sym.bit? Sym.bit (.inr 2) (.inr 3)
else .halt
abbrev Lab := SSVerify.Lab ⊕ Fin 4
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:65
inductive K | X | W | T | A | B | P | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:299
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
def mapS : TM2.Stmt Γ Λ σ → TM2.Stmt Γ' Λ' σ
| .push k f q => .push (E.e k) (fun s => E.ι k (f s)) (mapS q)
| .peek k f q => .peek (E.e k) (fun s o => f s (o.map (E.ι k).symm)) (mapS q)
| .pop k f q => .pop (E.e k) (fun s o => f s (o.map (E.ι k).symm)) (mapS q)
| .load a q => .load a (mapS q)
| .branch f q₁ q₂ => .branch f (mapS q₁) (mapS q₂)
| .goto f => .goto fun s => φ (f s)
| .halt => .halt
MathlibExt/Computability/TuringMachine/StackEmbedding.lean:65
def identity : SEmb (fun _ : SSVerify.K => Sym)
(fun _ : SSVerify.K => Sym) where
e := id
inj := injective_id
ι _ := Equiv.refl _
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:68
def redirect : SSVerify.Lab → Lab
| .yes | .no => .inr 1
| l => .inl l
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:75
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .tgt z => rdS z (.goto fun _ => .next) fun b =>
.push .T (fun _ => .bit b) <| .goto fun _ => .tgt (!b)
| .next => nextS
| .add c z => rdS z (.goto fun _ => .fin c) (addS c)
| .skip z => rdS z (.goto fun _ => .next) fun b => .goto fun _ => .skip (!b)
| .fin c => finS c
| .back => moveB .B .A Sym.bit? Sym.bit .back .next
| .fmove => moveB .A .B Sym.bit? Sym.bit .fmove .cmp
| .cmp => cmpB .B .T .P .Q Sym.bit? Sym.bit? Sym.bit Sym.bit .cmp .yes .no
| .yes => .halt
| .no => .halt
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:357
def cleanS (ks : List K) (self next : Λ) : TM2.Stmt Γ Λ σ :=
.load (fun _ => Flag.tag false) <| popAll ks <|
.branch Flag.untag (.goto fun _ => self) (.goto fun _ => next)
MathlibExt/Computability/TuringMachine/Cleanup.lean:41
def moveB (a b : K) (d : Γ a → Option Bool) (g : Bool → Γ b) (self next : Λ) :
TM2.Stmt Γ Λ σ :=
.peek a (fun _ o => Flag.tag (isBit d o))
(.branch Flag.untag
(.pop a (fun _ o => Flag.tag (bitOf d o))
(.branch Flag.untag
(.push b (fun _ => g true) (.goto fun _ => self))
(.push b (fun _ => g false) (.goto fun _ => self))))
(.goto fun _ => next))
MathlibExt/Computability/TuringMachine/BitOps.lean:86
def Sym.bit? : Sym → Option Bool
| .bit b => some b
| _ => none
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:46
Uses 12 · Used by 2
TheoremBit length of the sum is at most the input length#✓fully proved
The canonical sum fits within the two framed operands' bit length.
theorem length_sum_le_input (m n : ℕ) :
(encodeNat (m + n)).length ≤ (pairInput m n).length
def pairInput (m n : ℕ) : List Bool :=
delimit (encodeNat m) ++ delimit (encodeNat n)
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:61
Uses 6 · Used by 1
TheoremBinary addition of framed numbers in quadratic time#✓fully proved
Add two canonically framed numbers, leaving only the LSB-first result. The bound is quadratic in encoded input length; no loop enumerates values.
theorem run (m n : ℕ) (v : Bool) :
let N := (pairInput m n).length
∃ v', RunLe prog (N * (2 * N + 6) + 2 * N + 8)
⟨some (.inr 0), v,
SSVerify.st ((pairInput m n).map .bit) [] [] [] []⟩
⟨some (.inr 3), v',
SSVerify.st [] [] [] ((encodeNat (m + n)).map .bit) []⟩
def pairInput (m n : ℕ) : List Bool :=
delimit (encodeNat m) ++ delimit (encodeNat n)
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:61
def RunLe (M : Λ → TM2.Stmt Γ Λ σ) (B : ℕ) (c d : TM2.Cfg Γ Λ σ) : Prop :=
∃ n, n ≤ B ∧ Run M n c d
MathlibExt/Computability/TuringMachine/Program.lean:901
def prog : Lab → TM2.Stmt (fun _ : SSVerify.K => Sym) Lab Bool
| .inl l => mapS identity redirect (SSVerify.prog l)
| .inr i =>
if i = 0 then
.push .W (fun _ => .bit true) <|
.push .W (fun _ => .bit true) <| .goto fun _ => .inl .next
else if i = 1 then
cleanS [.W] (.inr 1) (.inr 2)
else if i = 2 then
moveB .B .A Sym.bit? Sym.bit (.inr 2) (.inr 3)
else .halt
CSLibExt/Computability/Complexity/SSVerifierArithmetic.lean:86
def st (x w t a b : List Sym) : K → List Sym
| .X => x
| .W => w
| .T => t
| .A => a
| .B => b
| .P => []
| .Q => []
CSLibExt/Computability/Complexity/Karp/SubsetSumVerify.lean:376
Uses 34 · Used by 1
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.