307 |
307 |
308 fun transpose eq_comp g = |
308 fun transpose eq_comp g = |
309 let |
309 let |
310 (* Compute list of reversed edges for each adjacency list *) |
310 (* Compute list of reversed edges for each adjacency list *) |
311 fun flip (u,(v,l)::el) = (v,(u,l)) :: flip (u,el) |
311 fun flip (u,(v,l)::el) = (v,(u,l)) :: flip (u,el) |
312 | flip (_,nil) = nil |
312 | flip (_,[]) = [] |
313 |
313 |
314 (* Compute adjacency list for node u from the list of edges |
314 (* Compute adjacency list for node u from the list of edges |
315 and return a likewise reduced list of edges. The list of edges |
315 and return a likewise reduced list of edges. The list of edges |
316 is searches for edges starting from u, and these edges are removed. *) |
316 is searches for edges starting from u, and these edges are removed. *) |
317 fun gather (u,(v,w)::el) = |
317 fun gather (u,(v,w)::el) = |
319 val (adj,edges) = gather (u,el) |
319 val (adj,edges) = gather (u,el) |
320 in |
320 in |
321 if eq_comp (u, v) then (w::adj,edges) |
321 if eq_comp (u, v) then (w::adj,edges) |
322 else (adj,(v,w)::edges) |
322 else (adj,(v,w)::edges) |
323 end |
323 end |
324 | gather (_,nil) = (nil,nil) |
324 | gather (_,[]) = ([],[]) |
325 |
325 |
326 (* For every node in the input graph, call gather to find all reachable |
326 (* For every node in the input graph, call gather to find all reachable |
327 nodes in the list of edges *) |
327 nodes in the list of edges *) |
328 fun assemble ((u,_)::el) edges = |
328 fun assemble ((u,_)::el) edges = |
329 let val (adj,edges) = gather (u,edges) |
329 let val (adj,edges) = gather (u,edges) |
330 in (u,adj) :: assemble el edges |
330 in (u,adj) :: assemble el edges |
331 end |
331 end |
332 | assemble nil _ = nil |
332 | assemble [] _ = [] |
333 |
333 |
334 (* Compute, for each adjacency list, the list with reversed edges, |
334 (* Compute, for each adjacency list, the list with reversed edges, |
335 and concatenate these lists. *) |
335 and concatenate these lists. *) |
336 val flipped = List.foldr (op @) nil (map flip g) |
336 val flipped = maps flip g |
337 |
337 |
338 in assemble g flipped end |
338 in assemble g flipped end |
339 |
339 |
340 (* *********************************************************************** *) |
340 (* *********************************************************************** *) |
341 (* *) |
341 (* *) |
347 (* *********************************************************************** *) |
347 (* *********************************************************************** *) |
348 |
348 |
349 fun dfs_reachable eq_comp g u = |
349 fun dfs_reachable eq_comp g u = |
350 let |
350 let |
351 (* List of vertices which have been visited. *) |
351 (* List of vertices which have been visited. *) |
352 val visited = Unsynchronized.ref nil; |
352 val visited = Unsynchronized.ref []; |
353 |
353 |
354 fun been_visited v = exists (fn w => eq_comp (w, v)) (!visited) |
354 fun been_visited v = exists (fn w => eq_comp (w, v)) (!visited) |
355 |
355 |
356 fun dfs_visit g u = |
356 fun dfs_visit g u = |
357 let |
357 let |
358 val _ = visited := u :: !visited |
358 val _ = visited := u :: !visited |
359 val descendents = |
359 val descendents = |
360 List.foldr (fn ((v,l),ds) => if been_visited v then ds |
360 List.foldr (fn ((v,l),ds) => if been_visited v then ds |
361 else v :: dfs_visit g v @ ds) |
361 else v :: dfs_visit g v @ ds) |
362 nil (adjacent eq_comp g u) |
362 [] (adjacent eq_comp g u) |
363 in descendents end |
363 in descendents end |
364 |
364 |
365 in u :: dfs_visit g u end; |
365 in u :: dfs_visit g u end; |
366 |
366 |
367 (* *********************************************************************** *) |
367 (* *********************************************************************** *) |