turingMachine 0.1.3.0 → 1.0.0.0
raw patch · 16 files changed
+1341/−360 lines, 16 filesdep +QuickCheckdep +QuickCheckVariantdep +hspecdep ~basedep ~containers
Dependencies added: QuickCheck, QuickCheckVariant, hspec, hspecVariant, mtl, turingMachine
Dependency ranges changed: base, containers
Files
- README.md +53/−2
- src/Data/Delta.hs +175/−20
- src/Data/Helper.hs +39/−0
- src/Data/Label.hs +117/−0
- src/Data/Numerable.hs +50/−0
- src/Data/Sigma.hs +64/−11
- src/Data/State.hs +0/−92
- src/Math/Model/Automaton/Finite.hs +461/−101
- src/Math/Model/Automaton/Stack.hs +43/−49
- src/Math/Model/Turing.hs +23/−23
- src/Math/Model/Turing/FourWays.hs +20/−20
- src/Math/Model/Turing/TwoWays.hs +31/−34
- test/FiniteTest.hs +156/−0
- test/LabelTest.hs +23/−0
- test/SigmaTest.hs +33/−0
- turingMachine.cabal +53/−8
README.md view
@@ -1,7 +1,13 @@ # Turing Machine Model-An implementation of Turing Machine and Automaton for language theory+An implementation of Turing Machine and Automaton for Language Theory -## Models+ [](https://hackage.haskell.org/package/turingMachine)+ [](https://travis-ci.org/sanjorgek/turingMachine)+ [](https://codeclimate.com/github/sanjorgek/turingMachine)+ [](https://codeclimate.com/github/sanjorgek/turingMachine)+ [](https://circleci.com/gh/sanjorgek/turingMachine)++## Math Models ### Finite Automaton Finite State machine, with no memory.@@ -15,3 +21,48 @@ Stack memory machine with states ### Turing Machine++## To Do++- [ ] Finite Automaton+ - [x] Delta+ - [x] Deterministic+ - [x] Non-deterministic+ - [x] Lift deltas+ - [x] Lambda+ - [x] Lambda1+ - [x] Lambda2+ - [x] Lift lambda+ - [ ] Recognizer+ - [x] Deterministic def+ - [x] Non-deterministic def+ - [x] Check Word+ - [ ] k-distinguishable states+ - [ ] Distinguishable states+ - [ ] Equivalent states+ - [x] Equivalent recognizer+ - [x] Non-deterministic to deterministic, and viceversa+ - [x] Recheable recognizer+ - [x] Distinguishable recognizer+ - [x] Minimize recognizer+ - [ ] Remove Ambiguity+ - [x] Language cadinality+ - [ ] Transductor+ - [x] Moore+ - [x] Mealy+ - [x] translate+ - [ ] Moore to Mealy, and viceversa + - [ ] Recognizer with epsilon transitions+ - [ ] def+ - [ ] Recognizer with epsilon transitions to Recognizer without epsilon transitions+- [ ] Stack Automaton+ - [x] Lift delta+ - [x] Deterministic stack automaton def+ - [ ] Non-deterministic stack automaton def+ - [ ] Non-deterministic to deterministic stack automaton+ - [ ] Recognizer with epsilon transitions+- [ ] Turing Machine+ - [ ] Class def+ - [ ] Tape def+ - [ ] Delta def+ - [ ] Accept word
src/Data/Delta.hs view
@@ -1,9 +1,9 @@-{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeOperators #-} {-|-Module : Delta-Description : Implementacion de un mapeo+Module : Data.Delta+Description : Partial functions Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016 License : GPL-3 Maintainer : sanjorgek@ciencias.unam.mx@@ -14,30 +14,185 @@ -} module Data.Delta (- -- * Delta+ -- * Delta+ -- ** Generic+ (:*>:)(..) -- ** Deterministic -- *** Constructor- (:->:)(..)+ ,(:->:)(..) -- *** Functions+ ,liftD ,nextD -- ** Not deterministic -- *** Constructor- ,(:>-:)(..)- -- * Transductor- -- ** Constructor- ,(:*>:)(..)+ ,(:-<:)(..)+ -- *** Functions+ ,liftND+ ,nextND+ -- ** Functions+ ,liftL+ ,nextTMaybe+ ,nextSymbol+ -- * Auxiliar functions+ ,getFirstParam+ ,getFirstParamSet+ ,getSecondParamD+ ,getSecondParamND+ ,getSecondParamSetD+ ,getSecondParamSetND+ ,getStateDomain+ ,getStateDomainSet+ ,getStateRangeD+ ,getStateRangeND+ ,getStateRangeSetD+ ,getStateRangeSetND ) where-import Data.State-import Control.Applicative-import Data.Monoid-import Data.Foldable-import qualified Data.Map.Lazy as Map+import qualified Data.Foldable as Fold+import Data.Label+import Data.List+import qualified Data.Map.Strict as Map+import Data.Maybe+import qualified Data.Set as Set+import Data.Sigma -type (:->:) a p1 p2 = Map.Map (State a, p1) (State a, p2)+{-|+Map a tuple, a state and a param, to some output+-}+type (:*>:) a p o = Map.Map (Label a, p) o -nextD :: (Ord p1, Ord a) => (:->:) a p1 p2 -> (State a, p1) -> State a-nextD dt k = if Map.member k dt then fst (dt Map.! k) else QE +{-|+Lift a generic delta/map from a 3-tuple list+-}+liftL :: (Ord a, Ord p) => [(a, p, o)] -> (:*>:) a p o+liftL ds = let+ (xs, ys, zs) = unzip3 ds+ in Map.fromList $ zip (zip (fmap return xs) ys) zs -type (:>-:) a p1 p2 = Map.Map (State a, p1) ([State a], p2)+{-|+Take a state and a param and maybe resolve some output+-}+nextTMaybe :: (Ord p1, Ord a) => (:*>:) a p1 o -> (Label a, p1) -> Maybe o+nextTMaybe dt k = if Map.member k dt+ then Just $ dt Map.! k+ else Nothing -type (:*>:) a p o = Map.Map (State a, p) o+{-|+For simple map with Chars range+-}+nextSymbol::(Ord p1, Ord a) => (:*>:) a p1 Symbol -> (Label a, p1) -> Symbol+nextSymbol dt k = fromMaybe '\NUL' $ nextTMaybe dt k++{-|+Deterministic Delta++Maps a tuple, a state and a param, to another tuple, a state and a param.+-}+type (:->:) a p1 p2 = (:*>:) a p1 (Label a, p2)++{-|+Lifts a deterministic delta from a 4-tuple list+-}+liftD::(Ord a, Ord p1) => [(a, p1, a, p2)] -> (:->:) a p1 p2+liftD ds = let+ (xs, ys, ws, zs) = unzip4 ds+ in liftL $ zip3 xs ys $ zip (fmap return ws) zs++{-|+Next state function for deterministic delta+-}+nextD :: (Ord p1, Ord a) => (:->:) a p1 p2 -> (Label a, p1) -> Label a+nextD dt k = maybe QE fst $ nextTMaybe dt k++{-|+Non-Deterministic Delta++Maps a tuple, a state and a param, to a tuple, a state list and a param.+-}+type (:-<:) a p1 p2 = (:*>:) a p1 (Set.Set (Label a, p2))++{-|+Lifts a non-deterministic delta from a 4-tuple list+-}+liftND::(Ord a, Ord p1, Ord p2) => [(a, p1, [(a,p2)])] -> (:-<:) a p1 p2+liftND ds = let+ (xs, ys, wss) = unzip3 ds+ f (x,y) = (return x, y)+ in liftL $ zip3 xs ys $ fmap (Set.fromList . fmap f) wss++{-|+Next state function for non-deterministic delta+-}+nextND :: (Ord p1, Ord a) => (:-<:) a p1 p2 -> p2 -> (Label a, p1) -> Set.Set (Label a)+nextND dt p k = maybe (Set.singleton QE) (Set.map fst) $ nextTMaybe dt k++{-|+Gets all params at domain, for (:->:) and (:-<:)+-}+getFirstParam::(Eq b) => Map.Map (a, b) a1 -> [b]+getFirstParam = nub . fmap snd . Map.keys++{-|+Gets all params at domain, for (:-<:) and (:-<:)+-}+getFirstParamSet::(Ord b) => Map.Map (a, b) a1 -> Set.Set b+getFirstParamSet = Set.fromList . fmap snd . Map.keys++{-|+Gets all states at domain, for (:->:) and (:-<:)+-}+getStateDomain::(Eq a) => Map.Map (a, b) a1 -> [a]+getStateDomain = nub . fmap fst . Map.keys++{-|+Gets all states at domain, for (:->:) and (:-<:)+-}+getStateDomainSet::(Ord a) => Map.Map (a, b) a1 -> Set.Set a+getStateDomainSet = Set.fromList . fmap fst . Map.keys++{-|+Gets all params at range, for (:->:)+-}+getSecondParamD::(Eq p2) => (:->:) a p1 p2 -> [p2]+getSecondParamD = nub . fmap snd . Map.elems++{-|+Gets all params at range, for (:->:)+-}+getSecondParamSetD::(Ord b) => Map.Map k (a, b) -> Set.Set b+getSecondParamSetD = Set.fromList . fmap snd . Map.elems++{-|+Gets all params at range, for (:-<:)+-}+getSecondParamND::(Ord p2) => (:-<:) a p1 p2 -> [p2]+getSecondParamND = foldr union [] . fmap (Set.toList . Set.map snd) . Map.elems++{-|+Gets all params at range, for (:-<:)+-}+getSecondParamSetND::(Ord p2) => (:-<:) a p1 p2 -> Set.Set p2+getSecondParamSetND = Set.unions . fmap (Set.map snd) . Map.elems++{-|+Gets first param at range, for (:->:)+-}+getStateRangeD::(Eq a) => (:->:) a p1 p2 -> [Label a]+getStateRangeD = nub . fmap fst . Map.elems++{-|+Gets first param at range, for (:->:)+-}+getStateRangeSetD::(Ord a) => (:->:) a p1 p2 -> Set.Set (Label a)+getStateRangeSetD = Set.fromList . fmap fst . Map.elems++{-|+Gets state at range in a list, for (:-<:)+-}+getStateRangeND::(Ord a) => (:-<:) a p1 p2 -> [Label a]+getStateRangeND = Set.toList . Set.unions . fmap (Set.map fst) . Map.elems++{-|+Gets state at range in a set, for (:-<:)+-}+getStateRangeSetND::(Ord a) => (:-<:) a p1 p2 -> Set.Set (Label a)+getStateRangeSetND = Set.unions . fmap (Set.map fst) . Map.elems
+ src/Data/Helper.hs view
@@ -0,0 +1,39 @@+{-# OPTIONS_HADDOCK show-extensions #-}+{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-|+Module : Helper+Description : Aux Functions+Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016+License : GPL-3+Maintainer : sanjorgek@ciencias.unam.mx+Stability : experimental+Portability : portable++Auxiliar Functions+-}+module Data.Helper+(+ -- * Set+ unionsFold+ ,setGenericSize+) where+import qualified Data.Foldable as Fold+import Data.List+import qualified Data.Map.Lazy as Map+import qualified Data.Set as Set++{-|+Union of set monad+-}+unionsFold:: (Ord a, Fold.Foldable t) => t (Set.Set a) -> Set.Set a+unionsFold = Fold.foldr Set.union Set.empty++{-|+Size of a set, with large integers+-}+setGenericSize:: (Ord a) => Set.Set a -> Integer+setGenericSize s = if Set.null s+ then 0+ else 1 + setGenericSize (Set.delete (Set.findMin s) s)
+ src/Data/Label.hs view
@@ -0,0 +1,117 @@+{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# OPTIONS_HADDOCK show-extensions #-}+{-|+Module : Data.State+Description : Simple label state data+Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016+License : GPL-3+Maintainer : sanjorgek@ciencias.unam.mx+Stability : experimental+Portability : portable++Simple Label-State function, have an isomorphism with Maybe but order are diferent+-}+module Data.Label+(+ -- * Data and type+ Label(..)+ ,Final(..)+ -- * Functions+ ,isError+ ,terminal+ -- * Alias+ ,SetLabel(..)+ ,LabelSS(..)+) where+import Control.Applicative+import Control.Monad+import qualified Data.Foldable as F+import Data.Monoid+import qualified Data.Set as Set++{-|+Machine states are only a label, maybe a letter+-}+data Label a =+ -- |State constructor+ Q a+ -- |Error state+ | QE deriving(Show, Eq)++-- |Same as Maybe+instance Functor Label where+ fmap _ QE = QE+ fmap f (Q q) = Q $ f q++-- |Same as Maybe+instance Applicative Label where+ pure = Q+ QE <*> _ = QE+ (Q f) <*> q = fmap f q++-- |Same as Maybe+instance Monad Label where+ return = pure+ QE >>= _ = QE+ (Q q) >>= f = f q++{-|+Holds++>>> QE /= (toEnum:: State Int) . fromEnum QE+True+-}+instance (Enum a) => Enum (Label a) where+ toEnum = return . toEnum+ fromEnum (Q x) = fromEnum x+ fromEnum QE = maxBound++-- |In this differ with Maybe because this show a upper bounded order+instance (Bounded a) => Bounded (Label a) where+ minBound = Q minBound+ maxBound = QE++instance (Ord a) => Ord (Label a) where+ compare QE QE = EQ+ compare _ QE = LT+ compare QE _ = GT+ compare (Q a) (Q b) = compare a b++instance Monoid a => Monoid (Label a) where+ mempty = QE+ QE `mappend` m = m+ m `mappend` QE = m+ (Q a) `mappend` (Q b) = Q (a `mappend` b)++instance F.Foldable Label where+ foldr _ z QE = z+ foldr f z (Q x) = f x z+ foldl _ z QE = z+ foldl f z (Q x) = f z x++{-|+Final label state represent a set of states which elements put end to computation+-}+type Final a = Set.Set (Label a)++{-|+Tells if a label state is final+-}+terminal :: (Ord a) => Final a -> Label a -> Bool+terminal qs q = Set.member q qs++{-|+Tells if a label state is a error state+-}+isError::(Eq a) => Label a -> Bool+isError = (QE==)++{-|+Alias for a set of lalbel states+-}+type SetLabel a = Set.Set (Label a)++{-|+Alias for a label state of a set of label states+-}+type LabelSS a = Label (SetLabel a)
+ src/Data/Numerable.hs view
@@ -0,0 +1,50 @@+{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# OPTIONS_HADDOCK show-extensions #-}+{-# LANGUAGE FlexibleInstances #-}+{-|+Module : Cardinal+Description : Cardinal Def+Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016+License : GPL-3+Maintainer : sanjorgek@ciencias.unam.mx+Stability : experimental+Portability : portable++Cardinal definitions+-}+module Data.Numerable where++{-|+All sets can be one and only one:++- a empty set+- a set with, at least, one element+-}+data Essence = Empty | Occupied deriving(Show, Eq, Ord, Bounded)++{-|+Simple cardinality definition, we work here with numerable sets.++All numerable set have one and only one:++1. A finite size++2. A infinite size+-}+data Discrete = Fin Integer | Numerable deriving(Show, Eq)++{-|+Order for numerable cardinality+-}+instance Ord Discrete where+ compare (Fin n) (Fin m) = compare n m+ compare Numerable Numerable = EQ+ compare Numerable _ = GT+ compare _ _ = LT++{-|+Bound limits for numerable cardinality+-}+instance Bounded Discrete where+ minBound = Fin 0+ maxBound = Numerable
src/Data/Sigma.hs view
@@ -1,6 +1,7 @@ {-# OPTIONS_HADDOCK show-extensions #-}-{-# OPTIONS_GHC -fno-warn-tabs #-}-{-# LANGUAGE TypeSynonymInstances #-}+{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeSynonymInstances #-} {-| Module : Sigma Description : Alphabet and symbols@@ -12,15 +13,24 @@ Alphabet and symbols of languaje -}-module Data.Sigma +module Data.Sigma (+ -- * Symbols Symbol(..) ,blank- ,z0 ,Wd(..)+ -- * Alphabets+ ,Alphabet(..)+ ,enumWord+ ,closureAlph+ ,lessKWords+ ,kWords ) where-import Data.Monoid-import Data.Char+import Data.Char+import Data.List+import qualified Data.Map.Lazy as Map+import Data.Monoid+import qualified Data.Set as Set {-| Symbols are character, and with Unicode CharSet we have a big amount of them.@@ -32,17 +42,60 @@ -} instance Monoid Symbol where mempty = blank- mappend x y = chr (mod ((ord x)+(ord y)) (ord maxBound)) -- |Blank symbol blank::Symbol blank = '\164' --- |Initial symbol for stack-z0::Symbol-z0 = '\248'- {-| List symbol alias, Word are defined in Prelude -} type Wd = [Symbol]++-- |An alphabet is a set of symbols+type Alphabet = Set.Set Symbol++{-|+For every alphabet there is a function __h__ that maps one symbol to one+natural. For every __h__ function there is a function that enumerete every+words in that alphabet+-}+enumWord::Alphabet -> Wd -> Integer+enumWord sig w = let+ sigL = Set.toList sig+ n = genericLength sigL+ map' = Map.fromList (zip (Set.toList sig) [1..])+ f [] = 0+ f xs = (n * f (init xs))+(map' Map.! last xs)+ in f w++closureAlph' sigL = fmap (:"") sigL ++ [x:ys | ys<-closureAlph' sigL, x<-sigL]++{-|+Gives the Kleene Closure for all alphabets. closureAlph is a infinite list of+words.+-}+closureAlph::Alphabet -> [Wd]+closureAlph sig = if Set.null sig+ then [""]+ else "":closureAlph' (Set.toList sig)++{-|+For some alphabet __S__ and a natural number __n__ take all words of length+__n__ or less+-}+lessKWords::Alphabet -> Integer -> [Wd]+lessKWords sig k = let+ f x y = genericLength y <= x+ in+ takeWhile (f k) (closureAlph sig)++{-|+For some alphabet __S__ and a natural number __n__ take all words of length __n__+-}+kWords::Alphabet -> Integer -> [Wd]+kWords sig k = let+ f x y = genericLength y == x+ g x y = genericLength y < x+ in+ takeWhile (f k) (dropWhile (g k) (closureAlph sig))
− src/Data/State.hs
@@ -1,92 +0,0 @@-{-# OPTIONS_GHC -fno-warn-tabs #-}-{-# OPTIONS_HADDOCK show-extensions #-}-{-|-Module : State-Description : Simple state data-Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016-License : GPL-3-Maintainer : sanjorgek@ciencias.unam.mx-Stability : experimental-Portability : portable--Simple State function, have an isomorphism with Maybe but order are diferent--}-module Data.State -(- -- * Data and type- State(..)- ,Final(..)- ,terminal- -- * Functions- ,isError-) where-import Control.Applicative-import Control.Monad--{-|-Macine states are only a label, maybe a letter--}-data State a = - -- |State constructor- Q a - -- |Error state- | QE deriving(Show, Eq, Ord)---- |Same as Maybe-instance Functor State where- fmap _ QE = QE- fmap f (Q q) = Q $ f q ---- |Same as Maybe-instance Applicative State where- pure = Q- QE <*> _ = QE- (Q f) <*> q = fmap f q---- |Same as Maybe-instance Monad State where- return = pure- QE >>= _ = QE- (Q q) >>= f = f q---- |Same as Maybe-instance (Enum a) => Enum (State a) where- toEnum n = if n<0 then QE else Q (toEnum n)- fromEnum QE = -1- fromEnum (Q a) = fromEnum a---- |In this differ with Maybe because this show a upper bounded order-instance (Bounded a)=> Bounded (State a) where- minBound = Q minBound- maxBound = QE --instance Monoid a => Monoid (State a) where- mempty = QE- QE `mappend` m = m- m `mappend` QE = m- (Q a) `mappend` (Q b) = Q (a `mappend` b)--instance Foldable State where- foldr _ z QE = z- foldr f z (Q x) = f x z- foldl _ z QE = z- foldl f z (Q x) = f z x--{-|-Final state represent a set of states which elements put end to computation--}-type Final a = [State a]--{-|-Tells if a state is final--}-terminal :: (Eq a) => Final a -> State a -> Bool-terminal qs q = elem q qs---- |Verifica si el estado es de error, comparandolo con la definicion de --- estado de error-{-|-Tells if a state is a error state--}-isError::(Eq a) => State a -> Bool-isError q = q==QE
src/Math/Model/Automaton/Finite.hs view
@@ -1,6 +1,6 @@-{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeOperators #-} {-| Module : Finite Automaton Description : Finite Automaton@@ -10,89 +10,173 @@ Stability : experimental Portability : portable -Finite Automaton is a stateful machine where all transition means that machine +Finite Automaton is a stateful machine where all transition means that machine reads a symbol -} module Math.Model.Automaton.Finite (- -- * Deterministic- -- ** Function - -- *** Recognizer+ -- * Recognizer+ -- ** Functions Delta(..)- ,liftD- -- ** Transducer+ ,NDelta(..)+ -- ** Constructor+ ,FiniteA(..)+ ,checkString+ -- * Transducer+ -- ** Functions ,Lambda1(..)- ,liftL1 ,Lambda2(..)- ,liftL2- -- ** Constructor- ,FiniteA(..)+ -- ** Constructor ,Transductor(..)- -- ** Function- ,checkString ,translate- -- * Not deterministic- -- ** Function- ,DeltaN(..)- ,liftDN- -- ** Constructor- ,FiniteAN(..)- ,checkStringN+ -- * Auxiliar functions+ ,getAlphabet+ ,endState+ ,endStates+ -- ** Create deltas and lambdas+ ,liftDelta+ ,liftNDelta+ ,liftL1+ ,liftL2+ -- ** Mininmize delta+ ,reachableDelta+ ,distinguishableDelta+ ,minimizeFinite+ -- ** Equivalence+ ,convertFA+ ,transducerToFinite+ ,finiteToMoore+ ,finiteToMealy+ -- * Language+ ,automatonEssence+ ,automatonCardinality ) where-import Data.State-import Data.Sigma-import Data.Delta-import Data.List-import Data.Monoid-import Control.Monad-import qualified Data.Map.Lazy as Map-import qualified Data.Foldable as Fold+import Data.Numerable+import Data.Delta+import qualified Data.Foldable as Fold+import Data.Label+import Data.List+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import Data.Sigma+import Control.Monad.State.Lazy +tupleVoid:: (a,b,c) -> (a,b,c,())+tupleVoid (a,b,c) = (a,b,c,())+ {-|-Transition function hava a State and a Symbol by domain to decide next state in -machine+Union of set monad -}+unionsFold:: (Ord a, Fold.Foldable t) => t (Set.Set a) -> Set.Set a+unionsFold = Fold.foldr Set.union Set.empty++{-|+Size of a set, with large integers+-}+setGenericSize:: (Ord a) => Set.Set a -> Integer+setGenericSize s = if Set.null s+ then 0+ else 1 + setGenericSize (Set.delete (Set.findMin s) s)++{-|+Transition function that for every pair, a State and a Symbol by domain, decide+next state in machine+-} type Delta a = (:->:) a Symbol () {-|-Lift a list of 3-tuples in a Delta+Lift a list of 3-tuples to a Delta ->>>let delta = liftD [(0,'0',0),(0,'1',1),(1,'0',1),(1,'1',0)]+>>>let delta = liftDelta [(0,'0',0),(0,'1',1),(1,'0',1),(1,'1',0)] -}-liftD::(Ord a) => [(a,Symbol,a)] -> Delta a-liftD ds = let- (xs,ys,zs) = unzip3 ds- f = map return - xys = zip (f xs) ys- qzs = zip (f zs) (repeat ())- in Map.fromList (zip xys qzs)+liftDelta::(Ord a) => [(a,Symbol,a)] -> Delta a+liftDelta ds = liftD $ fmap tupleVoid ds +{-|+Transition function that for every pair, a State and a Symbol by domain, decide+next list of states in machine+-}+type NDelta a = (:-<:) a Symbol ()++tupleLast:: (a,b,[c]) -> (a,b,[(c,())])+tupleLast (a,b,xs) = let+ f x = (x,())+ in (a,b,fmap f xs)++{-|+Lift a list of 3-tuples to a non deterministic delta++>>>let deltaN = liftNDelta [(0,'0',[0]),(0,'1',[1]),(1,'0',[1]),(1,'1',[0])]+-}+liftNDelta::(Ord a) => [(a,Symbol,[a])] -> NDelta a+liftNDelta ds = liftND $ fmap tupleLast ds++{-|+Transducer function+-} type Lambda1 a = (:*>:) a () Symbol +tupleMidVoid :: (a, b) -> (a, (), b)+tupleMidVoid (a, b) = (a, (), b)++{-|+Lift simple transducer function+-} liftL1::(Ord a) => [(a, Symbol)] -> Lambda1 a-liftL1 ds = let- (xs, ys) = unzip ds- f = map return- nds = zip (zip (f xs) (repeat ())) ys- in Map.fromList nds+liftL1 = liftL . fmap tupleMidVoid +{-|+Transducer function with output at transition+-} type Lambda2 a = (:*>:) a Symbol Symbol +{-|+Lift second transducer function+-} liftL2::(Ord a) => [(a, Symbol, Symbol)] -> Lambda2 a-liftL2 ds = let- (xs, ys, zs) = unzip3 ds- f = map return- nds = zip (zip (f xs) ys) zs- in Map.fromList nds- +liftL2 = liftL+ {-| Finite deterministic Automaton -}-data FiniteA a = - -- |>>>let autFin = F delta [Q 0] (Q 0)- F (Delta a) (Final a) (State a) deriving(Show, Eq)+data FiniteA a =+ -- |>>>let autFin = F delta (Set.fromList [Q 0]) (Q 0)+ F (Delta a) (Final a) (Label a)+ -- |>>>let autFinN = FN deltaN (Set.fromList [Q 0]) (Q 0)+ | FN (NDelta a) (Final a) (Label a) deriving(Show,Eq) {-|+Gets alphabet for some finite automaton+-}+getAlphabet:: FiniteA a -> Alphabet+getAlphabet (F d _ _) = getFirstParamSet d+getAlphabet (FN dn _ _) = getFirstParamSet dn++getAlphabetList::FiniteA a -> [Symbol]+getAlphabetList (F d _ _) = getFirstParam d+getAlphabetList (FN dn _ _) = getFirstParam dn++{-|+For some delta, an initial state anf a word returns final state for that word+-}+endState:: (Ord a) => Delta a -> Wd -> State (Label a) (Label a)+endState _ [] = get+endState d (x:xs) = do+ q <- get+ put (nextD d (q,x))+ endState d xs++{-|+Same as endState but work with no deterministic delta+-}+endStates::(Ord a) => NDelta a -> Wd -> State (SetLabel a) (SetLabel a)+endStates _ [] = get+endStates dn (x:xs) = do+ sq <- get+ put ((Set.unions . Set.toList) (Set.map (\q -> nextND dn () (q,x)) sq))+ endStates dn xs++{-| Executes a automaton over a word >>>checkString autFin "1010010101101010"@@ -102,67 +186,343 @@ -} checkString::(Ord a) => FiniteA a -> Wd -> Bool checkString (F d qF s) ws = let- q = checkString' d s ws- f y = ((not.isError) y)&&(terminal qF y)+ q = evalState (endState d ws) s+ f y = (not.isError) y && terminal qF y in f q- where- checkString' _ q [] = q- checkString' dt q (x:xs) = checkString' dt (nextD dt (q,x)) xs+checkString (FN dn qF s) ws = let+ sq = evalState (endStates dn ws) (Set.fromList [s])+ qs = Set.toList sq+ f y = (not.isError) y && terminal qF y+ g = any f+ in g qs -data Transductor a = - Moore (Delta a) (Lambda1 a) (Final a) (State a) - |Mealy (Delta a) (Lambda2 a) (Final a) (State a) deriving(Show, Eq)+{-|+Transducer Autmaton, both types: -translate::(Ord a) => Transductor a -> Wd -> Wd+1. Moore++2. Mealy+-}+data Transductor a =+ Moore (Delta a) (Lambda1 a) (Final a) (Label a)+ |Mealy (Delta a) (Lambda2 a) (Final a) (Label a) deriving(Show, Eq)+++transMoore:: (Ord a) => Delta a -> Lambda1 a -> Wd -> State (Wd, Label a) (Label a)+transMoore _ _ [] = do+ (_, q) <- get+ return q+transMoore d l (x:xs) = do+ (ys, q) <- get+ put (ys++[nextSymbol l (q, ())], nextD d (q,x))+ transMoore d l xs++transMealy:: (Ord a) => Delta a -> Lambda2 a -> Wd -> State (Wd, Label a) (Label a)+transMealy _ _ [] = do+ (_, q) <- get+ return q+transMealy d l (x:xs) = do+ (ys, q) <- get+ put (ys++[nextSymbol l (q,x)], nextD d (q,x))+ transMealy d l xs++{-|+For every transducer, given a word the automaton change all symbols in lambda+-}+translate::(Ord a) => Transductor a -> Wd -> (Wd, Bool) translate (Moore d l qF s) ws = let- (q, w) = translate d l s ws []- in w- where- translate _ _ QE xs ys = (QE, "Error: \nCadena:"++xs++"\nResp parcial: "++ys)- translate _ _ q [] xs = (q, xs)- translate dt lm q (y:ys) xs = translate dt lm (nextD dt (q,y)) ys (xs++[lm Map.! (q, ())])+ (q, (nws, _)) = runState (transMoore d l ws) ([], s)+ f y = (not.isError) y && terminal qF y+ in (nws, f q) translate (Mealy d l qF s) ws = let- (q, w) = translate d l s ws []- in ws- where - translate _ _ QE xs ys = (QE, "Error: \nCadena:"++xs++"\nResp parcial: "++ys)- translate _ _ q [] xs = (q, xs)- translate dt lm q (x:xs) ys = translate dt lm (nextD dt (q, x)) xs (ys++[lm Map.! (q,x)])+ (q, (nws, _)) = runState (transMealy d l ws) ([], s)+ f y = (not.isError) y && terminal qF y+ in (nws, f q) +{-|+Transforms a Transducer to a Finite Autmaton+-}+transducerToFinite:: Transductor a -> FiniteA a+transducerToFinite (Moore d _ qf s) = F d qf s+transducerToFinite (Mealy d _ qf s) = F d qf s -type DeltaN a = (:>-:) a Symbol ()+{-|+Transforms a Finite Autmaton with some lambda to a Moore Transducer+-}+finiteToMoore:: (Enum a, Ord a) => FiniteA a -> Lambda1 a -> Transductor a+finiteToMoore (F d qf s) l = Moore d l qf s+finiteToMoore fn l = finiteToMoore (convertFA fn) l {-|-Lift a list of 3-tuples in a non deterministic delta+Transforms a Finite Autmaton with some lambda to a Mealy Transducer+-}+finiteToMealy:: (Enum a, Ord a) => FiniteA a -> Lambda2 a -> Transductor a+finiteToMealy (F d qf s) l = Mealy d l qf s+finiteToMealy fn l = finiteToMealy (convertFA fn) l ->>>let deltaN = liftDN [(0,'0',[0]),(0,'1',[1]),(1,'0',[1]),(1,'1',[0])]+reachableStates1 alp d xs = let+ qs = xs ++ [nextD d (y,x) | x<-alp, y<-xs]+ nqs = (\\) (nub qs) [QE]+ in+ if nqs==xs then nqs else reachableStates1 alp d nqs++reachableStates2 alp d xs = let+ qs = (xs ++ concat [Set.toList (nextND d () (y,x)) | x<-alp, y<-xs])\\[QE]+ nqs = nub qs+ in+ if nqs==xs then nqs else reachableStates2 alp d nqs++{-|+Minimaize a delta for some finite automaton.+Gets a delta with all reachable states from initial state. -}-liftDN::(Ord a) => [(a,Symbol,[a])] -> DeltaN a-liftDN ds = let- (xs,ys,zs) = unzip3 ds- f = map return- xys = zip (f xs) ys- qzs = zip (map f zs) (repeat ())- in Map.fromList (zip xys qzs)+reachableDelta::(Ord a) => FiniteA a -> FiniteA a+reachableDelta af@(F d sqf qi) = let+ alp = getAlphabetList af+ qs = reachableStates1 alp d [qi]+ allUnused = (\\) (getStateDomain d) qs+ ks = [(x,y) | x<-allUnused, y<-alp]+ nDelta = foldl (flip Map.delete) d ks+ in+ F nDelta (Set.intersection sqf (Set.fromList qs)) qi+reachableDelta afn@(FN dn sqf qi) = let+ alp = getAlphabetList afn+ qs = reachableStates2 alp dn [qi]+ allUnused = (\\) (getStateDomain dn) qs+ ks = [(x,y) | x<-allUnused, y<-alp]+ nDelta = foldl (flip Map.delete) dn ks+ in+ FN nDelta (Set.intersection sqf (Set.fromList qs)) qi +fstPartitionSet sf qs = let+ (xs,ys) = Set.partition (terminal sf) qs+ in+ Set.delete Set.empty $ Set.fromList [xs, ys]++partitionSet q = Set.filter (Set.member q)+partitionSet2 q = Set.filter (Set.isSubsetOf q)++distinguishableSet alp d partSet pi = let+ qM = Set.findMin pi+ eqD p q = (==) (partitionSet p partSet) (partitionSet q partSet)+ g p q a = eqD (nextD d (p, a)) (nextD d (q, a))+ f p q = Fold.all (g p q) alp+ (sx, sy) = Set.partition (f qM) pi+ in Set.delete Set.empty $ Set.fromList [sx, sy]++distinguishableSet2 alp nd partSet pi = let+ qM = Set.findMin pi+ eqD p q = (==) (partitionSet2 p partSet) (partitionSet2 q partSet)+ g p q a = eqD (nextND nd () (p, a)) (nextND nd () (q, a))+ f p q = Fold.all (g p q) alp+ (sx, sy) = Set.partition (f qM) pi+ in Set.delete Set.empty $ Set.fromList [sx, sy]++lDistinguishableSet alp d partSet = let+ g = distinguishableSet alp d partSet+ f = unionsFold . Set.map g+ nPartSet = f partSet+ in if nPartSet == partSet+ then nPartSet+ else lDistinguishableSet alp d nPartSet++lDistinguishableSet2 alp nd partSet = let+ g = distinguishableSet2 alp nd partSet+ f = unionsFold . Set.map g+ nPartSet = f partSet+ in if nPartSet == partSet+ then nPartSet+ else lDistinguishableSet2 alp nd nPartSet++allStateSet (F d sqf q0) = Set.unions [getStateRangeSetD d, getStateDomainSet d, sqf, Set.singleton q0]+allStateSet (FN nd sqf q0) = Set.unions [getStateRangeSetND nd, getStateDomainSet nd, sqf, Set.singleton q0]+ {-|-Finite non deterministic Automaton+Delete redundant states and their transitions, if a state is equivalent to+another then is redundant, two state are equivalent if they are+undistinguisahbles. -}-data FiniteAN a = - -- |>>>let autFinN = FN deltaN (terminal [Q 0]) (Q 0)- FN (DeltaN a) (Final a) (State a) deriving(Show,Eq)+distinguishableDelta::(Ord a) => FiniteA a -> FiniteA a+distinguishableDelta af@(F d sf si) = let+ allState = allStateSet af+ pInitSet = fstPartitionSet sf allState+ alp = getAlphabet af+ partSet = lDistinguishableSet alp d pInitSet+ f q = (Set.findMin . Set.findMin) $ partitionSet q partSet+ allNewStateSet = Set.map f allState+ g q delta a = let+ k = (q, a)+ nQ = nextD d k+ in if nQ==QE+ then delta+ else Map.insert k (f nQ, ()) delta+ h delta q = Fold.foldl (g q) delta alp+ newDelta = Fold.foldl h Map.empty allNewStateSet+ in+ F newDelta (Set.map f sf) (f si)+distinguishableDelta afn@(FN nd sf si) = let+ allState = allStateSet afn+ pInitSet = fstPartitionSet sf allState+ alp = getAlphabet afn+ partSet = lDistinguishableSet2 alp nd pInitSet+ f q = (Set.findMin . Set.findMin) $ partitionSet q partSet+ allNewStateSet = Set.map f allState+ g q ndelta a = let+ k = (q, a)+ nQ = nextND nd () k+ in if Set.null nQ+ then ndelta+ else Map.insert k (Set.map f nQ, ()) ndelta+ h ndelta q = Fold.foldl (g q) ndelta alp+ newDelta = Fold.foldl h Map.empty allNewStateSet+ in+ afn {-|-Executes a non-deterministic automaton over a word, maybe overload your pc +Minimize a finite automaton,++1. Delete redundant states++2. Delete unreachable states and their transitions -}-checkStringN::(Ord a) => FiniteAN a -> Wd -> Bool-checkStringN (FN dn qF s) ws = let- qs = checkStringN' dn [s] ws- f y = ((not.isError) y)&&(terminal qF y)- g y = or (map f y)- in g qs- where- check dt k = if Map.member k dt then dt Map.! k else ([QE], ())- mDelta dt lq a = (nub.concat.(map fst)) (map (\q -> check dt (q,a)) lq)- checkStringN' _ qs [] = qs- checkStringN' dn qs (x:xs) = checkStringN' dn (mDelta dn qs x) xs+minimizeFinite::(Ord a) => FiniteA a -> FiniteA a+minimizeFinite = reachableDelta . distinguishableDelta++state2Set::(Ord a) => Label a -> Set.Set a+state2Set QE = Set.empty+state2Set (Q x) = Set.fromList [x]++setState2Set'::(Ord a) => Set.Set a -> SetLabel a -> Set.Set a+setState2Set' sa sP = if sP==Set.empty+ then sa+ else let+ p = Set.elemAt 0 sP+ in setState2Set' (Set.union (state2Set p) sa) (Set.delete p sP)++setState2Set::(Ord a) => SetLabel a -> Set.Set a+setState2Set = setState2Set' Set.empty++nextStateSet::(Ord a) => NDelta a -> LabelSS a -> Symbol -> SetLabel a+nextStateSet nd qsq a = let+ f q = nextND nd () (q, a)+ g = Set.map f+ Q sq = fmap g qsq+ in unionsFold sq++updateDeltaBySym::(Ord a) => NDelta a -> LabelSS a -> Symbol -> Delta (SetLabel a) -> Delta (SetLabel a)+updateDeltaBySym nd qsq a d = let+ k = (qsq, a)+ psp = Q $ nextStateSet nd qsq a+ in Map.insert k (psp, ()) d++updateDeltaByState::(Ord a) => NDelta a -> LabelSS a -> Delta (SetLabel a) -> Delta (SetLabel a)+updateDeltaByState nd qsq delta = let+ f d a = updateDeltaBySym nd qsq a d+ in Fold.foldl f delta (getFirstParamSet nd)++updateDelta::(Ord a) => NDelta a -> LabelSS a -> Delta (SetLabel a) -> Delta (SetLabel a)+updateDelta nd qsq d = let+ dDom = getStateDomainSet d+ newD = updateDeltaByState nd qsq d+ newDDom = getStateRangeSetD newD+ difS = Set.difference (Set.difference newDDom dDom) (Set.fromList [qsq])+ f delta psp = updateDelta nd psp delta+ in if Set.null difS+ then newD+ else Fold.foldl f newD difS++isNewFinal::(Ord a) => Set.Set a -> LabelSS a -> Bool+isNewFinal _ QE = False+isNewFinal sa (Q sq) = let+ sInter = Set.intersection sa (setState2Set sq)+ in not $ Set.null sInter++convertFA'::(Ord a) => FiniteA a -> FiniteA (SetLabel a)+convertFA' (FN nd sqf q0) = let+ alp = getFirstParamSet nd+ newQ0 = Q $ Set.singleton q0+ newD = updateDelta nd newQ0 Map.empty+ sf = setState2Set sqf+ dDom = Set.unions [getStateDomainSet newD, getStateRangeSetD newD, Set.singleton newQ0]+ newSQF = Set.filter (isNewFinal sf) dDom+ in minimizeFinite $ F newD newSQF newQ0++enumDom::(Ord a) => Set.Set (LabelSS a) -> LabelSS a -> Int+enumDom sqsq qsq = Set.findIndex qsq sqsq++succN:: (Enum a) => a -> Int -> a+succN a 0 = a+succN a n = succN (succ a) (n-1)++newLabel::(Enum a, Ord a) => a -> Set.Set (LabelSS a) -> LabelSS a -> Label a+newLabel o sqsq qsq = Q . succN o $ enumDom sqsq qsq++mapSetLabel::(Enum a, Ord a) => a -> Set.Set (LabelSS a) -> Set.Set (LabelSS a) -> Set.Set (Label a)+mapSetLabel o sqsq = Set.map $ newLabel o sqsq++mapDeltaLabel::(Enum a, Ord a) => a -> Set.Set (LabelSS a) -> Delta (SetLabel a) -> Delta a+mapDeltaLabel o sqsq rareD = let+ f (qsq, x) = (newLabel o sqsq qsq, x)+ in Map.mapKeys f (Map.map f rareD)++state2Enum::(Enum a) => Label a -> a+state2Enum QE = toEnum 0+state2Enum (Q a) = a++mapAFLabel::(Enum a, Ord a) => Label a -> FiniteA (SetLabel a) -> FiniteA a+mapAFLabel q af@(F d sqf q0) = let+ o = state2Enum q+ sqsq = allStateSet af+ in F (mapDeltaLabel o sqsq d) (mapSetLabel o sqsq sqf) (newLabel o sqsq q0)++{-|+Finite Autmaton Equivalence+-}+convertFA::(Enum a, Ord a) => FiniteA a -> FiniteA a+convertFA (F d sqf q0) = let+ f (x, y) = Set.singleton (x, y)+ in+ FN (fmap f d) sqf q0+convertFA afn@(FN nd sqf q0) = let+ afRare = convertFA' afn+ in+ mapAFLabel q0 afRare++{-|+Tells if a finite automaton had empty language or not.+-}+automatonEssence:: (Ord a) => FiniteA a -> Essence+automatonEssence af@F{} = let+ (F d sqf q0) = reachableDelta af+ rangeD = getStateRangeSetD d+ in if Set.null (Set.intersection rangeD sqf) && Set.notMember q0 sqf+ then Empty+ else Occupied+automatonEssence af@FN{} = let+ (FN nd sqf q0) = reachableDelta af+ rangeD = getStateRangeSetND nd+ in if Set.null (Set.intersection rangeD sqf) && Set.notMember q0 sqf+ then Empty+ else Occupied++acceptWord _ [] = False+acceptWord af (w:ws) = checkString af w || acceptWord af ws++allStateSize s = setGenericSize $ allStateSet s++filterWords af = filter (checkString af)++{-|+Tells if a finite automaton had infinite language or the number or words in his+language+-}+automatonCardinality::(Ord a) => FiniteA a -> Discrete+automatonCardinality af = let+ afm = minimizeFinite af+ alp = getAlphabet afm+ n = allStateSize afm+ g = kWords alp+ acceptedWord = acceptWord afm $ g =<< [n..(2*(n-1))]+ in if acceptedWord+ then Numerable+ else Fin . genericLength . filterWords afm $ lessKWords alp (n-1)
src/Math/Model/Automaton/Stack.hs view
@@ -1,6 +1,6 @@-{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeOperators #-} {-| Module : StackA Description : Stack Automaton@@ -12,61 +12,55 @@ Stack Automaton -}-module Math.Model.Automaton.Stack-(- Delta(..)- ,liftD- ,StackA(..)- ,checkString-) where-import Data.List-import Data.Monoid-import qualified Data.Map.Lazy as Map-import qualified Data.Foldable as Fold-import Data.Delta-import Data.State-import Data.Sigma+module Math.Model.Automaton.Stack where+import Data.Delta+import qualified Data.Foldable as Fold+import Data.List+import qualified Data.Map.Strict as Map+import Data.Sigma+import Data.Label+import Control.Monad.State.Lazy {-|-Delta for stack machine, takes a state, a symbol in string input and a symbol in-stack head and returns next state and update stack+Delta for stack machine, takes a state, a symbol in string input or not and a+symbol in stack head and returns next state and update stack -}-type Delta a = (:->:) a (Symbol, Symbol) [Symbol]+type Delta a = (:->:) a (Maybe Symbol, Symbol) Wd {-|+A key for a delta.+-}+type Key a = (Label a, (Maybe Symbol, Symbol))++{-| Takes a list of tuples and lift a Delta ->>>let delta = liftD [(0,'1','A',1,[AA]),(0,'0',blank,0,[A])]+>>>let delta = liftD [(0,"(",'Z',0,"IZ"),(0,"",'Z',0,""),(0,"(",'I',0,"II"),(0,")",'I',0,"")] -}-liftD::(Ord a) => [(a, Symbol, Symbol, a, [Symbol])]-> Delta a-liftD xs = let- (as,bs,cs,ds,es) = unzip5 xs- f = map (Q)- p = zip bs cs- k = zip (f as) p- r = zip (f ds) es- in Map.fromList (zip k r)+liftDelta:: Ord a => [(a, Wd, Symbol, a, Wd)]-> Delta a+liftDelta xs = let+ (as,bs,cs,ds,es) = unzip5 xs+ f = fmap Q+ g [] = Nothing+ g (x:_) = Just x+ ps = zip (fmap g bs) cs+ ks = zip (f as) ps+ rs = zip (f ds) es+ in Map.fromList (zip ks rs) --- |Stack machine only needs a delta and a init state-data StackA a = S (Delta a) (State a)+nextDTuple :: Ord a => Delta a -> Key a -> (Label a, Wd)+nextDTuple dt k = if Map.member k dt then dt Map.! k else (QE,[]) -{-|-Executes a stack machine over a word+-- |Stack machine only needs a delta, an init state and an initial symbol.+--+-- This works for empty stack and final state acceptor+data StackA a = Stack {+ getDelta::Delta a+ ,getInitState::Label a+ ,getFinal::Final a+ ,getInitSymbol::Symbol} deriving(Show, Eq) ->>>checkString autStack 'aaabbbcccccc'-True--}-checkString::(Ord a) => StackA a -> Wd -> Bool-checkString (S d s) ws = let- q = checkString' d s [z0] ws- f = not.isError- in f q- where- check dt s = if Map.member s dt then dt Map.! s else (QE,[])- checkString' _ QE _ _ = QE- checkString' _ q [] [] = q- checkString' _ _ (_:_) [] = QE- checkString' _ q [] (_:_) = QE- checkString' dt q (x:xs) (y:ys) = let - (qn, st) = check dt (q, (y, x))- in checkString' dt qn (st++xs) ys+nextState::(Ord a) => Delta a -> Wd -> State (Wd, Label a) (Label a)+nextState _ [] = do+ (_, q) <- get+ return q
src/Math/Model/Turing.hs view
@@ -1,8 +1,10 @@ {-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE GADTSyntax #-} {-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE GADTSyntax #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeOperators #-} {-| Module : Turing Description : Turing machine abstaction@@ -15,19 +17,19 @@ Turing machine abstaction -} module Math.Model.Turing where-import Data.Delta-import Data.State-import Data.Sigma-import Data.List-import Data.Monoid-import Control.Applicative-import qualified Data.Map.Lazy as Map-import qualified Data.Foldable as Fold+import Control.Applicative+import Data.Delta+import qualified Data.Foldable as Fold+import Data.Label+import Data.List+import qualified Data.Map.Strict as Map+import Data.Monoid+import Data.Sigma class Ways a where oposite::a -> a -data LRS = +data LRS = -- |Left move L -- |No move@@ -40,7 +42,7 @@ oposite R = L oposite S = S -data FW = +data FW = Dw |Lf |Rt@@ -57,17 +59,15 @@ type MDelta a b c = (:->:) a [b] ([b],[c]) liftD::(Ord a, Ord b) => [(a,b,a,b,c)]->Delta a b c-liftD ls = let- (as,bs,cs,ds,es) = unzip5 ls- f = map return- xs = zip (f as) bs- ys = zip (f cs) (zip ds es)- in Map.fromList (zip xs ys)+liftD = liftDAux liftMD::(Ord a, Ord b) => [(a,[b],a,[b],[c])]->MDelta a b c-liftMD ls = let+liftMD = liftDAux++liftDAux:: (Ord a, Ord b) => [(a,b,a,b,c)]-> (:->:) a b (b,c)+liftDAux ls = let (as,bs,cs,ds,es) = unzip5 ls- f = map return+ f = fmap return xs = zip (f as) bs ys = zip (f cs) (zip ds es) in Map.fromList (zip xs ys)@@ -76,7 +76,7 @@ getHead::t a -> a liftTape::(Monoid (t a)) => [a] -> t a -data MultiTape t a = MT [t a] deriving(Show, Eq)+newtype MultiTape t a = MT [t a] getMHead::(Tapeable t a) => MultiTape t a -> [a] getMHead (MT ts) = [getHead t | t<-ts]@@ -88,7 +88,7 @@ moveHead::(Monoid b) => w -> t b -> t b data Model a b c where- TS::(Ways c) => Delta a b c->State a->Final a->Model a b c+ TS::(Ways c) => Delta a b c->Label a->Final a->Model a b c data MultiModel a b c where- MTS::(Ways c) => MDelta a b c->State a->[Final a]->MultiModel a b c+ MTS::(Ways c) => MDelta a b c->Label a->[Final a]->MultiModel a b c
src/Math/Model/Turing/FourWays.hs view
@@ -1,9 +1,9 @@ {-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-} {-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-} {-| Module : Turing1T4W Description : Four ways turing machine@@ -16,27 +16,27 @@ Four ways turing machine -} module Math.Model.Turing.FourWays where-import Data.Delta-import Data.State-import Data.Sigma-import Math.Model.Turing-import Math.Model.Turing.TwoWays-import Data.List-import Data.Monoid-import qualified Data.Foldable as Fold+import Control.Applicative+import Data.Delta+import qualified Data.Foldable as Fold+import Data.List+import Data.Monoid+import Data.Sigma+import Data.Label+import Math.Model.Turing+import Math.Model.Turing.TwoWays data Tracks a = Track [Tape a] (Tape a) [Tape a] deriving(Eq) instance (Show a) => Show (Tracks a) where- show (Track xts ts yts) = let - f x = "--"++(show x)++"\n"- g x = "->"++(show x)++"\n"- h x y = (concat.(map x)) y- in (h f xts)++(g ts)++(h f yts)+ show (Track xts ts yts) = let+ f x = "--" ++ show x ++ "\n"+ g x = "->" ++ show x ++ "\n"+ in (f =<< xts) ++ g ts ++ (f =<< yts) instance Functor Tracks where- fmap f (Track xts ts yts) = let - g = map (fmap f)+ fmap f (Track xts ts yts) = let+ g = fmap (fmap f) in Track (g xts) (fmap f ts) (g yts) instance Applicative Tracks where@@ -45,7 +45,7 @@ instance (Eq s, Monoid s) => Monoid (Tracks s) where mempty = Track [] mempty []- mappend (Track xts ts yts) (Track zts ss wts) = let + mappend (Track xts ts yts) (Track zts ss wts) = let f = zipWith mappend in Track (f xts zts) (mappend ts ss) (f yts wts) @@ -53,7 +53,7 @@ getHead (Track _ ts _) = getHead ts liftTape ws = Track [] (liftTape ws) [] -instance TuringM Tape Symbol FW where +instance TuringM Tape Symbol FW where moveHead Rt (T xs a []) = T (xs++[a]) mempty [] moveHead Rt (T xs a (y:ys)) = T (xs++[a]) y ys moveHead Lf (T [] a ys) = T [] mempty (a:ys)
src/Math/Model/Turing/TwoWays.hs view
@@ -1,10 +1,10 @@ {-# OPTIONS_GHC -fno-warn-tabs #-} {-# OPTIONS_HADDOCK show-extensions #-}-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeSynonymInstances #-} {-| Module : Turing1T4W Description : Two ways turing machine@@ -17,34 +17,31 @@ Two ways turing machine -} module Math.Model.Turing.TwoWays where-import Data.Delta-import Data.State-import Data.Sigma-import Math.Model.Turing-import Data.List-import Data.Monoid-import Control.Applicative-import qualified Data.Foldable as Fold+import Control.Applicative+import Data.Delta+import qualified Data.Foldable as Fold+import Data.List+import Data.Monoid+import Data.Sigma+import Data.Label+import Math.Model.Turing data Tape a = T [a] a [a] deriving(Show, Eq) instance Functor Tape where- fmap f (T xs a ys) = T (map f xs) (f a) (map f ys)+ fmap f (T xs a ys) = T (fmap f xs) (f a) (fmap f ys) instance Applicative Tape where- pure x = T [] x [] + pure x = T [] x [] -- (<*>) (T fs f gs) (T xs a ys) = T [] (f a) [] instance (Eq s, Monoid s) => Monoid (Tape s) where mempty = T [] mempty []- mappend (T xs a ys) (T [] b zs) = if - b==mempty - then T xs a (ys++zs) - else T xs a (ys++(b:zs))- mappend t (T (x:xs) a ys) = if - x==mempty - then mappend t (T [] mempty (xs++(a:ys))) + mappend (T xs a ys) (T [] b zs) = T xs a ((++) ys (if b == mempty then zs else b : zs))+ mappend t (T (x:xs) a ys) = if+ x==mempty+ then mappend t (T [] mempty (xs++(a:ys))) else mappend t (T [] x (xs++(a:ys))) {-|@@ -54,14 +51,14 @@ -} instance Tapeable Tape Symbol where getHead (T _ a _) = a- liftTape ws = Fold.foldMap pure ws+ liftTape = Fold.foldMap pure instance Tapeable Tape [Symbol] where getHead (T _ as _) = as liftTape [] = T [[]] [blank] [[]] liftTape wss = let- f = map head- g = map tail+ f = fmap head+ g = fmap tail in T (genericReplicate (genericLength wss) []) (f wss) (g wss) instance TuringM Tape Symbol LRS where@@ -74,28 +71,28 @@ instance TuringM Tape [Symbol] LRS where moveHead S t = t moveHead R (T xss as []) = let- f z = zipWith (\x y -> x++[y]) z+ f = zipWith (\x y -> x++[y]) g x = genericReplicate (genericLength x) mempty in T (f xss as) (g as) [] moveHead R (T xss as l@([]:yss)) = let- f z = zipWith (\x y -> x++[y]) z+ f = zipWith (\x y -> x++[y]) g x = genericReplicate (genericLength x) mempty in T (f xss as) (g as) l moveHead R (T xss as yss) = let- f = map head- g = map tail- h z = zipWith (\x y -> x++[y]) z+ f = fmap head+ g = fmap tail+ h = zipWith (\x y -> x++[y]) in T (h xss as) (f yss) (g yss) moveHead L (T [] as yss) = let g x = genericReplicate (genericLength x) mempty- f x y = zipWith (:) x y+ f = zipWith (:) in T [] (g as) (f as yss) moveHead L (T l@([]:xss) as yss) = let- f x y = zipWith (:) x y+ f = zipWith (:) g x = genericReplicate (genericLength x) mempty in T l (g as) (f as yss) moveHead L (T xss as yss) = let- f = map last- g = map init- h z = zipWith (:) z+ f = fmap last+ g = fmap init+ h = zipWith (:) in T (g yss) (f yss) (h as xss)
+ test/FiniteTest.hs view
@@ -0,0 +1,156 @@+{-# OPTIONS_GHC -fno-warn-tabs #-}+{-# LANGUAGE TypeSynonymInstances #-}+module Main where++import Data.Numerable+import qualified Data.Map as Map+import qualified Data.Set as Set+import Data.Label+import Math.Model.Automaton.Finite+import Test.Hspec+import Test.Hspec.QuickCheck+import Test.Hspec.Variant+import Test.QuickCheck+import Test.QuickCheck.Variant++returnEnum = return . toEnum++oneOfEnum = oneof . fmap returnEnum++instance Variant () where+ invalid = return ()+ valid = return ()++instance Variant Char where+ invalid = oneOfEnum $ [0..31]++[127..1114111]+ valid = oneOfEnum [32..126]++instance (Arbitrary a) => Variant (Label a) where+ invalid = return QE+ valid = do+ x <- arbitrary+ return $ Q x++instance (Variant a) => Variant [a] where+ valid = do+ x <- valid+ xs <- valid+ (oneof . fmap return) [x:xs, []]+ invalid = do+ x <- invalid+ xs <- invalid+ y <- valid+ ys <- valid+ (oneof . fmap return) [[x], x:xs, x:ys, y:xs]++instance (Arbitrary a) => Arbitrary (Label a) where+ arbitrary = oneof [invalid, valid]++instance (Variant a, Variant b) => Variant ((,) a b) where+ invalid = do+ x <- invalid+ y <- invalid+ z <- valid+ w <- valid+ (oneof . fmap return) [(x,y), (x,z), (w,y)]+ valid = do+ x <- valid+ y <- valid+ return (x, y)++instance (Ord a, Variant a) => Variant (Set.Set a) where+ invalid = do+ xs <- invalid+ return $ Set.fromList xs+ valid = do+ xs <- valid+ (oneof . fmap return) [Set.empty, Set.fromList xs]++instance (Ord k, Variant k, Variant a) => Variant (Map.Map k a) where+ invalid = do+ xs <- invalid+ return $ Map.fromList xs+ valid = do+ xs <- valid+ (oneof . fmap return) [Map.empty, Map.fromList xs]++instance (Ord a,Arbitrary a) => Variant (FiniteA a) where+ invalid = do+ nd <- valid+ sqf <- valid+ q0 <- valid+ return $ FN nd sqf q0+ valid = do+ d <- valid+ sqf <- valid+ q0 <- valid+ return $ F d sqf q0++instance (Ord a, Arbitrary a) => Arbitrary (FiniteA a) where+ arbitrary = do+ afn <- invalid+ af <- valid+ (oneof . fmap return) [afn, af]++pairWord = F (liftDelta [(1,'0',1),(1,'1',2),(2,'0',2),(2,'1',1)]) (Set.fromList [Q 2]) (Q 2)++emptyLang1 = F (liftDelta [(1,'0',1),(1,'1',2),(2,'0',2),(2,'1',1)]) (Set.fromList [Q 3]) (Q 2)++finiteLang = F (liftDelta []) (Set.fromList [Q 2]) (Q 2)++finiteAut = describe "Finite automaton check" . it "pair of one's" $ do+ checkString pairWord "" `shouldBe` True+ checkString pairWord "00000" `shouldBe` True+ checkString pairWord "00101" `shouldBe` True+ checkString pairWord "00001" `shouldBe` False+ checkString pairWord "11111" `shouldBe` False+ checkString pairWord "11011" `shouldBe` True++transDetTest = describe "Transform" $ do+ prop "reachable check same" $+ \ af w -> checkString (reachableDelta (af::FiniteA Int)) w == checkString af w+ prop "distinguishable check same" $+ \ af w -> checkString (distinguishableDelta (af::FiniteA Int)) w == checkString af w+ prop "minimize check same" $+ \ af w -> checkString (minimizeFinite (af::FiniteA Int)) w == checkString af w+ prop "minimize" $+ \ af -> let naf = minimizeFinite (af::FiniteA Int) in minimizeFinite naf == naf+ prop "equivalence" $+ \fa w -> checkString (fa:: FiniteA Int) w == checkString (convertFA fa) w++cardinalityTest = describe "Cardinal" $ do+ it "essence" $ do+ automatonEssence pairWord `shouldBe` Occupied+ automatonEssence emptyLang1 `shouldBe` Empty+ automatonEssence finiteLang `shouldBe` Occupied+ it "cardinality" $ do+ automatonCardinality pairWord `shouldBe` Numerable+ automatonCardinality emptyLang1 `shouldBe` Fin 0+ automatonCardinality finiteLang `shouldBe` Fin 1+ prop "if empty then Fin 0" $+ \ af -> let+ e = automatonEssence (af:: FiniteA Int)+ c = automatonCardinality af+ in (e /= Empty) || (c == Fin 0)+ prop "if (Fin n) where n>0 then Occupied" $+ \ af -> let+ e = automatonEssence (af:: FiniteA Int)+ c@(Fin n) = automatonCardinality af+ in (c /= Numerable) || (n == 0) || (e == Occupied)+ prop "if Numerable then Occupied" $+ \ af -> let+ e = automatonEssence (af:: FiniteA Int)+ c = automatonCardinality af+ in (c /= Numerable) || (e == Occupied)+ prop "if Numerable then not Empty" $+ \ af -> let+ e = automatonEssence (af:: FiniteA Int)+ c = automatonCardinality af+ in (c /= Numerable) || (e /= Empty)+++main::IO ()+main = hspec . describe "Math.Model.Automaton.Finite" $ do+ finiteAut+ transDetTest+ cardinalityTest
+ test/LabelTest.hs view
@@ -0,0 +1,23 @@+{-# OPTIONS_GHC -fno-warn-tabs #-}+module Main where++import qualified Data.Set as Set+import Data.Label+import Test.Hspec+import Test.Hspec.QuickCheck+import Test.QuickCheck++instance (Arbitrary a) => Arbitrary (Label a) where+ arbitrary = do+ x <- arbitrary+ (oneof . fmap return) [QE, Q x]++terminalTest = describe "terminal" $ do+ prop "Not in" $+ \x y -> (x == y) || not (terminal (Set.fromList [x]) (y:: Label Int))+ prop "In" $+ \x -> terminal (Set.fromList [x]) (x:: Label Int)++main::IO ()+main = hspec $+ describe "Data.State" terminalTest
+ test/SigmaTest.hs view
@@ -0,0 +1,33 @@+{-# OPTIONS_GHC -fno-warn-tabs #-}+module Main where++import qualified Data.Set as Set+import Data.Sigma+import Test.Hspec+import Test.Hspec.QuickCheck+import Test.QuickCheck++enumWordTest = describe "enumWordTest" $ do+ let alpF = enumWord (Set.fromList ['a','b','c'])+ it "Empty word and empty alphabet" $+ enumWord Set.empty [] `shouldBe` 0+ it "Empty word and non-empty alphabet" $+ alpF [] `shouldBe` 0+ it "Symbol word1" $+ alpF "a" `shouldBe` 1+ it "Symbol word2" $+ alpF "b" `shouldBe` 2+ it "Symbol word3" $+ alpF "c" `shouldBe` 3+ it "Two Symbol word" $+ alpF "aa" `shouldBe` 4+ it "Two Symbol word1" $+ alpF "ab" `shouldBe` 5+ it "Two Symbol word2" $+ alpF "bc" `shouldBe` 9+ it "Two Symbol word3" $+ alpF "ca" `shouldBe` 10++main::IO ()+main = hspec $+ describe "Data.Sigma" enumWordTest
turingMachine.cabal view
@@ -1,13 +1,10 @@--- Initial turingMachine.cabal generated by cabal init. For further --- documentation, see http://haskell.org/cabal/users-guide/- name: turingMachine -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.1.3.0+version: 1.0.0.0 synopsis: An implementation of Turing Machine and Automaton-description: An implementation of Turing Machine and Automaton for +description: An implementation of Turing Machine and Automaton for language theory homepage: https://github.com/sanjorgek/turingMachine license: GPL-3@@ -27,22 +24,70 @@ library exposed-modules: Data.Delta+ , Data.Helper+ , Data.Numerable , Data.Sigma- , Data.State+ , Data.Label , Math.Model.Automaton.Finite , Math.Model.Automaton.Stack , Math.Model.Turing , Math.Model.Turing.TwoWays , Math.Model.Turing.FourWays- -- other-modules: + -- other-modules: other-extensions: TypeSynonymInstances , TypeOperators , MultiParamTypeClasses , GADTSyntax+ , GADTs , ExistentialQuantification , TypeFamilies , FlexibleInstances- build-depends: base >=4.8 && <4.9+ build-depends: base >=4.6 && <5 , containers >= 0.5.6.2+ , mtl >= 2 && < 2.3 hs-source-dirs: src+ default-language: Haskell2010+++test-suite state+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: LabelTest.hs+ --other-modules:+ build-depends: base+ , containers+ , hspec+ , hspecVariant >=1 && <2+ , QuickCheck+ , QuickCheckVariant >=1 && <2+ , turingMachine+ default-language: Haskell2010++test-suite sigma+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: SigmaTest.hs+ --other-modules:+ build-depends: base+ , hspec+ , hspecVariant >=1 && <2+ , QuickCheck+ , QuickCheckVariant >=1 && <2+ , QuickCheck+ , containers+ , turingMachine+ default-language: Haskell2010++test-suite finite+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: FiniteTest.hs+ --other-modules:+ build-depends: base+ , hspec+ , hspecVariant >=1 && <2+ , QuickCheck+ , QuickCheckVariant >=1 && <2+ , containers+ , turingMachine default-language: Haskell2010