~npalix/coccinelle/upstream

« back to all changes in this revision

Viewing changes to commons/ograph_extended.ml

  • Committer: Nicolas Palix
  • Date: 2010-01-28 14:23:49 UTC
  • Revision ID: git-v1:70d17887795852eca805bfe27745b9810c0a39be
Remove trailing whitespace/tab

svn path=/coccinelle/; revision=8684

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
open Oassocb
9
9
open Osetb
10
10
 
11
 
(* 
12
 
 * graph structure: 
 
11
(*
 
12
 * graph structure:
13
13
 *  -  node: index -> nodevalue
14
14
 *  -  arc: (index * index) * edgevalue
15
 
 * 
16
 
 * invariant: key in pred is also in succ (completness) and value in 
 
15
 *
 
16
 * invariant: key in pred is also in succ (completness) and value in
17
17
 * either assoc is a key also.
18
 
 * 
 
18
 *
19
19
 * How ? matrix ? but no growing array :(
20
 
 * 
 
20
 *
21
21
 * When need index ? Must have an index when can't just use nodevalue
22
22
 * as a key, cos sometimes may have 2 times the same key, but it must
23
23
 * be 2 different nodes. For instance in program f(); f(); we want 2
24
24
 * nodes, one per f(); hence the index. If each node is different,
25
25
 * then no problem, can omit index.
26
 
 * 
 
26
 *
27
27
 * todo?: prend en parametre le type de finitemap et set a prendre
28
 
 * todo?: add_arc doit ramer, car del la key, puis add => better to 
 
28
 * todo?: add_arc doit ramer, car del la key, puis add => better to
29
29
 * have a ref to a set.
30
 
 * 
31
 
 * opti: graph with pointers and a tag visited => need keep global value 
 
30
 *
 
31
 * opti: graph with pointers and a tag visited => need keep global value
32
32
 * visited_counter.  check(that node is in, ...), display.
33
 
 * opti: when the graph structure is stable, have a method compact,  that 
34
 
 * transforms that in a matrix (assert that all number between 0 and 
 
33
 * opti: when the graph structure is stable, have a method compact,  that
 
34
 * transforms that in a matrix (assert that all number between 0 and
35
35
 * free_index are used,  or do some defrag-like-move/renaming).
36
 
 * 
 
36
 *
37
37
 *)
38
38
 
39
39
type nodei = int
44
44
 
45
45
  object(o)
46
46
    (* inherit ['a] ograph *)
47
 
      
 
47
 
48
48
    val free_index = 0
49
49
 
50
50
    val succ = build_assoc()
51
51
    val pred = build_assoc()
52
52
    val nods = build_assoc()
53
53
 
54
 
    method add_node (e: 'a) = 
 
54
    method add_node (e: 'a) =
55
55
      let i = free_index in
56
 
      ({< 
57
 
        nods = nods#add (i, e); 
 
56
      ({<
 
57
        nods = nods#add (i, e);
58
58
        pred = pred#add (i, build_set() );
59
59
        succ = succ#add (i, build_set() );
60
60
        free_index = i + 1;
61
61
       >}, i)
62
62
 
63
 
    method add_nodei i (e: 'a) = 
64
 
      ({< 
65
 
        nods = nods#add (i, e); 
 
63
    method add_nodei i (e: 'a) =
 
64
      ({<
 
65
        nods = nods#add (i, e);
66
66
        pred = pred#add (i, build_set() );
67
67
        succ = succ#add (i, build_set() );
68
68
        free_index = (max free_index i) + 1;
69
69
       >}, i)
70
70
 
71
71
 
72
 
    method del_node (i) = 
 
72
    method del_node (i) =
73
73
      {<
74
 
        (* check: e is effectively the index associated with e, 
 
74
        (* check: e is effectively the index associated with e,
75
75
           and check that already in *)
76
76
 
77
77
        (* todo: assert that have no pred and succ, otherwise
78
 
         * will have some dangling pointers 
 
78
         * will have some dangling pointers
79
79
         *)
80
 
        nods = nods#delkey i; 
 
80
        nods = nods#delkey i;
81
81
        pred = pred#delkey i;
82
82
        succ = succ#delkey i;
83
83
        >}
84
84
 
85
 
    method replace_node (i, (e: 'a)) = 
 
85
    method replace_node (i, (e: 'a)) =
86
86
      assert (nods#haskey i);
87
87
      {<
88
88
        nods = nods#replkey (i, e);
89
89
       >}
90
90
 
91
 
    method add_arc ((a,b),(v: 'b)) = 
92
 
      {< 
 
91
    method add_arc ((a,b),(v: 'b)) =
 
92
      {<
93
93
        succ = succ#replkey (a, (succ#find a)#add (b, v));
94
94
        pred = pred#replkey (b, (pred#find b)#add (a, v));
95
95
        >}
96
96
    method del_arc ((a,b),v) =
97
 
      {< 
 
97
      {<
98
98
        succ = succ#replkey (a, (succ#find a)#del (b,v));
99
99
        pred = pred#replkey (b, (pred#find b)#del (a,v));
100
100
        >}
106
106
    method allsuccessors = succ
107
107
 
108
108
(*
109
 
    method ancestors xs = 
110
 
      let rec aux xs acc = 
 
109
    method ancestors xs =
 
110
      let rec aux xs acc =
111
111
        match xs#view with (* could be done with an iter *)
112
112
        | Empty -> acc
113
 
        | Cons(x, xs) -> (acc#add x) 
 
113
        | Cons(x, xs) -> (acc#add x)
114
114
              +> (fun newacc -> aux (o#predecessors x) newacc)
115
115
              +> (fun newacc -> aux xs newacc)
116
116
      in aux xs (f2()) (* (new osetb []) *)
117
117
 
118
 
    method children  xs = 
119
 
      let rec aux xs acc = 
 
118
    method children  xs =
 
119
      let rec aux xs acc =
120
120
        match xs#view with (* could be done with an iter *)
121
121
        | Empty -> acc
122
 
        | Cons(x, xs) -> (acc#add x) 
 
122
        | Cons(x, xs) -> (acc#add x)
123
123
              +> (fun newacc -> aux (o#successors x) newacc)
124
124
              +> (fun newacc -> aux xs newacc)
125
125
      in aux xs (f2()) (* (new osetb []) *)
126
126
 
127
 
    method brothers  x = 
 
127
    method brothers  x =
128
128
      let parents = o#predecessors x in
129
129
      (parents#fold (fun acc e -> acc $++$ o#successors e) (f2()))#del x
130
130
 
131
131
*)
132
132
 
133
 
  end   
 
133
  end
134
134
 
135
135
 
136
136
 
140
140
  let build_set ()   = new osetb Setb.empty in
141
141
 
142
142
  object(o)
143
 
      
 
143
 
144
144
    val mutable free_index = 0
145
145
 
146
146
    val mutable succ = build_assoc()
147
147
    val mutable pred = build_assoc()
148
148
    val mutable nods = build_assoc()
149
149
 
150
 
    method add_node (e: 'a) = 
 
150
    method add_node (e: 'a) =
151
151
      let i = free_index in
152
 
      nods <- nods#add (i, e); 
 
152
      nods <- nods#add (i, e);
153
153
      pred <- pred#add (i, build_set() );
154
154
      succ <- succ#add (i, build_set() );
155
155
      free_index <- i + 1;
156
156
      i
157
157
 
158
 
    method add_nodei i (e: 'a) = 
159
 
      nods <- nods#add (i, e); 
 
158
    method add_nodei i (e: 'a) =
 
159
      nods <- nods#add (i, e);
160
160
      pred <- pred#add (i, build_set() );
161
161
      succ <- succ#add (i, build_set() );
162
162
      free_index <- (max free_index i) + 1;
163
163
 
164
164
 
165
 
    method del_node (i) = 
166
 
        (* check: e is effectively the index associated with e, 
 
165
    method del_node (i) =
 
166
        (* check: e is effectively the index associated with e,
167
167
           and check that already in *)
168
168
 
169
169
        (* todo: assert that have no pred and succ, otherwise
170
 
         * will have some dangling pointers 
 
170
         * will have some dangling pointers
171
171
         *)
172
 
        nods <- nods#delkey i; 
 
172
        nods <- nods#delkey i;
173
173
        pred <- pred#delkey i;
174
174
        succ <- succ#delkey i;
175
175
 
176
 
    method replace_node (i, (e: 'a)) = 
 
176
    method replace_node (i, (e: 'a)) =
177
177
      assert (nods#haskey i);
178
178
      nods <- nods#replkey (i, e);
179
 
        
180
 
    method add_arc ((a,b),(v: 'b)) = 
 
179
 
 
180
    method add_arc ((a,b),(v: 'b)) =
181
181
      succ <- succ#replkey (a, (succ#find a)#add (b, v));
182
182
      pred <- pred#replkey (b, (pred#find b)#add (a, v));
183
183
    method del_arc ((a,b),v) =
190
190
    method nodes = nods
191
191
    method allsuccessors = succ
192
192
 
193
 
  end   
 
193
  end
194
194
 
195
195
 
196
196
(* depth first search *)
197
197
let dfs_iter xi f g =
198
198
  let already = Hashtbl.create 101 in
199
 
  let rec aux_dfs xs = 
200
 
    xs +> List.iter (fun xi -> 
 
199
  let rec aux_dfs xs =
 
200
    xs +> List.iter (fun xi ->
201
201
      if Hashtbl.mem already xi then ()
202
202
      else begin
203
203
        Hashtbl.add already xi true;
209
209
  aux_dfs [xi]
210
210
 
211
211
 
212
 
let dfs_iter_with_path xi f g = 
 
212
let dfs_iter_with_path xi f g =
213
213
  let already = Hashtbl.create 101 in
214
 
  let rec aux_dfs path xi = 
 
214
  let rec aux_dfs path xi =
215
215
    if Hashtbl.mem already xi then ()
216
216
    else begin
217
217
      Hashtbl.add already xi true;
218
218
      f xi path;
219
219
      let succ = g#successors xi in
220
220
      let succ' = succ#tolist +> List.map fst in
221
 
      succ' +> List.iter (fun yi -> 
 
221
      succ' +> List.iter (fun yi ->
222
222
          aux_dfs (xi::path) yi
223
223
      );
224
224
      end
225
225
  in
226
226
  aux_dfs [] xi
227
 
  
228
 
    
 
227
 
 
228
 
229
229
 
230
230
let generate_ograph_generic g label fnode filename =
231
231
  Common.with_open_outfile filename (fun (pr,_) ->
236
236
    | Some x -> pr (Printf.sprintf "label = \"%s\";\n" x));
237
237
 
238
238
    let nodes = g#nodes in
239
 
    nodes#iter (fun (k,node) -> 
 
239
    nodes#iter (fun (k,node) ->
240
240
      let (str,border_color,inner_color) = fnode (k, node) in
241
241
      let color =
242
242
        match inner_color with
246
246
            | Some x -> Printf.sprintf ", style=\"setlinewidth(3)\", color = %s" x)
247
247
        | Some x ->
248
248
            (match border_color with
249
 
              None -> Printf.sprintf ", style=\"setlinewidth(3),filled\", fillcolor = %s" x 
 
249
              None -> Printf.sprintf ", style=\"setlinewidth(3),filled\", fillcolor = %s" x
250
250
            | Some x' -> Printf.sprintf ", style=\"setlinewidth(3),filled\", fillcolor = %s, color = %s" x x') in
251
 
     (* so can see if nodes without arcs were created *) 
 
251
     (* so can see if nodes without arcs were created *)
252
252
      pr (sprintf "%d [label=\"%s   [%d]\"%s];\n" k str k color)
253
253
    );
254
254
 
255
 
    nodes#iter (fun (k,node) -> 
 
255
    nodes#iter (fun (k,node) ->
256
256
      let succ = g#successors k in
257
257
      succ#iter (fun (j,edge) ->
258
258
        pr (sprintf "%d -> %d;\n" k j);
269
269
    pr "size = \"10,10\";\n" ;
270
270
 
271
271
    let nodes = g#nodes in
272
 
    nodes#iter (fun (k,(node, s)) -> 
273
 
     (* so can see if nodes without arcs were created *) 
 
272
    nodes#iter (fun (k,(node, s)) ->
 
273
     (* so can see if nodes without arcs were created *)
274
274
      pr (sprintf "%d [label=\"%s   [%d]\"];\n" k s k)
275
275
    );
276
276
 
277
 
    nodes#iter (fun (k,node) -> 
 
277
    nodes#iter (fun (k,node) ->
278
278
      let succ = g#successors k in
279
279
      succ#iter (fun (j,edge) ->
280
280
        pr (sprintf "%d -> %d;\n" k j);
286
286
 
287
287
 
288
288
let launch_gv_cmd filename =
289
 
  let _status = 
 
289
  let _status =
290
290
    Unix.system ("dot " ^ filename ^ " -Tps  -o " ^ filename ^ ".ps;") in
291
291
  let _status = Unix.system ("gv " ^ filename ^ ".ps &")
292
292
  in
293
293
  (* zarb: I need this when I launch the program via eshell, otherwise gv
294
294
     do not get the chance to be launched *)
295
 
  Unix.sleep 1; 
 
295
  Unix.sleep 1;
296
296
  ()
297
297
 
298
 
let print_ograph_extended g filename launchgv = 
299
 
  generate_ograph_xxx g filename;
300
 
  if launchgv then launch_gv_cmd filename
301
 
 
302
 
let print_ograph_mutable g filename launchgv = 
303
 
  generate_ograph_xxx g filename;
304
 
  if launchgv then launch_gv_cmd filename
305
 
 
306
 
let print_ograph_mutable_generic g label fnode ~output_file ~launch_gv = 
 
298
let print_ograph_extended g filename launchgv =
 
299
  generate_ograph_xxx g filename;
 
300
  if launchgv then launch_gv_cmd filename
 
301
 
 
302
let print_ograph_mutable g filename launchgv =
 
303
  generate_ograph_xxx g filename;
 
304
  if launchgv then launch_gv_cmd filename
 
305
 
 
306
let print_ograph_mutable_generic g label fnode ~output_file ~launch_gv =
307
307
  generate_ograph_generic g label fnode output_file;
308
308
  if launch_gv then launch_gv_cmd output_file