Single-Tape Turing Machines #
Defines a single-tape Turing machine for computing functions on List Symbol
for finite alphabet Symbol.
Design #
Here are some design choices made in this file:
These machines have access to a single bidirectionally-infinite tape (BiTape)
which uses symbols from Option Symbol.
The transition function of the machine takes a state
and a tape alphabet character under the read-head (i.e. an Option Symbol)
and returns a Stmt describing the tape action to take,
as well as an optional new state to transition to (where none means halt).
We do not make the "halting state" a member of the state type for a few reasons:
- To avoid the need for passing a subtype of "non-halting states" to the transition function.
- To make clear that TMs are not expected to continue on after entering this special state (in contrast to, say, a DFA entering/leaving an accepting state).
- To make it simpler to match on halting when modifying a machine.
We also include the possibility for non-movement actions, for convenience in composition of machines.
Important Declarations #
We define a number of structures related to Turing machine computation:
Stmt: the write and movement operations a TM can do in a single step.SingleTapeTM: the TM itself.Cfg: the configuration of a TM, including internal and tape state.TimeComputable f: a TM for computingf, packaged with a bound on runtime.PolyTimeComputable f:TimeComputable fpackaged with a polynomial bound on runtime.
We also provide ways of constructing polynomial-runtime TMs
PolyTimeComputable.id: computes the identity functionPolyTimeComputable.comp: computes the composition of polynomial time machines
TODOs #
- Encoding of types in lists to represent computations on arbitrary types.
- Add
∘notation forcompComputer.
Equations
Instances For
A single-tape Turing machine
over the alphabet of Option Symbol (where none is the blank BiTape symbol).
- State : Type
type of state labels
finiteness of the state type
- q₀ : self.State
Initial state
Transition function, mapping a state and a head symbol to a
Stmtto invoke, and optionally the new state to transition to afterwards (nonefor halt)
Instances For
Configurations of a Turing Machine #
This section defines the configurations of a Turing machine, the step function that lets the machine transition from one configuration to the next, and the intended initial and final configurations.
Equations
- tm.instInhabitedState = { default := tm.q₀ }
Equations
- tm.instFintypeState = tm.stateFintype
The configurations of a Turing machine consist of:
an Optional state (or none for the halting state),
and a BiTape representing the tape contents.
the state of the TM (or none for the halting state)
- BiTape : Turing.BiTape Symbol
the BiTape contents
Instances For
Instances For
Equations
The step function corresponding to a SingleTapeTM.
Equations
Instances For
The initial configuration corresponding to a list in the input alphabet.
Note that the entries of the tape constructed by BiTape.mk₁ are all some values.
This is to ensure that distinct lists map to distinct initial configurations.
Instances For
The final configuration corresponding to a list in the output alphabet. (We demand that the head halts at the leftmost position of the output.)
Instances For
The space used by a configuration is the space used by its tape.
Equations
- Turing.SingleTapeTM.Cfg.space_used tm cfg = cfg.BiTape.space_used
Instances For
The TransitionRelation corresponding to a SingleTapeTM Symbol
is defined by the step function,
which maps a configuration to its next configuration, if it exists.
Equations
- tm.TransitionRelation c₁ c₂ = (tm.step c₁ = some c₂)
Instances For
A proof of tm outputting l' on input l.
Equations
- tm.Outputs l l' = Relation.ReflTransGen tm.TransitionRelation (tm.initCfg l) (tm.haltCfg l')
Instances For
A proof of tm outputting l' on input l in at most m steps.
Equations
- tm.OutputsWithinTime l l' m = Relation.RelatesWithinSteps tm.TransitionRelation (tm.initCfg l) (tm.haltCfg l') m
Instances For
This lemma bounds the size blow-up of the output of a Turing machine. It states that the increase in length of the output over the input is bounded by the runtime. This is important for guaranteeing that composition of polynomial time Turing machines remains polynomial time, as the input to the second machine is bounded by the output length of the first machine.
A Turing machine computing the identity.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A Turing machine computing the composition of two other Turing machines.
If f and g are computed by Turing machines tm1 and tm2
then we can construct a Turing machine which computes g ∘ f by first running tm1
and then, when tm1 halts, transitioning to the start state of tm2 and running tm2.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Composition Computer Lemmas #
Time Computability #
This section defines the notion of time-bounded Turing Machines
A Turing machine + a time function +
a proof it outputs f in at most time(input.length) steps.
- tm : SingleTapeTM Symbol
the underlying bundled SingleTapeTM
a bound on runtime
- outputsFunInTime (a : List Symbol) : self.tm.OutputsWithinTime a (f a) (self.time_bound a.length)
proof this machine outputs
fin at mosttime_bound(input.length)steps
Instances For
The identity map on Symbol is computable in constant time.
Equations
- Turing.SingleTapeTM.TimeComputable.id = { tm := Turing.SingleTapeTM.idComputer, time_bound := fun (x : ℕ) => 1, outputsFunInTime := ⋯ }
Instances For
Time bounds for compComputer.
The compComputer of two machines which have time bounds is bounded by
- The time taken by the first machine on the input size
- added to the time taken by the second machine on the output size of the first machine (which is itself bounded by the time taken by the first machine)
Note that we require the time function of the second machine to be monotone; this is to ensure that if the first machine returns an output which is shorter than the maximum possible length of output for that input size, then the time bound for the second machine still holds for that shorter input to the second machine.
Equations
- hf.comp hg h_mono = { tm := hf.tm.compComputer hg.tm, time_bound := fun (l : ℕ) => hf.time_bound l + hg.time_bound (max 1 l + hf.time_bound l), outputsFunInTime := ⋯ }
Instances For
Polynomial Time Computability #
This section defines polynomial time computable functions on Turing machines, and proves that:
- The identity function is polynomial time computable
- The composition of two polynomial time computable functions is polynomial time computable
A Turing machine + a polynomial time function +
a proof it outputs f in at most time(input.length) steps.
- tm : SingleTapeTM Symbol
- time_bound : ℕ → ℕ
- poly : Polynomial ℕ
a polynomial time bound
proof that this machine outputs
fin at mosttime(input.length)steps
Instances For
A proof that the identity map on Symbol is computable in polytime.
Equations
- Turing.SingleTapeTM.PolyTimeComputable.id = { toTimeComputable := Turing.SingleTapeTM.TimeComputable.id, poly := 1, bounds := ⋯ }
Instances For
A proof that the composition of two polytime computable functions is polytime computable.