FrontPage FindPage TitleIndex RecentChanges UserPreferences E D R S I H C
 
NFA2DFA
FrontPageCategoryPapersGNUMakelow-las-vegas-airfare-100 › NFA2DFA


import List

fix f x = if x' == x then x' else fix f x' where x' = f x

data DFA a s = DFA [a] [s] s [(s,a,s)] [s] deriving Show
data NFA a s = NFA [a] [s] s [(s,EpsilonLift a,[s])] [s] deriving Show

data EpsilonLift a = Epsilon | Alphabet a deriving (Eq, Ord)

instance Show a => Show (EpsilonLift a) where
  show Epsilon = "''"
  show (Alphabet c) = show c

eKleen ss dl = nub $ [(s,[s])| s<-ss] ++ eTrans dl

eTrans dl = fix transitive [(x,y) | (x,Epsilon,y) <- dl] where
  transitive ts = nub (ts ++ [(x,z) | (x,ys)<-ts, (y,z)<-ts, y`elem`ys])

nfa2dfa (NFA sigma ss s0 dl fs) = DFA sigma ss' s0' dl' fs'
  where
  eTransCl = eTrans dl
  eKleenClOf sl = nub [y | s<-sl, (x,ys)<-eKleen ss dl, s==x, y<-ys]
  dla = [(x,a,ys)|(x,Alphabet a,ys)<-dl]
  dla1 = nub $ dla++[(x,a,z)| (x,a,ys)<-dla, (y,z)<-eTransCl, y`elem`ys]
  dla2 = nub $ dla1++[(x,a,z)| (x,ys)<-eTransCl, (y,a,z)<-dla1, y`elem`ys]
  s0' = eKleenClOf [s0]
  fs' = nub $ map eKleenClOf [s | s<-ss', not (null (intersect fs s))]
  dl' = fix nexts (nub $ adjs s0')
  ss' = nub $ map eKleenClOf (qs1++qs2)
      where (qs1,qs2) = unzip [(x,y)|(x,a,y)<-dl']
  nexts trs = nub $ trs ++ [tr | (_,_,xs) <- trs, tr <- adjs xs]
  adjs qs = do
    a <- sigma
    qs2@(_:_) <- [nub $ concat [y | (x,a',y)<-dla2, x`elem`qs, a==a']]
    return (eKleenClOf qs,a,eKleenClOf qs2)

-- for test

runDFA (DFA sigma ss s0 dl fs) str = foldl delta s0 str `elem` fs
  where
  delta s a = case find (\(s',a',_) -> s'==s && a'==a) dl of
                Just (_,_,s'') -> s''
                Nothing -> error ("no transition defined for "++show a)


runNFA (NFA sigma ss s0 dl fs) str =
  any (`elem` fs) $ foldl delta' (eKleenClOf [s0]) str
  where
  eKleenClOf sl = nub [y | s<-sl, (x,ys)<-eKleen ss dl, s==x, y<-ys]
  delta' sl a = nub [z | y<-eKleenClOf sl, z<-eKleenClOf(delta y a)]
  delta s a =
    case find (\(s',a',_) -> s'==s && (a'==Alphabet a || a'==Epsilon)) dl of
      Just (_,_,sl) -> sl
      Nothing -> error ("no transition defined for "++show a)

-- some test data
dfa = DFA "ab" "abx" 'a' d "ab"
  where
  d = [ ('a','a','a'),
        ('a','b','b'),
        ('b','a','x'),
        ('b','b','b'),
        ('x','a','x'),
        ('x','b','x')
      ]

nfa = NFA "abc" "abcx" 'a' d "c"
  where
  d = [
       ('a',Alphabet 'a',"b"),
       ('a',Alphabet 'b',"x"),
       ('a',Alphabet 'c',"x"),
       ('a',Epsilon,"b"),
       ('b',Alphabet 'a',"x"),
       ('b',Alphabet 'b',"c"),
       ('b',Alphabet 'c',"x"),
       ('b',Epsilon,"c"),
       ('c',Alphabet 'a',"x"),
       ('c',Alphabet 'b',"x"),
       ('c',Alphabet 'c',"c"),
       ('x',Alphabet 'a',"x"),
       ('x',Alphabet 'b',"x"),
       ('x',Alphabet 'c',"x")
      ]


~$ hugs nfa2dfa.hs
__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2005
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Report bugs to: hugs-bugs@haskell.org
||   || Version: 20050308       _________________________________________

Haskell 98 mode: Restart with command line option -98 to enable extensions

Type :? for help
Main> nfa
NFA "abc" "abcx" 'a' [('a','a',"b"),('a','b',"x"),('a','c',"x"),('a','',"b"),('b','a',"x"),('b','b',"c"),('b','c',"x"),('b','',"c"),('c','a',"x"),('c','b',"x"),('c','c',"c"),('x','a',"x"),('x','b',"x"),('x','c',"x")] "c"
Main> nfa2dfa nfa
DFA "abc" ["abc","bcx","xc","x","cx"] "abc" [("abc",'a',"bcx"),("abc",'b',"xc"),("abc",'c',"xc"),("bcx",'a',"x"),("bcx",'b',"cx"),("bcx",'c',"xc"),("xc",'a',"x"),("xc",'b',"x"),("xc",'c',"cx"),("x",'a',"x"),("x",'b',"x"),("x",'c',"x"),("cx",'a',"x"),("cx",'b',"x"),("cx",'c',"cx")] ["abc","bcx","xc","cx"]
Main> runNFA nfa ""
True
Main> runNFA nfa "a"
True
Main> runNFA nfa "aa"
False
Main> runNFA nfa "ab"
True
Main> runNFA nfa "abb"
False
Main> runNFA nfa "abc"
True
Main> runNFA nfa "abca"
False
Main> runNFA nfa "abcb"
False
Main> runNFA nfa "abcc"
True
Main> runNFA nfa "abccc"
True
Main> runDFA (nfa2dfa nfa) ""
True
Main> runDFA (nfa2dfa nfa) "a"
True
Main> runDFA (nfa2dfa nfa) "aa"
False
Main> runDFA (nfa2dfa nfa) "ab"
True
Main> runDFA (nfa2dfa nfa) "abb"
False
Main> runDFA (nfa2dfa nfa) "abc"
True
Main> runDFA (nfa2dfa nfa) "abca"
False
Main> runDFA (nfa2dfa nfa) "abcb"
False
Main> runDFA (nfa2dfa nfa) "abcc"
True
Main> runDFA (nfa2dfa nfa) "abccc"
True
last modified 2009-03-09 12:46:55
EditTextFindPageDeletePageLikePages