# CleanTuringMachines Turing machines implementation in [Clean](http://wiki.clean.cs.ru.nl/Clean). Features include: * Straightforward types for turing machines and their states * Running and stepping a turing machine in execution * Simple `toString` instances for easy display of the types * A `turinglog` program as an example and to be used to get a trace of the execution of a machine Read further for examples. ### License This program and the example are distributed under the MIT license. For more details, see the LICENSE file. ## Types and classes ### IterableClass Provides two general classes: class step a :: !a -> a class rewind a :: !a -> a Both are meant to be instantiated by types that can be 'stepped'. For example, the TuringMachineState instantiates the `step` class to be able to compute the next state for a current state. The `rewind` class is currently unused, but it only made sense to include it and make this a separate module. It allows a type to step backwards. Note, that for a Turing machine it is impossible to instantiate this class, because the transition function need not have an inverse. There are three derivative functions: stepn :: Int !a -> a | step a rewindn :: Int !a -> a | rewind a stepOrRewindn :: Int !a -> a | step, rewind a The first and second simply iterate `step` and `rewind`. Negative values for the first argument will never terminate. The latter function will evaluate to either `rewindn` or `stepn`, depending on the sign of the first argument. ### TuringMachines The tape is a simple list of Maybes of an arbitrary type. `Nothing` encodes a blank, `Just a` encodes the value `a`. :: Tape a :== [Maybe a] The transition function (shown subsequently) results in a `TuringMachineMove`. This can either be a `Step`, or a `Halt`. Normally, the transition function is a partial function. Here, it is expected to be a nonpartial function to avoid runtime errors. What would normally be undefined is now `Halt`: it tells the turing machine to terminate. :: TuringMachineMove a = Step Int (Maybe a) Direction | Halt :: Direction = Left | Right Here, `a` is the alphabet once again. A step changes state to the first argument, writes the second argument on the tape, and moves in the specified direction. A Turing machine state consists of a Turing machine definition, but also includes the current state, the position of the tape head, the tape itself, and whether the machine is running or not: :: TuringMachineState a = { machine :: TuringMachine a, state :: Int, tapeHead :: Int, tape :: Tape a, running :: TuringMachineTermination } :: TuringMachineTermination = Running | Normal | Abnormal Here, `a` is the tape alphabet. We will come back to that. As you can see, we specify states simply with integers. Mathematically, a Turing machine is a quintuple (Q,Σ,Γ,δ,q0) where Q is the set of states and q0 the initial state (Sudkamp, Languages and Machines, 1997). Here, we take the integers as Q and 0 as q0. `a` relates to Γ, `i` relates to Σ and we will get back to δ. The machine may be `Running`, or it may be terminated. In the latter case we distinguish between `Normal` termination (after a `Halt` move) and `Abnormal` termination (if the tape head position goes negative). Finaly, the definition of the Turing machine itself: :: TuringMachine a = { alphabet :: [a], inputs :: [a], transition :: Int (Maybe a) -> TuringMachineMove a } Again, we see the alphabet `a`. The transition function (δ) is a function from `Int` (the current state) and `Maybe a` (the character read by the tape head to a `TuringMachineMove a`. The `inputs` key specifies the input alphabet, typically a subset of the alphabet itself. It defines the characters allowed in the input. ### Examples The following is a simple machine to replace `a` with `b` and vice versa. It is an example from Sudkamp, Languages and Machines, 1997, where it is represented as a state machine: ![A graphical representation of the replace machine](http://i.stack.imgur.com/gOtXY.png) replace :: TuringMachine Char replace = { alphabet = ['a','b'], inputs = ['a','b'], transition = f } where f :: Int (Maybe Char) -> TuringMachineMove Char f 0 Nothing = Step 1 Nothing Right f 1 Nothing = Step 2 Nothing Left f 1 (Just 'a') = Step 1 (Just 'b') Right f 1 (Just 'b') = Step 1 (Just 'a') Right f 2 (Just 'a') = Step 2 (Just 'a') Left f 2 (Just 'b') = Step 2 (Just 'b') Left f _ _ = Halt Note the final catch-all alternative of the transition function `f`, which is used to make sure `f` is nonpartial. ## Firing up the machine Getting a `TuringMachineState` from a `TuringMachine` is fairly straightforward. All you need is a `Tape`. For the example above, we may write: state :: TuringMachineState Char Char state = initTuringMachine replace tape where tape = [Just c \\ c <- fromString "aabbaa"] The set builder for the tape is just ease of notation, we may as well have written `['a','a','b','b','a','b']`. A first and final blank is added to the tape by `initTuringMachine`. `initTuringMachine` checks that there are no characters on the tape that are not in the input alphabet, and aborts if there are. ## Stepping and running From this state we can either `step`... state1 = step state state5 = stepn 5 state ... or run until termination: statef = run state ## Showing results The `TuringMachineState` instantiates `toString`. The result of `toString statef` would be: [q2]BbbaabbB (Normally terminated) As you can see, the machine definition is in no way represented by this function. Blanks (`Nothing` on the tape) are represented with 'B'. ## Using `turinglog` `turinglog` is a simple implementation of the library and can be used to get a trace of the execution of a machine. Compile with: clm -I /opt/clean/lib/StdLib turinglog -o turinglog Replace `/opt/clean/lib/StdLib` with the appropriate path. Run with: ./turinglog Example output: [q0]BabbabaB (Running) B[q1]abbabaB (Running) Bb[q1]bbabaB (Running) Bba[q1]babaB (Running) Bbaa[q1]abaB (Running) Bbaab[q1]baB (Running) Bbaaba[q1]aB (Running) Bbaabab[q1]B (Running) Bbaaba[q2]bB (Running) Bbaab[q2]abB (Running) Bbaa[q2]babB (Running) Bba[q2]ababB (Running) Bb[q2]aababB (Running) B[q2]baababB (Running) [q2]BbaababB (Running) [q2]BbaababB (Normally terminated) As you can see, for each iteration the state is outputted. This example is using the `replace` machine of above and using the input `abbaba`. This is also the values in `turinglog` at the moment. Replace the machine and the tape as needed. ## Future ideas * It would be really cool to have some kind of graphical frontend and a possibility to step through the machine with some input