iterator interface for CCGraph.scc

This commit is contained in:
Simon Cruanes 2015-06-10 16:57:07 +02:00
parent 54c690467f
commit d8a0bbc748
2 changed files with 54 additions and 51 deletions

View file

@ -41,6 +41,7 @@ module Seq = struct
let acc = ref acc in
a (fun x -> acc := f !acc x);
!acc
let to_list seq = fold (fun acc x->x::acc) [] seq |> List.rev
end
let (|>) x f = f x
@ -368,14 +369,15 @@ module SCC = struct
) else pop_down_to ~id (cell.vertex::acc) stack
let explore ~tbl ~graph seq =
let first = ref true in
fun k ->
if !first then first := false else raise Sequence_once;
(* stack of nodes being explored, for the DFS *)
let to_explore = Stack.create() in
(* stack for Tarjan's algorithm itself *)
let stack = Stack.create () in
(* unique ID *)
let n = ref 0 in
(* result *)
let res = ref [] in
(* exploration *)
Seq.iter
(fun v ->
@ -412,12 +414,12 @@ module SCC = struct
(* pop from stack if SCC found *)
if cell.id = cell.min_id then (
let scc = pop_down_to ~id:cell.id [] stack in
res := scc :: !res
k scc
)
done
) seq;
assert (Stack.is_empty stack);
!res
()
end
type 'v scc_state = 'v SCC.state
@ -443,7 +445,7 @@ let scc ?(tbl=mk_table 128) ~graph seq = SCC.explore ~tbl ~graph seq
; "h", "d"
; "h", "g"
] in
let res = scc ~graph (Seq.return "a") in
let res = scc ~graph (Seq.return "a") |> Seq.to_list in
assert_bool "scc"
(set_eq ~eq:(set_eq ?eq:None) res
[ [ "a"; "b"; "e" ]

View file

@ -43,6 +43,7 @@ module Seq : sig
val filter_map : ('a -> 'b option) -> 'a t -> 'b t
val iter : ('a -> unit) -> 'a t -> unit
val fold: ('b -> 'a -> 'b) -> 'b -> 'a t -> 'b
val to_list : 'a t -> 'a list
end
(** {2 Interfaces for graphs} *)
@ -224,7 +225,7 @@ type 'v scc_state
val scc : ?tbl:('v, 'v scc_state) table ->
graph:('v, 'e) t ->
'v sequence ->
'v list list
'v list sequence_once
(** Strongly connected components reachable from the given vertices.
Each component is a list of vertices that are all mutually reachable
in the graph.