The repeat scan of the Hamiltonian path verifier to HAMPATH is NP-complete
TheoremThe repeat scan of the Hamiltonian path verifier#✓fully proved
For a list \(p\) of natural numbers
write \(\mathrm{enc}(p)\) for its witness encoding: each entry in unary (that many copies of
true) followed by false. Let \(a\) be a natural number and \(q\), \(d\) lists of natural numbers.
Suppose that the verifier's stacks hold, as bit symbols with the first bit on top, the bits of
\(\mathrm{enc}(q)\) on \(\mathsf{W}\), the bits of \(\mathrm{enc}(d)\) in reverse order on
\(\mathsf{Z}\), \(a\) copies of the bit true on \(\mathsf{A}\), and nothing on \(\mathsf{R}\), the
other stacks being arbitrary. Started at label \(\mathrm{nd}\) with either value of its Boolean
variable, the verifier reaches, within \(4|\mathrm{enc}(q)| + |\mathrm{enc}(d)| + 2\) steps, the
label \(\mathrm{no}\) if \(a\) is an entry of \(q\) and the label \(\mathrm{incC}\) otherwise. In the
second case its stacks are then the initial ones except that \(\mathsf{W}\) holds the bits of the
encoding of \(d\) followed by \(q\), and \(\mathsf{Z}\) is empty.
theorem nd_run (a : ℕ) : ∀ (q done : List ℕ) (v : Bool) (St : ∀ _ : K, List Sym),
St .W = (encW q).map Sym.bit → St .Z = (encW done).reverse.map Sym.bit →
St .A = cnt (Sym.bit true) a → St .R = [] →
∃ v' S', RunLe prog (4 * (encW q).length + (encW done).length + 2) ⟨some .nd, v, St⟩
⟨some (if a ∈ q then .no else .incC), v', S'⟩ ∧
(a ∉ q → S' = update (update St .W ((encW (done ++ q)).map Sym.bit)) .Z [])
inductive K | X | W | S | T | N | C | A | B | E | Z | R | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:49
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
def encW (p : List ℕ) : List Bool := p.flatMap fun v => List.replicate v true ++ [false]
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:53
abbrev cnt {α : Type} (u : α) (n : ℕ) : List α := List.replicate n u
MathlibExt/Computability/TuringMachine/Program.lean:115
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
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
Uses 13 · Used by 1
DefinitionStack layout between vertex steps#✓fully proved
For an edge list \(es\), numbers \(s, t, n, c, b\) and a list \(q\) of vertices, the stacks of the verifier between two vertex steps: \(X\) holds the bits of the edge list \(es\), \(W\) holds the bits of the witness encoding of \(q\), the counters \(S\), \(T\), \(N\), \(C\) and \(B\) hold \(s\), \(t\), \(n\), \(c\) and \(b\) in unary, and the stacks \(A\), \(E\), \(Z\), \(R\) and \(Q\) are empty.
def lay (es : List (ℕ × ℕ)) (s t n c b : ℕ) (q : List ℕ) : K → List Sym
| .X => (Karp.edgeBits es).map Sym.bit
| .W => (encW q).map Sym.bit
| .S => cnt (Sym.bit true) s
| .T => cnt (Sym.bit true) t
| .N => cnt (Sym.bit true) n
| .C => cnt (Sym.bit true) c
| .A => []
| .B => cnt (Sym.bit true) b
| .E => []
| .Z => []
| .R => []
| .Q => []
inductive K | X | W | S | T | N | C | A | B | E | Z | R | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:49
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
def edgeBits (es : List (ℕ × ℕ)) : List Bool :=
es.flatMap fun e => List.replicate e.1 true ++ false :: (List.replicate e.2 true ++ [false])
CSLibExt/Computability/Complexity/Karp/Color.lean:160
def encW (p : List ℕ) : List Bool := p.flatMap fun v => List.replicate v true ++ [false]
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:53
abbrev cnt {α : Type} (u : α) (n : ℕ) : List α := List.replicate n u
MathlibExt/Computability/TuringMachine/Program.lean:115
Uses 5 · Used by 6
DefinitionStack layout during a vertex step#✓fully proved
For an edge list \(es\), numbers \(s, t, n, c, b, a\) and a list \(q\) of vertices, the stacks of the verifier during the step on vertex \(a\): the layout between vertex steps for \(es, s, t, n, c, b, q\), except that stack \(A\) holds \(a\) in unary.
def mid (es : List (ℕ × ℕ)) (s t n c b a : ℕ) (q : List ℕ) : K → List Sym :=
update (lay es s t n c b q) .A (cnt (Sym.bit true) a)
inductive K | X | W | S | T | N | C | A | B | E | Z | R | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:49
inductive Sym
| bit (b : Bool) | lit (p : Bool) | cl | val (b : Bool) | dead
deriving DecidableEq
CSLibExt/Computability/Complexity/SatVerifierSpec.lean:41
def lay (es : List (ℕ × ℕ)) (s t n c b : ℕ) (q : List ℕ) : K → List Sym
| .X => (Karp.edgeBits es).map Sym.bit
| .W => (encW q).map Sym.bit
| .S => cnt (Sym.bit true) s
| .T => cnt (Sym.bit true) t
| .N => cnt (Sym.bit true) n
| .C => cnt (Sym.bit true) c
| .A => []
| .B => cnt (Sym.bit true) b
| .E => []
| .Z => []
| .R => []
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:703
abbrev cnt {α : Type} (u : α) (n : ℕ) : List α := List.replicate n u
MathlibExt/Computability/TuringMachine/Program.lean:115
Uses 4 · Used by 3
TheoremRunning the head-or-edge check#✓fully proved
Let \(es\) be an edge list, \(s, t, n, c, b, a\) numbers and \(q\) a list of vertices, and say the check passes when \(a = s\) in case \(c = 0\), and \((b, a) \in es\) in case \(c \neq 0\). Started at the head-or-edge dispatch, in any internal state, on the stack layout during the step on vertex \(a\) for \(es, s, t, n, c, b, a, q\), the verifier reaches within \(3a + 4\ell + 7\) steps, where \(\ell\) is the number of bits of \(es\), the repeat scan if the check passes and the reject label otherwise, in some internal state and with some stacks; if the check passes, these stacks are the ones it started on.
theorem hd_run (es : List (ℕ × ℕ)) (s t n c b a : ℕ) (q : List ℕ) (v : Bool) :
∃ v' S', RunLe prog (3 * a + 4 * (Karp.edgeBits es).length + 7)
⟨some .hd, v, mid es s t n c b a q⟩
⟨some (if (if c = 0 then decide (a = s) else decide ((b, a) ∈ es)) = true then .nd
else .no), v', S'⟩ ∧
((if c = 0 then decide (a = s) else decide ((b, a) ∈ es)) = true →
S' = mid es s t n c b a q)
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
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
def edgeBits (es : List (ℕ × ℕ)) : List Bool :=
es.flatMap fun e => List.replicate e.1 true ++ false :: (List.replicate e.2 true ++ [false])
CSLibExt/Computability/Complexity/Karp/Color.lean:160
def mid (es : List (ℕ × ℕ)) (s t n c b a : ℕ) (q : List ℕ) : K → List Sym :=
update (lay es s t n c b q) .A (cnt (Sym.bit true) a)
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:718
Uses 19 · Used by 1
TheoremThe rest of a vertex step in the Hamiltonian-path verifier#✓fully proved
Let \(es\) be an edge list, \(s, t, n, c, b, a\) natural numbers and \(q\) a list of natural numbers. Start the verifier, with any flag value, at the label \(\mathsf{nd}\) (the repeat scan) with its stacks in the mid-step layout: the between-steps layout for \(es\), \(s\), \(t\), \(n\), count \(c\), previous vertex \(b\) and remaining vertices \(q\), with \(a\) in unary on the stack \(A\). Let \(w\) be the unary encoding of \(q\). Then within at most \(4|w| + a + b + 6\) steps it reaches the label \(\mathsf{no}\) if \(a \in q\) and the label \(\mathsf{loop}\) if \(a \notin q\). In the second case (\(a\) has been counted and become the previous vertex) the stacks end in the between-steps layout for \(es\), \(s\), \(t\), \(n\), count \(c + 1\), previous vertex \(a\) and remaining vertices \(q\).
theorem tail_run (es : List (ℕ × ℕ)) (s t n c b a : ℕ) (q : List ℕ) (v : Bool) :
∃ v' S', RunLe prog (4 * (encW q).length + a + b + 6) ⟨some .nd, v, mid es s t n c b a q⟩
⟨some (if a ∈ q then .no else .loop), v', S'⟩ ∧
(a ∉ q → S' = lay es s t n (c + 1) a q)
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
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
def encW (p : List ℕ) : List Bool := p.flatMap fun v => List.replicate v true ++ [false]
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:53
def mid (es : List (ℕ × ℕ)) (s t n c b a : ℕ) (q : List ℕ) : K → List Sym :=
update (lay es s t n c b q) .A (cnt (Sym.bit true) a)
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:718
def lay (es : List (ℕ × ℕ)) (s t n c b : ℕ) (q : List ℕ) : K → List Sym
| .X => (Karp.edgeBits es).map Sym.bit
| .W => (encW q).map Sym.bit
| .S => cnt (Sym.bit true) s
| .T => cnt (Sym.bit true) t
| .N => cnt (Sym.bit true) n
| .C => cnt (Sym.bit true) c
| .A => []
| .B => cnt (Sym.bit true) b
| .E => []
| .Z => []
| .R => []
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:703
Uses 17 · Used by 1
TheoremOne vertex step of the Hamiltonian-path verifier#✓fully proved
Let \(es\) be an edge list, \(s, t, n, c, b, a\) natural numbers and \(q\) a list of natural numbers. Start the verifier, with any flag value, at the label \(\mathsf{rdA}\) (read the next vertex) with its stacks in the between-steps layout for \(es\), \(s\), \(t\), \(n\), count \(c\), previous vertex \(b\) and remaining vertices \(a, q\). Let \(e\) be the bit encoding of \(es\) and \(w\) the unary encoding of \(q\). Then within at most \(8a + b + 4|e| + 4|w| + 20\) steps it reaches the label \(\mathsf{loop}\) if the step check on \(a\) passes and the label \(\mathsf{no}\) otherwise. The step check passes when \(a < n\), \(a = s\) in case \(c = 0\) and \((b, a) \in es\) in case \(c \ne 0\), and \(a \notin q\). When it passes, the stacks end in the between-steps layout for \(es\), \(s\), \(t\), \(n\), count \(c + 1\), previous vertex \(a\) and remaining vertices \(q\).
theorem step_run (es : List (ℕ × ℕ)) (s t n c b a : ℕ) (q : List ℕ) (v : Bool) :
∃ v' S', RunLe prog (8 * a + b + 4 * (Karp.edgeBits es).length + 4 * (encW q).length + 20)
⟨some .rdA, v, lay es s t n c b (a :: q)⟩
⟨some (if stepOk s n es c b a q then .loop else .no), v', S'⟩ ∧
(stepOk s n es c b a q = true → S' = lay es s t n (c + 1) a q)
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
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
def edgeBits (es : List (ℕ × ℕ)) : List Bool :=
es.flatMap fun e => List.replicate e.1 true ++ false :: (List.replicate e.2 true ++ [false])
CSLibExt/Computability/Complexity/Karp/Color.lean:160
def encW (p : List ℕ) : List Bool := p.flatMap fun v => List.replicate v true ++ [false]
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:53
def lay (es : List (ℕ × ℕ)) (s t n c b : ℕ) (q : List ℕ) : K → List Sym
| .X => (Karp.edgeBits es).map Sym.bit
| .W => (encW q).map Sym.bit
| .S => cnt (Sym.bit true) s
| .T => cnt (Sym.bit true) t
| .N => cnt (Sym.bit true) n
| .C => cnt (Sym.bit true) c
| .A => []
| .B => cnt (Sym.bit true) b
| .E => []
| .Z => []
| .R => []
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:703
def stepOk (s n : ℕ) (es : List (ℕ × ℕ)) (c b a : ℕ) (q : List ℕ) : Bool :=
decide (a < n) && (if c = 0 then decide (a = s) else decide ((b, a) ∈ es)) && !decide (a ∈ q)
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:248
Uses 22 · Used by 1
TheoremRunning the vertex loop#✓fully proved
Let \(es\) be an edge list, \(s, t, n\) numbers and \(L\) a bound with \(n \le L\), \(t \le L\) and at most \(L\) bits in the encoding of \(es\). For every list \(q\) of vertices whose witness encoding has at most \(L\) bits, every count \(c\), every previous vertex \(b \le L\) and every internal state, the verifier started at the vertex loop on the stack layout between vertex steps for \(es, s, t, n, c, b, q\) reaches within \((|q| + 1)(20L + 20)\) steps, with some internal state and stacks, the accept label if the walk check for \(s, t, n, es, c, b, q\) passes and the reject label otherwise.
theorem loop_run (es : List (ℕ × ℕ)) (s t n L : ℕ) (hn : n ≤ L) (ht : t ≤ L)
(he : (Karp.edgeBits es).length ≤ L) : ∀ (q : List ℕ) (c b : ℕ) (v : Bool),
(encW q).length ≤ L → b ≤ L →
∃ v' S', RunLe prog ((q.length + 1) * (20 * L + 20)) ⟨some .loop, v, lay es s t n c b q⟩
⟨some (if walkOk s t n es c b q then .yes else .no), v', S'⟩
def edgeBits (es : List (ℕ × ℕ)) : List Bool :=
es.flatMap fun e => List.replicate e.1 true ++ false :: (List.replicate e.2 true ++ [false])
CSLibExt/Computability/Complexity/Karp/Color.lean:160
def encW (p : List ℕ) : List Bool := p.flatMap fun v => List.replicate v true ++ [false]
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:53
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
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
def lay (es : List (ℕ × ℕ)) (s t n c b : ℕ) (q : List ℕ) : K → List Sym
| .X => (Karp.edgeBits es).map Sym.bit
| .W => (encW q).map Sym.bit
| .S => cnt (Sym.bit true) s
| .T => cnt (Sym.bit true) t
| .N => cnt (Sym.bit true) n
| .C => cnt (Sym.bit true) c
| .A => []
| .B => cnt (Sym.bit true) b
| .E => []
| .Z => []
| .R => []
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:703
def walkOk (s t n : ℕ) (es : List (ℕ × ℕ)) : ℕ → ℕ → List ℕ → Bool
| c, b, [] => decide (c = n) && decide (c ≠ 0) && decide (b = t)
| c, b, a :: q => stepOk s n es c b a q && walkOk s t n es (c + 1) a q
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:253
Uses 19 · Used by 1
TheoremCorrectness and running time of the Hamiltonian path verifier#✓fully proved
Let \(x\) and \(w\) be bit lists. Start the verifier at its start label, with either value of its Boolean variable, with \(x\) on stack \(\mathsf{X}\) and \(w\) on stack \(\mathsf{W}\) (as bit symbols, first bit on top) and all other stacks empty. Then within \(100(|x| + |w| + 1)^4\) steps it reaches the label \(\mathrm{yes}\) if the Hamiltonian path check accepts \(x\) and \(w\), and the label \(\mathrm{no}\) otherwise.
The machine in fact takes quadratically many steps; the theorem states only the quartic bound.
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 (100 * (x.length + w.length + 1) ^ 4) ⟨some start, v, St⟩
⟨some (if hamCheck x w then .yes else .no), v', S'⟩
inductive K | X | W | S | T | N | C | A | B | E | Z | R | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:49
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
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
def start : Lab := .rdS
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:186
def hamCheck (x w : List Bool) : Bool :=
match Path.decodeP x, decodeW w with
| some (s, t, n, es), some p => hamOk n es s t p
| _, _ => false
CSLibExt/Computability/Complexity/Karp/HamPathCheck.lean:189
Uses 33 · Used by 1
AbbreviationThe HAMPATH verifier as a host component#✓fully proved
The component machine whose program and labels are those of the HAMPATH verifier machine, whose stacks are the twelve stacks of that machine (the input \(X\), the witness \(W\), the counters \(S, T, N, C, A, B\), the save stacks \(E, Z\) and the scratch stacks \(R, Q\)), each over the symbol alphabet of the SAT verifier.
abbrev hamVerifyComp : Host.Comp where
K := HamVerify.K
Γ := fun _ => SatVerifier.Sym
finΓ := fun _ => SatVerifier.Sym.instFintype
L := HamVerify.Lab
prog := HamVerify.prog
ks := [.X, .W, .S, .T, .N, .C, .A, .B, .E, .Z, .R, .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 | S | T | N | C | A | B | E | Z | R | Q
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:49
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
| rdS | rdT | rdN | vE | vEU | vEV | vEb | vW | vWU | vWb | loop | rdA | hd
| cmp (i : CI) | cr (i : CI) (o : Ordering) | crb (i : CI) (o : Ordering)
| scan | ceU (ok : Bool) | rsU (ok : Bool) | ceV (ok : Bool) | rsV (ok : Bool) | scB
| nd | cbN (ok : Bool) | rsN (ok : Bool) | ndB | fin | incC | dB | mA | yes | no
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:72
def prog : Lab → TM2.Stmt (fun _ : K => Sym) Lab Bool
| .rdS => readU .X .S .rdS .rdT
| .rdT => readU .X .T .rdT .rdN
| .rdN => readU .X .N .rdN .vE
| .vE => ifE .X .vEb .vEU
| .vEU => skipU .X .E .vEU .vEV
| .vEV => skipU .X .E .vEV .vE
| .vEb => moveB .E .X Sym.bit? Sym.bit .vEb .vW
| .vW => ifE .W .vWb .vWU
| .vWU => skipU .W .Z .vWU .vW
| .vWb => moveB .Z .W Sym.bit? Sym.bit .vWb .loop
| .loop => ifE .W (.cmp .cn) .rdA
⋯
CSLibExt/Computability/Complexity/Karp/HamPathVerify.lean:150
TheoremHAMPATH is in NP#✓fully proved
HAMPATH is in NP.
theorem hamPathDec_mem_NP : hamPathDec ∈ NP
noncomputable def hamPathDec : MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
decide (∃ s t n es, Path.encodeP s t n es = x ∧ ∃ p, IsHamPath n es s t p)
CSLibExt/Computability/Complexity/Karp/HamPath.lean:59
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 27 · Used by 1
AbbreviationThe HAMPATH emitter#✓fully proved
The emitter whose stacks, alphabets, labels, program and start label are those of the HAMPATH emitter machine, which exits at the machine's label \(\mathsf{done}\), reads the tokens of a CNF formula from stack \(T\) and writes its output bits on stack \(O\) (both symbol maps being the identity), and has step bound \(B(n) = 2000 (n + 1)^5\) for \(n\) tokens. Its output for a CNF formula \(\varphi\) is Sipser's HAMPATH instance of \(\varphi\), and for an undecodable input the fixed HAMPATH no-instance (two vertices, no arcs, source and target \(0\)).
Cslib.Complexity.Karp.emitHam · 21 lines
abbrev emitHam : Emitter where
K := EmitHam.K
Γ := EmitHam.Γ
L := EmitHam.Lab
prog := EmitHam.prog
start := EmitHam.start
done := .done
start_ne_done := by decide
prog_done := rfl
cT := .T
cO := .O
cT_ne_cO := by decide
iT := Equiv.refl _
eO := Equiv.refl _
g := toHam
noOut := noHam
B n := 2000 * (n + 1) ^ 5
B_mono a b h := by dsimp only; gcongr
run φ v St hT hO h0 := by
obtain ⟨v', S', r, h⟩ := EmitHam.run φ [] v St (by simpa using hT) hO h0
exact ⟨v', S', r, by simpa using h⟩
structure Emitter where
/-- Stacks. -/
K : Type
[decK : DecidableEq K]
/-- Alphabets. -/
Γ : K → Type
/-- Labels. -/
L : Type
[decL : DecidableEq L]
/-- The program. -/
prog : L → TM2.Stmt Γ L Bool
/-- Start label. -/
⋯
CSLibExt/Computability/Complexity/Karp/TokThen.lean:37
inductive K | T | O | F | V | W | Q | G | X | Y | C | M | P | N | R | L | J | D | Z
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathEmitMachine.lean:58
@[reducible] def Γ : K → Type
| .O => Bool
| _ => Sym
CSLibExt/Computability/Complexity/Karp/HamPathEmitMachine.lean:69
inductive Lab
| a0 | anm | aw (f : Bool) | ac (f : Bool) | ar1 (f : Bool) | ar2 (f : Bool) | amv (f : Bool)
| asep (f : Bool) | ab (f : Bool) | ad2 | ad3
| b0 | b1 | h0 | h1 | h2 | h3 | h4 | h5 | r0 | r1 | r2 | r3 | r4 | wi | e0 | e1 | e2
| dw (pp pn : Bool) | dk (pp pn : Bool) | dr1 (pp pn b : Bool) | dr2 (pp pn b : Bool)
| dm (pp pn b : Bool) | dl (pp pn b : Bool) | dj
| t0 | t1 | t2 | t3 | t4 | t5 | t6 | t7 | t8
| z0 | z1 | z2 | z3 | z4 | z5 | z6 | z7 | z8 | z9
| cpA (j : Site) (b : Bool) | cpB (j : Site) (b : Bool) | post (j : Site) (b : Bool) | done
deriving DecidableEq
CSLibExt/Computability/Complexity/Karp/HamPathEmitMachine.lean:130
def prog : Lab → TM2.Stmt Γ Lab Bool
| .a0 => .peek .T (fun _ o => o.isNone) <| .branch id (.goto fun _ => .b0) <|
.peek .T (fun _ o => o == some .cl) <| .branch id
(.pop .T (fun s _ => s) <| .push .F (fun _ => Sym.cl) <| .push .C (fun _ => Sym.cl) <|
pushList .M [Sym.cl, Sym.cl, Sym.cl] <| .goto fun _ => .a0)
(.pop .T (fun _ o => o == some (.lit true)) <| .push .F (fun s => Sym.lit s) <|
.goto fun _ => .anm)
| .anm => moveB .T .F Sym.bit? Sym.bit .anm (.aw false)
| .aw f => .peek .V (fun _ o => o.isNone) <| .branch id (.goto fun _ => .ab f)
(.goto fun _ => .ac f)
| .ac f => cmpB .F .V .X .Y Sym.bit? Sym.bit? Sym.bit Sym.bit (.ac f) (.ar1 true) (.ar1 f)
| .ar1 f => moveB .X .F Sym.bit? Sym.bit (.ar1 f) (.ar2 f)
⋯
CSLibExt/Computability/Complexity/Karp/HamPathEmitMachine.lean:188
def start : Lab := .a0
CSLibExt/Computability/Complexity/Karp/HamPathEmitMachine.lean:277
Uses 14 · Used by 1
TheoremSAT ≤ HAMPATH is polynomial-time#✓fully proved
The map on bit strings that sends a bit string decoding to a CNF formula \(\varphi\) to Sipser's HAMPATH instance for \(\varphi\), and every other bit string to the fixed no-instance with two vertices, no arcs and \(s = t = 0\), is computable in polynomial time.
theorem isPolyTime_reduceHam : IsPolyTime reduceHam
def IsPolyTime {α β : Type} [BitstringEncoding α] [BitstringEncoding β]
(f : α → β) : Prop :=
IsPolyTimeWithEncoding (BitstringEncoding.toEncoding (α := α))
(BitstringEncoding.toEncoding (α := β)) f
MathlibExt/Computability/Complexity.lean:186
def reduceHam (x : List Bool) : List Bool :=
match decodeCNF x with
| some φ => toHam φ
| none => noHam
CSLibExt/Computability/Complexity/Karp/HamPath.lean:97
Uses 25 · Used by 1
TheoremHAMPATH is NP-hard#✓fully proved
Every decision problem \(L\) in NP has a polynomial-time many-one reduction to HAMPATH: a polynomial-time computable map \(f\) on bit strings such that, for every bit string \(x\), \(L\) accepts \(x\) exactly when HAMPATH accepts \(f(x)\).
theorem hamPathDec_npHard : ∀ L : DecisionProblem, L ∈ NP → PolyManyOneRed L hamPathDec
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 hamPathDec : MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
decide (∃ s t n es, Path.encodeP s t n es = x ∧ ∃ p, IsHamPath n es s t p)
CSLibExt/Computability/Complexity/Karp/HamPath.lean:59
Uses 20 · Used by 1
TheoremHAMPATH is NP-complete#✓fully proved
HAMPATH lies in NP, and every decision problem \(L\) in NP has a polynomial-time many-one reduction to HAMPATH: a polynomial-time computable map \(f\) on bit strings such that, for every bit string \(x\), \(L\) accepts \(x\) exactly when HAMPATH accepts \(f(x)\).
theorem hamPathDec_npComplete :
hamPathDec ∈ NP ∧ ∀ L : DecisionProblem, L ∈ NP → PolyManyOneRed L hamPathDec
noncomputable def hamPathDec : MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
decide (∃ s t n es, Path.encodeP s t n es = x ∧ ∃ p, IsHamPath n es s t p)
CSLibExt/Computability/Complexity/Karp/HamPath.lean:59
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
Sources
- Sipser, Theorem 7.46.
Uses 7
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.