Skip to content

Commit

Permalink
fixed documentation of map_vertex
Browse files Browse the repository at this point in the history
fixes #31
  • Loading branch information
backtracking committed Oct 22, 2020
1 parent 8e250de commit b4eb651
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

- #31: fixed documentation of [map_vertex]: the supplied function
must be injective
- #110: ensure that map_vertex applies the function only once per vertex

# 2.0.0 (October 2, 2020)
Expand Down
8 changes: 7 additions & 1 deletion src/sig.mli
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,13 @@ module type G = sig
(** Fold on all edges of a graph. *)

val map_vertex : (vertex -> vertex) -> t -> t
(** Map on all vertices of a graph. *)
(** Map on all vertices of a graph.
The current implementation requires the supplied function to be
injective. Said otherwise, [map_vertex] cannot be used to contract
a graph by mapping several vertices to the same vertex.
To contract a graph, use instead [create], [add_vertex],
and [add_edge]. *)

(** {2 Vertex iterators}
Expand Down
32 changes: 32 additions & 0 deletions tests/test_31.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

(* Issue #31
This would fail in the current state of OCamlGraph,
as map_vertex requires a supplied function that is injective.
*)

module String = struct include String let hash = Hashtbl.hash end
module G = Graph.Persistent.Digraph.ConcreteBidirectional(String)

(* Make a persistent graph where:
A -> B
B -> C
C -> B *)
let g = List.fold_left (fun g (x, y) ->
G.add_edge g x y) G.empty [("A", "B"); ("B", "C"); ("C", "B")]

(* Contract the SCC *)
module C = Graph.Components.Make(G)

let contract g =
let names = Array.map (String.concat ",") (C.scc_array g) in
let (_, numbering) = C.scc g in
Array.fold_left (fun g x -> G.remove_edge g x x)
(G.map_vertex (fun x -> names.(numbering x)) g)
names

let g' = contract g
(* this is now "A" -> "C,B" *)

let () =
assert (G.in_degree g' "C,B" = 1)

0 comments on commit b4eb651

Please sign in to comment.