add CCGraph.spanning_tree with a lazy tree

This commit is contained in:
Simon Cruanes 2015-06-10 17:23:55 +02:00
parent d8a0bbc748
commit eed339463d
2 changed files with 56 additions and 0 deletions

View file

@ -341,6 +341,44 @@ let topo_sort ?eq ?rev ?(tbl=mk_table 128) ~graph seq =
[ 42, 21; 14, 2; 3, 1; 21, 7; 42, 3]
*)
(** {2 Lazy Spanning Tree} *)
module LazyTree = struct
type ('v, 'e) t =
| Vertex of 'v * ('e * ('v, 'e) t) list Lazy.t
let rec map_v f (Vertex (v, l)) =
let l' = lazy (List.map (fun (e, child) -> e, map_v f child) (Lazy.force l)) in
Vertex (f v, l')
let rec fold_v f acc t = match t with
| Vertex (v, l) ->
let acc = f acc v in
List.fold_left
(fun acc (_, t') -> fold_v f acc t')
acc
(Lazy.force l)
end
let spanning_tree ?(tbl=mk_table 128) ~graph v =
let rec mk_node v =
let children = lazy (
Seq.fold
(fun acc e ->
let v' = graph.dest e in
if tbl.mem v'
then acc
else (
tbl.add v' ();
(e, mk_node v') :: acc
)
) [] (graph.children v)
)
in
LazyTree.Vertex (v, children)
in
mk_node v
(** {2 Strongly Connected Components} *)
module SCC = struct

View file

@ -217,6 +217,24 @@ val topo_sort_tag : ?eq:('v -> 'v -> bool) ->
'v list
(** Same as {!topo_sort} *)
(** {2 Lazy Spanning Tree} *)
module LazyTree : sig
type ('v, 'e) t =
| Vertex of 'v * ('e * ('v, 'e) t) list Lazy.t
val map_v : ('a -> 'b) -> ('a, 'e) t -> ('b, 'e) t
val fold_v : ('acc -> 'v -> 'acc) -> 'acc -> ('v, _) t -> 'acc
end
val spanning_tree : ?tbl:'v set ->
graph:('v, 'e) t ->
'v ->
('v, 'e) LazyTree.t
(** [spanning_tree ~graph v] computes a lazy spanning tree that has [v]
as a root. The table [tbl] is used for the memoization part *)
(** {2 Strongly Connected Components} *)
type 'v scc_state