diff options
author | Edward Z. Yang <ezyang@cs.stanford.edu> | 2015-03-09 13:14:13 -0700 |
---|---|---|
committer | Edward Z. Yang <ezyang@cs.stanford.edu> | 2015-03-09 13:15:07 -0700 |
commit | fe3cf4d277b55f99feb9e143705d414f8ca7133b (patch) | |
tree | b1cf9ff4f7718755fc4f1664da7641a825d3ce97 /compiler | |
parent | f9344f3646156a9efff2dcfb90e1d5d67fd4f5a1 (diff) | |
download | haskell-fe3cf4d277b55f99feb9e143705d414f8ca7133b.tar.gz |
Revert "Refactor Digraph to use Data.Graph when possible"
This breaks the build with GHC 7.6 bootstrapping, since the Functor SCC
instance is not available.
This reverts commit c439af5f5baa2c8af3434652554135230edbf5c3.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/utils/Digraph.hs | 300 | ||||
-rw-r--r-- | compiler/utils/Outputable.hs | 5 |
2 files changed, 264 insertions, 41 deletions
diff --git a/compiler/utils/Digraph.hs b/compiler/utils/Digraph.hs index 448935bea6..8f5df0ce05 100644 --- a/compiler/utils/Digraph.hs +++ b/compiler/utils/Digraph.hs @@ -17,6 +17,13 @@ module Digraph( -- For backwards compatability with the simpler version of Digraph stronglyConnCompFromEdgedVertices, stronglyConnCompFromEdgedVerticesR, + + -- No friendly interface yet, not used but exported to avoid warnings + tabulate, preArr, + components, undirected, + back, cross, forward, + path, + bcc, do_label, bicomps, collect ) where #include "HsVersions.h" @@ -28,11 +35,6 @@ module Digraph( -- by David King and John Launchbury -- -- Also included is some additional code for printing tree structures ... --- --- If you ever find yourself in need of algorithms for classifying edges, --- or finding connected/biconnected components, consult the history; Sigbjorn --- Finne contributed some implementations in 1997, although we've since --- removed them since they were not used anywhere in GHC. ------------------------------------------------------------------------------ @@ -54,10 +56,6 @@ import Data.Array.ST import qualified Data.Map as Map import qualified Data.Set as Set -import qualified Data.Graph as G -import Data.Graph hiding (Graph, Edge, transposeG, reachable) -import Data.Tree - {- ************************************************************************ * * @@ -211,6 +209,32 @@ findCycle graph {- ************************************************************************ * * +* SCC +* * +************************************************************************ +-} + +data SCC vertex = AcyclicSCC vertex + | CyclicSCC [vertex] + +instance Functor SCC where + fmap f (AcyclicSCC v) = AcyclicSCC (f v) + fmap f (CyclicSCC vs) = CyclicSCC (fmap f vs) + +flattenSCCs :: [SCC a] -> [a] +flattenSCCs = concatMap flattenSCC + +flattenSCC :: SCC a -> [a] +flattenSCC (AcyclicSCC v) = [v] +flattenSCC (CyclicSCC vs) = vs + +instance Outputable a => Outputable (SCC a) where + ppr (AcyclicSCC v) = text "NONREC" $$ (nest 3 (ppr v)) + ppr (CyclicSCC vs) = text "REC" $$ (nest 3 (vcat (map ppr vs))) + +{- +************************************************************************ +* * * Strongly Connected Component wrappers for Graph * * ************************************************************************ @@ -266,7 +290,7 @@ topologicalSortG graph = map (gr_vertex_to_node graph) result dfsTopSortG :: Graph node -> [[node]] dfsTopSortG graph = - map (map (gr_vertex_to_node graph) . flatten) $ dfs g (topSort g) + map (map (gr_vertex_to_node graph) . flattenTree) $ dfs g (topSort g) where g = gr_int_graph graph @@ -292,9 +316,7 @@ edgesG graph = map (\(v1, v2) -> Edge (v2n v1) (v2n v2)) $ edges (gr_int_graph g where v2n = gr_vertex_to_node graph transposeG :: Graph node -> Graph node -transposeG graph = Graph (G.transposeG (gr_int_graph graph)) - (gr_vertex_to_node graph) - (gr_node_to_vertex graph) +transposeG graph = Graph (transpose (gr_int_graph graph)) (gr_vertex_to_node graph) (gr_node_to_vertex graph) outdegreeG :: Graph node -> node -> Maybe Int outdegreeG = degreeG outdegree @@ -302,7 +324,7 @@ outdegreeG = degreeG outdegree indegreeG :: Graph node -> node -> Maybe Int indegreeG = degreeG indegree -degreeG :: (G.Graph -> Table Int) -> Graph node -> node -> Maybe Int +degreeG :: (IntGraph -> Table Int) -> Graph node -> node -> Maybe Int degreeG degree graph node = let table = degree (gr_int_graph graph) in fmap ((!) table) $ gr_node_to_vertex graph node @@ -314,8 +336,7 @@ emptyG :: Graph node -> Bool emptyG g = graphEmpty (gr_int_graph g) componentsG :: Graph node -> [[node]] -componentsG graph = map (map (gr_vertex_to_node graph) . flatten) - $ components (gr_int_graph graph) +componentsG graph = map (map (gr_vertex_to_node graph) . flattenTree) $ components (gr_int_graph graph) {- ************************************************************************ @@ -334,43 +355,261 @@ instance Outputable node => Outputable (Graph node) where instance Outputable node => Outputable (Edge node) where ppr (Edge from to) = ppr from <+> text "->" <+> ppr to -graphEmpty :: G.Graph -> Bool +{- +************************************************************************ +* * +* IntGraphs +* * +************************************************************************ +-} + +type Vertex = Int +type Table a = Array Vertex a +type IntGraph = Table [Vertex] +type Bounds = (Vertex, Vertex) +type IntEdge = (Vertex, Vertex) + +vertices :: IntGraph -> [Vertex] +vertices = indices + +edges :: IntGraph -> [IntEdge] +edges g = [ (v, w) | v <- vertices g, w <- g!v ] + +mapT :: (Vertex -> a -> b) -> Table a -> Table b +mapT f t = array (bounds t) [ (v, f v (t ! v)) | v <- indices t ] + +buildG :: Bounds -> [IntEdge] -> IntGraph +buildG bounds edges = accumArray (flip (:)) [] bounds edges + +transpose :: IntGraph -> IntGraph +transpose g = buildG (bounds g) (reverseE g) + +reverseE :: IntGraph -> [IntEdge] +reverseE g = [ (w, v) | (v, w) <- edges g ] + +outdegree :: IntGraph -> Table Int +outdegree = mapT numEdges + where numEdges _ ws = length ws + +indegree :: IntGraph -> Table Int +indegree = outdegree . transpose + +graphEmpty :: IntGraph -> Bool graphEmpty g = lo > hi where (lo, hi) = bounds g {- ************************************************************************ * * -* IntGraphs +* Trees and forests * * ************************************************************************ -} -type IntGraph = G.Graph +data Tree a = Node a (Forest a) +type Forest a = [Tree a] + +mapTree :: (a -> b) -> (Tree a -> Tree b) +mapTree f (Node x ts) = Node (f x) (map (mapTree f) ts) + +flattenTree :: Tree a -> [a] +flattenTree (Node x ts) = x : concatMap flattenTree ts + +instance Show a => Show (Tree a) where + showsPrec _ t s = showTree t ++ s + +showTree :: Show a => Tree a -> String +showTree = drawTree . mapTree show + +drawTree :: Tree String -> String +drawTree = unlines . draw + +draw :: Tree String -> [String] +draw (Node x ts) = grp this (space (length this)) (stLoop ts) + where this = s1 ++ x ++ " " + + space n = replicate n ' ' + + stLoop [] = [""] + stLoop [t] = grp s2 " " (draw t) + stLoop (t:ts) = grp s3 s4 (draw t) ++ [s4] ++ rsLoop ts + + rsLoop [] = [] + rsLoop [t] = grp s5 " " (draw t) + rsLoop (t:ts) = grp s6 s4 (draw t) ++ [s4] ++ rsLoop ts + + grp fst rst = zipWith (++) (fst:repeat rst) + + [s1,s2,s3,s4,s5,s6] = ["- ", "--", "-+", " |", " `", " +"] {- +************************************************************************ +* * +* Depth first search +* * +************************************************************************ +-} + +type Set s = STArray s Vertex Bool + +mkEmpty :: Bounds -> ST s (Set s) +mkEmpty bnds = newArray bnds False + +contains :: Set s -> Vertex -> ST s Bool +contains m v = readArray m v + +include :: Set s -> Vertex -> ST s () +include m v = writeArray m v True + +dff :: IntGraph -> Forest Vertex +dff g = dfs g (vertices g) + +dfs :: IntGraph -> [Vertex] -> Forest Vertex +dfs g vs = prune (bounds g) (map (generate g) vs) + +generate :: IntGraph -> Vertex -> Tree Vertex +generate g v = Node v (map (generate g) (g!v)) + +prune :: Bounds -> Forest Vertex -> Forest Vertex +prune bnds ts = runST (mkEmpty bnds >>= \m -> + chop m ts) + +chop :: Set s -> Forest Vertex -> ST s (Forest Vertex) +chop _ [] = return [] +chop m (Node v ts : us) + = contains m v >>= \visited -> + if visited then + chop m us + else + include m v >>= \_ -> + chop m ts >>= \as -> + chop m us >>= \bs -> + return (Node v as : bs) + +{- +************************************************************************ +* * +* Algorithms +* * +************************************************************************ + ------------------------------------------------------------ --- Depth first search numbering +-- Algorithm 1: depth first search numbering ------------------------------------------------------------ -} --- Data.Tree has flatten for Tree, but nothing for Forest +preorder :: Tree a -> [a] +preorder (Node a ts) = a : preorderF ts + preorderF :: Forest a -> [a] -preorderF ts = concat (map flatten ts) +preorderF ts = concat (map preorder ts) + +tabulate :: Bounds -> [Vertex] -> Table Int +tabulate bnds vs = array bnds (zip vs [1..]) + +preArr :: Bounds -> Forest Vertex -> Table Int +preArr bnds = tabulate bnds . preorderF + +{- +------------------------------------------------------------ +-- Algorithm 2: topological sorting +------------------------------------------------------------ +-} + +postorder :: Tree a -> [a] -> [a] +postorder (Node a ts) = postorderF ts . (a :) + +postorderF :: Forest a -> [a] -> [a] +postorderF ts = foldr (.) id $ map postorder ts + +postOrd :: IntGraph -> [Vertex] +postOrd g = postorderF (dff g) [] + +topSort :: IntGraph -> [Vertex] +topSort = reverse . postOrd + +{- +------------------------------------------------------------ +-- Algorithm 3: connected components +------------------------------------------------------------ +-} + +components :: IntGraph -> Forest Vertex +components = dff . undirected + +undirected :: IntGraph -> IntGraph +undirected g = buildG (bounds g) (edges g ++ reverseE g) {- ------------------------------------------------------------ --- Finding reachable vertices +-- Algorithm 4: strongly connected components +------------------------------------------------------------ +-} + +scc :: IntGraph -> Forest Vertex +scc g = dfs g (reverse (postOrd (transpose g))) + +{- +------------------------------------------------------------ +-- Algorithm 5: Classifying edges +------------------------------------------------------------ +-} + +back :: IntGraph -> Table Int -> IntGraph +back g post = mapT select g + where select v ws = [ w | w <- ws, post!v < post!w ] + +cross :: IntGraph -> Table Int -> Table Int -> IntGraph +cross g pre post = mapT select g + where select v ws = [ w | w <- ws, post!v > post!w, pre!v > pre!w ] + +forward :: IntGraph -> IntGraph -> Table Int -> IntGraph +forward g tree pre = mapT select g + where select v ws = [ w | w <- ws, pre!v < pre!w ] \\ tree!v + +{- +------------------------------------------------------------ +-- Algorithm 6: Finding reachable vertices ------------------------------------------------------------ -} --- This generalizes reachable which was found in Data.Graph reachable :: IntGraph -> [Vertex] -> [Vertex] reachable g vs = preorderF (dfs g vs) +path :: IntGraph -> Vertex -> Vertex -> Bool +path g v w = w `elem` (reachable g [v]) + {- ------------------------------------------------------------ --- Total ordering on groups of vertices +-- Algorithm 7: Biconnected components +------------------------------------------------------------ +-} + +bcc :: IntGraph -> Forest [Vertex] +bcc g = (concat . map bicomps . map (do_label g dnum)) forest + where forest = dff g + dnum = preArr (bounds g) forest + +do_label :: IntGraph -> Table Int -> Tree Vertex -> Tree (Vertex,Int,Int) +do_label g dnum (Node v ts) = Node (v,dnum!v,lv) us + where us = map (do_label g dnum) ts + lv = minimum ([dnum!v] ++ [dnum!w | w <- g!v] + ++ [lu | Node (_,_,lu) _ <- us]) + +bicomps :: Tree (Vertex, Int, Int) -> Forest [Vertex] +bicomps (Node (v,_,_) ts) + = [ Node (v:vs) us | (_,Node vs us) <- map collect ts] + +collect :: Tree (Vertex, Int, Int) -> (Int, Tree [Vertex]) +collect (Node (v,dv,lv) ts) = (lv, Node (v:vs) cs) + where collected = map collect ts + vs = concat [ ws | (lw, Node ws _) <- collected, lw<dv] + cs = concat [ if lw<dv then us else [Node (v:ws) us] + | (lw, Node ws us) <- collected ] + +{- +------------------------------------------------------------ +-- Algorithm 8: Total ordering on groups of vertices ------------------------------------------------------------ The plan here is to extract a list of groups of elements of the graph @@ -386,17 +625,6 @@ and their associated edges from the graph. This probably isn't very efficient and certainly isn't very clever. -} -type Set s = STArray s Vertex Bool - -mkEmpty :: Bounds -> ST s (Set s) -mkEmpty bnds = newArray bnds False - -contains :: Set s -> Vertex -> ST s Bool -contains m v = readArray m v - -include :: Set s -> Vertex -> ST s () -include m v = writeArray m v True - vertexGroups :: IntGraph -> [[Vertex]] vertexGroups g = runST (mkEmpty (bounds g) >>= \provided -> vertexGroupsS provided g next_vertices) where next_vertices = noOutEdges g diff --git a/compiler/utils/Outputable.hs b/compiler/utils/Outputable.hs index c557224fc1..6c7ae08379 100644 --- a/compiler/utils/Outputable.hs +++ b/compiler/utils/Outputable.hs @@ -105,7 +105,6 @@ import Data.Word import System.IO ( Handle ) import System.FilePath import Text.Printf -import Data.Graph (SCC(..)) import GHC.Fingerprint import GHC.Show ( showMultiLineString ) @@ -770,10 +769,6 @@ instance (Outputable elt) => Outputable (IM.IntMap elt) where instance Outputable Fingerprint where ppr (Fingerprint w1 w2) = text (printf "%016x%016x" w1 w2) -instance Outputable a => Outputable (SCC a) where - ppr (AcyclicSCC v) = text "NONREC" $$ (nest 3 (ppr v)) - ppr (CyclicSCC vs) = text "REC" $$ (nest 3 (vcat (map ppr vs))) - {- ************************************************************************ * * |