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.TransitionOut (k : ) (Symbol : Type u_3) (State : Type u_4) :
Type (max u_3 u_4)

The output of the transition function.

  • inputMove : SignType

    The movement (attempt) of the input head.

  • workActions : Fin kOption (Option Symbol) × SignType

    Actions on the work tapes: optionally a symbol to write and the head movement.

  • outS : Option Symbol

    An optional symbol to output.

  • q' : Option State

    The successor state or none to halt.

Instances For
    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 BiTape 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) : TransitionOut 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

      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, the resulting sequence of configurations and the initial configuration.

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

      The configurations of a Turing machine is relative to the input of the machine and consist of:

      • an Optional 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.
      • state : Option State

        the state of the TM (or none for the halting state)

      • inputPos : Fin (input.length + 2)

        the position of the input head, shifted by one

      • workTapes : Fin kOption Symbol

        the work tapes

      • workTapePos : Fin k

        the positions of the heads on the work tapes

      Instances For
        theorem Turing.MultiTapeTM.Cfg.ext {k : } {Symbol : Type u_3} {State : Type u_4} {input : List Symbol} {x y : Cfg k Symbol State input} (state : x.state = y.state) (inputPos : x.inputPos = y.inputPos) (workTapes : x.workTapes = y.workTapes) (workTapePos : x.workTapePos = y.workTapePos) :
        x = y
        theorem Turing.MultiTapeTM.Cfg.ext_iff {k : } {Symbol : Type u_3} {State : Type u_4} {input : List Symbol} {x y : Cfg k Symbol State input} :
        @[instance_reducible]
        instance Turing.MultiTapeTM.instInhabitedCfg {a✝ : } {a✝¹ : Type u_3} {a✝² : Type u_4} {a✝³ : List a✝¹} :
        Inhabited (Cfg a✝ a✝¹ a✝² a✝³)
        Equations
        def Turing.MultiTapeTM.moveInputPos {n : } (pos : Fin (n + 2)) (m : SignType) :
        Fin (n + 2)

        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.

        Equations
        Instances For
          @[simp]
          theorem Turing.MultiTapeTM.moveInputPos_zero {n : } (pos : Fin (n + 2)) :
          moveInputPos pos 0 = pos
          theorem Turing.MultiTapeTM.moveInputPos_neg_of_ne_left {n : } (p : Fin (n + 2)) (h : p 0) :

          A left move away from the left input boundary decrements the native input position.

          theorem Turing.MultiTapeTM.moveInputPos_pos_of_ne_right {n : } (p : Fin (n + 2)) (h : p n + 1) :

          A right move away from the right input boundary increments the native input position.

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

          The symbol currently under the input tape head.

          Equations
          Instances For
            @[simp]
            theorem Turing.MultiTapeTM.inputSymbolInner {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} {cfg : Cfg k Symbol State input} (p : ) (h₁ : cfg.inputPos = 1 + p) (h₂ : p < input.length) :
            cfg.inputSymbol = some input[p]
            def Turing.MultiTapeTM.Cfg.workTapeSymbols {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (cfg : Cfg k Symbol State input) (i : Fin k) :
            Option Symbol

            The symbol read by work tape i.

            Equations
            Instances For
              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
              • One or more equations did not get rendered due to their size.
              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
                    def Turing.MultiTapeTM.configs {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 sequence of configurations of the Turing machine starting from cfg. If the Turing machine halts, it will stay at the halting configuration.

                    Equations
                    Instances For
                      @[simp]
                      theorem Turing.MultiTapeTM.iter_step_eq_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} {n : } (h_halt : cfg.state = none) :
                      step^[n] cfg = cfg

                      Any number of steps run from a halting configuration results in the same configuration.

                      @[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.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 {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) :
                          spaceUsedByTape cfg t i t + 1

                          The number of cells touched by a single work tape grows by at most one each step.

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

                          The space used by a computation is bounded linearly by the number of steps.

                          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
                            def Turing.MultiTapeTM.outputString {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg₀ : Cfg k Symbol State input) (t : ) :
                            List Symbol

                            The string output by the Turing machine tm starting in configuration cfg₀, executing for t steps. It is the concatenation of the symbols (optionally) emitted at each of the first t steps.

                            Equations
                            Instances For
                              theorem Turing.MultiTapeTM.outputString_succ {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg : Cfg k Symbol State input) (t : ) :
                              tm.outputString cfg (t + 1) = tm.outputString cfg t ++ (outputSymbol (configs cfg t)).toList

                              The output produced in t + 1 steps is the output produced in t steps followed by the symbol (optionally) emitted at step t.

                              theorem Turing.MultiTapeTM.outputString_halt {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg : Cfg k Symbol State input) (h_halt : cfg.state = none) (t : ) :
                              tm.outputString cfg t = []

                              From a halting configuration, a TM does not output anything.

                              theorem Turing.MultiTapeTM.outputString_add_eq_append {k : } {State : Type u_1} {Symbol : Type u_2} {input : List Symbol} (tm : MultiTapeTM k Symbol State) (cfg : Cfg k Symbol State input) (t₁ t₂ : ) :
                              tm.outputString cfg (t₁ + t₂) = tm.outputString cfg t₁ ++ tm.outputString (configs cfg t₁) t₂
                              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} (tm : MultiTapeTM k Symbol State) {IOSymbol : Type u_3} (f : List IOSymbolList IOSymbol) (toMachineSymbol : IOSymbol Symbol) (t s : ) :

                                A proof that the Turing machine tm computes the function f such that on all inputs of length n it uses at most t n steps and s n space. It assumes an embedding function from the input/output alphabet into the machine alphabet. 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.ComputableInTimeAndSpace {IOSymbol : Type u_3} (f : List IOSymbolList IOSymbol) (t s : ) :

                                  The main definition of complexity of multi-tape Turing machines: A proof that the function f is computable by some multi-tape Turing machine tm (with finite work alphabet and finite state set) via an alphabet embedding function toMachineSymbol, such that on all inputs of length n, tm uses at most t n steps and at most s n space.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    noncomputable def Turing.MultiTapeTM.indicator {Symbol : Type u_3} [Inhabited Symbol] (L : Language Symbol) :
                                    List SymbolList Symbol

                                    The indicator function of a language.

                                    Equations
                                    Instances For
                                      def Turing.MultiTapeTM.DecidableInTimeAndSpace {IOSymbol : Type} [Inhabited IOSymbol] (L : Language IOSymbol) (t s : ) :

                                      A language is decidable in time t and space s if and only if its indicator function is computable in time t and space s.

                                      Equations
                                      Instances For
                                        theorem Turing.MultiTapeTM.relatesInSteps_iff_configs_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 configs 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.