FSMOpt.hs

module FSMOpt where
import FSM
import GraphOps
import MUtils(collectByFst,collectBySnd,mapFst,mapSnd,usort)
import qualified IntMap as M
import qualified IntSet as S
import qualified OrdMap as OM
import List(sort,partition)

rmeqstate (n,NFA m) = (n',NFA (M.fromList m'))
  where (n',m') = repeat' rmeqstate1 (n,M.toList m)

repeat' f x =
  case f x of
    (True,x') -> x'
    (False,x') -> repeat' f x'

rmeqstate1 ((st,go),m) = (null sml,((s st,s go), m3))
  where
    m3 = [(st,[(e,s go)|(e,go)<-es])|(st:_,es)<-m2b]
    s x= M.lookupWithDefault sm x x
    sm = M.fromList sml
    sml = smla++smlb
    smlb = [(old,new)|(new:ss,_)<-m2b,old<-ss]
    smla = [(old,new)|(olds,[(E,new)])<-m2a,old<-olds]
    (m2a,m2b) = partition jumpstate m2
    m2 = opt m

    jumpstate (ss,[(E,g)]) = True
    jumpstate _ = False

    opt = collectBySnd . mapSnd usort

connectivity (n,NFA m) = (n,fmap next m)
  where next = S.fromList . map snd

epsilonconnectivity m = fmap epsnext m
  where epsnext ns = S.fromList [s|(E,s)<-ns]

unreachable fsm = sort . S.toList $ all `S.minus` r
  where
    r = reachable g start
    all = S.fromList . map fst . M.toList $ g
    ((start,_),g) = connectivity fsm

tokenclasses x = collectBySnd . collectByFst . tokenedges . edges $x

tokenedges edges = [(i,sg)|(T (I i),sg)<-edges]
outputedges edges = [(o,sg)|(T (O o),sg)<-edges]
epsilonedges edges = [sg|(E,sg)<-edges]

edges (NFA m) = [(e,(s,g))|(s,es)<-M.toList m,(e,g)<-es]

renumberEdges tclss (NFA ss) = NFA (fmap (usort . mapFst renEdge) ss)
  where
    renEdge (T (I c)) = case OM.lookup c tcmap of Just i -> T (I i)
    renEdge (T (O x)) = T (O x)
    renEdge E = E
    tcmap = OM.fromList tclss

Plain-text version of FSMOpt.hs | Valid HTML?