aboutsummaryrefslogtreecommitdiff
path: root/Turing/Machine.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Turing/Machine.hs')
-rw-r--r--Turing/Machine.hs139
1 files changed, 139 insertions, 0 deletions
diff --git a/Turing/Machine.hs b/Turing/Machine.hs
new file mode 100644
index 0000000..1eace5e
--- /dev/null
+++ b/Turing/Machine.hs
@@ -0,0 +1,139 @@
+module Turing.Machine where
+
+import Import
+
+import qualified Data.Map.Strict as Map
+
+import Data.List
+import Data.Monoid
+import Control.Monad
+
+data Symbol = SymInit | SymWild | SymSpace | Symbol Char deriving (Eq, Ord)
+instance Show Symbol where
+ show (Symbol c) = [c]
+ show SymInit = ">"
+ show SymWild = "*"
+ show SymSpace = "_"
+
+special :: Symbol -> Bool
+special (Symbol _) = False
+special _ = True
+
+charToSym :: Char -> Symbol
+charToSym '_' = SymSpace
+charToSym c = Symbol c
+
+data Action = W Symbol | L | R
+instance Show Action where
+ show (W sym) = show sym
+ show L = "←"
+ show R = "→"
+
+type State = Int
+type TransF = State -> Symbol -> Maybe (Action, State) -- TODO delete
+type Trans = Map.Map (State,Symbol) (Action,State)
+
+-- Turing Machine
+data Machine = Machine { states :: [State]
+ , s0 :: State
+ , finals :: [State]
+ , symbols :: [Symbol]
+ , delta :: TransF
+ , trans :: Trans }
+instance Show Machine where
+ show (Machine sts ini fins syms _ trs) =
+ intercalate "\n\n"
+ [ "--- Turing Machine ---"
+ , " States: [" ++ show (head sts) ++ ".." ++ show (last sts) ++ "]"
+ , " Initial state: " ++ show ini
+ , " Final states: " ++ show fins
+ , " Symbols: " ++ show syms
+ , " Transition table:\n" ++ showTrans trs ]
+instance Monoid Machine where
+ mempty = nop
+ mappend = comp
+
+showTrans :: Trans -> String
+showTrans trs = separator ++ intercalate' "\n" table ++ separator
+ where separator = " +" ++ concatMap (\s -> replicate s '-' ++ "--+") lengths
+ table = map (intercalate' " | "
+ . map (\ (ml, f) -> replicate (ml - length f) ' ' ++ f)
+ . zip lengths) fields
+ lengths = map (maximum . map length) (transpose fields)
+ fields = map (\ ((a, b), (c, d)) -> [show a, show b, show c, show d])
+ (Map.toList trs)
+ intercalate' x xs = x ++ intercalate x xs ++ x
+
+mkDelta :: Trans -> TransF
+mkDelta trs st sym =
+ msum $ map (`Map.lookup` trs) [(st, sym), (st, SymWild)]
+
+mkMachine :: [(State, Symbol, Action, State)] -> Machine
+mkMachine trs = Machine sts ini fins syms (mkDelta trns) trns
+ where sts = sort $ union stsFrom stsTo
+ ini = minimum sts
+ fins = sort $ stsTo \\ stsFrom
+ syms = nub . filter (not . special) . map (\(_,sy,_,_) -> sy) $ trs
+ trns = Map.fromList (map (\(s1,sy,a,s2) -> ((s1,sy),(a,s2))) trs)
+ stsTo = nub $ map (\(_,_,_,s) -> s) trs
+ stsFrom = nub $ map (\(s,_,_,_) -> s) trs
+
+nop :: Machine
+nop = mkMachine [(0, SymWild, W SymWild, 1)]
+
+freshen :: Machine -> Machine -> Machine
+freshen m1 m2 = Machine sts ini fins syms d trns
+ where sts = map (+ offset) (states m2)
+ ini = s0 m2 + offset
+ fins = map (+ offset) (finals m2)
+ syms = symbols m2
+ d = mkDelta trns
+ trns = Map.map (\(a,s2) -> (a,s2+offset)) $
+ Map.mapKeys (\(s1,sy) -> (s1+offset,sy)) (trans m2)
+ offset = maximum (states m1) + 1
+
+comp :: Machine -> Machine -> Machine
+comp m1 m2 = Machine sts ini fins syms d trns
+ where sts = sort $ states m1 `union` states m2'
+ ini = s0 m1
+ fins = finals m2'
+ syms = symbols m1 `union` symbols m2'
+ d st sym = msum $ map (\ s -> Map.lookup (st,s) trns) [sym, SymWild]
+ trns = Map.union connect $ Map.union (trans m1) (trans m2')
+ connect = Map.fromList $
+ map (\ s1 -> ((s1,SymWild),(W SymWild, s0 m2'))) (finals m1)
+ m2' = freshen m1 m2
+
+-- Configuration
+type Tape = [Symbol]
+
+showTape :: Tape -> String
+showTape = concatMap show
+
+type Position = Int
+data Config = Config { tape :: Tape
+ , pos :: Position
+ , state :: State }
+instance Show Config where
+ show (Config t p s) = concat [roof, "\n|", showTape t, "\n", pointer, "\n"]
+ where roof = ' ' : replicate (length t) '_'
+ pointer = replicate (p+1) ' ' ++ "▲" ++ show s
+
+mkConfig :: Tape -> Config
+mkConfig t = Config (SymInit:t) 1 0
+
+step :: Config -> TransF -> Maybe Config
+step (Config t p s) d = fmap doAction (d s (t !! p))
+ where doAction (L, s') = Config (adjust t (p-1)) (p-1) s'
+ doAction (R, s') = Config (adjust t (p+1)) (p+1) s'
+ doAction (W sy, s')
+ | sy == SymWild = Config t p s'
+ | otherwise = Config (adjust (replace t p sy) p) p s'
+ adjust l newpos
+ | diff > 0 = l ++ replicate diff SymSpace
+ | diff < 0 && last l == SymSpace = init l
+ | otherwise = l
+ where diff = newpos - (length l - 1)
+ replace [] _ _ = []
+ replace (_:xs) 0 e = e : xs
+ replace (x:xs) n e = x : replace xs (n-1) e