diff --git a/src/data/CCGraph.ml b/src/data/CCGraph.ml index 37a9da15..2155f089 100644 --- a/src/data/CCGraph.ml +++ b/src/data/CCGraph.ml @@ -43,6 +43,10 @@ module Seq = struct a (fun x -> acc := f !acc x); !acc let to_list seq = fold (fun acc x->x::acc) [] seq |> List.rev + exception Exit_ + let exists_ f seq = + try seq (fun x -> if f x then raise Exit_); false + with Exit_ -> true end (** {2 Interfaces for graphs} *) @@ -315,6 +319,15 @@ module Traverse = struct end end +(** {2 Cycles} *) + +let is_dag ?(tbl=mk_table 128) ~graph vs = + Traverse.Event.dfs ~tbl ~graph vs + |> Seq.exists_ + (function + | `Edge (_, `Back) -> true + | _ -> false) + (** {2 Topological Sort} *) exception Has_cycle diff --git a/src/data/CCGraph.mli b/src/data/CCGraph.mli index 22bc1233..36511313 100644 --- a/src/data/CCGraph.mli +++ b/src/data/CCGraph.mli @@ -224,6 +224,17 @@ module Traverse : sig end end +(** {2 Cycles} *) + +val is_dag : + ?tbl:'v set -> + graph:('v, _) t -> + 'v sequence -> + bool +(** [is_dag ~graph vs] returns [true] if the subset of [graph] reachable + from [vs] is acyclic. + @since NEXT_RELEASE *) + (** {2 Topological Sort} *) exception Has_cycle