package ocamlgraph

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file dGraphSubTree.ml

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
(**************************************************************************)
(*                                                                        *)
(*  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)                      *)
(*                                                                        *)
(**************************************************************************)

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)
OCaml

Innovation. Community. Security.