Polynomial time on single-tape machines
Rev Tail
InductiveStacks of the reversal component#✓fully proved
The two stack indices of the reversal component: the input stack \(X\) and the output stack \(O\).
inductive K | X | O
deriving DecidableEq
InductiveLabels of the reversal component#✓fully proved
The three labels of the reversal component: mv (move the input onto the output), drop (drop one symbol) and done.
inductive L | mv | drop | done
deriving DecidableEq
DefinitionProgram of the reversal component#✓fully proved
The multi-stack program over the stacks \(X\) and \(O\), both with alphabet \(\mathrm{Bool}\), with a Boolean internal state: at label mv it moves the bits of \(X\) one at a time onto \(O\) (reversing them) and then goes to drop; at drop it pops \(O\) once and goes to done; at done it halts.
def prog : L → TM2.Stmt (fun _ : K ↦ Bool) L Bool
| .mv => moveB .X .O some id .mv .drop
| .drop => .pop .O (fun s _ ↦ s) (.goto fun _ ↦ .done)
| .done => .halt
inductive L | mv | drop | done
deriving DecidableEq
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:74
inductive K | X | O
deriving DecidableEq
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:67
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
Uses 4 · Used by 2
AbbreviationThe reversal component#✓fully proved
The component machine with two stacks, the input stack \(X\) and the output stack \(O\), both over the alphabet \(\mathrm{Bool}\); the three labels mv, drop and done; the program that moves the bits of \(X\) onto \(O\) (reversing them), pops \(O\) once and halts; and the stack list \([X, O]\).
noncomputable abbrev comp : Cslib.Complexity.Host.Comp where
K := K
Γ := fun _ ↦ Bool
L := L
prog := prog
ks := [.X, .O]
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
deriving DecidableEq
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:67
inductive L | mv | drop | done
deriving DecidableEq
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:74
def prog : L → TM2.Stmt (fun _ : K ↦ Bool) L Bool
| .mv => moveB .X .O some id .mv .drop
| .drop => .pop .O (fun s _ ↦ s) (.goto fun _ ↦ .done)
| .done => .halt
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:81
Uses 4 · Used by 2
TheoremRunning the reversal component#✓fully proved
For every bit list \(x\), the program of the reversal component, started at label mv with internal state false, with the bits of \(x\) on the input stack \(X\) and every other stack empty, reaches label done within at most \(|x| + 2\) steps, with some internal state and some stacks whose output stack \(O\) holds the reversal of \(x\) with its first entry removed.
theorem run (x : List Bool) : ∃ v S', RunLe comp.prog (x.length + 2)
⟨some L.mv, false, Function.update (fun _ ↦ []) K.X (x.map id)⟩ ⟨some L.done, v, S'⟩ ∧
S' K.O = x.reverse.tail.map (Equiv.refl Bool).symm
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
noncomputable abbrev comp : Cslib.Complexity.Host.Comp where
K := K
Γ := fun _ ↦ Bool
L := L
prog := prog
ks := [.X, .O]
ks_nodup := by decide
mem_ks k := by cases k <;> decide
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:87
Uses 9 · Used by 1
DefinitionReversing and dropping the first bit is polynomial-time#✓fully proved
A finite multi-stack Turing machine whose input and output alphabets are both identified with the bits, together with a polynomial \(p\) with natural-number coefficients, such that for every bit list \(x\), given bit by bit as its own encoding, the machine outputs the reversal of \(x\) with its first entry removed (that is, \(x\) without its last bit, in reverse order) within \(p(|x|)\) steps.
noncomputable def computable :
TM2ComputableInPolyTime (fun l : List Bool ↦ l) (fun l : List Bool ↦ l)
(fun x : List Bool ↦ x.reverse.tail) :=
Cslib.Complexity.Host.reduction (c := comp) (cX := K.X) (cO := K.O) (gX := id)
(start := L.mv) (done := L.done) (Equiv.refl Bool) _ (Polynomial.X + Polynomial.C 2) rfl
fun x ↦ by simpa using run x
noncomputable def reduction (eO : c.Γ cO ≃ Bool) (f : List Bool → List Bool) (p : Polynomial ℕ)
(hdone : c.prog done = .halt)
(hrun : ∀ x, ∃ v S', RunLe c.prog (p.eval x.length)
⟨some start, false, update (fun _ => []) cX (x.map gX)⟩ ⟨some done, v, S'⟩ ∧
S' cO = (f x).map eO.symm) :
TM2ComputableInPolyTime (fun l : List Bool => l) (fun l : List Bool => l) f where
tm := rtm c cX cO gX start done
inputAlphabet := Equiv.refl Bool
outputAlphabet := eO
time := rtime c cX cO gX start done p
outputsFun := fun x => by
have h := rprog_run eO f p hdone hrun x
⋯
CSLibExt/Computability/Complexity/Host.lean:348
noncomputable abbrev comp : Cslib.Complexity.Host.Comp where
K := K
Γ := fun _ ↦ Bool
L := L
prog := prog
ks := [.X, .O]
ks_nodup := by decide
mem_ks k := by cases k <;> decide
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:87
Uses 8 · Used by 1
Of TM2
TheoremThe answer machine runs in one step#✓fully proved
Let \(M\) be a finite multi-stack machine with finite stack alphabets, whose input alphabet is identified with the bits by \(e\) and whose output alphabet by \(e_1\). For every non-blank cell \(x\) of the single-tape emulation alphabet of \(M\), the answer machine of \(M\), started on the one-cell tape \(x\), halts within at most one step on the one-cell tape holding the input-bit cell of the answer of \(x\) (the bit telling whether \(x\) holds \(e_1^{-1}(\mathrm{true})\) on the output stack).
theorem answerTM_outputsWithinTime (x : NonBlank (TM2to1.Γ' tm.K tm.Γ)) :
(answerTM tm e e₁).OutputsWithinTime [x] [inCell tm e (cellAnswer tm e₁ x)] 1
abbrev NonBlank (Γ₀ : Type) [Inhabited Γ₀] : Type := {x : Γ₀ // x ≠ default}
CSLibExt/Computability/Machines/Turing/SingleTape/OfTM0.lean:61
noncomputable def answerTM : SingleTapeTM (NonBlank (TM2to1.Γ' tm.K tm.Γ)) where
State := Unit
q₀ := ()
tr _ s := (⟨some (inCell tm e (s.elim false (cellAnswer tm e₁))), none⟩, none)
CSLibExt/Computability/Machines/Turing/SingleTape/OfRecursive.lean:283
def inCell (b : Bool) : NonBlank (TM2to1.Γ' tm.K tm.Γ) :=
⟨(false, Function.update (fun _ ↦ none) tm.k₀ (some (e.symm b))), fun h ↦ by
have := congrFun (congrArg Prod.snd h) tm.k₀
simp only [Function.update_self] at this
cases this⟩
CSLibExt/Computability/Machines/Turing/SingleTape/OfRecursive.lean:163
noncomputable def cellAnswer (x : NonBlank (TM2to1.Γ' tm.K tm.Γ)) : Bool :=
decide (x.1.2 tm.k₁ = some (e₁.symm true))
CSLibExt/Computability/Machines/Turing/SingleTape/OfRecursive.lean:278
Uses 4 · Used by 1
TheoremThe decider within time#✓fully proved
Let \(M\) be a finite multi-stack machine with finite stack alphabets, whose input alphabet is identified with the bits by \(e\) and whose output alphabet by \(e_1\), and let \(C\) be the emulation constant of \(M\). Let \(w\) be a bit list, \(b\) a bit and \(t\) a natural number. Suppose \(M\), started with its input stack holding the bits of \(w\) in reverse order followed by \(\mathrm{true}\) (read through \(e^{-1}\)), is after exactly \(t\) steps in the halting configuration whose output stack holds just \(e_1^{-1}(b)\), whose other stacks are empty and whose internal state is the initial one. Then the single-tape decider of \(M\), started on the tape of input-bit cells of \(w\), halts on the one-cell tape holding the input-bit cell of \(b\) within \(C t (|w| + 1 + C t + 1) + 4\) steps.
theorem deciderTM_outputsWithinTime {w : List Bool} (b : Bool) {t : ℕ}
(h : (flip bind tm.step)^[t] (some (initList tm ((w.reverse ++ [true]).map e.symm))) =
some (haltList tm [e₁.symm b])) :
(deciderTM tm e e₁).OutputsWithinTime (w.map (inCell tm e)) [inCell tm e b]
(emulationConstant tm * t * (w.length + 1 + emulationConstant tm * t + 1) + 4)
noncomputable def deciderTM : SingleTapeTM (NonBlank (TM2to1.Γ' tm.K tm.Γ)) :=
compComputer (recognizerTM tm e) (answerTM tm e e₁)
CSLibExt/Computability/Machines/Turing/SingleTape/OfRecursive.lean:294
def inCell (b : Bool) : NonBlank (TM2to1.Γ' tm.K tm.Γ) :=
⟨(false, Function.update (fun _ ↦ none) tm.k₀ (some (e.symm b))), fun h ↦ by
have := congrFun (congrArg Prod.snd h) tm.k₀
simp only [Function.update_self] at this
cases this⟩
CSLibExt/Computability/Machines/Turing/SingleTape/OfRecursive.lean:163
noncomputable def emulationConstant (tm : FinTM2) : ℕ :=
3 * (2 * ∑ l, sizeOf (tm.m l) + 1) + MetaMathlibExt.TM2Composition.pushBound tm
CSLibExt/Computability/Machines/Turing/SingleTape/TM2Time.lean:370
Uses 20 · Used by 1
Complexity
DefinitionPolynomial time on single-tape machines#✓fully proved
The class of decision problems \(L\) for which there are a finite alphabet \(\Sigma\) with a designated default element, an injective map \(\iota\) from the bits to \(\Sigma\), a single-tape Turing machine \(M\) over \(\Sigma\) and a polynomial \(p\) with natural-number coefficients such that, for every bit list \(w\), the machine \(M\) started on the word \(\iota(w)\) (the bits of \(w\) mapped by \(\iota\)) halts on the one-cell tape \(\iota(L(w))\) within \(p(|w|)\) steps.
def SingleTapeP : DecisionComplexityClass :=
{L | ∃ (Symbol : Type) (_ : Inhabited Symbol) (_ : Fintype Symbol) (ι : Bool → Symbol),
Function.Injective ι ∧ ∃ (tm : SingleTapeTM Symbol) (p : Polynomial ℕ),
∀ w : List Bool, tm.OutputsWithinTime (w.map ι) [ι (L w)] (p.eval w.length)}
abbrev DecisionComplexityClass := Set DecisionProblem
MathlibExt/Computability/Complexity.lean:174
Uses 2 · Used by 1
TheoremProblems in P are decided in polynomial time by single-tape machines#✓fully proved
Every decision problem in the class \(\mathrm{P}\) (defined with multi-stack machines) belongs to the class of decision problems decided in polynomial time by single-tape machines.
The proof reverses the input, restricts the multi-stack machine to finite alphabets and emulates it on a single tape within quadratic overhead.
theorem P_subset_singleTapeP : P ⊆ SingleTapeP
def P : DecisionComplexityClass :=
{ L | IsPolyTime L }
MathlibExt/Computability/Complexity.lean:194
def SingleTapeP : DecisionComplexityClass :=
{L | ∃ (Symbol : Type) (_ : Inhabited Symbol) (_ : Fintype Symbol) (ι : Bool → Symbol),
Function.Injective ι ∧ ∃ (tm : SingleTapeTM Symbol) (p : Polynomial ℕ),
∀ w : List Bool, tm.OutputsWithinTime (w.map ι) [ι (L w)] (p.eval w.length)}
CSLibExt/Computability/Machines/Turing/SingleTape/PolyTime.lean:455
Uses 22
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.