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