Documentation

Cslib.Computability.Machines.Turing.MultiTape.Deterministic

Deterministic Multi-Tape Turing Machines #

Defines deterministic Turing machines with a read-only input tape, k work tapes and one write-only output tape. The tapes contain symbols from Option Symbol for a finite alphabet Symbol (where none is the blank symbol).

Design #

The multi-tape Turing machine uses a read-only input tape, k work tapes and a write-only output tape. The input head can move freely on the input, but any move attempt beyond one cell outside the input results in no movement. The transition function can optionally output one symbol, which models the write-only output tape. Because of these restrictions, we ignore the input and output tapes for space usage of the machine. The space usage is defined as the total number of cells the work tape heads visited during execution.

Restricting the movement of the input head is not essential, but useful because it allows us to easily bound the number of possible configurations of a space-bounded machine. Most textbooks have this restriction.

Instead of considering the cells visited by the work tape heads, some textbooks (including [AB09]) only consider the number of cells that contain a non-blank symbol at some point in the execution or the number of cells written to. This allows work tape heads to freely move at no cost as long as they do not write. It is important to note that this causes DSPACE(1) to include DSPACE(log log n), a class that contains e.g. the non-regular language {0^n 1^n | n ∈ ℕ} (it is accepted by a TM that writes a single marker on the work tape and then counts the number of symbols by work tape head movement without writing). Defining space usage via "cells visited" thus yields the more fine-grained "complexity world" in which DSPACE(1) is exactly the class of regular languages.

This definition is adapted from the one in [Pap94], chapter 2.3 including the sub-linear space modifications from chapter 2.5 with the following changes:

Important Declarations #

We define a number of structures and concepts related to multi-tape Turing machine computation:

There are two ways to talk about the behaviour of a multi-tape Turing machine, and they are proven to be equivalent.

References #

structure Turing.MultiTapeTM (k : ) (Symbol : Type u_3) (State : Type u_4) :
Type (max u_3 u_4)

A multi-tape Turing machine with k work tapes over the alphabet of Option Symbol (where none is the blank tape symbol). Note that it is not required that Symbol or State are finite to keep the definition more general. The restriction will be introduced once we start talking about computability by Turing machines in general.

  • q₀ : State

    initial state

  • tr (q : State) (input : Option Symbol) (work : Fin kOption Symbol) : Action k Symbol State

    transition function, mapping a state, the current input symbol and a tuple of work head symbols to a movement for the input head, actions on the work tape, optionally a symbol to output and the successor state

Instances For

    Stepping a Turing Machine #

    This section defines the step function that lets the machine transition from one configuration to the next, and the configuration reached after a number of steps. Configurations themselves are defined in Cslib.Computability.Machines.Turing.MultiTape.Configuration.

    def Turing.MultiTapeTM.step {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) :
    Cfg k Symbol State input

    The step function corresponding to a MultiTapeTM.

    Equations
    Instances For
      def Turing.MultiTapeTM.outputSymbol {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) :
      Option Symbol

      The symbol (optionally) output when executing one step starting from configuration cfg.

      Equations
      Instances For
        def Turing.MultiTapeTM.initCfg {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} (input : List Symbol) :
        Cfg k Symbol State input

        The initial configuration corresponding to an input string.

        Equations
        Instances For
          @[simp]
          theorem Turing.MultiTapeTM.step_of_halt {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} {cfg : Cfg k Symbol State input} (h : cfg.state = none) :
          step cfg = cfg
          def Turing.MultiTapeTM.runFrom {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) :
          Cfg k Symbol State input

          The configuration reached by running the Turing machine for t steps from cfg. If the Turing machine halts, it will stay at the halting configuration.

          Equations
          Instances For
            @[simp]
            theorem Turing.MultiTapeTM.runFrom_zero {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} {cfg : Cfg k Symbol State input} :
            runFrom cfg 0 = cfg
            theorem Turing.MultiTapeTM.runFrom_succ_eq_step {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} {cfg : Cfg k Symbol State input} {t : } :
            runFrom cfg (t + 1) = runFrom (step cfg) t
            theorem Turing.MultiTapeTM.runFrom_succ_eq_step' {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} {cfg : Cfg k Symbol State input} {t : } :
            runFrom cfg (t + 1) = step (runFrom cfg t)
            theorem Turing.MultiTapeTM.runFrom_add {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (a b : ) :
            runFrom cfg (a + b) = runFrom (runFrom cfg a) b

            Running a + b steps equals running b steps from the configuration reached after a.

            theorem Turing.MultiTapeTM.runFrom_comm_of_step {k : } {State : Type u_1} {Symbol : Type u_2} {k' : } {State' : Type u_3} {input input' : List Symbol} {tm : MultiTapeTM k Symbol State} {tm' : MultiTapeTM k' Symbol State'} (f : Cfg k Symbol State inputCfg k' Symbol State' input') (hstep : ∀ (cfg : Cfg k Symbol State input), step (f cfg) = f (step cfg)) (cfg : Cfg k Symbol State input) (n : ) :
            runFrom (f cfg) n = f (runFrom cfg n)

            If a function f that maps the configurations of one TM to those of another one commutes with their step function, then it also commutes with their runFrom function.

            @[simp]
            theorem Turing.MultiTapeTM.runFrom_of_halt {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (h : cfg.state = none) {n : } :
            runFrom cfg n = cfg

            Running from a halting configuration stays at that configuration.

            theorem Turing.MultiTapeTM.runFrom_eq_of_halt {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg : Cfg k Symbol State input) {τ t : } (hle : τ t) (hhalt : (runFrom cfg τ).state = none) :
            runFrom cfg t = runFrom cfg τ

            Nothing changes after the machine has halted.

            theorem Turing.MultiTapeTM.exists_minimal_halting_time {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg : Cfg k Symbol State input) (t : ) (hhalt : (runFrom cfg t).state = none) :
            ut, (runFrom cfg u).state = none s < u, (runFrom cfg s).state none

            Every halted run has a first halting time no later than the supplied one.

            @[simp]
            theorem Turing.MultiTapeTM.outputSymbol_of_halt {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} {cfg : Cfg k Symbol State input} (h_halt : cfg.state = none) :
            theorem Turing.MultiTapeTM.workTapePos_step_le {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (c : Cfg k Symbol State input) (i : Fin k) :

            The work-tape head moves by at most one cell in a single step.

            Now we define space usage and add some helper lemmas.

            def Turing.MultiTapeTM.visitedByTapeHead {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) (i : Fin k) :

            The set of positions visited by the head of work tape i in the computation starting from configuration cfg up to step t.

            Equations
            Instances For
              def Turing.MultiTapeTM.spaceUsedByTape {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) (i : Fin k) :

              The number of work tape cells touched by the head of tape i in the computation starting from configuration cfg up to step t.

              Equations
              Instances For
                def Turing.MultiTapeTM.spaceUsed {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) :

                The number of work tape cells touched by a computation starting from configuration cfg up to step t.

                Equations
                Instances For
                  @[simp]
                  theorem Turing.MultiTapeTM.spaceUsed_zero_tapes_eq_zero {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) (h_zero : k = 0) :
                  spaceUsed cfg t = 0

                  A zero-tape Turing machine uses zero space.

                  theorem Turing.MultiTapeTM.spaceUsedByTape_le_spaceUsed {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) (i : Fin k) :

                  Each tape's space usage is bounded by the total space used.

                  theorem Turing.MultiTapeTM.spaceUsed_eq_spaceUsedOfCfgs {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (t : ) :

                  The space used up to step t is the space touched by the configurations up to step t.

                  def Turing.MultiTapeTM.TransitionRelation {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (c₁ c₂ : Cfg k Symbol State input) :

                  The TransitionRelation corresponding to a MultiTapeTM k Symbol is defined by the step function, which maps a configuration to its next configuration.

                  Equations
                  Instances For
                    @[simp]
                    theorem Turing.MultiTapeTM.step_output {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) :

                    One step appends the symbol (optionally) emitted by that step to the output tape.

                    theorem Turing.MultiTapeTM.runFrom_output_eq_of_halt {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg : Cfg k Symbol State input) {τ t : } (hle : τ t) (hhalt : (runFrom cfg τ).state = none) :
                    (runFrom cfg t).output = (runFrom cfg τ).output

                    The output does not change after the machine has halted.

                    def Turing.MultiTapeTM.ComputesInTimeAndSpace {k : } {State : Type u_1} {Symbol : Type u_2} (tm : MultiTapeTM k Symbol State) (input output : List Symbol) (t s : ) :

                    A proof that the Turing machine tm on input input outputs output in at most t steps and uses exactly s space. Note that this does not require the alphabet or state set to be finite.

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For
                      def Turing.MultiTapeTM.ComputesFunInTimeAndSpace {k : } {State : Type u_1} {Symbol : Type u_2} {α : Type u_3} {β : Type u_4} (tm : MultiTapeTM k Symbol State) (encIn : α List Symbol) (encOut : β List Symbol) (f : αβ) (t s : α) :

                      A machine computes f between the supplied encodings, with bounds depending on the input. The machine's alphabet and state type need not be finite.

                      Equations
                      Instances For
                        def Turing.MultiTapeTM.ComputableInTimeAndSpace {α : Type u_3} {β : Type u_4} (f : αβ) (encIn : α List Bool) (encOut : β List Bool) (t s : α) :

                        A function is computable within the input-indexed bounds by a machine with binary alphabet and finitely many states.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          @[reducible, inline]
                          abbrev Turing.MultiTapeTM.ComputableInTimeAndSpaceOfLength {α : Type u_3} {β : Type u_4} (f : αβ) (encIn : α List Bool) (encOut : β List Bool) (t s : ) :

                          There exists a binary Turing machine with finitely many states that, for every input a, computes encOut (f a) from encIn a in at most t (encIn a).length steps, using at most s (encIn a).length work-tape cells.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            theorem Turing.MultiTapeTM.ComputesFunInTimeAndSpace.mono {k : } {State : Type u_1} {Symbol : Type u_2} {α : Type u_3} {β : Type u_4} {tm : MultiTapeTM k Symbol State} {encIn : α List Symbol} {encOut : β List Symbol} {f : αβ} {t s t' s' : α} (h : tm.ComputesFunInTimeAndSpace encIn encOut f t s) (ht : ∀ (a : α), t a t' a) (hs : ∀ (a : α), s a s' a) :
                            tm.ComputesFunInTimeAndSpace encIn encOut f t' s'

                            Resource bounds can be weakened independently on every input.

                            theorem Turing.MultiTapeTM.ComputableInTimeAndSpace.mono {α : Type u_3} {β : Type u_4} {f : αβ} {encIn : α List Bool} {encOut : β List Bool} {t s t' s' : α} (h : ComputableInTimeAndSpace f encIn encOut t s) (ht : ∀ (a : α), t a t' a) (hs : ∀ (a : α), s a s' a) :
                            ComputableInTimeAndSpace f encIn encOut t' s'

                            Computability is monotone in the resource bounds.

                            noncomputable def Turing.MultiTapeTM.indicator {α : Type u_3} (L : Set α) :
                            αBool

                            The Boolean indicator function of a set.

                            Equations
                            Instances For
                              def Turing.MultiTapeTM.DecidableInTimeAndSpace {α : Type u_3} (L : Set α) (enc : α List Bool) (t s : α) :

                              A set is decidable within the given input-indexed bounds when its Boolean indicator is.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                theorem Turing.MultiTapeTM.relatesInSteps_iff_runFrom_eq {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg₁ cfg₂ : Cfg k Symbol State input) (t : ) :
                                Relation.RelatesInSteps TransitionRelation cfg₁ cfg₂ t runFrom cfg₁ t = cfg₂

                                This lemma translates between the relational notion and the iterated step notion. The latter can be more convenient especially for deterministic machines as we have here.

                                def Turing.MultiTapeTM.haltsAtStep {k : } {State : Type u_1} {Symbol : Type u_2} (tm : MultiTapeTM k Symbol State) (input : List Symbol) (t : ) :

                                The Turing machine tm halts after exactly t steps on input input if its state is none at step t and non-none at step t - 1. Note that every Turing machine hast to perform at least one step to halt.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  theorem Turing.MultiTapeTM.halting_step_unique {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} {t₁ t₂ : } (h_halts₁ : tm.haltsAtStep input t₁ = true) (h_halts₂ : tm.haltsAtStep input t₂ = true) :
                                  t₁ = t₂

                                  If a Turing machine halts, the time step is uniquely determined.

                                  theorem Turing.MultiTapeTM.not_halts_of_repeat_nonhalt {k : } {State : Type u_1} {Symbol : Type u_2} {tm : MultiTapeTM k Symbol State} {input : List Symbol} (cfg : Cfg k Symbol State input) (h_not_halt : cfg.state none) (t : ) (heq : runFrom cfg (t + 1) = cfg) (t' : ) :

                                  If a deterministic machine repeats a non-halting configuration, it never halts, because the sequence between the two configurations will loop forever. Note that this can be applied to two arbitrary and different time steps t and t + Δ using tm.runFrom_add.