c36e7058fc9c9da8c0fb8cfe41875b0b6ebe08dd
[ghc-hetmet.git] / compiler / utils / Digraph.lhs
1 %
2 % (c) The University of Glasgow 2006
3 %
4
5 \begin{code}
6 module Digraph(
7
8         -- At present the only one with a "nice" external interface
9         stronglyConnComp, stronglyConnCompR, SCC(..), flattenSCC, flattenSCCs,
10
11         Graph, Vertex,
12         graphFromEdges, graphFromEdges',
13         buildG, transposeG, reverseE, outdegree, indegree,
14
15         Tree(..), Forest,
16         showTree, showForest,
17
18         dfs, dff,
19         topSort,
20         components,
21         scc,
22         back, cross, forward,
23         reachable, path,
24         bcc
25     ) where
26
27 -- XXX This define is a bit of a hack, and should be done more nicely
28 #define FAST_STRING_NOT_NEEDED 1
29 #include "HsVersions.h"
30
31 ------------------------------------------------------------------------------
32 -- A version of the graph algorithms described in:
33 --
34 -- ``Lazy Depth-First Search and Linear Graph Algorithms in Haskell''
35 --   by David King and John Launchbury
36 --
37 -- Also included is some additional code for printing tree structures ...
38 ------------------------------------------------------------------------------
39
40
41 import Util        ( sortLe )
42 import Outputable
43
44 -- Extensions
45 import Control.Monad.ST
46
47 -- std interfaces
48 import Data.Maybe
49 import Data.Array
50 import Data.List
51
52 #if !defined(__GLASGOW_HASKELL__) || __GLASGOW_HASKELL__ > 604
53 import Data.Array.ST
54 #else
55 import Data.Array.ST  hiding ( indices, bounds )
56 #endif
57 \end{code}
58
59
60 %************************************************************************
61 %*                                                                      *
62 %*      External interface
63 %*                                                                      *
64 %************************************************************************
65
66 \begin{code}
67 data SCC vertex = AcyclicSCC vertex
68                 | CyclicSCC  [vertex]
69
70 flattenSCCs :: [SCC a] -> [a]
71 flattenSCCs = concatMap flattenSCC
72
73 flattenSCC :: SCC a -> [a]
74 flattenSCC (AcyclicSCC v) = [v]
75 flattenSCC (CyclicSCC vs) = vs
76
77 instance Outputable a => Outputable (SCC a) where
78    ppr (AcyclicSCC v) = text "NONREC" $$ (nest 3 (ppr v))
79    ppr (CyclicSCC vs) = text "REC" $$ (nest 3 (vcat (map ppr vs)))
80 \end{code}
81
82 Note [Nodes, keys, vertices]
83 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84  * A 'node' is a big blob of client-stuff
85
86  * Each 'node' has a unique (client) 'key', but the latter 
87         is in Ord and has fast comparison
88
89  * Digraph then maps each 'key' to a Vertex (Int) which is
90         arranged densely in 0.n
91
92 \begin{code}
93 stronglyConnComp
94         :: Ord key
95         => [(node, key, [key])]         -- The graph; its ok for the
96                                         -- out-list to contain keys which arent
97                                         -- a vertex key, they are ignored
98         -> [SCC node]   -- Returned in topologically sorted order
99                         -- Later components depend on earlier ones, but not vice versa
100
101 stronglyConnComp edges
102   = map get_node (stronglyConnCompR edges)
103   where
104     get_node (AcyclicSCC (n, _, _)) = AcyclicSCC n
105     get_node (CyclicSCC triples)     = CyclicSCC [n | (n,_,_) <- triples]
106
107 -- The "R" interface is used when you expect to apply SCC to
108 -- the (some of) the result of SCC, so you dont want to lose the dependency info
109 stronglyConnCompR
110         :: Ord key
111         => [(node, key, [key])]         -- The graph; its ok for the
112                                         -- out-list to contain keys which arent
113                                         -- a vertex key, they are ignored
114         -> [SCC (node, key, [key])]     -- Topologically sorted
115
116 stronglyConnCompR [] = []  -- added to avoid creating empty array in graphFromEdges -- SOF
117 stronglyConnCompR edges
118   = map decode forest
119   where
120     (graph, vertex_fn) = {-# SCC "graphFromEdges" #-} graphFromEdges edges
121     forest             = {-# SCC "Digraph.scc" #-} scc graph
122     decode (Node v []) | mentions_itself v = CyclicSCC [vertex_fn v]
123                        | otherwise         = AcyclicSCC (vertex_fn v)
124     decode other = CyclicSCC (dec other [])
125                  where
126                    dec (Node v ts) vs = vertex_fn v : foldr dec vs ts
127     mentions_itself v = v `elem` (graph ! v)
128 \end{code}
129
130 %************************************************************************
131 %*                                                                      *
132 %*      Graphs
133 %*                                                                      *
134 %************************************************************************
135
136
137 \begin{code}
138 type Vertex  = Int
139 type Table a = Array Vertex a
140 type Graph   = Table [Vertex]
141 type Bounds  = (Vertex, Vertex)
142 type Edge    = (Vertex, Vertex)
143 \end{code}
144
145 \begin{code}
146 vertices :: Graph -> [Vertex]
147 vertices  = indices
148
149 edges    :: Graph -> [Edge]
150 edges g   = [ (v, w) | v <- vertices g, w <- g!v ]
151
152 mapT    :: (Vertex -> a -> b) -> Table a -> Table b
153 mapT f t = array (bounds t) [ (v, f v (t ! v)) | v <- indices t ]
154
155 buildG :: Bounds -> [Edge] -> Graph
156 buildG bounds edges = accumArray (flip (:)) [] bounds edges
157
158 transposeG  :: Graph -> Graph
159 transposeG g = buildG (bounds g) (reverseE g)
160
161 reverseE    :: Graph -> [Edge]
162 reverseE g   = [ (w, v) | (v, w) <- edges g ]
163
164 outdegree :: Graph -> Table Int
165 outdegree  = mapT numEdges
166              where numEdges _ ws = length ws
167
168 indegree :: Graph -> Table Int
169 indegree  = outdegree . transposeG
170 \end{code}
171
172
173 \begin{code}
174 graphFromEdges
175         :: Ord key
176         => [(node, key, [key])]
177         -> (Graph, Vertex -> (node, key, [key]))
178 graphFromEdges edges =
179   case graphFromEdges' edges of (graph, vertex_fn, _) -> (graph, vertex_fn)
180
181 graphFromEdges'
182         :: Ord key
183         => [(node, key, [key])]
184         -> (Graph, Vertex -> (node, key, [key]), key -> Maybe Vertex)
185 graphFromEdges' edges
186   = (graph, \v -> vertex_map ! v, key_vertex)
187   where
188     max_v           = length edges - 1
189     bounds          = (0,max_v) :: (Vertex, Vertex)
190     sorted_edges    = let
191                          (_,k1,_) `le` (_,k2,_) = (k1 `compare` k2) /= GT
192                       in
193                         sortLe le edges
194     edges1          = zipWith (,) [0..] sorted_edges
195
196     graph           = array bounds [ (v, mapMaybe key_vertex ks)
197                                | (v, (_,    _, ks)) <- edges1]
198     key_map         = array bounds [ (v, k)
199                                | (v, (_,    k, _ )) <- edges1]
200     vertex_map      = array bounds edges1
201
202
203     -- key_vertex :: key -> Maybe Vertex
204     --  returns Nothing for non-interesting vertices
205     key_vertex k   = find 0 max_v
206                    where
207                      find a b | a > b
208                               = Nothing
209                      find a b = case compare k (key_map ! mid) of
210                                    LT -> find a (mid-1)
211                                    EQ -> Just mid
212                                    GT -> find (mid+1) b
213                               where
214                                 mid = (a + b) `div` 2
215 \end{code}
216
217 %************************************************************************
218 %*                                                                      *
219 %*      Trees and forests
220 %*                                                                      *
221 %************************************************************************
222
223 \begin{code}
224 data Tree a   = Node a (Forest a)
225 type Forest a = [Tree a]
226
227 mapTree              :: (a -> b) -> (Tree a -> Tree b)
228 mapTree f (Node x ts) = Node (f x) (map (mapTree f) ts)
229 \end{code}
230
231 \begin{code}
232 instance Show a => Show (Tree a) where
233   showsPrec _ t s = showTree t ++ s
234
235 showTree :: Show a => Tree a -> String
236 showTree  = drawTree . mapTree show
237
238 showForest :: Show a => Forest a -> String
239 showForest  = unlines . map showTree
240
241 drawTree        :: Tree String -> String
242 drawTree         = unlines . draw
243
244 draw :: Tree String -> [String]
245 draw (Node x ts) = grp this (space (length this)) (stLoop ts)
246  where this          = s1 ++ x ++ " "
247
248        space n       = replicate n ' '
249
250        stLoop []     = [""]
251        stLoop [t]    = grp s2 "  " (draw t)
252        stLoop (t:ts) = grp s3 s4 (draw t) ++ [s4] ++ rsLoop ts
253
254        rsLoop []     = []
255        rsLoop [t]    = grp s5 "  " (draw t)
256        rsLoop (t:ts) = grp s6 s4 (draw t) ++ [s4] ++ rsLoop ts
257
258        grp fst rst   = zipWith (++) (fst:repeat rst)
259
260        [s1,s2,s3,s4,s5,s6] = ["- ", "--", "-+", " |", " `", " +"]
261 \end{code}
262
263
264 %************************************************************************
265 %*                                                                      *
266 %*      Depth first search
267 %*                                                                      *
268 %************************************************************************
269
270 \begin{code}
271 type Set s    = STArray s Vertex Bool
272
273 mkEmpty      :: Bounds -> ST s (Set s)
274 mkEmpty bnds  = newArray bnds False
275
276 contains     :: Set s -> Vertex -> ST s Bool
277 contains m v  = readArray m v
278
279 include      :: Set s -> Vertex -> ST s ()
280 include m v   = writeArray m v True
281 \end{code}
282
283 \begin{code}
284 dff          :: Graph -> Forest Vertex
285 dff g         = dfs g (vertices g)
286
287 dfs          :: Graph -> [Vertex] -> Forest Vertex
288 dfs g vs      = prune (bounds g) (map (generate g) vs)
289
290 generate     :: Graph -> Vertex -> Tree Vertex
291 generate g v  = Node v (map (generate g) (g!v))
292
293 prune        :: Bounds -> Forest Vertex -> Forest Vertex
294 prune bnds ts = runST (mkEmpty bnds  >>= \m ->
295                        chop m ts)
296
297 chop         :: Set s -> Forest Vertex -> ST s (Forest Vertex)
298 chop _ []     = return []
299 chop m (Node v ts : us)
300               = contains m v >>= \visited ->
301                 if visited then
302                   chop m us
303                 else
304                   include m v >>= \_  ->
305                   chop m ts   >>= \as ->
306                   chop m us   >>= \bs ->
307                   return (Node v as : bs)
308 \end{code}
309
310
311 %************************************************************************
312 %*                                                                      *
313 %*      Algorithms
314 %*                                                                      *
315 %************************************************************************
316
317 ------------------------------------------------------------
318 -- Algorithm 1: depth first search numbering
319 ------------------------------------------------------------
320
321 \begin{code}
322 preorder            :: Tree a -> [a]
323 preorder (Node a ts) = a : preorderF ts
324
325 preorderF           :: Forest a -> [a]
326 preorderF ts         = concat (map preorder ts)
327
328 tabulate        :: Bounds -> [Vertex] -> Table Int
329 tabulate bnds vs = array bnds (zipWith (,) vs [1..])
330
331 preArr          :: Bounds -> Forest Vertex -> Table Int
332 preArr bnds      = tabulate bnds . preorderF
333 \end{code}
334
335
336 ------------------------------------------------------------
337 -- Algorithm 2: topological sorting
338 ------------------------------------------------------------
339
340 \begin{code}
341 postorder :: Tree a -> [a] -> [a]
342 postorder (Node a ts) = postorderF ts . (a :)
343
344 postorderF   :: Forest a -> [a] -> [a]
345 postorderF ts = foldr (.) id $ map postorder ts
346
347 postOrd :: Graph -> [Vertex]
348 postOrd g = postorderF (dff g) []
349
350 topSort :: Graph -> [Vertex]
351 topSort = reverse . postOrd
352 \end{code}
353
354
355 ------------------------------------------------------------
356 -- Algorithm 3: connected components
357 ------------------------------------------------------------
358
359 \begin{code}
360 components   :: Graph -> Forest Vertex
361 components    = dff . undirected
362
363 undirected   :: Graph -> Graph
364 undirected g  = buildG (bounds g) (edges g ++ reverseE g)
365 \end{code}
366
367
368 -- Algorithm 4: strongly connected components
369
370 \begin{code}
371 scc  :: Graph -> Forest Vertex
372 scc g = dfs g (reverse (postOrd (transposeG g)))
373 \end{code}
374
375
376 ------------------------------------------------------------
377 -- Algorithm 5: Classifying edges
378 ------------------------------------------------------------
379
380 \begin{code}
381 back              :: Graph -> Table Int -> Graph
382 back g post        = mapT select g
383  where select v ws = [ w | w <- ws, post!v < post!w ]
384
385 cross             :: Graph -> Table Int -> Table Int -> Graph
386 cross g pre post   = mapT select g
387  where select v ws = [ w | w <- ws, post!v > post!w, pre!v > pre!w ]
388
389 forward           :: Graph -> Graph -> Table Int -> Graph
390 forward g tree pre = mapT select g
391  where select v ws = [ w | w <- ws, pre!v < pre!w ] \\ tree!v
392 \end{code}
393
394
395 ------------------------------------------------------------
396 -- Algorithm 6: Finding reachable vertices
397 ------------------------------------------------------------
398
399 \begin{code}
400 reachable    :: Graph -> Vertex -> [Vertex]
401 reachable g v = preorderF (dfs g [v])
402
403 path         :: Graph -> Vertex -> Vertex -> Bool
404 path g v w    = w `elem` (reachable g v)
405 \end{code}
406
407
408 ------------------------------------------------------------
409 -- Algorithm 7: Biconnected components
410 ------------------------------------------------------------
411
412 \begin{code}
413 bcc :: Graph -> Forest [Vertex]
414 bcc g = (concat . map bicomps . map (do_label g dnum)) forest
415  where forest = dff g
416        dnum   = preArr (bounds g) forest
417
418 do_label :: Graph -> Table Int -> Tree Vertex -> Tree (Vertex,Int,Int)
419 do_label g dnum (Node v ts) = Node (v,dnum!v,lv) us
420  where us = map (do_label g dnum) ts
421        lv = minimum ([dnum!v] ++ [dnum!w | w <- g!v]
422                      ++ [lu | Node (_,_,lu) _ <- us])
423
424 bicomps :: Tree (Vertex,Int,Int) -> Forest [Vertex]
425 bicomps (Node (v,_,_) ts)
426       = [ Node (v:vs) us | (_,Node vs us) <- map collect ts]
427
428 collect :: Tree (Vertex,Int,Int) -> (Int, Tree [Vertex])
429 collect (Node (v,dv,lv) ts) = (lv, Node (v:vs) cs)
430  where collected = map collect ts
431        vs = concat [ ws | (lw, Node ws _)  <- collected, lw<dv]
432        cs = concat [ if lw<dv then us else [Node (v:ws) us]
433                         | (lw, Node ws us) <- collected ]
434 \end{code}
435