27 [C;M;I], Le, [M;I]; (* ??? *)
29 [I;M;C], Ge, [I;M]; (* ??? *)
46 | he::tl -> aux (4 * acc + (match he with I -> 1 | C -> 2 | M -> 3)) tl
53 type t = int * int * w
54 let compare (h1,l1,_) (h2,l2,_) = compare (h1,l1) (h2,l2)
56 let equal ((h1 : int),(l1 : int),_) (h2,l2,_) = l1=l2 && h1=h2
59 module G = Graph.Imperative.Digraph.Concrete(V);;
65 let hash = Hashtbl.hash
69 module GL = Graph.Imperative.Digraph.Concrete(VL);;
71 let swap = function Le -> Ge | Ge -> Le;;
76 | M::tl -> new_dir (swap dir) tl
77 | (C|I)::tl -> new_dir dir tl
82 (List.map (function I -> "i" | C -> "c" | M -> "-") w)
87 (List.map (function I -> "i" | C -> "c" | M -> "m") w)
90 let string_of_eqclass l =
91 let s = String.concat "=" (List.map string_of_w l) in
92 if s = "" then "." else s
95 let name_of_eqclass l =
96 let s = String.concat "_" (List.map string_of_w' l) in
97 if s = "" then "E" else s
102 let (@@) l1 ll2 = List.map (function l2 -> l1 @ l2) ll2;;
105 let rec aux acc = function
108 | h1::h2::tl when h1=h2 -> aux (h2::acc) tl
109 | h1::tl (* when h1 <> h2 *) -> aux (h1::acc) tl
111 List.rev (aux [] (List.sort compare l))
114 let rec apply_rule_at_beginning (lhs,dir',rhs) (w,dir) =
121 | x::lhs,x'::w when x = x' -> aux (lhs,w)
122 | _,_ -> raise NoMatch in
123 let w' = aux (lhs,w) in
124 if List.length rhs < List.length lhs then rhs @@ [w']
125 else rhs @@ apply_rules (aux (lhs,w),new_dir dir lhs)
126 and apply_rules (w,_ as w_and_dir) =
133 (try apply_rule_at_beginning rule w_and_dir
141 let apply_rules (w,dir as w_and_dir) =
142 List.map (fun w' -> w,dir,w')
143 (uniq (apply_rules w_and_dir))
146 let step (l : w list) =
151 List.map (fun x -> x@w)
152 (if List.length (List.filter (fun w -> w = M) w) >= 7 then
164 if i mod 1000 = 0 then
166 print_string ("@" ^ string_of_int i ^ " ");
169 aux (f he :: acc) (i+1) tl
171 let res = List.rev (aux [] 1 l) in
181 if i mod 1000 = 0 then
183 print_string ("@" ^ string_of_int i ^ " ");
192 let normalize (l : w list) =
193 print_endline (string_of_int (List.length l) ^ " nodes to be normalized");
196 (mapi (fun x -> apply_rules (x,Le) @ apply_rules (x,Ge)) l) in
199 (function (x,rel,y) ->
202 match rel with Le -> x,y | Ge -> y,x) rels
207 let visualize graph =
211 let edge_attributes _ = []
212 let default_edge_attributes _ = []
213 let get_subgraph _ = None
214 let vertex_attributes v = [`Label (string_of_eqclass (GL.V.label v))]
215 let vertex_name v = name_of_eqclass (GL.V.label v)
216 let default_vertex_attributes _ = []
217 let graph_attributes _ = []
219 let module D = Graph.Graphviz.Dot(GL) in
220 let ch = open_out "/tmp/comb.dot" in
221 D.output_graph ch graph;
223 ignore (Unix.system ("tred /tmp/comb.dot > /tmp/red.dot"));
224 ignore (Unix.system ("dot -Tps /tmp/red.dot > /tmp/red.ps"));
225 (*Unix.system ("ggv /tmp/red.ps");*)
228 let w_compare s1 s2 =
229 let c = compare (List.length s1) (List.length s2) in
230 if c = 0 then compare s1 s2 else c
233 let normalize_and_describe norm =
234 let cache = Hashtbl.create 5393 in
235 let canonicals = Hashtbl.create 5393 in
236 let descriptions = Hashtbl.create 5393 in
238 let normalized = norm v in
239 let _,_,dsc = G.V.label v in
240 if not (List.mem dsc (Hashtbl.find_all cache normalized)) then
241 Hashtbl.add cache normalized dsc;
244 let vertexes = uniq (Hashtbl.fold (fun k _ l -> k::l) cache []) in
247 (fun v -> v, List.sort w_compare (Hashtbl.find_all cache v)) vertexes in
248 iteri (function (_,w::_) -> Hashtbl.add canonicals w () | _ -> ()) xx;
249 let is_not_redundant =
253 try Hashtbl.find canonicals w; true with Not_found -> false
257 Hashtbl.add descriptions v ((List.filter is_not_redundant x) : eqclass)) xx),
258 Hashtbl.find descriptions
262 print_endline (string_of_int (List.length arcs) ^ " arcs to be classified");
263 let graph = G.create () in
264 iteri (fun (x,y) -> G.add_edge graph x y) arcs;
265 print_endline ("<scc>");
267 let module SCC = Graph.Components.Make(G) in SCC.scc graph in
268 print_endline (string_of_int classes ^ " classes");
269 print_endline ("-----");
273 let analyze (norm,arcs) =
274 print_endline ("building class graph (" ^ string_of_int (List.length arcs) ^ ")");
275 let normalize,finish,describe = normalize_and_describe norm in
276 let arcs = uniq (mapi (fun (x,y) -> normalize x,normalize y) arcs) in
277 print_endline "finish";
279 print_endline ("collapse " ^ string_of_int (List.length arcs) ^ " arcs");
280 let arcs = uniq (mapi (function (x,y) -> describe x,describe y) arcs) in
281 print_endline ("build (" ^ string_of_int (List.length arcs) ^ " arcs)");
282 let cgraph = GL.create () in
283 iteri (function (x,y) -> if x <> y then GL.add_edge cgraph x y) arcs;
284 print_endline "visualize";
286 print_endline ("/////");
289 let rec iter n nodes old_arcs =
290 print_endline ("STEP " ^ string_of_int n);
291 let arcs = old_arcs @ normalize nodes in
292 let pkg = classify arcs in
294 iter (n - 1) (step nodes) arcs