Skip to content

Commit

Permalink
[incremental cycles] Abstract vertex set type
Browse files Browse the repository at this point in the history
This way clients can provide their own iterator.

Signed-off-by: Emilio Jesus Gallego Arias <[email protected]>
  • Loading branch information
ejgallego committed Feb 4, 2020
1 parent 99425f1 commit c0fe8cc
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 18 deletions.
5 changes: 5 additions & 0 deletions src/dag/dag.ml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ module Make (Value : Value) : S with type value := Value.t = struct

type vertex = node

module Vertex_set = struct
type t = vertex list
let interruptible_fold = List.interruptible_fold
end

let new_mark g =
let m = g.fresh_mark in
g.fresh_mark <- g.fresh_mark + 1;
Expand Down
32 changes: 16 additions & 16 deletions vendor/incremental-cycles/src/incremental_cycles.ml
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,28 @@ let rec visit_backward
match stack with
| [] -> VisitBackwardCompleted
| vertex :: stack ->
let res = interruptible_fold (fun y (stack, fuel) ->
let res = Vertex_set.interruptible_fold ~f:(fun y (stack, fuel) ->
if fuel = 0 then
(* There is no fuel left *)
Break true
Error true
else if is_marked g y mark then
(* This vertex has already been visited, skip it *)
Continue (stack, fuel - 1)
Ok (stack, fuel - 1)
else if vertex_eq y target then
(* A path to [target] has been found *)
Break false
Error false
else begin
set_mark g y mark;
set_parent g y vertex;
Continue (y :: stack, fuel - 1)
Ok (y :: stack, fuel - 1)
end
) (get_incoming g vertex) (stack, fuel)
) (get_incoming g vertex) ~init:(stack, fuel)
in
match res with
| Break timeout ->
| Error timeout ->
if timeout then VisitBackwardInterrupted
else (set_parent g target vertex; VisitBackwardCyclic)
| Continue (stack, fuel) ->
| Ok (stack, fuel) ->
visit_backward g target mark fuel stack

type backward_search_result =
Expand Down Expand Up @@ -163,29 +163,29 @@ let rec visit_forward
match stack with
| [] -> ForwardCompleted
| x :: stack ->
let res = interruptible_fold (fun y stack ->
let res = Vertex_set.interruptible_fold ~f:(fun y stack ->
if is_marked g y visited then
(* We found a path to a marked vertex *)
Break y
Error y
else begin
let y_level = get_level g y in
set_parent g y x;
if y_level < new_level then begin
set_level g y new_level;
clear_incoming g y;
add_incoming g y x;
Continue (y :: stack)
Ok (y :: stack)
end else if y_level = new_level then begin
add_incoming g y x;
Continue stack
Ok stack
end else (* y_level > new_level *)
Continue stack
Ok stack
end
) (get_outgoing g x) stack
) (get_outgoing g x) ~init:stack
in
match res with
| Break y -> ForwardCyclic (x, y)
| Continue stack -> visit_forward g new_level visited stack
| Error y -> ForwardCyclic (x, y)
| Ok stack -> visit_forward g new_level visited stack

(* The whole forward search phase (Step 3 of the algorithm). Explores the
graph forwards starting from [w], updating the levels and incoming edges
Expand Down
14 changes: 12 additions & 2 deletions vendor/incremental-cycles/src/incremental_cycles_intf.ml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ module type Raw_graph = sig
(** The type of vertices of the graph. *)
type vertex

module Vertex_set : sig
type t

val interruptible_fold
: t
-> init:'b
-> f:(vertex -> 'b -> ('b, 'c) Result.t)
-> ('b, 'c) Result.t
end

(** The type of marks (each vertex has an associated mark). *)
type mark

Expand All @@ -22,7 +32,7 @@ module type Raw_graph = sig
val vertex_eq : vertex -> vertex -> bool

(** [get_outgoing g v] returns the list of successors of [v] in the graph. *)
val get_outgoing : graph -> vertex -> vertex list
val get_outgoing : graph -> vertex -> Vertex_set.t

(** [raw_add_edge g v w] inserts a new (directed) arc between vertices [v] and
[w].
Expand Down Expand Up @@ -75,7 +85,7 @@ module type Raw_graph = sig
It corresponds to either the default value for a newly created vertex
(i.e. the empty list, see [raw_add_vertex]), or the result of previous
calls to [clear_incoming] and [add_incoming]. *)
val get_incoming : graph -> vertex -> vertex list
val get_incoming : graph -> vertex -> Vertex_set.t

(** [clear_incoming g v] sets the list of "incoming" vertices of [v] to be the
empty list. *)
Expand Down

0 comments on commit c0fe8cc

Please sign in to comment.