-
Notifications
You must be signed in to change notification settings - Fork 183
feat(MultiTapeTM): Nondeterministic multi-tape Turing machines #820
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
barni120400
wants to merge
4
commits into
leanprover:main
Choose a base branch
from
barni120400:multitape/ntm
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
2b62c21
refactor(MultiTapeTM): Put the output tape into the configuration
avivbarnatan-air 794c978
refactor(MultiTapeTM): Rename `configs` to `runFrom`
avivbarnatan-air 3f015fb
docs(MultiTapeTM): address review comments
avivbarnatan-air e9426ed
feat(MultiTapeTM): Nondeterministic multi-tape Turing machines
avivbarnatan-air File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
187 changes: 187 additions & 0 deletions
187
Cslib/Computability/Machines/Turing/MultiTape/Configuration.lean
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| /- | ||
| Copyright (c) 2026 Christian Reitwiessner. All rights reserved. | ||
| Released under Apache 2.0 license as described in the file LICENSE. | ||
| Authors: Christian Reitwiessner, Aviv Bar Natan | ||
| -/ | ||
|
|
||
| module | ||
|
|
||
| public import Mathlib.Algebra.Order.BigOperators.Group.Finset | ||
| public import Mathlib.Algebra.Order.Group.Abs | ||
| public import Mathlib.Algebra.Order.Group.Int | ||
| public import Mathlib.Data.Finset.Dedup | ||
| public import Mathlib.Data.Finset.Max | ||
| public import Mathlib.Data.Int.Interval | ||
| public import Mathlib.Data.Sign.Defs | ||
| public import Cslib.Init | ||
|
|
||
| /-! | ||
| # Configurations of Multi-Tape Turing Machines | ||
|
|
||
| Configurations of a multi-tape Turing machine with a read-only input tape, `k` work tapes and one | ||
| write-only output tape, together with what a single transition does to one and the space measure | ||
| read off a list of them. | ||
|
|
||
| ## Design | ||
|
|
||
| Nothing here mentions a machine. A step is described in two parts: an `Action`, recording | ||
| which way the input head moves, what is written and where the work heads move, which symbol is | ||
| emitted and which state follows; and `Action.apply`, which carries it out on a | ||
| configuration. | ||
|
|
||
| The output tape is part of the configuration, so the string emitted along a run can be read off | ||
| the configuration the run ends in. | ||
|
|
||
| ## Important Declarations | ||
|
|
||
| * `Cfg`: the configuration: the internal state, the tape contents and head positions, and the | ||
| output tape | ||
| * `Action`: what a machine does in one step | ||
| * `Action.apply`: the effect of one action on a configuration | ||
| * `Cfg.Halted`, `Cfg.init`: halting, and the configuration a machine starts in | ||
| * `spaceUsedOfCfgs`: work tape cells touched along a list of configurations | ||
| -/ | ||
|
|
||
| @[expose] public section | ||
|
|
||
| namespace Turing | ||
|
|
||
| variable {k : ℕ} {State Symbol : Type*} {input : List Symbol} | ||
|
|
||
| /-- What a machine does in one step. -/ | ||
| structure Action (k : ℕ) (Symbol State : Type*) where | ||
| /-- The movement (attempt) of the input head. -/ | ||
| inputMove : SignType | ||
| /-- Actions on the work tapes: optionally a symbol to write and the head movement. -/ | ||
| workActions : Fin k → (Option (Option Symbol)) × SignType | ||
| /-- An optional symbol to output. -/ | ||
| outS : Option Symbol | ||
| /-- The successor state or none to halt. -/ | ||
| q' : Option State | ||
|
|
||
| /-- | ||
| The configurations of a Turing machine is relative to the input of the machine and consist of: | ||
| - an `Option`al state (or none for the halting state), | ||
| - the position of the input head (shifted by one), | ||
| - the contents of the work tape, | ||
| - the positions of the work tape heads, | ||
| - the contents of the write-only output tape | ||
| -/ | ||
| @[ext] | ||
| structure Cfg (k : ℕ) (Symbol State : Type*) (input : List Symbol) where | ||
| /-- the state of the TM (or none for the halting state) -/ | ||
| state : Option State | ||
| /-- the position of the input head, shifted by one -/ | ||
| inputPos : Fin (input.length + 2) | ||
| /-- the work tapes -/ | ||
| workTapes : Fin k → ℤ → Option Symbol | ||
| /-- the positions of the heads on the work tapes -/ | ||
| workTapePos : Fin k → ℤ | ||
| /-- the contents of the write-only output tape -/ | ||
| output : List Symbol | ||
| deriving Inhabited | ||
|
|
||
| /-- Attempt to move the input tape head. | ||
| The machine can only read one empty cell outside of the input, | ||
| any attempted movement beyond that results in no movement. | ||
|
|
||
| The addition is performed in `ℤ` before clamping. Performing it in `Fin (n + 2)` would wrap an | ||
| outward boundary move to the opposite end of the input. -/ | ||
| @[scoped grind =] | ||
| def moveInputPos {n : ℕ} (pos : Fin (n + 2)) (m : SignType) : Fin (n + 2) := | ||
| let p := ((pos.val : ℤ) + (m.cast : ℤ)).toNat | ||
| if h : p < n + 2 then ⟨p, h⟩ else ⟨n + 1, by omega⟩ | ||
|
|
||
| @[simp] | ||
| lemma moveInputPos_zero {n : ℕ} (pos : Fin (n + 2)) : | ||
| moveInputPos pos 0 = pos := by | ||
| apply Fin.ext | ||
| simp [moveInputPos, pos.isLt] | ||
|
|
||
| @[simp] | ||
| lemma moveInputPos_leftBoundary {n : ℕ} : | ||
| moveInputPos (0 : Fin (n + 2)) (-1) = 0 := by | ||
| apply Fin.ext | ||
| simp [moveInputPos] | ||
|
|
||
| @[simp] | ||
| lemma moveInputPos_rightBoundary {n : ℕ} : | ||
| moveInputPos (⟨n + 1, by omega⟩ : Fin (n + 2)) 1 = ⟨n + 1, by omega⟩ := by | ||
| unfold moveInputPos | ||
| rw [dite_eq_right (by simp; omega)] | ||
|
|
||
| /-- A left move away from the left input boundary decrements the native input position. -/ | ||
| lemma moveInputPos_neg_of_ne_left {n : ℕ} (p : Fin (n + 2)) (h : p ≠ 0) : | ||
| moveInputPos p .neg = ⟨p.val - 1, by have := p.isLt; omega⟩ := by | ||
| have hp : 0 < p.val := Nat.pos_of_ne_zero (fun hz => h (Fin.ext hz)) | ||
| unfold moveInputPos | ||
| apply Fin.ext | ||
| rw [dite_eq_left] <;> simp <;> omega | ||
|
|
||
| /-- A right move away from the right input boundary increments the native input position. -/ | ||
| lemma moveInputPos_pos_of_ne_right {n : ℕ} (p : Fin (n + 2)) (h : p.val ≠ n + 1) : | ||
| moveInputPos p .pos = ⟨p.val + 1, by have := p.isLt; omega⟩ := by | ||
| unfold moveInputPos | ||
| rw [dite_eq_left] | ||
| · apply Fin.ext | ||
| simp | ||
| · simp | ||
| omega | ||
|
|
||
| /-- The symbol currently under the input tape head. -/ | ||
| def Cfg.inputSymbol (cfg : Cfg k Symbol State input) : Option Symbol := | ||
| if h₁ : cfg.inputPos = 0 then none | ||
| else if h₂ : cfg.inputPos = input.length + 1 then none | ||
| else input[cfg.inputPos.val - 1]'(by grind) | ||
|
|
||
| @[simp] | ||
| lemma inputSymbolInner {cfg : Cfg k Symbol State input} (p : ℕ) | ||
| (h₁ : cfg.inputPos.val = 1 + p) | ||
| (h₂ : p < input.length) : | ||
| cfg.inputSymbol = some input[p] := by | ||
| grind [Cfg.inputSymbol] | ||
|
|
||
| /-- The symbol read by work tape `i`. -/ | ||
| def Cfg.workTapeSymbols (cfg : Cfg k Symbol State input) (i : Fin k) : Option Symbol := | ||
| cfg.workTapes i (cfg.workTapePos i) | ||
|
|
||
| /-- A configuration is halted when it has no state to continue from. -/ | ||
| abbrev Cfg.Halted (cfg : Cfg k Symbol State input) : Prop := cfg.state = none | ||
|
|
||
| /-- The initial configuration for a starting state and an input string. -/ | ||
| @[simp] | ||
| def Cfg.init (q₀ : State) (input : List Symbol) : Cfg k Symbol State input := | ||
| ⟨some q₀, 1, fun _ _ => none, fun _ => 0, []⟩ | ||
|
|
||
| /-- | ||
| The effect of an action on a configuration: move the input head, write and move on the work tapes, | ||
| append the emitted symbol to the output tape, and go to the successor state. This is the part of a | ||
| step that does not depend on how the action was chosen. | ||
| -/ | ||
| @[simp] | ||
| def Action.apply (out : Action k Symbol State) (cfg : Cfg k Symbol State input) : | ||
| Cfg k Symbol State input where | ||
| state := out.q' | ||
| inputPos := moveInputPos cfg.inputPos out.inputMove | ||
| workTapes i := match (out.workActions i).1 with | ||
| | none => cfg.workTapes i | ||
| | some s => Function.update (cfg.workTapes i) (cfg.workTapePos i) s | ||
| workTapePos i := cfg.workTapePos i + (out.workActions i).2 | ||
| output := cfg.output ++ out.outS.toList | ||
|
|
||
| /-- A work tape head moves by at most one cell when an action is applied. -/ | ||
| lemma workTapePos_apply_le (out : Action k Symbol State) | ||
| (cfg : Cfg k Symbol State input) (i : Fin k) : | ||
| |(out.apply cfg).workTapePos i - cfg.workTapePos i| ≤ 1 := by | ||
| simp only [Action.apply, add_sub_cancel_left, abs_le, SignType.cast] | ||
| grind | ||
|
|
||
| /-- The work tape cells visited by the head of tape `i` along a list of configurations. -/ | ||
| def visitedOfCfgs (cfgs : List (Cfg k Symbol State input)) (i : Fin k) : Finset ℤ := | ||
| (cfgs.map (·.workTapePos i)).toFinset | ||
|
|
||
| /-- The number of work tape cells touched by the heads along a list of configurations. -/ | ||
| def spaceUsedOfCfgs (cfgs : List (Cfg k Symbol State input)) : ℕ := | ||
| ∑ i, (visitedOfCfgs cfgs i).card | ||
|
|
||
| end Turing | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.