Commit 41bf7ca8 authored by POTTIER Francois's avatar POTTIER Francois

Simplify the implementation of graph numbering using [Numbering].

parent 56d72622
......@@ -17,58 +17,46 @@ module Make
(G : GRAPH with type t = M.key)
= struct
type t = G.t
(* Set up a facility for numbering vertices. *)
let push frontier x =
module N =
Numbering.Make(M)
(* Implement a depth-first search. The functions [N.has_been_encoded]
and [N.encode] allow us not only to assign a unique number to each
vertex, but also to mark a vertex and test whether a vertex has been
marked. *)
let frontier =
Stack.create()
let push x =
Stack.push x frontier
let rec visit gensym table frontier =
let rec visit () =
match Stack.pop frontier with
| exception Stack.Empty ->
(* The stack is empty: we are done. *)
()
| x ->
match M.find x table with
| _ ->
(* [x] is known already: ignore it. *)
visit gensym table frontier
| exception Not_found ->
(* Assign the number [i] to [x]. *)
let i = gensym() in
M.add x i table;
G.foreach_successor x (push frontier);
visit gensym table frontier
let n, encode, decode =
(* Perform a depth-first traversal of the graph. Assign a unique number [i]
to every newly-discovered vertex [x]. *)
let gensym = Gensym.make() in
let table = M.create() in
let frontier = Stack.create() in
G.foreach_root (push frontier);
visit gensym table frontier;
let n = gensym() in
(* We have discovered [n] graph vertices. [table] now contains a mapping
of these vertices to integers in the range [0..n). We now build the
reverse mapping in an array. This may seem a little clumsy (an array of
options is allocated in an intermediate step), but requires only linear
time. *)
let vertex : G.t option array = Array.make n None in
M.iter (fun x i ->
vertex.(i) <- Some x
) table;
let force = function Some x -> x | None -> assert false in
let vertex : G.t array = Array.map force vertex in
(* Return two conversions functions. *)
let encode x =
try
M.find x table
with Not_found ->
let msg = Printf.sprintf "\n Fix.Number says: \
please check the argument passed to \"encode\".\n %s\n" __LOC__ in
raise (Invalid_argument msg)
and decode i = vertex.(i) in
n, encode, decode
if N.has_been_encoded x then
(* [x] is known already: ignore it. *)
visit()
else
(* Assign a number to [x]. *)
let (_ : int) = N.encode x in
G.foreach_successor x push;
visit()
(* Perform the depth-first search. *)
let () =
G.foreach_root push;
visit()
(* We are done! This defines [n], [encode], [decode]. *)
include N.Done()
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment