1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
|
(**************************************************************************)
(* *)
(* This file is part of OcamlGraph. *)
(* *)
(* Copyright (C) 2009-2010 *)
(* CEA (Commissariat l'nergie Atomique) *)
(* *)
(* you can redistribute it and/or modify it under the terms of the GNU *)
(* Lesser General Public License as published by the Free Software *)
(* Foundation, version 2.1, with a linking exception. *)
(* *)
(* It is distributed in the hope that it will be useful, *)
(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
(* GNU Lesser General Public License for more details. *)
(* *)
(* See the file ../LICENSE for more details. *)
(* *)
(* Authors: *)
(* - Julien Signoles (Julien.Signoles@cea.fr) *)
(* - Jean-Denis Koeck (jdkoeck@gmail.com) *)
(* - Benoit Bataille (benoit.bataille@gmail.com) *)
(* *)
(**************************************************************************)
open Graph
module type G = sig
type t
module V : sig
type t
type label
val label : t -> label
val hash : t -> int
val equal : t -> t -> bool
end
module E : sig
type t
end
val iter_succ : (V.t -> unit) -> t -> V.t -> unit
val iter_pred : (V.t -> unit) -> t -> V.t -> unit
val find_edge : t -> V.t -> V.t -> E.t
end
module type Tree = sig
type t
module V : sig
type t
type label
val create : label -> t
val label : t -> label
val hash: t -> int
val equal: t -> t -> bool
end
module E : Sig.EDGE with type vertex = V.t
val create : ?size:int -> unit -> t
val add_vertex : t -> V.t -> unit
val add_edge_e : t -> E.t -> unit
end
module type S = sig
module Tree: Tree with type E.label = unit
type t
val get_structure : t -> Tree.t
val get_root : t -> Tree.V.t
val get_tree_vertices : Tree.V.label -> t -> Tree.V.t list
val is_ghost_node : Tree.V.t -> t -> bool
val is_ghost_edge : Tree.E.t -> t -> bool
exception Ghost_node
val get_graph_vertex : Tree.V.t -> t -> Tree.V.label
end
module Build
(G : G)
(Tree : Tree with type V.label = G.V.t and type E.label = unit)
(GA: sig
type t
val iter_succ: (G.V.t -> unit) -> t -> G.V.t -> unit
val iter_pred: (G.V.t -> unit) -> t -> G.V.t -> unit
end) =
struct
module Tree = Tree
module H = Hashtbl.Make(G.V)
module HT = Hashtbl.Make(Tree.V)
module HE =
Hashtbl.Make
(struct
type t = Tree.E.t
let equal x y = Tree.E.compare x y = 0
let hash = Hashtbl.hash
end)
type t = {
structure: Tree.t; (* the tree itself *)
root : Tree.V.t; (* the root *)
(* nodes of the tree corresponding to the original nodes *)
assoc_vertex_table: Tree.V.t H.t;
ghost_vertices: unit HT.t;
ghost_edges: unit HE.t;
}
(* Getter *)
let get_structure t = t.structure;;
let get_root t = t.root;;
(** Give the list of vertices in the tree graph representing a vertex
from the old graph *)
let get_tree_vertices vertex tree =
try H.find_all tree.assoc_vertex_table vertex
with Not_found -> assert false;;
(** True if the vertex is not to be shown *)
let is_ghost_node v tree = HT.mem tree.ghost_vertices v;;
(** True if the edge is not to be shown *)
let is_ghost_edge e tree = HE.mem tree.ghost_edges e;;
exception Ghost_node;;
(** Give the old graph vertex represented by a vertex in the tree -
@raise Ghost_node if the vertex is a ghost vertex *)
let get_graph_vertex vertex tree =
if is_ghost_node vertex tree then raise Ghost_node
else Tree.V.label vertex;;
(* Explore the graph from a vertex and build a tree -
Will be used forward and backward *)
let build src_graph tree src_vertex tree_root backward_flag depth =
let complete_to_depth v missing =
let pred_vertex = ref v in
let next_vertex = ref v in
for i = 1 to missing - 1 do
next_vertex := Tree.V.create (Tree.V.label v);
HT.add tree.ghost_vertices !next_vertex ();
let new_ghost_edge =
if backward_flag then Tree.E.create !next_vertex () !pred_vertex
else Tree.E.create !pred_vertex () !next_vertex
in Tree.add_edge_e tree.structure new_ghost_edge;
HE.add tree.ghost_edges new_ghost_edge ();
pred_vertex := !next_vertex;
done
in
let has_succ = ref false in
let vertex_visited = H.create 97 in
let queue = Queue.create () in
H.add vertex_visited src_vertex true;
(* Initialize queue *)
if depth <> 0 then
if backward_flag then
GA.iter_pred
(fun a -> Queue.add (a, tree_root, depth) queue)
src_graph
src_vertex
else
GA.iter_succ
(fun a -> Queue.add (a, tree_root, depth) queue)
src_graph
src_vertex;
(* Empty queue *)
let rec empty_queue () =
if not(Queue.is_empty queue) then begin
let vertex, origin_vertex, depth = Queue.take queue in
if depth > 0 then begin
let new_vertex = Tree.V.create vertex in
H.add tree.assoc_vertex_table vertex new_vertex;
if backward_flag then begin
let new_edge = Tree.E.create new_vertex () origin_vertex in
Tree.add_edge_e tree.structure new_edge
end else begin
let new_edge = Tree.E.create origin_vertex () new_vertex in
Tree.add_edge_e tree.structure new_edge
end;
if not(H.mem vertex_visited vertex) then begin
H.add vertex_visited vertex true;
let iter f =
f
(fun a ->
Queue.add (a, new_vertex, depth - 1) queue;
has_succ := true)
src_graph
vertex
in
if backward_flag then iter GA.iter_pred else iter GA.iter_succ;
if not !has_succ then complete_to_depth new_vertex depth;
has_succ := false;
end else if depth <> 1 then begin
if backward_flag then
GA.iter_pred (fun _ -> has_succ := true) src_graph vertex
else
GA.iter_succ (fun _ -> has_succ := true) src_graph vertex;
if !has_succ then begin
let ghost_vertex = Tree.V.create vertex in
HT.add tree.ghost_vertices ghost_vertex ();
let new_edge =
if backward_flag then Tree.E.create ghost_vertex () new_vertex
else Tree.E.create new_vertex () ghost_vertex
in Tree.add_edge_e tree.structure new_edge;
complete_to_depth ghost_vertex (depth-1)
end else
complete_to_depth new_vertex depth;
has_succ := false;
end
end;
empty_queue ()
end
in
empty_queue ()
(* [JS 2010/11/10] trying to simplify the algorithm. Not finish yet
let new_build graph tree root troot depth backward =
let first = ref true in
let q = Queue.create () in
(* invariant: [h] contains exactly the vertices which have been pushed *)
let must_add_ghost = ref true in
let add_tree_vertex v =
let tv = if !first then troot else Tree.V.create v in
first := false;
Tree.add_vertex tree.structure tv;
H.add tree.assoc_vertex_table v tv;
tv
in
let add_tree_edge tsrc dst =
let tdst = add_tree_vertex dst in
let tsrc, tdst = if backward then tdst, tsrc else tsrc, tdst in
let e = Tree.E.create tsrc () tdst in
Tree.add_edge_e tree.structure e;
tdst, e
in
let push n src dst =
if n < depth then Queue.add (dst, n + 1) q;
ignore (add_tree_edge src dst);
must_add_ghost := false
in
let loop () =
while not (Queue.is_empty q) do
let v, n = Queue.pop q in
let tv = add_tree_vertex v in
must_add_ghost := true;
(if backward then GA.iter_pred else GA.iter_succ) (push n tv) graph v;
if !must_add_ghost then
let tsrc = ref tv in
for i = n to depth do
let tdst, te = add_tree_edge !tsrc v in
HT.add tree.ghost_vertices tdst ();
HE.add tree.ghost_edges te ();
tsrc := tdst
done
done
in
Queue.add (root, 0) q;
loop ()
*)
(** Build a tree graph centered on a vertex and containing its
predecessors and successors *)
let make src_graph src_vertex depth_forward depth_backward =
let tree = {
structure = Tree.create ();
root = Tree.V.create src_vertex;
assoc_vertex_table = H.create 97;
ghost_vertices = HT.create 17;
ghost_edges = HE.create 17;
}
in
H.add tree.assoc_vertex_table src_vertex tree.root;
Tree.add_vertex tree.structure tree.root;
build src_graph tree src_vertex tree.root false depth_forward;
build src_graph tree src_vertex tree.root true depth_backward;
(* new_build src_graph tree src_vertex tree.root depth_forward false;
new_build src_graph tree src_vertex tree.root depth_backward true;*)
tree
end
module Make
(G : G)
(Tree : Tree with type V.label = G.V.t and type E.label = unit) =
Build(G)(Tree)(G)
module Make_from_dot_model
(Tree : Tree with type V.label = DGraphModel.DotG.V.t
and type E.label = unit) =
Build
(DGraphModel.DotG)
(Tree)
(struct
type t = DGraphModel.dotg_model
let iter_succ f g = g#iter_succ f
let iter_pred f g = g#iter_pred f
end)
|