File: dGraphSubTree.ml

package info (click to toggle)
ocamlgraph 1.8.5-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,888 kB
  • ctags: 2,576
  • sloc: ml: 15,777; makefile: 513; xml: 151
file content (292 lines) | stat: -rwxr-xr-x 9,802 bytes parent folder | download | duplicates (3)
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)