forked from GitHub/gf-core
Sort sub-networks topologically. HTK's HBuild seems to require this.
This commit is contained in:
@@ -154,7 +154,7 @@ data MFA a = MFA (DFA (MFALabel a)) [(String,DFA (MFALabel a))]
|
|||||||
--
|
--
|
||||||
|
|
||||||
cfgToMFA :: Options -> CGrammar -> MFA String
|
cfgToMFA :: Options -> CGrammar -> MFA String
|
||||||
cfgToMFA opts g = removeUnusedSubLats mfa
|
cfgToMFA opts g = sortSubLats $ removeUnusedSubLats mfa
|
||||||
where start = getStartCat opts
|
where start = getStartCat opts
|
||||||
startFA = let (fa,s,f) = newFA_
|
startFA = let (fa,s,f) = newFA_
|
||||||
in newTransition s f (MFASub start) fa
|
in newTransition s f (MFASub start) fa
|
||||||
@@ -165,13 +165,32 @@ cfgToMFA opts g = removeUnusedSubLats mfa
|
|||||||
mfa = MFA startFA [(c, toMFA (minimize fa)) | (c,fa) <- fas]
|
mfa = MFA startFA [(c, toMFA (minimize fa)) | (c,fa) <- fas]
|
||||||
|
|
||||||
removeUnusedSubLats :: MFA a -> MFA a
|
removeUnusedSubLats :: MFA a -> MFA a
|
||||||
removeUnusedSubLats (MFA main subs) = MFA main [(c,s) | (c,s) <- subs, isUsed c]
|
removeUnusedSubLats mfa@(MFA main subs) = MFA main [(c,s) | (c,s) <- subs, isUsed c]
|
||||||
where
|
where
|
||||||
usedMap = Map.fromList [(c,usedSubLats n) | (c,n) <- subs]
|
usedMap = subLatUseMap mfa
|
||||||
used = growUsedSet (usedSubLats main)
|
used = growUsedSet (usedSubLats main)
|
||||||
isUsed c = c `Set.member` used
|
isUsed c = c `Set.member` used
|
||||||
growUsedSet = fix (\s -> foldl Set.union s $ mapMaybe (flip Map.lookup usedMap) $ Set.toList s)
|
growUsedSet = fix (\s -> foldl Set.union s $ mapMaybe (flip Map.lookup usedMap) $ Set.toList s)
|
||||||
usedSubLats fa = Set.fromList [s | (_,_,MFASub s) <- transitions fa]
|
|
||||||
|
subLatUseMap :: MFA a -> Map String (Set String)
|
||||||
|
subLatUseMap (MFA _ subs) = Map.fromList [(c,usedSubLats n) | (c,n) <- subs]
|
||||||
|
|
||||||
|
usedSubLats :: DFA (MFALabel a) -> Set String
|
||||||
|
usedSubLats fa = Set.fromList [s | (_,_,MFASub s) <- transitions fa]
|
||||||
|
|
||||||
|
revMultiMap :: (Ord a, Ord b) => Map a (Set b) -> Map b (Set a)
|
||||||
|
revMultiMap m = Map.fromListWith Set.union [ (y,Set.singleton x) | (x,s) <- Map.toList m, y <- Set.toList s]
|
||||||
|
|
||||||
|
-- | Sort sub-networks topologically.
|
||||||
|
sortSubLats :: MFA a -> MFA a
|
||||||
|
sortSubLats mfa@(MFA main subs) = MFA main (reverse $ sortLats usedByMap subs)
|
||||||
|
where
|
||||||
|
usedByMap = revMultiMap (subLatUseMap mfa)
|
||||||
|
sortLats _ [] = []
|
||||||
|
sortLats ub ls = xs ++ sortLats ub' ys
|
||||||
|
where (xs,ys) = partition ((==0) . indeg) ls
|
||||||
|
ub' = Map.map (Set.\\ Set.fromList (map fst xs)) ub
|
||||||
|
indeg (c,_) = maybe 0 Set.size $ Map.lookup c ub
|
||||||
|
|
||||||
-- | Convert a strongly regular grammar to a number of finite automata,
|
-- | Convert a strongly regular grammar to a number of finite automata,
|
||||||
-- one for each non-terminal.
|
-- one for each non-terminal.
|
||||||
|
|||||||
@@ -53,10 +53,24 @@ data SLFEdge = SLFEdge { eId :: Int, eStart :: Int, eEnd :: Int }
|
|||||||
|
|
||||||
type SLF_FA = FA State (Maybe (MFALabel String)) ()
|
type SLF_FA = FA State (Maybe (MFALabel String)) ()
|
||||||
|
|
||||||
|
mkFAs :: Options -> CGrammar -> (SLF_FA, [(String,SLF_FA)])
|
||||||
|
mkFAs opts cfg = (slfStyleFA main, [(c,slfStyleFA n) | (c,n) <- subs])
|
||||||
|
where MFA main subs = {- renameSubs $ -} cfgToMFA opts cfg
|
||||||
|
|
||||||
slfStyleFA :: DFA (MFALabel String) -> SLF_FA
|
slfStyleFA :: DFA (MFALabel String) -> SLF_FA
|
||||||
slfStyleFA = renameStates [0..] . removeTrivialEmptyNodes . oneFinalState Nothing ()
|
slfStyleFA = renameStates [0..] . removeTrivialEmptyNodes . oneFinalState Nothing ()
|
||||||
. moveLabelsToNodes . dfa2nfa
|
. moveLabelsToNodes . dfa2nfa
|
||||||
|
|
||||||
|
-- | Give sequential names to subnetworks.
|
||||||
|
renameSubs :: MFA String -> MFA String
|
||||||
|
renameSubs (MFA main subs) = MFA (renameLabels main) subs'
|
||||||
|
where newNames = zip (map fst subs) ["sub"++show n | n <- [0..]]
|
||||||
|
newName s = lookup' s newNames
|
||||||
|
subs' = [(newName s,renameLabels n) | (s,n) <- subs]
|
||||||
|
renameLabels = mapTransitions renameLabel
|
||||||
|
renameLabel (MFASub x) = MFASub (newName x)
|
||||||
|
renameLabel l = l
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * SLF graphviz printing
|
-- * SLF graphviz printing
|
||||||
--
|
--
|
||||||
@@ -64,15 +78,15 @@ slfStyleFA = renameStates [0..] . removeTrivialEmptyNodes . oneFinalState Nothin
|
|||||||
slfGraphvizPrinter :: Ident -- ^ Grammar name
|
slfGraphvizPrinter :: Ident -- ^ Grammar name
|
||||||
-> Options -> CGrammar -> String
|
-> Options -> CGrammar -> String
|
||||||
slfGraphvizPrinter name opts cfg = Dot.prGraphviz g
|
slfGraphvizPrinter name opts cfg = Dot.prGraphviz g
|
||||||
where MFA main subs = cfgToMFA opts cfg
|
where (main, subs) = mkFAs opts cfg
|
||||||
g = STM.evalState (liftM2 Dot.addSubGraphs ss m) [0..]
|
g = STM.evalState (liftM2 Dot.addSubGraphs ss m) [0..]
|
||||||
ss = mapM (\ (c,f) -> gvSLFFA (Just c) f) subs
|
ss = mapM (\ (c,f) -> gvSLFFA (Just c) f) subs
|
||||||
m = gvSLFFA Nothing main
|
m = gvSLFFA Nothing main
|
||||||
|
|
||||||
gvSLFFA :: Maybe String -> DFA (MFALabel String) -> STM.State [State] Dot.Graph
|
gvSLFFA :: Maybe String -> SLF_FA -> STM.State [State] Dot.Graph
|
||||||
gvSLFFA n fa =
|
gvSLFFA n fa =
|
||||||
liftM (mkCluster n . faToGraphviz . mapStates (maybe "" mfaLabelToGv)
|
liftM (mkCluster n . faToGraphviz . mapStates (maybe "" mfaLabelToGv)
|
||||||
. mapTransitions (const "")) (rename $ slfStyleFA fa)
|
. mapTransitions (const "")) (rename fa)
|
||||||
where mfaLabelToGv (MFASym s) = s
|
where mfaLabelToGv (MFASym s) = s
|
||||||
mfaLabelToGv (MFASub s) = "#" ++ s
|
mfaLabelToGv (MFASub s) = "#" ++ s
|
||||||
mkCluster Nothing = id
|
mkCluster Nothing = id
|
||||||
@@ -92,21 +106,10 @@ gvSLFFA n fa =
|
|||||||
-- | Make a network with subnetworks in SLF
|
-- | Make a network with subnetworks in SLF
|
||||||
slfPrinter :: Ident -- ^ Grammar name
|
slfPrinter :: Ident -- ^ Grammar name
|
||||||
-> Options -> CGrammar -> String
|
-> Options -> CGrammar -> String
|
||||||
slfPrinter name opts cfg = prSLFs (mfaToSLFs $ renameSubs $ cfgToMFA opts cfg) ""
|
slfPrinter name opts cfg = prSLFs slfs ""
|
||||||
|
where
|
||||||
renameSubs :: MFA String -> MFA String
|
(main,subs) = mkFAs opts cfg
|
||||||
renameSubs (MFA main subs) = MFA (renameLabels main) subs'
|
slfs = SLFs [(c, automatonToSLF fa) | (c,fa) <- subs] (automatonToSLF main)
|
||||||
where newNames = zip (map fst subs) ["sub"++show n | n <- [0..]]
|
|
||||||
newName s = lookup' s newNames
|
|
||||||
subs' = [(newName s,renameLabels n) | (s,n) <- subs]
|
|
||||||
renameLabels = mapTransitions renameLabel
|
|
||||||
renameLabel (MFASub x) = MFASub (newName x)
|
|
||||||
renameLabel l = l
|
|
||||||
|
|
||||||
mfaToSLFs :: MFA String -> SLFs
|
|
||||||
mfaToSLFs (MFA main subs)
|
|
||||||
= SLFs [(c, dfaToSLF fa) | (c,fa) <- subs] (dfaToSLF main)
|
|
||||||
where dfaToSLF = automatonToSLF . slfStyleFA
|
|
||||||
|
|
||||||
automatonToSLF :: SLF_FA -> SLF
|
automatonToSLF :: SLF_FA -> SLF
|
||||||
automatonToSLF fa = SLF { slfNodes = ns, slfEdges = es }
|
automatonToSLF fa = SLF { slfNodes = ns, slfEdges = es }
|
||||||
@@ -115,9 +118,9 @@ automatonToSLF fa = SLF { slfNodes = ns, slfEdges = es }
|
|||||||
|
|
||||||
mfaNodeToSLFNode :: Int -> Maybe (MFALabel String) -> SLFNode
|
mfaNodeToSLFNode :: Int -> Maybe (MFALabel String) -> SLFNode
|
||||||
mfaNodeToSLFNode i l = case l of
|
mfaNodeToSLFNode i l = case l of
|
||||||
Nothing -> mkSLFNode i Nothing
|
Nothing -> mkSLFNode i Nothing
|
||||||
Just (MFASym x) -> mkSLFNode i (Just x)
|
Just (MFASym x) -> mkSLFNode i (Just x)
|
||||||
Just (MFASub s) -> mkSLFSubLat i s
|
Just (MFASub s) -> mkSLFSubLat i s
|
||||||
|
|
||||||
mkSLFNode :: Int -> Maybe String -> SLFNode
|
mkSLFNode :: Int -> Maybe String -> SLFNode
|
||||||
mkSLFNode i Nothing = SLFNode { nId = i, nWord = Nothing, nTag = Nothing }
|
mkSLFNode i Nothing = SLFNode { nId = i, nWord = Nothing, nTag = Nothing }
|
||||||
|
|||||||
Reference in New Issue
Block a user