24 [C;M;I], Le, [M;I]; (* ??? *)
26 [I;M;C], Ge, [I;M]; (* ??? *)
38 module V = struct type t = eqclass end;;
39 module G = Graph.Imperative.Digraph.Abstract(V);;
41 let swap = function Le -> Ge | Ge -> Le;;
46 | M::tl -> new_dir (swap dir) tl
47 | (C|I)::tl -> new_dir dir tl
52 (List.map (function I -> "i" | C -> "c" | M -> "-") w)
57 (List.map (function I -> "i" | C -> "c" | M -> "m") w)
60 let string_of_eqclass l =
61 let s = String.concat "=" (List.map string_of_w l) in
62 if s = "" then "." else s
65 let name_of_eqclass l =
66 let s = String.concat "_" (List.map string_of_w' l) in
67 if s = "" then "E" else s
72 let (@@) l1 ll2 = List.map (function l2 -> l1 @ l2) ll2;;
75 let rec aux acc = function
78 | h1::h2::tl when h1=h2 -> aux (h2::acc) tl
79 | h1::tl (* when h1 <> h2 *) -> aux (h1::acc) tl
81 List.rev (aux [] (List.sort compare l))
84 let rec apply_rule_at_beginning (lhs,dir',rhs) (w,dir) =
91 | x::lhs,x'::w when x = x' -> aux (lhs,w)
92 | _,_ -> raise NoMatch
94 rhs @@ apply_rules (aux (lhs,w),new_dir dir lhs)
95 and apply_rules (w,_ as w_and_dir) =
102 (try apply_rule_at_beginning rule w_and_dir
110 let apply_rules (w,dir as w_and_dir) =
111 List.map (fun w' -> w,dir,w')
112 (uniq (apply_rules w_and_dir))
115 let step (l : w list) =
120 List.map (fun x -> x@w)
121 (if List.length (List.filter (fun w -> w = M) w) >= 2 then
133 if i mod 1000 = 0 then
135 print_string ("@" ^ string_of_int i ^ " ");
138 aux (f he :: acc) (i+1) tl
140 let res = List.rev (aux [] 1 l) in
150 if i mod 1000 = 0 then
152 print_string ("@" ^ string_of_int i ^ " ");
161 let normalize (l : w list) =
162 print_endline (string_of_int (List.length l) ^ " nodes to be normalized");
165 (mapi (fun x -> apply_rules (x,Le) @ apply_rules (x,Ge)) l) in
167 List.rev (List.rev_map
168 (function (x,rel,y) -> match rel with Le -> [x],[y] | Ge -> [y],[x]) rels) in
169 let res = uniq arcs in
173 let visualize graph =
177 let edge_attributes _ = []
178 let default_edge_attributes _ = []
179 let get_subgraph _ = None
180 let vertex_attributes v = [`Label (string_of_eqclass (G.V.label v))]
181 let vertex_name v = name_of_eqclass (G.V.label v)
182 let default_vertex_attributes _ = []
183 let graph_attributes _ = []
185 let module D = Graph.Graphviz.Dot(G) in
186 let ch = open_out "/tmp/comb.dot" in
187 D.output_graph ch graph;
189 ignore (Unix.system ("tred /tmp/comb.dot > /tmp/red.dot"));
190 ignore (Unix.system ("dot -Tps /tmp/red.dot > /tmp/red.ps"));
191 (*Unix.system ("ggv /tmp/red.ps");*)
195 let cache1 = Hashtbl.create 5393 in
198 Hashtbl.find cache1 w
201 let v = G.V.create w in
202 Hashtbl.add cache1 w v;
206 let w_compare s1 s2 =
207 let c = compare (List.length s1) (List.length s2) in
208 if c = 0 then compare s1 s2 else c
211 let normalize_and_describe norm =
212 let cache = Hashtbl.create 5393 in
213 let canonicals = Hashtbl.create 5393 in
214 let descriptions = Hashtbl.create 5393 in
216 let normalized = norm v in
218 match G.V.label v with
222 if not (List.mem dsc (Hashtbl.find_all cache normalized)) then
223 Hashtbl.add cache normalized dsc;
226 let vertexes = uniq (Hashtbl.fold (fun k _ l -> k::l) cache []) in
229 (fun v -> v, List.sort w_compare (Hashtbl.find_all cache v)) vertexes in
230 iteri (function (_,w::_) -> Hashtbl.add canonicals w () | _ -> ()) xx;
231 let is_not_redundant =
235 try Hashtbl.find canonicals w; true with Not_found -> false
239 Hashtbl.add descriptions v ((List.filter is_not_redundant x) : eqclass)) xx),
240 Hashtbl.find descriptions
244 print_endline (string_of_int (List.length arcs) ^ " arcs to be classified");
245 let mk_vertex = mk_vertex () in
246 let graph = G.create () in
247 let varcs = mapi (fun (x,y) -> mk_vertex x,mk_vertex y) arcs in
248 iteri (fun (x,y) -> G.add_edge graph x y) varcs;
249 print_endline ("<scc>");
251 let module SCC = Graph.Components.Make(G) in SCC.scc graph in
252 print_endline (string_of_int classes ^ " classes");
253 print_endline ("-----");
257 let analyze (norm,arcs) =
258 print_endline ("building class graph (" ^ string_of_int (List.length arcs) ^ ")");
259 let normalize,finish,describe = normalize_and_describe norm in
261 uniq (mapi (fun (x,y) -> normalize x,normalize y) arcs) in
262 print_endline "finish";
264 let cgraph = G.create () in
265 let mk_vertex = mk_vertex () in
269 G.add_edge cgraph (mk_vertex (describe x)) (mk_vertex (describe y))) arcs;
270 print_endline "visualize";
272 print_endline ("/////");
276 let pkg = classify (normalize l) in
278 iter (n - 1) (step l)