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