forked from GitHub/gf-core
The SLF removeTrivialEmptyNodes optimization could orphan the final node. Fixed this by not bypassing final nodes.
This commit is contained in:
@@ -150,8 +150,9 @@ removeTrivialEmptyNodes = pruneUnusable . skipSimpleEmptyNodes
|
|||||||
|
|
||||||
-- | Move edges to empty nodes with exactly one outgoing edge
|
-- | Move edges to empty nodes with exactly one outgoing edge
|
||||||
-- or exactly one incoming edge to point to the next node(s).
|
-- or exactly one incoming edge to point to the next node(s).
|
||||||
|
-- This is not done if the pointed-to node is a final node.
|
||||||
skipSimpleEmptyNodes :: (Eq a, Ord n) => FA n (Maybe a) () -> FA n (Maybe a) ()
|
skipSimpleEmptyNodes :: (Eq a, Ord n) => FA n (Maybe a) () -> FA n (Maybe a) ()
|
||||||
skipSimpleEmptyNodes = onGraph og
|
skipSimpleEmptyNodes fa = onGraph og fa
|
||||||
where
|
where
|
||||||
og g@(Graph c ns es) = if es' == es then g else og (Graph c ns es')
|
og g@(Graph c ns es) = if es' == es then g else og (Graph c ns es')
|
||||||
where
|
where
|
||||||
@@ -160,13 +161,16 @@ skipSimpleEmptyNodes = onGraph og
|
|||||||
changeEdge e@(f,t,())
|
changeEdge e@(f,t,())
|
||||||
| isNothing (getNodeLabel info t)
|
| isNothing (getNodeLabel info t)
|
||||||
&& (inDegree info t == 1 || outDegree info t == 1)
|
&& (inDegree info t == 1 || outDegree info t == 1)
|
||||||
|
&& not (isFinal fa t)
|
||||||
= [ (f,t',()) | (_,t',()) <- getOutgoing info t]
|
= [ (f,t',()) | (_,t',()) <- getOutgoing info t]
|
||||||
| otherwise = [e]
|
| otherwise = [e]
|
||||||
|
|
||||||
|
|
||||||
isInternal :: Eq n => FA n a b -> n -> Bool
|
isInternal :: Eq n => FA n a b -> n -> Bool
|
||||||
isInternal (FA _ start final) n = n /= start && n `notElem` final
|
isInternal (FA _ start final) n = n /= start && n `notElem` final
|
||||||
|
|
||||||
|
isFinal :: Eq n => FA n a b -> n -> Bool
|
||||||
|
isFinal (FA _ _ final) n = n `elem` final
|
||||||
|
|
||||||
-- | Remove all internal nodes with no incoming edges
|
-- | Remove all internal nodes with no incoming edges
|
||||||
-- or no outgoing edges.
|
-- or no outgoing edges.
|
||||||
pruneUnusable :: Ord n => FA n (Maybe a) () -> FA n (Maybe a) ()
|
pruneUnusable :: Ord n => FA n (Maybe a) () -> FA n (Maybe a) ()
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ mkFAs start cfg = (slfStyleFA main, [(c,slfStyleFA n) | (c,n) <- subs])
|
|||||||
where MFA main subs = {- renameSubs $ -} cfgToMFA start cfg
|
where MFA main subs = {- renameSubs $ -} cfgToMFA start cfg
|
||||||
|
|
||||||
slfStyleFA :: Eq a => DFA a -> FA State (Maybe a) ()
|
slfStyleFA :: Eq a => DFA a -> FA State (Maybe a) ()
|
||||||
slfStyleFA = renameStates [0..] . removeTrivialEmptyNodes . oneFinalState Nothing ()
|
slfStyleFA = renameStates [0..] . removeTrivialEmptyNodes . oneFinalState Nothing ()
|
||||||
. moveLabelsToNodes . dfa2nfa
|
. moveLabelsToNodes . dfa2nfa
|
||||||
|
|
||||||
-- | Give sequential names to subnetworks.
|
-- | Give sequential names to subnetworks.
|
||||||
|
|||||||
Reference in New Issue
Block a user