ocamlgraph-1.8.3/0000755000175000017500000000000012133565072012602 5ustar mehdimehdiocamlgraph-1.8.3/examples/0000755000175000017500000000000012133565071014417 5ustar mehdimehdiocamlgraph-1.8.3/examples/demo_planar.ml0000644000175000017500000002205212133565071017233 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Printf open Graph module U = Unix let utime f x = let u = (U.times()).U.tms_utime in let y = f x in let ut = (U.times()).U.tms_utime -. u in (y,ut) let print_utime f x = let (y,ut) = utime f x in Printf.printf "user time: %2.2f\n" ut; flush Pervasives.stdout; y let () = printf "planar graphs demo use mouse to select two vertices (blue = source, green = destination) keys are - `r' generates a new random graph - `d' runs DFS - `b' runs BFS - `p' runs Dijkstra's shortest path - `q' to quit "; flush stdout (* directed graphs with integer coordinates and integer labels on edges *) module IntInt = struct type t = int * int end module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module G = Imperative.Digraph.AbstractLabeled(IntInt)(Int) open G let n_ = ref 30 let prob_ = ref 0.5 let () = Arg.parse ["-v", Arg.Int (fun i -> n_ := i), " number of vertices"; "-prob", Arg.Float (fun f -> prob_ := f), " probability to discrad an edge"; ] (fun _ -> ()) "usage: demo_planar " let n = !n_ let prob = !prob_ let round f = truncate (f +. 0.5) let pi = 4.0 *. atan 1.0 module Point = struct type point = V.t let ccw v1 v2 v3 = Delaunay.IntPoints.ccw (V.label v1) (V.label v2) (V.label v3) let in_circle v1 v2 v3 v4 = Delaunay.IntPoints.in_circle (V.label v1) (V.label v2) (V.label v3) (V.label v4) let distance v1 v2 = let x1,y1 = V.label v1 in let x2,y2 = V.label v2 in let sqr x = let x = float x in x *. x in truncate (sqrt (sqr (x1 - x2) +. sqr (y1 - y2))) end module Triangulation = Delaunay.Make(Point) let read_graph f = let c = open_in f in let l = ref [] in try while true do let s = input_line c in let x,y = Scanf.sscanf s "%d %f %f" (fun _ x y -> x,y) in printf "x=%f y=%f\n" x y; l := (x,y) :: !l done; assert false with End_of_file -> close_in c; let rec min_list cmp = function | [] -> assert false | [x] -> x | x :: l -> let m = min_list cmp l in if cmp x m then x else m in let xmin,_ = min_list (fun (x,_) (x',_) -> x < x') !l in let xmax,_ = min_list (fun (x,_) (x',_) -> x > x') !l in let _,ymin = min_list (fun (_,y) (_,y') -> y < y') !l in let _,ymax = min_list (fun (_,y) (_,y') -> y > y') !l in let calibrate (x,y) = round (20. +. 760. *. (x -. xmin) /. (xmax -. xmin)), round (20. +. 560. *. (y -. ymin) /. (ymax -. ymin)) in let vertices = Array.map (fun xy -> V.create (calibrate xy)) (Array.of_list !l) in let t = Triangulation.triangulate vertices in let g = create () in Array.iter (G.add_vertex g) vertices; let add_edge v1 v2 = let e = E.create v1 (Point.distance v1 v2) v2 in G.add_edge_e g e in Triangulation.iter (fun v1 v2 -> add_edge v1 v2; add_edge v2 v1) t; g (* a random digraph with n vertices *) let () = Random.self_init () module R = Rand.Planar.I(G) let new_graph () = R.graph ~xrange:(20,780) ~yrange:(20,580) ~prob n let g = ref (new_graph ()) let () = printf "nb edges : %d\n" (G.nb_edges !g); flush stdout (* let () = g := read_graph "tmp/carron.txt" *) open Graphics let () = open_graph " 800x600" let vertex_radius = 5 let draw_arrow ?(color=black) ?(width=1) (xu,yu) (xv,yv) = set_color color; set_line_width width; let dx = float (xv - xu) in let dy = float (yv - yu) in let alpha = atan2 dy dx in let r = sqrt (dx *. dx +. dy *. dy) in let ra = float vertex_radius *. 1.5 in let d = float vertex_radius +. 3. in let xs, ys = float xu +. d *. dx /. r, float yu +. d *. dy /. r in let xd, yd = float xv -. d *. dx /. r, float yv -. d *. dy /. r in let coords theta = round (xd +. ra *. cos (pi +. alpha +. theta)), round (yd +. ra *. sin (pi +. alpha +. theta)) in moveto (round xs) (round ys); lineto (round xd) (round yd); let x1,y1 = coords (pi /. 6.) in moveto (round xd) (round yd); lineto x1 y1; let x2,y2 = coords (-. pi /. 6.) in moveto (round xd) (round yd); lineto x2 y2 let color_vertex v color = let x,y = G.V.label v in set_color color; fill_circle x y vertex_radius type selection = | No | One of G.V.t | Two of G.V.t * G.V.t let selection = ref No let draw_selection () = match !selection with | No -> () | One v1 -> color_vertex v1 blue | Two (v1, v2) -> color_vertex v1 blue; color_vertex v2 green let draw_graph () = clear_graph (); set_color red; set_line_width 1; G.iter_vertex (fun v -> let (x,y) = G.V.label v in draw_circle x y vertex_radius) !g; set_color black; G.iter_edges (fun v1 v2 -> draw_arrow (G.V.label v1) (G.V.label v2)) !g; draw_selection () let distance (x1,y1) (x2,y2) = let dx = float (x1 - x2) in let dy = float (y1 - y2) in round (sqrt (dx *. dx +. dy *. dy)) let select () = let select_vertex v = match !selection with | No -> selection := One v | One v1 -> selection := Two (v1, v) | Two (_, v2) -> selection := Two (v2, v) in let p = mouse_pos () in try G.iter_vertex (fun v -> if distance p (G.V.label v) <= vertex_radius then begin select_vertex v; draw_graph (); raise Exit end) !g with Exit -> () module W = struct type label = G.E.label type t = int let weight x = x let zero = 0 let add = (+) let compare = compare end module Dij = Path.Dijkstra(G)(W) let dijkstra () = match !selection with | Two (v1, v2) -> printf "running Dijkstra... "; flush stdout; let t_ = ref 0.0 in begin try let (p,l),t = utime (Dij.shortest_path !g v1) v2 in t_ := t; printf "path of length %d (%d nodes) (%2.2f s)\n" l (List.length p) t; flush stdout; List.iter (fun e -> let v1 = G.E.src e in let v2 = G.E.dst e in draw_arrow ~color:red ~width:3 (G.V.label v1) (G.V.label v2)) p; ignore (Graphics.wait_next_event [ Key_pressed; Button_down ]); draw_graph () with Not_found -> printf "no path (%2.2f s)\n" !t_; flush stdout end | _ -> () let draw_iteration f = let pause () = for i = 1 to 10000000 do () done in f (fun v -> color_vertex v red; pause ()) !g; ignore (Graphics.wait_next_event [ Key_pressed; Button_down ]); draw_graph () module Dfs = Traverse.Dfs(G) let dfs () = draw_iteration Dfs.prefix module Bfs = Traverse.Bfs(G) let bfs () = draw_iteration Bfs.iter (* brute-force coloring *) let four_colors () = (* vertices still to be colored are queued in [q] *) let q = Queue.create () in let rec loop () = if not (Queue.is_empty q) then begin let v = Queue.pop q in assert (Mark.get v == 0); try_color v 1 || try_color v 2 || try_color v 3 || try_color v 4 || (Mark.set v 0; Queue.add v q; false) end else true and try_color v c = (try G.iter_succ (fun w -> if Mark.get w == c then raise Exit) !g v; true with Exit -> false) && (Mark.set v c; loop ()) in G.iter_vertex (fun v -> Queue.add v q) !g; Mark.clear !g; assert (loop ()); let color = [| black; red; green; blue; yellow |] in G.iter_vertex (fun v -> color_vertex v (color.(Mark.get v))) !g; ignore (Graphics.wait_next_event [ Key_pressed; Button_down ]) let () = try let () = draw_graph () in while true do let st = Graphics.wait_next_event [ Key_pressed; Button_down ] in if st.keypressed then match st.key with | 'q' -> raise Exit | 'r' -> g := new_graph (); selection := No; draw_graph () | 'p' -> dijkstra () | 'd' -> dfs () | 'b' -> bfs () (* | 'c' -> four_colors () *) | _ -> () else if st.button then select () done with Exit -> close_graph () (* Local Variables: compile-command: "make -C .. bin/demo_planar.opt" End: *) ocamlgraph-1.8.3/examples/demo.ml0000644000175000017500000000424412133565071015701 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Graph.Pack.Digraph (* to get undirected graphs, change to open Graph.Pack.Graph *) let show = display_with_gv let g = Rand.graph ~v:10 ~e:20 () let () = show g let g' = complement g let () = show g' let g' = mirror g let () = show g' let g' = transitive_closure ~reflexive:true g let () = show g' (* Intersection and union *) let g1 = create () let g2 = create () let v1 = V.create 1 let v2 = V.create 2 let v3 = V.create 3 let v4 = V.create 4 let v5 = V.create 5 let v6 = V.create 6 let v7 = V.create 7 let () = add_edge g1 v1 v2; add_edge g1 v2 v1; add_edge g1 v1 v3; add_edge g1 v2 v3; add_edge g1 v5 v3; add_edge g1 v6 v6; add_vertex g1 v4 let () = add_edge g2 v1 v2; add_edge g2 v2 v3; add_edge g2 v1 v4; add_edge g2 v3 v6; add_vertex g2 v7 let () = show g1 let () = show g2 let g' = intersect g1 g2 let () = show g' let g' = union g1 g2 let () = show g' (* Local Variables: compile-command: "make -C .. bin/demo.opt" End: *) ocamlgraph-1.8.3/examples/sudoku.ml0000644000175000017500000000630712133565071016271 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Ocamlgraph demo program: solving the Sudoku puzzle using graph coloring *) open Format open Graph (* We use undirected graphs with nodes containing a pair of integers (the cell coordinates in 0..8 x 0..8). The integer marks of the nodes will store the colors. *) module G = Imperative.Graph.Abstract(struct type t = int * int end) (* The Sudoku grid = a graph with 9x9 nodes *) let g = G.create () (* We create the 9x9 nodes, add them to the graph and keep them in a matrix for later access *) let nodes = let new_node i j = let v = G.V.create (i, j) in G.add_vertex g v; v in Array.init 9 (fun i -> Array.init 9 (new_node i)) let node i j = nodes.(i).(j) (* shortcut for easier access *) (* We add the edges: two nodes are connected whenever they can't have the same value, i.e. they belong to the same line, the same column or the same 3x3 group *) let () = for i = 0 to 8 do for j = 0 to 8 do for k = 0 to 8 do if k <> i then G.add_edge g (node i j) (node k j); if k <> j then G.add_edge g (node i j) (node i k); done; let gi = 3 * (i / 3) and gj = 3 * (j / 3) in for di = 0 to 2 do for dj = 0 to 2 do let i' = gi + di and j' = gj + dj in if i' <> i || j' <> j then G.add_edge g (node i j) (node i' j') done done done done (* Displaying the current state of the graph *) let display () = for i = 0 to 8 do for j = 0 to 8 do printf "%d" (G.Mark.get (node i j)) done; printf "\n"; done; printf "@?" (* We read the initial constraints from standard input and we display g *) let () = for i = 0 to 8 do let s = read_line () in for j = 0 to 8 do match s.[j] with | '1'..'9' as ch -> G.Mark.set (node i j) (Char.code ch - Char.code '0') | _ -> () done done; display (); printf "---------@." (* We solve the Sudoku by 9-coloring the graph g and we display the solution *) module C = Coloring.Mark(G) let () = C.coloring g 9; display () (* Local Variables: compile-command: "make -C .. bin/sudoku.opt" End: *) ocamlgraph-1.8.3/examples/color.ml0000644000175000017500000001737412133565071016103 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* 4-coloring planar graphs *) open Printf open Graph (* command line *) let n_ = ref 30 let prob_ = ref 0.5 let seed_ = ref None let arg_spec = ["-v", Arg.Int (fun i -> n_ := i), " number of vertices"; "-prob", Arg.Float (fun f -> prob_ := f), " probability to discrad an edge"; "-seed", Arg.Int (fun n -> seed_ := Some n), " random seed" ] let () = Arg.parse arg_spec (fun _ -> ()) "usage: color " let n = !n_ let prob = !prob_ let seed = match !seed_ with | None -> Random.self_init (); Random.int (1 lsl 29) | Some s -> s let () = Format.printf "seed = %d@." seed; Random.init seed (* undirected graphs with integer coordinates and integer labels on edges *) module IntInt = struct type t = int * int end module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module G = Imperative.Graph.AbstractLabeled(IntInt)(Int) open G (* a random graph with n vertices *) module R = Rand.Planar.I(G) let g0 = R.graph ~xrange:(20,780) ~yrange:(20,580) ~prob n (* drawing *) let round f = truncate (f +. 0.5) let pi = 4.0 *. atan 1.0 open Graphics let () = open_graph " 800x600" let vertex_radius = 5 let draw_edge v1 v2 = let (xu,yu) = G.V.label v1 in let (xv,yv) = G.V.label v2 in set_color black; let dx = float (xv - xu) in let dy = float (yv - yu) in let r = sqrt (dx *. dx +. dy *. dy) in let d = float vertex_radius +. 3. in let xs, ys = float xu +. d *. dx /. r, float yu +. d *. dy /. r in let xd, yd = float xv -. d *. dx /. r, float yv -. d *. dy /. r in moveto (round xs) (round ys); lineto (round xd) (round yd) let draw_vertex v = let (x,y) = G.V.label v in set_color red; draw_circle x y vertex_radius let color_vertex v color = let x,y = G.V.label v in set_color color; fill_circle x y vertex_radius let draw_graph () = clear_graph (); set_color red; set_line_width 1; G.iter_vertex draw_vertex g0; G.iter_edges draw_edge g0 module Dfs = Traverse.Dfs(G) module Bfs = Traverse.Bfs(G) let test_bfs () = let rec loop i = let v = Bfs.get i in color_vertex v red; ignore (Graphics.wait_next_event [ Key_pressed ]); loop (Bfs.step i) in try loop (Bfs.start g0) with Exit -> () let test_dfs () = let rec loop i = let v = Dfs.get i in color_vertex v red; ignore (Graphics.wait_next_event [ Key_pressed ]); loop (Dfs.step i) in try loop (Dfs.start g0) with Exit -> () let cols = [| white; red; green; blue; yellow; black |] exception NoColor (* Algo I. Brute force. *) module C = Coloring.Mark(G) let coloring_a k = Mark.clear g0; C.coloring g0 4; iter_vertex (fun v -> color_vertex v cols.(Mark.get v)) g0 (* Algo II. we use marks to color; bits are used as follows: 0: set if node is discarded at step 1 1-4: available colors 5-7: the color (0 = not colored, else color in 1..4 *) let print_8_bits x = for i = 7 downto 0 do if (x lsr i) land 1 = 1 then printf "1" else printf "0" done let dump () = let dump_mark v = printf "["; print_8_bits (Mark.get v); printf "]" in iter_vertex dump_mark g0; printf "\n"; flush stdout let mask_color = [| 0; 0b11101; 0b11011; 0b10111; 0b01111 |] let coloring_b () = (* initially all 4 colors available and every vertex to be colored *) iter_vertex (fun v -> Mark.set v 0b11110) g0; (* first step: we eliminate vertices with less than 4 successors *) let stack = Stack.create () in let finish = ref false in let round = ref 1 in let nb_to_color = ref n in while not !finish do let c = ref 0 in finish := true; let erase v = incr c; finish := false; Mark.set v 0b11111; Stack.push v stack in G.iter_vertex (fun v -> if Mark.get v = 0 && out_degree g0 v < 4 then erase v) g0; printf "round %d: removed %d vertices\n" !round !c; incr round; nb_to_color := !nb_to_color - !c done; flush stdout; (* second step: we 4-color the remaining of the graph *) (* [try_color v i] tries to assigne color [i] to vertex [v] *) let try_color v i = assert (1 <= i && i <= 4); let m = Mark.get v in assert (m lsr 5 = 0); if (m lsr i) land 1 = 0 then raise NoColor; (* color [i] not available *) let remove_color w = (* make color [i] unavailable for [w] *) let m = Mark.get w in if m lsr 5 > 0 then assert (m lsr 5 <> i) (* [w] already colored *) else begin let m' = m land mask_color.(i) in if m' = 0 then raise NoColor; (* no more color available for [w] *) Mark.set w m' end in iter_succ remove_color g0 v; Mark.set v (m lor (i lsl 5)) in let uncolor v = let m = Mark.get v in let c = m lsr 5 in assert (0 <= c && c <= 4); if c > 0 then begin Mark.set v (m land 0b11111); let update w = (* give back color [c] to [w] only when no more succ. has color [c] *) try iter_succ (fun u -> if Mark.get u lsr 5 = c then raise Exit) g0 w; Mark.set w ((Mark.get w) lor (1 lsl c)) with Exit -> () in iter_succ update g0 v end in if !nb_to_color > 0 then begin let rec iterate iter = let v = Bfs.get iter in if Mark.get v land 1 = 1 then (* no need to color this vertex *) iterate (Bfs.step iter) else begin for i = 1 to 4 do try try_color v i; iterate (Bfs.step iter); assert false with NoColor -> uncolor v done; raise NoColor end in try iterate (Bfs.start g0) with Exit -> () end; (* third step: we color the eliminated vertices, in reverse order *) Stack.iter (fun v -> assert (Mark.get v land 1 = 1); try for i = 1 to 4 do try try_color v i; raise Exit with NoColor -> uncolor v done; assert false (* we must succeed *) with Exit -> ()) stack; (* finally we display the coloring *) iter_vertex (fun v -> let c = (Mark.get v) lsr 5 in assert (1 <= c && c <= 4); color_vertex v cols.(c)) g0 open Unix let utime f x = let u = (times()).tms_utime in let y = f x in let ut = (times()).tms_utime -. u in (y,ut) let print_utime f x = let (y,ut) = utime f x in Format.printf "user time: %2.2f@." ut; y let () = draw_graph (); (* test_bfs (); *) (* test_dfs (); *) print_utime coloring_a 4; (*ignore (Graphics.wait_next_event [ Key_pressed ]);*) (*draw_graph ();*) print_utime coloring_b (); ignore (Graphics.wait_next_event [ Key_pressed ]); close_graph () (* Local Variables: compile-command: "make -C .. bin/color.opt" End: *) ocamlgraph-1.8.3/view_graph/0000755000175000017500000000000012133565071014734 5ustar mehdimehdiocamlgraph-1.8.3/view_graph/viewGraph_utils.ml0000644000175000017500000000601112133565071020440 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** This file provide useful function to build windows to put the graph *) let create_scrolled_canvas packing = let frame = GBin.frame ~shadow_type:`IN () in let canvas = let aa = false (* anti-aliasing *) in GnoCanvas.canvas ~aa ~width:600 ~height:400 ~packing:frame#add () in let _ = canvas#set_center_scroll_region true in (* if the graph is too big, show its center *) let table = GPack.table ~packing ~rows:2 ~columns:2 ~row_spacings:4 ~col_spacings:4 () in let _ = table#attach ~left:0 ~right:1 ~top:0 ~bottom:1 ~expand:`BOTH ~fill:`BOTH ~shrink:`BOTH ~xpadding:0 ~ypadding:0 frame#coerce in let w = GRange.scrollbar `HORIZONTAL ~adjustment:canvas#hadjustment () in let _ = table#attach ~left:0 ~right:1 ~top:1 ~bottom:2 ~expand:`X ~fill:`BOTH ~shrink:`X ~xpadding:0 ~ypadding:0 w#coerce in let w = GRange.scrollbar `VERTICAL ~adjustment:canvas#vadjustment () in let _ = table#attach ~left:1 ~right:2 ~top:0 ~bottom:1 ~expand:`Y ~fill:`BOTH ~shrink:`Y ~xpadding:0 ~ypadding:0 w#coerce in canvas let create_graph_win title = let window = GWindow.window ~title ~allow_shrink:true ~allow_grow:true () in let vbox = GPack.vbox ~border_width:4 ~spacing:4 ~packing:window#add () in let help_but = GButton.button ~label:"Help" ~packing:(vbox#pack ~expand:false ~fill:true) () in let _ = help_but#connect#clicked ~callback:ViewGraph_select.show_help in let canvas = create_scrolled_canvas (vbox#pack ~expand:true ~fill:true) in let hbox = GPack.hbox ~spacing:4 ~packing:vbox#pack () in let select_init_env = ViewGraph_select.init ViewGraph_select.default_options canvas (hbox#pack ~expand:true ~fill:true) in window#show (); select_init_env ocamlgraph-1.8.3/view_graph/viewGraph_select.mli0000644000175000017500000000455112133565071020737 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** This module can be used to add some selection feature to {!ViewGraph}. * See {!ViewGraph_test} to see how to use it. * *) (** object returned by [init] and used by [open_dot_file] *) type t_env type t_options = { sel_1_color : string; (** color of the selected node (default "red") *) sel_2_color : string; (** color of the selected neighbour (default "green") *) center_node_when_selected :bool; (** automatically center a node when it is selected (default true) *) } (** some default values for the options. * It is a good idea to use it and overwrite the one that have to be changed, * just in case some more options appear *) val default_options : t_options (** should be called only once because it creates widgets. * The packing function is the place to put the messages about selection. *) val init : t_options -> GnoCanvas.canvas -> (GObj.widget -> unit) -> t_env (** functor to instanciate with your callbacks *) module VG (UserCb : ViewGraph_core.SigCb) : sig val open_dot_file : UserCb.t_env -> t_env -> ?dot_cmd:string -> string -> ViewGraph_core.t_graph end (** Popup a message window with some help. *) val show_help : unit -> unit ocamlgraph-1.8.3/view_graph/viewGraph_core.ml0000644000175000017500000002645612133565071020247 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** ViewGraph : a library to view .dot graphs and interact with the GUI. *) (** This is Ocamlgraph library : see http://ocamlgraph.lri.fr/doc/ *) open Graph exception DotError of string type t_point = float * float type t_coord = t_point * t_point type t_shape = Srect | Sellipse (* TODO : add some more ! *) type t_gtk_obj = GnomeCanvas.re_p GnoCanvas.item module Node = struct type t = string * (t_shape * t_coord * t_gtk_obj) option let id n = fst n let shape n = match snd n with None -> None | Some (s, _, _) -> Some s let coord n = match snd n with None -> None | Some (_, c, _) -> Some c let item n = match snd n with None -> None | Some (_, _, r) -> Some r end module G = Imperative.Digraph.Abstract(Node) module B = Builder.I(G) type t_graph = B.G.t * GnoCanvas.pixbuf type t_node = B.G.V.t let get_graph g = fst g let get_pixbuf g = snd g let get_node_info n = B.G.V.label n let get_coord n = Node.coord (get_node_info n) let get_id n = Node.id (get_node_info n) let get_obj n = Node.item (get_node_info n) (** find the attributes [pos], [width] and [height] in the attribute list *) let get_info attr_list_list = let get (shp, p,w,h) (attr, val_opt) = match attr, val_opt with | (Dot_ast.Ident "shape"), Some (Dot_ast.String s) -> (* Format.printf "found pos = %s@." s; *) (Some s), p, w, h | (Dot_ast.Ident "pos"), Some (Dot_ast.String s) -> (* Format.printf "found pos = %s@." s; *) shp, (Some s), w, h | (Dot_ast.Ident "width"), Some (Dot_ast.String s) -> (* Format.printf "found width = %s@." s; *) shp, p, (Some s), h | (Dot_ast.Ident "height"), Some (Dot_ast.String s) -> (* Format.printf "found height = %s@." s; *) shp, p, w, (Some s) | (Dot_ast.Ident id), Some (Dot_ast.String s) -> (* Format.printf "found %s = %s -> ignored@." id s; *) (shp, p, w, h) | _ -> (shp, p,w,h) in let get acc attr_list = (* Format.printf "%d attr in attr_list@." (List.length attr_list); *) List.fold_left get acc attr_list in (*Format.printf "%d lists in attr_list_list@." (List.length attr_list_list); *) List.fold_left get (None, None, None, None) attr_list_list (** Translate the information given by dot * into the coordinate of a rectangle in the png image. * see http://www.graphviz.org/mywiki/FaqCoordTransformation * to understand the [pad] and [factor] variables. * @param pos position of the center of the node, in points. * @param w width of the node, in inch. * @param h height of the node, in inch. *) let compute_coord pos w h = let dot_ppi = 72. (* number of pixels per inch on a display device *) in let dot_png_ppi = 96. (* number of pixels per inch on a display device *) in try let w = float_of_string w in let h = float_of_string h in let x,y = Scanf.sscanf pos "%d,%d" (fun x y -> (x,y)) in let pad = 4 in let x = float_of_int (x + pad) in let y = float_of_int (y + pad) in let dx = w *. dot_ppi /. 2. in let dy = h *. dot_ppi /. 2. in let x1 = x -. dx in let y1 = y -. dy in let x2 = x +. dx in let y2 = y +. dy in let factor = dot_png_ppi /. dot_ppi in let x1 = x1 *. factor in let y1 = y1 *. factor in let x2 = x2 *. factor in let y2 = y2 *. factor in (* Format.printf "compute_coord -> x1=%f y1=%f x2=%f y2=%f@." x1 y1 x2 y2; *) Some ((x1,y1),(x2,y2)) with e -> let s = Printexc.to_string e in Format.printf "compute_coord failled : %s@." s; None module DotParser (C : sig val mk_node : t_shape -> t_coord -> t_gtk_obj end) = Dot.Parse (B) (struct let node (id,_) attr_list = let name = match id with | Dot_ast.Ident s | Dot_ast.Number s | Dot_ast.String s | Dot_ast.Html s -> s in let info = match get_info attr_list with | shp, Some pos, Some w, Some h -> let shp = match shp with | Some "ellipse" -> Sellipse | Some "box" -> Srect | Some _ -> Srect | None -> Sellipse (* default shape *) in begin match compute_coord pos w h with | None -> None | Some coord -> let n_obj = C.mk_node shp coord in Some (shp, coord, n_obj) end | _ -> Format.printf "info KO for %s@." name; None in (name, info) let edge _ = () end) (** Call [dot] to build the graph image in a [png] file *) let png_graph_image dot_cmd dot_file png_file = let cmd = Printf.sprintf "%s -T png %s > %s" dot_cmd dot_file png_file in match Sys.command cmd with | 0 -> png_file | _ -> raise (DotError cmd) (** Call 'dot' on the [dot_file] to get a file with position information, * and also to have a [png] image of the graph. * Then parse the annotated file to get the graph with the nodes coordinates. * @return the graph and the pgn filename. * *) let build_graph dot_cmd dot_file annot_dot_file mk_node_item = let cmd = Printf.sprintf "%s -y %s > %s " dot_cmd dot_file annot_dot_file in match Sys.command cmd with | 0 -> let module Parser = DotParser (struct let mk_node = mk_node_item end) in let graph = Parser.parse annot_dot_file in graph | _ -> raise (DotError cmd) (** @return 2 lists : the predecessors and successors of the node*) let get_neighbours graph n = let graph = get_graph graph in let preds = B.G.pred graph n in let succs = B.G.succ graph n in (preds, succs) (*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*) module type SigCb = sig type t_env val button_one_press_on_graph : t_env -> unit val button_two_press_on_graph : t_env -> unit val button_three_press_on_graph : t_env -> unit val button_one_press_on_node : t_env -> t_node -> unit val button_two_press_on_node : t_env -> t_node -> unit val button_three_press_on_node : t_env -> t_node -> unit val enter_node : t_env -> t_node -> unit val leave_node : t_env -> t_node -> unit end module EmptyCb = struct type t_env = unit let button_one_press_on_graph _env = () let button_two_press_on_graph _env = () let button_three_press_on_graph _env = () let button_one_press_on_node _env _n = () let button_two_press_on_node _env _n = () let button_three_press_on_node _env _n = () let enter_node _env _n = () let leave_node _env _n = () end module M (Cb : SigCb) = struct let mk_node_item canvas shp ((x1,y1),(x2,y2)) = (* we have to put some color on item in order to be able to get their events, * so let's cheat and add a bitmap with 0 every where... *) let no_color = [ `FILL_COLOR "black" ; `FILL_STIPPLE (Gdk.Bitmap.create_from_data ~width:1 ~height:1 "\000") ] in let props = [ `X1 x1; `Y1 y1; `X2 x2; `Y2 y2] @ no_color in let n_obj = match shp with | Srect -> GnoCanvas.rect canvas#root ~props | Sellipse -> GnoCanvas.ellipse canvas#root ~props in n_obj let graph_event env ev = begin match ev with | `BUTTON_PRESS ev -> begin (* let state = GdkEvent.Button.state ev in *) match GdkEvent.Button.button ev with (* | 1 when Gdk.Convert.test_modifier `SHIFT state -> | 1 when Gdk.Convert.test_modifier `CONTROL state -> let (x, y) = canvas#w2c_d (GdkEvent.Button.x ev) (GdkEvent.Button.y ev) in *) | 1 -> Cb.button_one_press_on_graph env | 2 -> Cb.button_two_press_on_graph env | 3 -> Cb.button_three_press_on_graph env | _ -> () end | _ -> () end ; false let node_event env node ev = begin match ev with | `ENTER_NOTIFY ev -> Cb.enter_node env node | `LEAVE_NOTIFY ev -> Cb.leave_node env node | `BUTTON_PRESS ev -> begin match GdkEvent.Button.button ev with | 1 -> Cb.button_one_press_on_node env node | 2 -> Cb.button_two_press_on_node env node | 3 -> Cb.button_three_press_on_node env node | _ -> () end | _ -> () end ; false (** for each node that has an item, connect the events *) let add_node_items env graph = let do_it n = match get_obj n with | None -> () | Some n_rect -> ignore (n_rect#connect#event (node_event env n)) in B.G.iter_vertex do_it graph let remove_node_items graph = let do_it n = match get_obj n with | None -> () | Some n_rect -> n_rect#destroy () in B.G.iter_vertex do_it graph let install_image (canvas :GnoCanvas.canvas) png_file = let im = GdkPixbuf.from_file png_file in (*let im = GdkPixbuf.add_alpha ~transparent:(0xff, 0xff, 0xff) im in*) let w = GdkPixbuf.get_width im in let h = GdkPixbuf.get_height im in (* Format.printf "GnoCanvas.pixbuf size = %dx%d@." w h; *) let _ = canvas#set_scroll_region 0. 0. (float w) (float h) in let px = GnoCanvas.pixbuf ~x:0. ~y:0. ~pixbuf:im canvas#root in px let open_dot_file env (canvas :GnoCanvas.canvas) ?(dot_cmd="dot") dot_file = let basename = try Filename.chop_extension dot_file with Invalid_argument _ -> dot_file in let png_file = Printf.sprintf "%s.png" basename in let annot_dot_file = Printf.sprintf "%s_annot" dot_file in let graph = build_graph dot_cmd dot_file annot_dot_file (mk_node_item canvas) in (* TODO : it would be better not to recompute the layout, * ie. use annot_dot_file instead of dot_file, * but it seems that it doesn't work properly... * It is ok for 'simple' graphs like unix.dot, * but not on crazy.dot for instance. What goes wrong ? * Anyway, it would be better to build GTK objects instead of a png image ! * *) let png_file = png_graph_image dot_cmd dot_file png_file in let pixbuf = install_image canvas png_file in let _ = pixbuf#connect#event (graph_event env) in let _ = add_node_items env graph in let _ = pixbuf#lower_to_bottom () in (graph, pixbuf) let clear _canvas graph = (* TODO : remove pixbuf from _canvas ? *) let pixbuf = get_pixbuf graph in pixbuf#destroy (); let graph = get_graph graph in remove_node_items graph end ocamlgraph-1.8.3/view_graph/viewGraph_test.ml0000644000175000017500000001513712133565071020270 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** This is only a test file to show how to use * [ViewGraph] and [ViewGraph_select]. * Just compile and test... (click on the Help button to know how to use it). *) (* Nice tutorial at : * http://plus.kaist.ac.kr/~shoh/ocaml/lablgtk2/lablgtk2-tutorial/book1.html * See also examples in : * /usr/share/doc/lablgtk-2.6.0/examples/canvas/ *) (** To test to callbacks : only print messages *) module CbTest = struct (** need nothing for this test, but usually contains at least the graph... *) type t_env = unit let button_one_press_on_graph _env = Format.printf "[CbTest] button_one_press_on_graph @." let button_two_press_on_graph _env = Format.printf "[CbTest] button_two_press_on_graph @." let button_three_press_on_graph _env = Format.printf "[CbTest] button_three_press_on_graph @." let button_one_press_on_node _env n = Format.printf "[CbTest] button_one_press_on_node %s@." (ViewGraph.get_id n) let button_two_press_on_node _env n = Format.printf "[CbTest] button_two_press_on_node %s@." (ViewGraph.get_id n) let button_three_press_on_node _env n = Format.printf "[CbTest] button_three_press_on_node %s@." (ViewGraph.get_id n) let enter_node _env n = Format.printf "[CbTest] enter_node %s@." (ViewGraph.get_id n) let leave_node _env n = Format.printf "[CbTest] leave_node %s@." (ViewGraph.get_id n) end module V = ViewGraph_select.VG (CbTest) let open_file select_init_env file = try let env = () in let _graph = V.open_dot_file env select_init_env file in () with ViewGraph.DotError cmd -> GToolbox.message_box "Error" (Printf.sprintf "%s failed\nDidn't succed to build graph for %s\nSorry !" cmd file) let open_cb select_init_env () = match GToolbox.select_file ~title:"Select a dot file" () with | None -> () | Some filename -> open_file select_init_env filename let help_act_cb _ac = ViewGraph_select.show_help () let error_act_cb ac = GToolbox.message_box "Error" (Printf.sprintf "Action '%s' activated : no callback ?\n" ac#name) let quit_cb () = GMain.Main.quit () let quit_act_cb _a = quit_cb () let menu_desc = "\ \ \ \ \ \ \ \ \ \ \ " let create_menu () = let ui_m = GAction.ui_manager () in let actions = GAction.action_group ~name:"Actions" () in GAction.add_actions actions [ GAction.add_action "FileMenu" ~label:"File" ; GAction.add_action "Open" ~label:"Open" ~accel:"o" (* callback connected later *); GAction.add_action "Quit" ~label:"Quit" ~accel:"q" ~callback:quit_act_cb; GAction.add_action "HelpMenu" ~label:"Help" ; GAction.add_action "Help" ~label:"Help" ~accel:"h" ~callback:help_act_cb; ]; ui_m#insert_action_group actions 0 ; let _ = ui_m#add_ui_from_string menu_desc in let help_item = ui_m#get_widget "/MenuBar/HelpMenu" in let help_item = GtkMenu.MenuItem.cast help_item#as_widget in GtkMenu.MenuItem.set_right_justified help_item true ; ui_m (* let create_menu2 packing open_cb = let file_item = GMenu.menu_item ~label:"File" ~packing () in let file_menu = GMenu.menu () in let item = GMenu.menu_item ~label:"Open" ~packing:file_menu#append () in let _ = item#connect#activate ~callback:open_cb in let item = GMenu.menu_item ~label:"Quit" ~packing:file_menu#append () in let _ = item#connect#activate ~callback:GMain.Main.quit in let _ = file_item#set_submenu file_menu in let help_item = GMenu.menu_item ~label:"Help" ~right_justified:true ~packing () in let help_menu = GMenu.menu () in let item = GMenu.menu_item ~label:"Help about ViewGraph" ~packing:help_menu#append () in let _ = item#connect#activate ~callback:ViewGraph_select.show_help in let _ = help_item#set_submenu help_menu in () *) let create_gui () = let window = GWindow.window ~title:"ViewGraph" ~allow_shrink:true ~allow_grow:true () in let vbox = GPack.vbox ~border_width:4 ~spacing:4 ~packing:window#add () in let ui_m = create_menu () in window#add_accel_group ui_m#get_accel_group ; vbox#pack ~expand:false (ui_m#get_widget "/MenuBar") ; let frame = GBin.frame ~label:"How to use this :" ~packing:vbox#pack () in let _ = GMisc.label ~text:"\n Open the Help window to know more...\n" ~packing:frame#add () in let pack = vbox#pack ~expand:true ~fill:true in let canvas = ViewGraph_utils.create_scrolled_canvas pack in let hbox = GPack.hbox ~spacing:4 ~packing:vbox#pack () in let select_init_env = ViewGraph_select.init ViewGraph_select.default_options canvas (hbox#pack ~expand:true ~fill:true) in let actions = match ui_m#get_action_groups with | a::[] -> a | _ -> assert false in let open_action = actions#get_action "Open" in let _ = open_action#connect#activate ~callback:(open_cb select_init_env) in let _ = window#connect#destroy ~callback:quit_cb in let _ = window#show () in (canvas, select_init_env) let main () = let _ = GMain.Main.init () in let canvas, select_init_env = create_gui () in if Array.length Sys.argv = 2 then open_file select_init_env Sys.argv.(1); GMain.Main.main () let _ = Printexc.print main () ocamlgraph-1.8.3/view_graph/viewGraph_core.mli0000644000175000017500000000600512133565071020404 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** ViewGraph : a library to view .dot graphs and interact with the GUI. * To use it you have : * - first to define callbacks (see {!modtype:ViewGraph.SigCb}) * - then instanciate the module {!module:ViewGraph.M} with your callbacks, * - then use {!ViewGraph.M.open_dot_file} * - don't forget to call {!ViewGraph.M.clear} when changing the file. *) (** raised when the call to a dot command fails. * The string gives the command that failed *) exception DotError of string type t_point = float * float type t_coord = t_point * t_point type t_graph type t_node type t_gtk_obj = GnomeCanvas.re_p GnoCanvas.item (*val get_canvas : t_graph -> GnoCanvas.canvas *) val get_id : t_node -> string val get_coord : t_node -> t_coord option val get_obj : t_node -> t_gtk_obj option (** @return 2 lists : the predecessors and successors of the node*) val get_neighbours : t_graph -> t_node -> t_node list * t_node list module type SigCb = sig type t_env val button_one_press_on_graph : t_env -> unit val button_two_press_on_graph : t_env -> unit val button_three_press_on_graph : t_env -> unit val button_one_press_on_node : t_env -> t_node -> unit val button_two_press_on_node : t_env -> t_node -> unit val button_three_press_on_node : t_env -> t_node -> unit val enter_node : t_env -> t_node -> unit val leave_node : t_env -> t_node -> unit end (** usefull when we don't want to have callbacks on the nodes *) module EmptyCb : SigCb with type t_env=unit module M (Cb : SigCb) : sig (** Open the dot file in the canvas. * @raise Error if either the image or the graph fail to build *) val open_dot_file : Cb.t_env -> GnoCanvas.canvas -> ?dot_cmd:string -> string -> t_graph (** it is very important to not using the graph anymore after calling [clear] *) val clear : GnoCanvas.canvas -> t_graph -> unit end ocamlgraph-1.8.3/view_graph/README0000644000175000017500000000073012133565071015614 0ustar mehdimehdi====================================================== ViewGraph is now deprecated. Prefer to use dgraph now. ====================================================== ViewGraph is a small ocaml library that helps to view a graph from a dot file in a Lablgtk canvas, and interact with it. To have more information : make doc and browse the documentation starting from doc/index.html You can also compile the test file, and try to use it : make; ./viewgraph file.dot ocamlgraph-1.8.3/view_graph/Makefile0000644000175000017500000000175012133565071016377 0ustar mehdimehdiOCAMLC=ocamlc.opt -dtypes OCAMLOPT=ocamlopt.opt OCAMLDOC=ocamldoc.opt GRAPH_DIR=.. GRAPH_LIB=graph.cmo INCLUDES=-I . -I +lablgtk2 -I $(GRAPH_DIR) FILES = viewGraph viewGraph_select viewGraph_utils viewGraph_test SRCS = $(wildcard *.ml *.mli) CMOS = $(FILES:%=%.cmo) CMXS = $(FILES:%=%.cmx) EXEC=viewgraph all : $(EXEC) $(CMXS) doc $(EXEC) : $(CMOS) $(GRAPH_DIR)/$(GRAPH_LIB) $(OCAMLC) $(INCLUDES) -o $@ \ unix.cma lablgtk.cma lablgnomecanvas.cma $(GRAPH_LIB) \ $(CMOS) depend: .depend .depend : $(SRCS) ocamldep $(SRCS) > $@ include .depend .PHONY: doc doc : $(CMOS) doc/intro.txt doc/style.css $(OCAMLDOC) -d doc \ -stars -html -intro doc/intro.txt -css-style style.css \ $(INCLUDES) $(SRCS) %.cmo :%.ml $(OCAMLC) $(INCLUDES) -c $< %.cmx :%.ml $(OCAMLOPT) $(INCLUDES) -c $< %.cmi :%.mli $(OCAMLC) $(INCLUDES) -c $< clean : rm -f $(EXEC) rm -f .depend rm -f $(FILES:%=%.cmo) $(FILES:%=%.cmx) $(FILES:%=%.o) $(FILES:%=%.cmi) $(FILES:%=%.annot) rm -f doc/*.html ocamlgraph-1.8.3/view_graph/viewGraph_select.ml0000644000175000017500000003026012133565071020562 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** This module can be used to add some selection feature to [ViewGraph]. * see [show_help] for more details. *) let debug format = if true then Format.printf format else Format.ifprintf Format.std_formatter format (** To manage the lists of neighbours of the selected node. * The type [t] is made of a boolean [b] and 3 lists [(l1, l2, l3)]. * [b] tells is [l1] is a list of predecessors (vs. successors). * [l3] has the same 'kind' than [l1], and [l2] the other. * [l1] cannot be empty, except if the 3 lists are empty. * The first node of [l1] is the currently selected neighbour. * When we go to the next one, [n] is removed and appended to [l3] tail. * If [l1] is then empty, [l2] becomes the first list, and [b] is changed. *) module CircLists = struct type t_elem = ViewGraph_core.t_node type t_lists = t_elem list * t_elem list * t_elem list type t = bool * t_lists let mk (l1, l2) = match l1, l2 with | [], [] -> true, ([], [], []) | [], l2 -> false, (l2, [], []) | l1, l2 -> true, (l1, l2, []) let current_node lists = match lists with | _, ( [] , _, _) -> None | b, (n::_, _, _) -> Some (b, n) let go_next lists = let lists = match lists with | _, ([], [], []) -> lists | _, ([], _, _) -> assert false (* l1 cannot be empty, except if every lists are *) | b, (n::[], [], l3) -> b, (l3 @ [n], [], []) | b, (n::[], l2, l3) -> not b, (l2, l3 @ [n], []) | b, (n::l1, l2, l3) -> b, (l1, l2, l3 @ [n]) in lists let goto_n ((_, (l1, l2, l3)) as lists) n = let max = List.length l1 + List.length l2 + List.length l3 in let rec find nb_iter lists = match current_node lists with | None -> raise Not_found | Some (_, cur_n) -> if cur_n = n then lists else if nb_iter >= 0 then find (nb_iter - 1) (go_next lists) else raise Not_found in find max lists end type t_options = { sel_1_color : string; sel_2_color : string; center_node_when_selected :bool; } let default_options = { sel_1_color = "red"; sel_2_color = "green"; center_node_when_selected = true; } (** Some widgets, useful for the selection. *) type t_widgets = { canvas : GnoCanvas.canvas; sel_1_txt : GMisc.label; sel_edge_txt : GMisc.label; sel_2_txt : GMisc.label; } type t_state = { w : t_widgets; opt : t_options; mutable graph : ViewGraph_core.t_graph option ; mutable ppu : float ; mutable selected : ViewGraph_core.t_node option ; mutable neighbours : CircLists.t option; mutable gui_sel : (ViewGraph_core.t_gtk_obj option) array; } type t_env = t_state (* horrible zoom : probably to be changed ! *) let change_zoom state delta = state.ppu <- state.ppu +. delta; state.w.canvas#set_pixels_per_unit state.ppu let center_selected_node state = match state.selected with | None -> () | Some n -> match ViewGraph_core.get_coord n with | None -> () | Some ((x1, y1), (x2, y2)) -> let canvas = state.w.canvas in let x = x1 +. (x2 -. x1) /. 2. in let y = y1 +. (y2 -. y1) /. 2. in (* Format.printf "want to see = %f x %f@." x y; *) let w = canvas#hadjustment#page_size in let h = canvas#vadjustment#page_size in (* Format.printf "page_size = %f x %f@." w h; *) let sx = x -. (w /. 2.) in let sy = y -. (h /. 2.) in (* Format.printf "scroll to = %f x %f (world) @." sx sy; *) let sx, sy = canvas#w2c sx sy in (* this is to handle zoom factor *) (* Format.printf "scroll to = %d x %d (canvas) @." sx sy; *) canvas#scroll_to sx sy let key_press state ev = let canvas = state.w.canvas in let (x, y) = canvas#get_scroll_offsets in match GdkEvent.Key.keyval ev with | k when k = GdkKeysyms._Up -> canvas#scroll_to x (y-20) ; true | k when k = GdkKeysyms._Down -> canvas#scroll_to x (y+20) ; true | k when k = GdkKeysyms._Left -> canvas#scroll_to (x-10) y ; true | k when k = GdkKeysyms._Right -> canvas#scroll_to (x+10) y ; true | k when k = GdkKeysyms._Page_Down -> change_zoom state 0.1; true | k when k = GdkKeysyms._Page_Up -> change_zoom state (-0.1); true | k when k = GdkKeysyms._Home -> center_selected_node state; true | _ -> false let init options (canvas : GnoCanvas.canvas) pack_txt = let _ = GMisc.label ~text:"Selected : " ~packing:pack_txt () in let sel_1_txt = GMisc.label ~packing:pack_txt () in let sel_edge_txt = GMisc.label ~packing:pack_txt () in let sel_2_txt = GMisc.label ~packing:pack_txt () in let w = { canvas = canvas; sel_1_txt = sel_1_txt; sel_edge_txt = sel_edge_txt; sel_2_txt = sel_2_txt } in let state = { w = w; opt = options; gui_sel = [| None; None |] ; graph = None ; ppu = 1.; selected = None; neighbours = None } in let _ = canvas#event#connect#after#key_press (key_press state) in state let sel_1_bitmap () = Gdk.Bitmap.create_from_data ~width:2 ~height:2 "\002\001" let sel_2_bitmap () = Gdk.Bitmap.create_from_data ~width:2 ~height:2 "\002\001" (* we have to put some color on item in order to be able to get their events, * so let's cheat and add a bitmap with 0 every where... *) let no_bitmap () = Gdk.Bitmap.create_from_data ~width:1 ~height:1 "\000" let move_selection state n_opt1 n_opt2 = let set_props o col bitmap = match o with None -> () | Some o -> o#set [ `FILL_COLOR col ; `FILL_STIPPLE bitmap] in let n_obj n_opt = match n_opt with | None -> None | Some n -> ViewGraph_core.get_obj n in let obj1 = n_obj n_opt1 in let obj2 = n_obj n_opt2 in let reset_old i = set_props state.gui_sel.(i) "black" (no_bitmap()) in reset_old 0; reset_old 1; state.gui_sel.(0) <- obj1; state.gui_sel.(1) <- obj2; set_props obj1 state.opt.sel_1_color (sel_1_bitmap()) ; set_props obj2 state.opt.sel_2_color (sel_2_bitmap()) let show_selection state = let n_opt, txt1, txt2, txt3 = match state.selected with | None -> None, "(none)", "", "" | Some n -> let txt1 = ViewGraph_core.get_id n in let n_opt, txt2, txt3 = match state.neighbours with | None -> None, "", "" | Some info -> match CircLists.current_node info with | None -> None, " --- ", "(none)" | Some (pred_first, n) -> let txt2 = if pred_first then " <-- " else " --> " in Some n, txt2, ViewGraph_core.get_id n in n_opt, txt1, txt2, txt3 in state.w.sel_1_txt#set_text txt1; state.w.sel_edge_txt#set_text txt2; state.w.sel_2_txt#set_text txt3; move_selection state state.selected n_opt; if state.opt.center_node_when_selected then center_selected_node state let select_node state n_opt = state.selected <- n_opt; state.neighbours <- None; show_selection state let select_neighbour state = match state.graph with None -> () | Some graph -> match state.selected with None -> () | Some n -> let new_info = match state.neighbours with | None -> let neighbours = ViewGraph_core.get_neighbours graph n in CircLists.mk neighbours | Some info -> CircLists.go_next info in state.neighbours <- Some (new_info); show_selection state let goto_neighbour state = match state.graph with None -> () | Some graph -> match state.neighbours with | None -> () | Some info -> match CircLists.current_node info with | None -> () | Some (_, n) -> match state.selected with | None -> (* neighbours without selected node ? Impossible... *) assert false | Some old_n -> state.selected <- Some n; let neighbours = ViewGraph_core.get_neighbours graph n in let neighbours = CircLists.mk neighbours in let neighbours = CircLists.goto_n neighbours old_n in state.neighbours <- Some neighbours; show_selection state let clear_state state = state.graph <- None; state.ppu <- 1.; state.selected <- None; state.neighbours <- None; state.gui_sel <- [| None; None |]; show_selection state module SelectCb (UserCb : ViewGraph_core.SigCb) = struct type t_env = UserCb.t_env * t_state let button_one_press_on_graph (u_env, state) = select_node state None; UserCb.button_one_press_on_graph (u_env) let button_two_press_on_graph (u_env, state) = select_neighbour state; UserCb.button_two_press_on_graph (u_env) let button_three_press_on_graph (u_env, state) = goto_neighbour state; UserCb.button_three_press_on_graph (u_env) let button_one_press_on_node (u_env, state) n = select_node state (Some n); UserCb.button_one_press_on_node (u_env) n let button_two_press_on_node ((u_env, state) as env) n = button_two_press_on_graph env; UserCb.button_two_press_on_node (u_env) n let button_three_press_on_node ((u_env, state) as env) n = button_three_press_on_graph env; UserCb.button_three_press_on_node (u_env) n let enter_node (u_env, state) n = begin match ViewGraph_core.get_obj n with None -> assert false | Some n_item -> n_item#set [`OUTLINE_COLOR "red"] end; UserCb.enter_node (u_env) n let leave_node (u_env, state) n = begin match ViewGraph_core.get_obj n with None -> assert false | Some n_item -> n_item#set [`NO_OUTLINE_COLOR] end; UserCb.leave_node (u_env) n end module VG (UserCb : ViewGraph_core.SigCb) = struct module Cb = SelectCb (UserCb) module V = ViewGraph_core.M (Cb) let open_dot_file u_env state ?(dot_cmd="dot") file = let canvas = state.w.canvas in (match state.graph with None -> () | Some g -> V.clear canvas g); let _ = clear_state state in let env = (u_env, state) in let graph = V.open_dot_file env canvas ~dot_cmd file in state.graph <- Some graph; graph end let show_help () = GToolbox.message_box ~title:"Help" "Selection :\n - use the mouse button-1 to select a node : \ it should turn red and (optionally) be centered. - when a node is selected, button-2 selects one of its neighbour : \ it should turn green. - using button-2 again selects the next neighbour, and so on. - when a neighbour is selected, button-3 makes it the selected node, and the previously selected node become the selected neighbour, so pressing the button-3 again brings back to it. - button-1 outside a node deselect everything. Have a look at the bottom line to see the selection. Moving arround :\n - the scrollbars, as well as the arrows, can be used to move in the window. - the Page-Up and Page-Down keys can be used to zoom \ (ugly zoom at the moment !). - the Home key centers the selected node in the window. " ocamlgraph-1.8.3/view_graph/viewGraph_utils.mli0000644000175000017500000000263612133565071020622 0ustar mehdimehdi(**************************************************************************) (* *) (* ViewGraph: a library to interact with graphs in ocaml and lablgtk2 *) (* *) (* Copyright (C) 2008 - Anne Pacalet *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** This file provide useful function to build windows to put the graph *) val create_scrolled_canvas : (GObj.widget -> unit) -> GnoCanvas.canvas val create_graph_win : string -> ViewGraph_select.t_env ocamlgraph-1.8.3/dgraph/0000755000175000017500000000000012133565071014046 5ustar mehdimehdiocamlgraph-1.8.3/dgraph/dGraphRandModel.mli0000644000175000017500000000401112133565071017540 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 G: Graph.Sig.G module GraphAttrs: Graph.Graphviz.GraphWithDotAttrs with type t = G.t and type V.t = G.V.t and type E.t = G.E.t val create: unit -> DGraphModel.Make(GraphAttrs).model ocamlgraph-1.8.3/dgraph/dGraphModel.ml0000644000175000017500000001745212133565071016577 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (* This graph model is for now immutable, no adding or removing nodes. *) open Graph open XDot open Printf exception DotError of string (* ABSTRACT CLASS *) class type ['vertex, 'edge, 'cluster] abstract_model = object method iter_edges : ('vertex -> 'vertex -> unit) -> unit method iter_edges_e : ('edge -> unit) -> unit method iter_pred : ('vertex -> unit) -> 'vertex -> unit method iter_pred_e : ('edge -> unit) -> 'vertex -> unit method iter_succ : ('vertex -> unit) -> 'vertex -> unit method iter_succ_e : ('edge -> unit) -> 'vertex -> unit method iter_vertex : ('vertex -> unit) -> unit method iter_clusters : ('cluster -> unit) -> unit method iter_associated_vertex : ('vertex -> unit) -> 'vertex -> unit (** Membership functions *) method find_edge : 'vertex -> 'vertex -> 'edge method mem_edge : 'vertex -> 'vertex -> bool method mem_edge_e : 'edge -> bool method mem_vertex : 'vertex -> bool method src : 'edge -> 'vertex method dst : 'edge -> 'vertex (** Dot layout *) method bounding_box : bounding_box method get_edge_layout : 'edge -> edge_layout method get_vertex_layout : 'vertex -> node_layout method get_cluster_layout : 'cluster -> cluster_layout end (* BUILDING A MODEL WITH AN OCAML GRAPH *) module Make(G : Graphviz.GraphWithDotAttrs) = struct type cluster = string module X = XDot.Make(G) class model layout g : [G.vertex, G.edge, cluster] abstract_model = object (* Iterators *) method iter_edges f = G.iter_edges f g method iter_edges_e f = G.iter_edges_e f g method iter_pred f v = G.iter_pred f g v method iter_pred_e f v = G.iter_pred_e f g v method iter_succ f = G.iter_succ f g method iter_succ_e f = G.iter_succ_e f g method iter_vertex f = G.iter_vertex f g method iter_associated_vertex f v = f v method iter_clusters f = Hashtbl.iter (fun k v -> f k) layout.X.cluster_layouts (* Membership functions *) method find_edge = try G.find_edge g with Not_found -> assert false method mem_edge = G.mem_edge g method mem_edge_e = G.mem_edge_e g method mem_vertex = G.mem_vertex g method src = G.E.src method dst = G.E.dst (* Layout *) method bounding_box = layout.X.bbox method get_vertex_layout v = try X.HV.find layout.X.vertex_layouts v with Not_found -> assert false method get_edge_layout e = try X.HE.find layout.X.edge_layouts e with Not_found -> assert false method get_cluster_layout c = try Hashtbl.find layout.X.cluster_layouts c with Not_found -> assert false end let from_graph ?(cmd="dot") ?(tmp_name = "dgraph") g = (* Output dot file *) let module DumpDot = Graphviz.Dot(G) in let dot_file, out = Filename.open_temp_file tmp_name ".dot" in DumpDot.output_graph out g; close_out out; (* Get layout from dot file *) let layout = try X.layout_of_dot ~cmd ~dot_file g with X.DotError err -> raise (DotError err) in let model = new model layout g in Sys.remove dot_file; model end (* BUILDING A MODEL WITH A DOT FILE *) (* Here we build a model from a graph where vertices and edges are labeled with xdot layouts *) module Vertex = struct type t = XDot.node_layout end module Edge = struct type t = XDot.edge_layout let default = XDot.mk_edge_layout ~draw:[] ~ldraw:[] ~hdraw:[] ~tdraw:[] ~hldraw:[] ~tldraw:[] let compare : t -> t -> int = Pervasives.compare end module DotG = Imperative.Digraph.AbstractLabeled(Vertex)(Edge) module DotB = Builder.I(DotG) type cluster = string type dotg_model = (DotG.vertex, DotG.edge, cluster) abstract_model module DotParser = Dot.Parse (DotB) (struct (* Read the attributes of a node *) let node = XDot.read_node_layout (* Read edge attributes *) let edge = XDot.read_edge_layout end) module DotModel = struct type cluster = string type clusters_hash = (cluster, Graph.Dot_ast.attr list) Hashtbl.t class model g clusters_hash bounding_box : [DotG.vertex, DotG.edge, cluster] abstract_model = object (* Iterators *) method iter_edges f = DotG.iter_edges f g method iter_edges_e f = DotG.iter_edges_e f g method iter_pred f v = DotG.iter_pred f g v method iter_pred_e f v = DotG.iter_pred_e f g v method iter_succ f = DotG.iter_succ f g method iter_succ_e f = DotG.iter_succ_e f g method iter_vertex f = DotG.iter_vertex f g method iter_associated_vertex f v = f v method iter_clusters f = Hashtbl.iter (fun k _ -> f k) clusters_hash (* Membership functions *) method find_edge = try DotG.find_edge g with Not_found -> assert false method mem_edge = DotG.mem_edge g method mem_edge_e = DotG.mem_edge_e g method mem_vertex = DotG.mem_vertex g method src = DotG.E.src method dst = DotG.E.dst (* Layout *) method bounding_box = bounding_box method get_vertex_layout = DotG.V.label method get_edge_layout = DotG.E.label method get_cluster_layout c = let attrs = try Hashtbl.find clusters_hash c with Not_found -> assert false in XDot.read_cluster_layout attrs end let model = new model end (* Runs graphviz, parses the graph and instantiates the model *) let read_dot ?(cmd="dot") dot_file = let basename = try Filename.chop_extension dot_file with Invalid_argument _ -> dot_file in let xdot_file = basename ^ ".xdot" in let dot_cmd = Printf.sprintf "%s -Txdot %s > %s" cmd dot_file xdot_file in (* Run graphviz *) match Sys.command dot_cmd with | 0 -> begin let graph, bb, clusters_hash = DotParser.parse_bounding_box_and_clusters xdot_file in DotModel.model graph clusters_hash (XDot.read_bounding_box bb) end | _ -> raise (DotError "Error during dot execution") (* Does not run graphviz. Parses a graph from an xdot file and instantiates the model. *) let read_xdot xdot_file = let graph, bb, clusters_hash = DotParser.parse_bounding_box_and_clusters xdot_file in DotModel.model graph clusters_hash (XDot.read_bounding_box bb) ocamlgraph-1.8.3/dgraph/xDotDraw.mli0000644000175000017500000000740412133565071016312 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (** Parses xdot drawing operations *) (** See {{:http://www.graphviz.org/doc/info/output.html#d:xdot}dot documentation} to understand the drawing operations *) (** {2 Types } *) (** Dot layout coordinates *) type pos = float * float (** Dimensions *) type width = float type height = float type size = int (** Text alignment *) type align = Left | Center | Right (** Style attributes *) type style_attr = | Filled | Invisible | Diagonals | Rounded | Dashed | Dotted | Solid | Bold | StyleString of string (** Drawing operations *) type operation = | Filled_ellipse of pos * width * height | Unfilled_ellipse of pos * width * height | Filled_polygon of pos array | Unfilled_polygon of pos array | Polyline of pos array | Bspline of pos array | Filled_bspline of pos array | Text of pos * align * width * string | Fill_color of string | Pen_color of string | Font of float * string | Style of style_attr list val string_scale_size: string -> float -> string -> width*height (** [string_scale_size font font_size text]. Interpolates the font metrics we have to use to draw the given [text] with the given font but preserving the bounding box of the [text] even with a proportional font. For a fixed width font the result is [font_size*font_size]. *) (** {2 Parsing and drawing state } *) (** Parses an xdot drawing attribute *) val parse : string -> operation list (** Some drawing operations modify the following drawing state (pen_color, font and style). *) type draw_state = private { mutable fill_color : string; mutable pen_color : string; mutable font : float * string; mutable style : style_attr list; } (** Iterates on the drawing operations and updates the implicit drawing state *) val draw_with : (draw_state -> operation -> unit) -> operation list -> unit (** {3 Miscellaneous} *) (** Reads the color string and converts to rgb if in an another format *) val normalize_color : string -> string ocamlgraph-1.8.3/dgraph/dGraphContainer.mli0000755000175000017500000001220612133565071017625 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 type cluster = string type status = Global | Tree | Both class type ['vertex, 'edge, 'cluster, 'tree_vertex, 'tree_edge, 'tree_cluster] view_container_type = object method global_view : ('vertex, 'edge, 'cluster) DGraphView.view option method tree_view: ('tree_vertex, 'tree_edge, 'tree_cluster) DGraphView.view option method tree_root: 'vertex option method depth_backward : int method depth_forward : int method status : status method set_depth_backward : int -> unit method set_depth_forward : int -> unit method set_tree_root: 'vertex -> unit method switch : status -> unit method adapt_zoom: unit -> unit end module type S = sig type graph type vertex type edge module Tree: Sig.G with type V.label = vertex module GView: DGraphView.S with type vertex = vertex and type edge = edge and type cluster = cluster module TView: DGraphView.S with type vertex = Tree.V.t and type edge = Tree.E.t and type cluster = cluster type global_view = (vertex, edge, cluster) DGraphView.view type tree_view = (Tree.V.t, Tree.E.t, cluster) DGraphView.view class view_container : ?packing:(GObj.widget -> unit) -> ?status:status -> ?default_callbacks:bool (* register default node callbacks (centering and highlighting). True by default *) -> mk_global_view: (unit -> global_view) -> mk_tree_view: (depth_backward:int -> depth_forward:int -> Gtk.widget Gtk.obj -> vertex -> tree_view) -> vertex option -> [ vertex, edge, cluster, Tree.V.t, Tree.E.t, cluster] view_container_type end module Make(G: Graphviz.GraphWithDotAttrs) : sig include S with type graph = G.t and type vertex = G.V.t and type edge = G.E.t val from_graph : ?packing:(GObj.widget -> unit) -> ?status:status -> ?default_callbacks:bool -> ?mk_global_view: ((G.V.t, G.E.t, cluster) DGraphModel.abstract_model -> global_view) -> ?mk_tree_view: ((Tree.V.t, Tree.E.t, cluster) DGraphModel.abstract_model -> tree_view) -> ?root:G.vertex -> G.t -> view_container val from_graph_with_commands : ?packing:(GObj.widget -> unit) -> ?status:status -> ?default_callbacks:bool -> ?mk_global_view: ((G.V.t, G.E.t, cluster) DGraphModel.abstract_model -> global_view) -> ?mk_tree_view: ((Tree.V.t, Tree.E.t, cluster) DGraphModel.abstract_model -> tree_view) -> ?root:G.vertex -> G.t -> GPack.table * view_container end module Dot : sig open DGraphModel include S with type graph = DotG.t and type vertex = DotG.V.t and type edge = DotG.E.t val from_dot : ?packing:(GObj.widget -> unit) -> ?status:status -> ?default_callbacks:bool -> ?mk_global_view: ((DotG.V.t, DotG.E.t, cluster) abstract_model -> global_view) -> ?mk_tree_view: ((Tree.V.t, Tree.E.t, cluster) abstract_model -> tree_view) -> string (* dot filename *) -> view_container val from_dot_with_commands : ?packing:(GObj.widget -> unit) -> ?status:status -> ?default_callbacks:bool -> ?mk_global_view: ((DotG.V.t, DotG.E.t, cluster) abstract_model -> global_view) -> ?mk_tree_view: ((Tree.V.t, Tree.E.t, cluster) abstract_model -> tree_view) -> string (* dot filename *) -> GPack.table * view_container end ocamlgraph-1.8.3/dgraph/dGraphTreeLayout.ml0000755000175000017500000010201512133565071017625 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 let ($) f x = f x let set_if_none field value = match field with | None -> Some value | Some a -> Some a let the = function None -> assert false | Some a -> a type cluster = string module Build (G: Graphviz.GraphWithDotAttrs) (TreeManipulation: sig val is_ghost_node: G.V.t -> bool end) = struct module Layout = struct include XDot.Make(G) open XDot type t = graph_layout = { vertex_layouts : node_layout HV.t; edge_layouts : edge_layout HE.t; cluster_layouts : (string, cluster_layout) Hashtbl.t; bbox : bounding_box } end open Layout type geometry_info = { dimensions : (float * float) HV.t; position : (float * float) HV.t; mutable x_offset : float; mutable y_offset : int; } let get_position v geometry_info = try HV.find geometry_info.position v with Not_found -> assert false let get_dimensions v geometry_info = try HV.find geometry_info.dimensions v with Not_found -> assert false let set_offset geometry_info = geometry_info.y_offset <- 150; geometry_info.x_offset <- HV.fold (fun _ (w, _) maxw -> max w maxw) geometry_info.dimensions 0. (* Calculate node positions for a tree *) let fill_tree_positions tree root iter_fun fold_fun table geometry_info = let vertex_x_space = 10. in let stack = Stack.create () in let fill_stack tree root = let stack_queue = Queue.create () in let rec flush_queue queue = if not(Queue.is_empty queue) then begin let elem, depth = Queue.take queue in iter_fun (fun v -> Queue.add (v, depth + 1) queue) tree elem; Stack.push (elem,depth) stack; flush_queue queue end in Queue.add (root, 0) stack_queue; flush_queue stack_queue; in fill_stack tree root; let offset = ref geometry_info.x_offset in let max_depth = snd (Stack.top stack) in let rec flush_stack stack = if not (Stack.is_empty stack) then begin let elem, depth = Stack.pop stack in if depth = max_depth then begin HV.add table elem (!offset, depth); offset := !offset +. geometry_info.x_offset +. vertex_x_space; end else begin let sum, cpt = fold_fun (fun v (sum, cpt) -> let (x, _) = try HV.find table v with Not_found -> assert false in sum +. x, cpt +. 1.) tree elem (0., 0.) in assert (cpt <> 0.); HV.add table elem (sum /. cpt, depth) end; flush_stack stack end in flush_stack stack (* Bind two tree position tables together *) let bind_tree_tables forward_table backward_table root geometry_info = (* Using dimension is required in order to be put at the middle of the canvas.*) let max_fwd, max_dim_fwd = HV.fold (fun v (_, y) (max_y, max_dimy as acc) -> if TreeManipulation.is_ghost_node v then acc else (*max y max_y*) if y < max_y then acc else let _, dimy = get_dimensions v geometry_info in (*[BM] why 1.5? *) let dimy = dimy *. 1.5 in y, if y = max_y then max max_dimy dimy else dimy) forward_table (0, 0.) in HV.iter (fun v (x, y) ->(*[BM]: why 0.5 and 1.5 ??? *) HV.add geometry_info.position v (x, ((float (max_fwd + y)) -. 0.5) *. float geometry_info.y_offset -. 1.5 *. max_dim_fwd)) backward_table; HV.iter (fun v (x, y) ->(*[BM]: why 0.5 and 1.5 ??? *) HV.add geometry_info.position v (x, ((float (max_fwd - y)) -. 0.5) *. float geometry_info.y_offset -. 1.5 *. max_dim_fwd)) forward_table; HV.remove geometry_info.position root (* DRAW OPERATIONS *) (* Convert an int in hexadecimal representing a color in rgb format to a string prefixed by # *) let string_color i = Printf.sprintf "#%06X" i;; let string_color32 i = Printf.sprintf "#%08lX" i;; (** @return an array of positions to draw an edge from positions and dimensions of vertices *) let edge_to_posarray src dst geometry_info = let xsrc, ysrc = get_position src geometry_info in let _, hsrc = get_dimensions src geometry_info in let xdst, ydst = get_position dst geometry_info in let _, hdst = get_dimensions dst geometry_info in let ystart = ysrc -. hsrc/.2. and yend = ydst +. hdst/. 2. in (* Bezier intermediate points. *) let xdec = (xdst -. xsrc)/.4.0 in let ydec = (ydst -. ysrc)/.4.0 in (* Format.printf "%f %f %f@." ystart yend ydec;*) [| xsrc, ystart; xsrc +. xdec, ystart +. ydec; xdst -. xdec, yend -. ydec; xdst, yend |];; (** @return an array to draw an arrow from start and end positions of the edge *) let edge_to_arrow (x1, y1) (x2, y2) = let warrow = 4. in (* Half-width of the arrow *) let harrow = 10. in (* Height of the arrow *) let dx = x2 -. x1 in let dy = y1 -. y2 in let d = sqrt (dx *. dx +. dy *. dy) in let xp1 = -. (harrow *. dx +. warrow *. dy) /. d +. x2 in let yp1 = (harrow *. dy -. warrow *. dx) /. d +. y2 in let xp2 = (warrow *. dy -. harrow *. dx) /. d +. x2 in let yp2 = (warrow *. dx +. harrow *. dy) /. d +. y2 in [ XDotDraw.Filled_polygon [| x2, y2; xp1, yp1; xp2, yp2 |] ] end (* FROM GRAPH *) module Make (Tree: Graphviz.GraphWithDotAttrs) (TreeManipulation: sig val is_ghost_node: Tree.V.t -> bool end) = struct include Build(Tree)(TreeManipulation) open Layout (* PARSE VERTICES ATTRIBUTES *) type vattributes = { (* See graphviz.mli for the meaning of each options *) mutable color : int32 option; mutable fontcolor : int option; mutable fontname : string option; mutable fontsize : int option; mutable height : float option; mutable label : string option; mutable orientation : float option; mutable peripheries : int option; mutable regular : bool option; mutable shape : [ `Ellipse | `Box | `Circle | `Doublecircle | `Diamond | `Plaintext | `Record | `Polygon of int * float ] option; mutable style : [ `Filled | `Solid | `Dashed | `Dotted | `Bold | `Invis ] list; mutable width : float option; mutable fillcolor : int32 option; } let set_vattribute vattrs = function | `Color c -> vattrs.color <- set_if_none vattrs.color (Graphviz.color_to_color_with_transparency c) | `ColorWithTransparency c -> vattrs.color <- set_if_none vattrs.color c | `Fontcolor c -> vattrs.fontcolor <- set_if_none vattrs.fontcolor c | `Fontname n -> vattrs.fontname <- set_if_none vattrs.fontname n | `Fontsize s -> vattrs.fontsize <- set_if_none vattrs.fontsize s | `Height h -> vattrs.height <- set_if_none vattrs.height h | `Label label -> vattrs.label <- set_if_none vattrs.label label | `Orientation o -> vattrs.orientation <- set_if_none vattrs.orientation o | `Peripheries p -> vattrs.peripheries <- set_if_none vattrs.peripheries p | `Regular r -> vattrs.regular <- set_if_none vattrs.regular r | `Shape shape -> vattrs.shape <- set_if_none vattrs.shape shape | `Style s -> vattrs.style <- s :: vattrs.style | `Width w -> vattrs.width <- set_if_none vattrs.width w | `Fillcolor c -> vattrs.fillcolor <- set_if_none vattrs.fillcolor (Graphviz.color_to_color_with_transparency c) | `FillcolorWithTransparency c -> vattrs.fillcolor <- set_if_none vattrs.fillcolor c | `Comment _ | `Distortion _ | `Fixedsize _ | `Layer _ | `Url _ | `Z _ -> () (* TODO *) let attributes_list_to_vattributes vattrs = List.iter (set_vattribute vattrs) let fill_vattributes tree vattributes = let vertex_to_vattrs v = let vattrs = { color = None; fontcolor = None; fontname = None; fontsize = None; height = None; label = None; orientation = None; peripheries = None; regular = None; shape = None; style = []; width = None; fillcolor = None } in let dgraph_layout_default = [ `Color 0xFFFFFF; `Fontcolor 0x000000; `Fontname "Sans"; `Fontsize 12; `Height 0.; `Label (Tree.vertex_name v); `Orientation 0.; `Peripheries 1; `Regular false; `Shape `Ellipse; `Width 0.; `Fillcolor 0xFFFFFF ] in attributes_list_to_vattributes vattrs (Tree.vertex_attributes v @ Tree.default_vertex_attributes tree @ dgraph_layout_default); vattrs in Tree.iter_vertex (fun v -> HV.add vattributes v (vertex_to_vattrs v)) tree (* PLACE VERTICES *) (* Calculate dimension of a string in pixel *) let calc_dimensions family ptsize ?(weight=`NORMAL) ?(style=`NORMAL) s context_obj = let width_margin = 20. in let height_margin = 0. in let font_description = Pango.Font.from_string "" in Pango.Font.modify font_description ~family:family ~weight ~style ~size:(ptsize * Pango.scale) (); let context = GtkBase.Widget.create_pango_context context_obj in Pango.Context.set_font_description context font_description; let layout = Pango.Layout.create context in Pango.Layout.set_text layout s; let width, height = Pango.Layout.get_pixel_size layout in float width +. width_margin, float height +. height_margin let fill_dimensions context tree vattributes geometry_info = let add_vertex_dimensions v = let vattrs = try HV.find vattributes v with Not_found -> assert false in let minwidth, minheight = the vattrs.width, the vattrs.height in let truewidth, trueheight = calc_dimensions (the vattrs.fontname) (the vattrs.fontsize) (the vattrs.label) context in let width = max minwidth truewidth in let height = max minheight trueheight in HV.replace geometry_info.dimensions v (width, height) in Tree.iter_vertex add_vertex_dimensions tree let fill_position tree root geometry_info = let forward_table = HV.create 97 in let backward_table = HV.create 97 in fill_tree_positions tree root Tree.iter_succ Tree.fold_succ forward_table geometry_info; fill_tree_positions tree root Tree.iter_pred Tree.fold_pred backward_table geometry_info; bind_tree_tables forward_table backward_table root geometry_info (* BUILD LAYOUT - ADD DRAW OPERATIONS *) let style_to_style_attr = function | `Filled -> XDotDraw.Filled | `Solid -> XDotDraw.Solid | `Dashed -> XDotDraw.Dashed | `Dotted -> XDotDraw.Dotted | `Bold -> XDotDraw.Bold | `Invis -> XDotDraw.Invisible;; (* FOR VERTEX *) let shape_to_operations v vattrs geometry_info shape = let width, height = let a, b = get_dimensions v geometry_info in a /. 2., b in let position = get_position v geometry_info in let filled = List.mem `Filled vattrs.style in match shape with | `Ellipse -> if filled then [ XDotDraw.Filled_ellipse (position,width,height) ] else [ XDotDraw.Unfilled_ellipse (position,width,height) ] | `Circle -> let diameter = max width height in if filled then [ XDotDraw.Filled_ellipse (position,diameter,diameter) ] else [ XDotDraw.Unfilled_ellipse (position,diameter,diameter) ] | `Doublecircle -> let diameter = max width height in let big_diameter = diameter +. 5. in (XDotDraw.Unfilled_ellipse (position,big_diameter,big_diameter)) :: [ if filled then XDotDraw.Filled_ellipse (position,diameter,diameter) else XDotDraw.Unfilled_ellipse (position,diameter,diameter) ] | `Box -> let x, y = position in let x1 = x -. width and x2 = x +. width in let y1 = y -. height and y2 = y +. height in let pos_array = [|(x1,y1);(x1,y2);(x2,y2);(x2,y1)|] in if filled then [ XDotDraw.Filled_polygon pos_array ] else [ XDotDraw.Unfilled_polygon pos_array ] | `Record -> let x, y = position in let x1 = x -. width and x2 = x +. width in let y1 = y -. height and y2 = y +. height in let pos_array = [|(x1,y1);(x1,y2);(x2,y2);(x2,y1)|] in if filled then [ XDotDraw.Filled_polygon pos_array ] else [ XDotDraw.Unfilled_polygon pos_array ] | `Diamond -> let x, y = position in let x1 = x -. width and x2 = x +. width in let y1 = y -. height and y2 = y +. height in let pos_array = [|(x,y1);(x1,y);(x,y2);(x2,y)|] in if filled then [ XDotDraw.Filled_polygon pos_array ] else [ XDotDraw.Unfilled_polygon pos_array ] |_ -> [ XDotDraw.Unfilled_ellipse ((0.,0.),0.,0.) ];; let vattrs_to_draw_operations v vattributes geometry_info = let vattrs = try HV.find vattributes v with Not_found -> assert false in let width, height = get_dimensions v geometry_info in (* Vertex shape drawing *) XDotDraw.Pen_color (string_color32 (the vattrs.color)) :: XDotDraw.Style (List.map (style_to_style_attr) vattrs.style) :: (if List.mem `Filled vattrs.style then XDotDraw.Fill_color (string_color32 (the vattrs.fillcolor)) :: shape_to_operations v vattrs geometry_info (the vattrs.shape) else shape_to_operations v vattrs geometry_info (the vattrs.shape)) , (* Vertex label drawing *) [ XDotDraw.Pen_color (string_color (the vattrs.fontcolor)); XDotDraw.Font (float (the vattrs.fontsize), the vattrs.fontname); let x, y = get_position v geometry_info in let _, h = get_dimensions v geometry_info in (* [JS 2010/10/08] "/. 4." is quite strange but gives better results *) XDotDraw.Text ((x, y +. h /. 4.), XDotDraw.Center, width, the vattrs.label) ] let vertex_to_node_layout v vattributes geometry_info = let draw, ldraw = vattrs_to_draw_operations v vattributes geometry_info in let width, height = get_dimensions v geometry_info in let abs, ord = get_position v geometry_info in { XDot.n_name = Tree.vertex_name v; XDot.n_pos = (abs,ord); XDot.n_bbox = XDot.bounding_box (abs, ord) width height; XDot.n_draw = draw; XDot.n_ldraw = ldraw } (* FOR CLUSTER *) open Graphviz.DotAttributes let get_clusters tree = let clusters = Hashtbl.create 20 in Tree.iter_vertex (fun v -> match Tree.get_subgraph v with | None -> () | Some c -> Hashtbl.add clusters c v) tree; clusters;; let rec get_cluster_color = function | [] -> 0x000000 | `Color c :: _ -> c | _ :: q -> get_cluster_color q;; let find_cluster_corners l geometry_info = let max_x_distance = 2. *. geometry_info.x_offset in let max_y_distance = 2. *. float geometry_info.y_offset in let rec find_corners l corners_array = let (minx,miny) = corners_array.(0) in let (maxx,maxy) = corners_array.(3) in match l with |[] -> corners_array |v :: tl -> let x, y = get_position v geometry_info in let w, h = get_dimensions v geometry_info in let halfw = w /. 2. in let x1 = x -. halfw and x2 = x +. halfw in let y1 = y -. h and y2 = y +. h in (* Should cluster be split in two *) let x1_distance = minx -. x1 in let x2_distance = x2 -. maxx in let y1_distance = miny -. y1 in let y2_distance = y2 -. maxy in if x1_distance > max_x_distance || x2_distance > max_x_distance || y1_distance > max_y_distance || y2_distance > max_y_distance || ((x1_distance <> 0. || x2_distance <> 0.) && (y1_distance <> 0. || y2_distance <> 0.)) then Array.append (find_corners tl corners_array) (find_corners tl [| x1, y1; x1, y2; x2, y2; x2, y1 |]) else let newminx = min x1 minx in let newminy = min y1 miny in let newmaxx = max x2 maxx in let newmaxy = max y2 maxy in find_corners tl [|(newminx,newminy);(newminx,newmaxy); (newmaxx,newmaxy);(newmaxx,newminy)|] in match l with | [] -> let z = 0., 0. in Array.make 4 z | v :: q -> let x, y = get_position v geometry_info in let w, h = get_dimensions v geometry_info in let halfw = w /. 2. in let x1 = x -. halfw in let x2 = x +. halfw in let y1 = y -. h in let y2 = y +. h in find_corners q [| x1, y1; x1, y2; x2, y2; x2, y1 |];; let cluster_to_cluster_layout tree c clusters geometry_info = let border_padding = 10. in let vertices = try Hashtbl.find_all clusters c with Not_found -> assert false in let corners_array = find_cluster_corners vertices geometry_info in let add_padding corners_array = let (x1,y1) = corners_array.(0) in let (x2,y2) = corners_array.(3) in let x1_padded = x1 -. border_padding in let x2_padded = x2 +. border_padding in let y1_padded = y1 -. border_padding in let y2_padded = y2 +. border_padding in [|(x1_padded,y1_padded);(x1_padded,y2_padded); (x2_padded,y2_padded);(x2_padded,y1_padded)|] in let rec cut_corners_array corners_array = ignore (assert false); (* [JS 2010/09/09] does not work: exponential time seems to be required! *) let length = Array.length corners_array in if length > 4 then XDotDraw.Unfilled_polygon (add_padding (Array.sub corners_array 0 4)) :: (cut_corners_array (Array.sub corners_array 4 (length-4))) else [ XDotDraw.Unfilled_polygon (add_padding corners_array) ] in let (x1,y1) = corners_array.(0) in let (x2,y2) = corners_array.(3) in { XDot.c_pos = ((x1 +. x2) /. 2., (y1 +. y2) /. 2.); XDot.c_bbox = ((x1,y1),(x2,y2)); XDot.c_draw = XDotDraw.Pen_color (string_color (get_cluster_color c.sg_attributes)) :: (*cut_corners_array corners_array*)[]; XDot.c_ldraw = [] };; let build_cluster_layouts tree geometry_info = let cluster_layouts = Hashtbl.create 7 in let clusters = get_clusters tree in let visited = ref [] in Hashtbl.iter (fun c _ -> if not (List.mem c !visited) then let lay = cluster_to_cluster_layout tree c clusters geometry_info in Hashtbl.add cluster_layouts c.sg_name lay) clusters; cluster_layouts;; (* FOR EDGE *) type eattributes = { (* See graphviz.mli for the meaning of each field *) mutable color : int32 option; mutable decorate : bool option; mutable dir : [ `Forward | `Back | `Both | `None ] option; mutable fontcolor : int option; mutable fontname : string option; mutable fontsize : int option; mutable label : string option; mutable labelfontcolor : int option; mutable labelfontname : string option; mutable labelfontsize : int option; mutable style : [ `Solid | `Dashed | `Dotted | `Bold | `Invis ] list } let rec attributes_list_to_eattributes eattrs = function |[] -> () | `Color c :: q -> eattrs.color <- set_if_none eattrs.color (Graphviz.color_to_color_with_transparency c); attributes_list_to_eattributes eattrs q | `ColorWithTransparency c :: q -> eattrs.color <- set_if_none eattrs.color c; attributes_list_to_eattributes eattrs q | `Decorate d :: q -> eattrs.decorate <- set_if_none eattrs.decorate d; attributes_list_to_eattributes eattrs q | `Dir d :: q -> eattrs.dir <- set_if_none eattrs.dir d; attributes_list_to_eattributes eattrs q | `Fontcolor c :: q -> eattrs.fontcolor <- set_if_none eattrs.fontcolor c; attributes_list_to_eattributes eattrs q | `Fontname n :: q -> eattrs.fontname <- set_if_none eattrs.fontname n; attributes_list_to_eattributes eattrs q | `Fontsize s :: q -> eattrs.fontsize <- set_if_none eattrs.fontsize s; attributes_list_to_eattributes eattrs q | `Label l :: q -> eattrs.label <- set_if_none eattrs.label l; attributes_list_to_eattributes eattrs q | `Labelfontcolor c :: q -> eattrs.fontcolor <- set_if_none eattrs.fontcolor c; attributes_list_to_eattributes eattrs q | `Labelfontname n :: q -> eattrs.labelfontname <- set_if_none eattrs.labelfontname n; attributes_list_to_eattributes eattrs q | `Labelfontsize s :: q -> eattrs.labelfontsize <- set_if_none eattrs.labelfontsize s; attributes_list_to_eattributes eattrs q | `Style s :: q -> eattrs.style <- s :: eattrs.style; attributes_list_to_eattributes eattrs q | (`Arrowhead _ | `Arrowsize _ | `Arrowtail _ | `Comment_ | `Constraint_ | `Headlabel _ | `Headport _ | `Headurl _ | `Labelangle _ |`Labeldistance _ | `Labelfloat _ | `Layer _ | `Minlen _ | `Samehead _ | `Sametail _ | `Taillabel _ | `Tailport _ | `Tailurl _ | `Weight _ | `Comment _ | `Constraint _) :: q -> attributes_list_to_eattributes eattrs q;; let eattrs_to_operation tree e geometry_info = let eattrs = { color = None; decorate = None; dir = None; fontcolor = None; fontname = None; fontsize = None; label = None; labelfontcolor = None; labelfontname = None; labelfontsize = None; style = [] } in let dgraph_layout_default = [ `Color 0xFF0000; `Decorate false; `Dir `Forward; `Fontcolor 0x00000; `Fontname "Sans"; `Fontsize 12; `Label ""; `Labelfontcolor 0x000000; `Labelfontname "Sans"; `Labelfontsize 12; `Style `Solid ] in attributes_list_to_eattributes eattrs (Tree.default_edge_attributes tree @ Tree.edge_attributes e @ dgraph_layout_default); let posarray = edge_to_posarray (Tree.E.src e) (Tree.E.dst e) geometry_info in let xsrc, ysrc = posarray.(0) in let xend, yend = posarray.(3) in ( (* Shapes and curves *) [ XDotDraw.Pen_color (string_color32 (the eattrs.color)); XDotDraw.Fill_color (string_color32 (the eattrs.color)); XDotDraw.Style (List.map (style_to_style_attr) eattrs.style); XDotDraw.Filled_bspline posarray ] , (* Label drawing *) [ XDotDraw.Pen_color (string_color (the eattrs.fontcolor)); XDotDraw.Fill_color (string_color (the eattrs.fontcolor)); XDotDraw.Font (float_of_int (the eattrs.fontsize), (the eattrs.fontname)); (let pos = ((xsrc +. xend) /. 2. +. 5., (ysrc +. yend) /. 2.) in XDotDraw.Text (pos,XDotDraw.Center,40.,the eattrs.label)) ] , (* Head arrowhead drawing *) (if eattrs.dir = Some `None then [] else XDotDraw.Pen_color (string_color32 (the eattrs.color)) :: XDotDraw.Fill_color (string_color32 (the eattrs.color)) :: XDotDraw.Style (List.map (style_to_style_attr) eattrs.style) :: (edge_to_arrow posarray.(2) posarray.(3))) , (* Tail arrowhead drawing *) [] , (* Head label drawing *) [] , (* Tail label drawing *) [] ) let edge_to_edge_layout tree e geometry_info = let (draw,ldraw,hdraw,tdraw,hldraw,tldraw) = eattrs_to_operation tree e geometry_info in { XDot.e_draw = draw; XDot.e_ldraw = ldraw; XDot.e_hdraw = hdraw; XDot.e_tdraw = tdraw; XDot.e_hldraw = hldraw; XDot.e_tldraw = tldraw } (* Graph *) let from_tree context tree root = let vattributes = HV.create 97 in fill_vattributes tree vattributes; let geometry_info = { dimensions = HV.create 97; position = HV.create 97; x_offset = 0.; y_offset = 0 } in fill_dimensions context tree vattributes geometry_info; set_offset geometry_info; fill_position tree root geometry_info; let vertex_layouts = HV.create 97 in Tree.iter_vertex (fun v -> let n_layout = vertex_to_node_layout v vattributes geometry_info in HV.add vertex_layouts v n_layout) tree; let edge_layouts = HE.create 97 in Tree.iter_edges_e (fun e -> let e_layout = edge_to_edge_layout tree e geometry_info in HE.add edge_layouts e e_layout) tree; let cluster_layouts = Hashtbl.create 7 (* [JS 2010/09/09] does not work *) (* build_cluster_layouts tree geometry_info*) in { vertex_layouts = vertex_layouts; edge_layouts = edge_layouts; cluster_layouts = cluster_layouts; bbox = let ((x1,y1), (x2,y2) as bb) = HV.fold (fun v (x, y) ((minx, miny),(maxx, maxy) as acc) -> if TreeManipulation.is_ghost_node v then acc else (min x minx, min y miny), (max x maxx, max y maxy)) geometry_info.position ((max_float, max_float), (0., 0.)) in (* Format.printf "BB=%f %f %f %f@." x1 y1 x2 y2;*) bb } end module MakeFromDotModel (Tree: Sig.G with type V.label = DGraphModel.DotG.V.t and type E.label = unit) (TreeManipulation: sig val is_ghost_node: Tree.V.t -> bool end) = struct module Tree = struct include Tree let graph_attributes _ = [] let default_vertex_attributes _ = [] let default_edge_attributes _ = [] let vertex_name _ = "" let vertex_attributes _ = [] let edge_attributes _ = [] let get_subgraph _ = None end include Build(Tree)(TreeManipulation) open Layout (* POSITIONS *) let fill_dimensions model tree geometry_info = let corners pos_array = let p0 = pos_array.(0) in Array.fold_left (fun ((minx, miny), (maxx, maxy)) (x, y) -> (min minx x, min miny y), (max maxx x, max maxy y)) (p0, p0) pos_array in (* The width and height of the bounding box of the first shape corresponding to a node.*) let rec get_size = function | [] -> 0., 0. | XDotDraw.Unfilled_ellipse (_,w,h) :: _ | XDotDraw.Filled_ellipse (_,w,h) :: _ -> 2. *. w, 2. *. h | XDotDraw.Unfilled_polygon pos_array :: _ | XDotDraw.Filled_polygon pos_array :: _ -> let (minx, miny), (maxx, maxy) = corners pos_array in maxx -. minx, maxy -. miny | (XDotDraw.Style _ |XDotDraw.Font _|XDotDraw.Pen_color _ |XDotDraw.Fill_color _|XDotDraw.Filled_bspline _ |XDotDraw.Bspline _ | XDotDraw.Polyline _|XDotDraw.Text _) :: tl -> get_size tl in Tree.iter_vertex (fun v -> let layout = model#get_vertex_layout (Tree.V.label v) in let dim = get_size layout.XDot.n_draw in HV.add geometry_info.dimensions v dim) tree let fill_position tree root geometry_info = let forward_table = HV.create 97 in let backward_table = HV.create 97 in fill_tree_positions tree root Tree.iter_succ Tree.fold_succ forward_table geometry_info; (*HV.iter (fun k (off,depth) -> Format.printf "off:%f depth:%d@." off depth) forward_table;*) fill_tree_positions tree root Tree.iter_pred Tree.fold_pred backward_table geometry_info; (* HV.iter (fun k (off,depth) -> Format.printf "BACKoff:%f depth:%d@." off depth) backward_table; Format.printf "DONE@.";*) bind_tree_tables forward_table backward_table root geometry_info (* VERTICES *) let rec parse_n_draw_operations operations (abs, ord as pos) = let polygon pts = let length = float (Array.length pts) in let oldabssum, oldordsum = Array.fold_left (fun (xsum, ysum) (x, y) -> xsum +. x, ysum +. y) (0.,0.) pts in let oldabs, oldord = oldabssum /. length, oldordsum /. length in Array.map (fun (x, y) -> x -. oldabs +. abs, y -. oldord +. ord) pts in let do_one = function | XDotDraw.Unfilled_ellipse (_, w, h) -> XDotDraw.Unfilled_ellipse (pos, w, h) | XDotDraw.Filled_ellipse (_, w, h) -> XDotDraw.Filled_ellipse (pos, w, h) | XDotDraw.Filled_polygon pts -> XDotDraw.Filled_polygon (polygon pts) | XDotDraw.Unfilled_polygon pts -> XDotDraw.Unfilled_polygon (polygon pts) | op -> op in List.map do_one operations let parse_n_ldraw_operations (initial_node_pos_x,initial_node_pos_y) (node_pos_x,node_pos_y) operations = List.map (function | XDotDraw.Text ((pos_x,pos_y), align, w, s) -> let translate_x,translate_y = node_pos_x-.initial_node_pos_x,node_pos_y-.initial_node_pos_y in let (x,y as pos) = (* same affine move as the attached node has had*) pos_x+.translate_x, pos_y+.translate_y in XDotDraw.Text (pos, align, w, s) | op -> op) operations let parse_vertex_layout tree v orig_layout geometry_info = let width, height = get_dimensions v geometry_info in let (abs, ord as pos) = get_position v geometry_info in { XDot.n_name = orig_layout.XDot.n_name; n_pos = pos; n_bbox = XDot.bounding_box pos width height; n_draw = parse_n_draw_operations orig_layout.XDot.n_draw pos; n_ldraw = parse_n_ldraw_operations orig_layout.XDot.n_pos pos orig_layout.XDot.n_ldraw} (* EDGES *) let rec parse_e_draw_operations operations src dst geometry_info = match operations with | [] -> [] | XDotDraw.Bspline _ :: tl -> let pos_array = edge_to_posarray src dst geometry_info in XDotDraw.Bspline pos_array :: (edge_to_arrow pos_array.(2) pos_array.(3)) @ (parse_e_draw_operations tl src dst geometry_info) | XDotDraw.Filled_bspline _ :: tl -> let pos_array = edge_to_posarray src dst geometry_info in XDotDraw.Filled_bspline pos_array :: (edge_to_arrow pos_array.(2) pos_array.(3)) @ (parse_e_draw_operations tl src dst geometry_info) | XDotDraw.Pen_color c :: tl -> XDotDraw.Pen_color c :: XDotDraw.Fill_color c :: (parse_e_draw_operations tl src dst geometry_info) | op :: tl -> op :: (parse_e_draw_operations tl src dst geometry_info);; let rec parse_e_ldraw_operations operations src dst geometry_info = match operations with | [] -> [] | XDotDraw.Text (_, align, w, s) :: tl -> let (xsrc,ysrc) = get_position src geometry_info in let (xdst,ydst) = get_position dst geometry_info in let pos = ((xsrc +. xdst) /. 2., (ysrc +. ydst) /. 2.) in XDotDraw.Text (pos, align, w, s) :: (parse_e_ldraw_operations tl src dst geometry_info) | op :: tl -> op :: (parse_e_ldraw_operations tl src dst geometry_info);; let parse_edge_layout tree e layout geometry_info = let src = Tree.E.src e and dst = Tree.E.dst e in { XDot.e_draw = parse_e_draw_operations layout.XDot.e_draw src dst geometry_info; e_ldraw = parse_e_ldraw_operations layout.XDot.e_ldraw src dst geometry_info; e_hdraw = []; e_tdraw = []; e_hldraw = []; e_tldraw = [] };; (* CLUSTERS *) let parse_cluster_layout tree c global_layout geometry_info = ();; let from_model tree root model = let geometry_info = { dimensions = HV.create 97; position = HV.create 97; x_offset = 0.; y_offset = 0 } in fill_dimensions model tree geometry_info; set_offset geometry_info; fill_position tree root geometry_info; let vertex_layouts = HV.create 97 in Tree.iter_vertex (fun v -> let old_layout = model#get_vertex_layout (Tree.V.label v) in let v_layout = parse_vertex_layout tree v old_layout geometry_info in HV.add vertex_layouts v v_layout) tree; let edge_layouts = HE.create 97 in Tree.iter_edges_e (fun e -> let src = Tree.V.label (Tree.E.src e) in let dst = Tree.V.label (Tree.E.dst e) in let old_layout = try model#get_edge_layout (model#find_edge src dst) with Not_found -> { XDot.e_draw = []; e_ldraw = []; e_hdraw = []; e_tdraw = []; e_hldraw = []; e_tldraw = [] } in let e_layout = parse_edge_layout tree e old_layout geometry_info in HE.add edge_layouts e e_layout) tree; let cluster_layouts = Hashtbl.create 7 in let root_pos = get_position root geometry_info in { vertex_layouts = vertex_layouts; edge_layouts = edge_layouts; cluster_layouts = cluster_layouts; bbox = let ((x1,y1), (x2,y2) as bb) = HV.fold (fun v (x, y) ((minx, miny),(maxx, maxy) as acc) -> if TreeManipulation.is_ghost_node v then acc else let width,height= get_dimensions v geometry_info in (min (x-.width) minx, min (y-.height) miny), (max (x+.width) maxx, max (y+.height) maxy)) geometry_info.position (root_pos, root_pos) in (* Format.printf "BB=%f %f %f %f@." x1 y1 x2 y2;*) bb } end ocamlgraph-1.8.3/dgraph/dGraphView.ml0000644000175000017500000002543312133565071016447 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 DGraphViewItem let ($) f x = f x let distance x y = if x > y then x - y else y - x class type ['vertex, 'edge, 'cluster] view = object inherit GnoCanvas.canvas method model : ('vertex, 'edge, 'cluster) DGraphModel.abstract_model method get_node : 'vertex -> 'vertex view_item method get_edge : 'edge -> 'edge view_item method get_cluster : 'cluster -> 'cluster view_item method iter_nodes: ('vertex view_item -> unit) -> unit method iter_edges: ('vertex view_item -> 'vertex view_item -> unit) -> unit method iter_edges_e: ('edge view_item -> unit) -> unit method iter_clusters: ('cluster view_item -> unit) -> unit method iter_succ: ('vertex view_item -> unit) -> 'vertex view_item -> unit method iter_pred: ('vertex view_item -> unit) -> 'vertex view_item -> unit method iter_succ_e: ('edge view_item -> unit) -> 'vertex view_item -> unit method iter_pred_e: ('edge view_item -> unit) -> 'vertex view_item -> unit method iter_associated_vertex: ('vertex view_item -> unit) -> 'vertex view_item -> unit method mem_edge: 'vertex view_item -> 'vertex view_item -> bool method find_edge: 'vertex view_item -> 'vertex view_item -> 'edge view_item method src: 'edge view_item -> 'vertex view_item method dst: 'edge view_item -> 'vertex view_item method zoom_factor : float method zoom_to : float -> unit method zoom_in : unit -> unit method zoom_out : unit -> unit method adapt_zoom : unit -> unit method center_node: 'vertex view_item -> unit method set_zoom_padding: float -> unit method connect_highlighting_event: unit -> unit method highlight: ?color: int32 * int32 -> 'vertex view_item -> unit method dehighlight: 'vertex view_item -> unit end module type S = sig type vertex type edge type cluster val view: ?aa:bool (** Anti-aliasing *) -> ?delay_node:(vertex -> bool) -> ?delay_edge:(edge -> bool) -> ?delay_cluster:(cluster -> bool) -> ?border_width:int -> ?width:int -> ?height:int -> ?packing:(GObj.widget -> unit) -> ?show:bool -> (vertex, edge, cluster) DGraphModel.abstract_model -> (vertex, edge, cluster) view (** View as a Gnome Canvas. Support zooming and scrolling. *) end (* ************************************************************************* *) (** View from a model *) (* ************************************************************************* *) module Make(V: Sig.HASHABLE)(E: Sig.HASHABLE)(C: Sig.HASHABLE) = struct type vertex = V.t type edge = E.t type cluster = C.t module HV = Hashtbl.Make(V) module HE = Hashtbl.Make(E) module HC = Hashtbl.Make(C) (* Widget derived from Gnome Canvas. Supports zooming and scrolling *) class view ?delay_node ?delay_edge ?delay_cluster obj (model : (V.t, E.t, C.t) DGraphModel.abstract_model) = let delay f v = match f with None -> false | Some f -> f v in let (x1, y1), (x2, y2) = model#bounding_box in object(self) inherit GnoCanvas.canvas obj method model = model (* Hash tables from the model to the view items*) val node_hash : V.t view_item HV.t = HV.create 17 val edge_hash : E.t view_item HE.t = HE.create 17 val cluster_hash : C.t view_item HC.t = HC.create 7 (* Canvas items creation *) method private add_vertex vertex = try let layout = model#get_vertex_layout vertex in let item = view_node ~delay:(delay delay_node vertex) ~view:(self :> common_view) ~vertex ~layout () in HV.add node_hash vertex item with Not_found -> assert false method private add_edge edge = try let layout = model#get_edge_layout edge in let item = view_edge ~delay:(delay delay_edge edge) ~view:(self:>common_view) ~edge ~layout () in HE.add edge_hash edge item with Not_found -> assert false method private add_cluster cluster = let layout = model#get_cluster_layout cluster in let item = view_cluster ~delay:(delay delay_cluster cluster) ~view:(self :> common_view) ~cluster ~layout () in HC.add cluster_hash cluster item (* From model to view items *) method get_node n = try HV.find node_hash n with Not_found -> assert false method get_edge e = try HE.find edge_hash e with Not_found -> assert false method get_cluster c = try HC.find cluster_hash c with Not_found -> assert false (* Iterate on nodes and edges *) method iter_nodes f = HV.iter (fun _ v -> f v) node_hash method iter_edges_e f = HE.iter (fun _ e -> f e) edge_hash method iter_clusters f = HC.iter (fun _ c -> f c) cluster_hash method iter_edges f = model#iter_edges (fun v1 v2 -> f (self#get_node v1) (self#get_node v2)) (* Iterate on successors of a node *) method iter_succ f (node: 'v view_item) = let f' v = f (self#get_node v) in model#iter_succ f' node#item (* Iterate on predecessors of a node *) method iter_pred f (node: 'v view_item) = let f' v = f (self#get_node v) in model#iter_pred f' node#item method iter_succ_e f (node: 'v view_item) = let f' e = f (self#get_edge e) in model#iter_succ_e f' node#item method iter_pred_e f (node: 'v view_item) = let f' e = f (self#get_edge e) in model#iter_pred_e f' node#item (* Iterate on associated nodes *) method iter_associated_vertex f (node: 'v view_item) = let f' v = f (self#get_node v) in model#iter_associated_vertex f' node#item (* Membership functions *) method mem_edge (n1:'v view_item) (n2:'v view_item) = model#mem_edge n1#item n2#item method find_edge (n1:'v view_item) (n2:'v view_item) = self#get_edge (model#find_edge n1#item n2#item) method src (e: 'e view_item) = self#get_node (model#src e#item) method dst (e: 'e view_item) = self#get_node (model#dst e#item) (* Zoom factor *) val mutable zoom_f = 1. method zoom_factor = zoom_f val mutable zoom_padding = 0.1 method set_zoom_padding n = zoom_padding <- n method private set_zoom_f x = if x > 1e-10 then zoom_f <- x (* Zoom to a particular factor *) method zoom_to x = self#set_zoom_f x; self#set_pixels_per_unit zoom_f; self#iter_clusters (fun c -> c#zoom_text zoom_f); self#iter_nodes (fun n -> n#zoom_text zoom_f); self#iter_edges_e (fun e -> e#zoom_text zoom_f) method zoom_in () = self#zoom_to (zoom_f +. zoom_padding *. zoom_f) method zoom_out () = self#zoom_to (zoom_f -. zoom_padding *. zoom_f) method center_node (node:V.t view_item) = node#center () (* self#zoom_in ();*) method adapt_zoom () = let width = self#hadjustment#page_size in let height = self#vadjustment#page_size in let w_zoom = width /. abs_float (x1-.x2) in let h_zoom = height /. abs_float (y1-.y2) in self#zoom_to (min 1. (min w_zoom h_zoom)) (* EVENTS *) (* Zoom with the keys *) method private zoom_keys_ev ev = match GdkEvent.Key.keyval ev with | k when k = GdkKeysyms._KP_Subtract -> self#zoom_out (); true | k when k = GdkKeysyms._KP_Add -> self#zoom_in (); true | _ -> false (* Zoom with the mouse *) method private zoom_mouse_ev ev = match GdkEvent.Scroll.direction ev with | `UP -> self#zoom_in (); true | `DOWN -> self#zoom_out (); true | _ -> false method highlight ?color node = let h e = e#highlight ?color () in h node; self#iter_associated_vertex (fun v -> h v; self#iter_succ_e h v; self#iter_pred_e h v) node method dehighlight node = let h e = e#dehighlight () in h node; self#iter_associated_vertex (fun v -> h v; self#iter_succ_e h v; self#iter_pred_e h v) node method connect_highlighting_event () = let connect node = let callback = function | `MOTION_NOTIFY _ -> self#highlight node; false | `LEAVE_NOTIFY _ -> self#dehighlight node; false | _ -> false in node#connect_event ~callback in self#iter_nodes connect initializer (* Create and add items from the model vertices, edges and clusters *) model#iter_clusters self#add_cluster; model#iter_vertex self#add_vertex; model#iter_edges_e self#add_edge; (* Scroll region management *) ignore $ self#set_center_scroll_region true; ignore $ self#set_scroll_region ~x1 ~y1 ~x2 ~y2 ; (* Attach zoom events *) ignore $ self#event#connect#key_press self#zoom_keys_ev; ignore $ self#event#connect#scroll self#zoom_mouse_ev; end let view ?(aa=false) ?delay_node ?delay_edge ?delay_cluster ?border_width ?width ?height ?packing ?show (model:(vertex, edge, cluster) DGraphModel.abstract_model) = let canvas = GnoCanvas.canvas ~aa ?border_width ?width ?height ?show ?packing () in (* Grab focus to process keyboard input *) ignore $ canvas#event#connect#enter_notify (fun _ -> canvas#misc#grab_focus () ; false); let view = new view ?delay_node ?delay_edge ?delay_cluster (Gobject.unsafe_cast canvas#as_widget) model in view end ocamlgraph-1.8.3/dgraph/dGraphViewItem.ml0000644000175000017500000003652712133565071017274 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 DGraphModel open XDot open XDotDraw open Printf let red_color = 0xFF0000FFl let blue_color = 0x0000FFFFl let green_color = 0x00FF00FFl let black_color = 0x000000FFl let white_color = 0xFFFFFFFFl exception Cannot_convert_color of string let rgba_to_int32 col = (* Graphivz sometimes insert named colors by itself, we need to catch those. The list might be incomplete though; if it is, we might need to translate http://www.w3.org/TR/SVG/types.html#ColorKeywords *) match col with | "black" -> black_color | "white" -> white_color | "red" -> red_color | "green" -> green_color | "blue" -> blue_color | _ -> try match String.length col with | 7 -> Graph.Graphviz.color_to_color_with_transparency (int_of_string ("0x" ^ String.sub col 1 6)) | 9 -> Int32.of_string ("0x" ^ String.sub col 1 8) | _ -> failwith "" with Failure _ -> (* Can fail either in the failed match above, or in int*of_string *) raise (Cannot_convert_color (col^" but int32 expected")) let convert_fill_color col = `FILL_COLOR_RGBA (rgba_to_int32 col) let convert_outline_color col = `OUTLINE_COLOR_RGBA (rgba_to_int32 col) let ($) f x = f x (* Derived text class. *) class graph_text txt_obj ~size_points ~(props:GnomeCanvas.text_p list) = let props = `SIZE_POINTS size_points :: props in object (self) inherit GnoCanvas.text txt_obj as text val original_size = size_points val mutable props = props method set p = props <- p; text#set p method highlight ?(color=red_color,green_color) () = let primary, secondary = color in let color = ref primary in let rec hi_props = function | [] -> [] | `SIZE_POINTS p :: l -> let p = if p >= 12. then p else max 6. (p *. 1.5) in `SIZE_POINTS p :: hi_props l | `WEIGHT d :: l -> `WEIGHT (max 600 (int_of_float (float d *. 1.5))) :: hi_props l | `FILL_COLOR_RGBA c :: l -> if c = primary then color := secondary; hi_props l | p :: l -> p :: hi_props l in (* as inserted in head, `WEIGHT 600 will not apply if there is already a specified weight *) text#set (`FILL_COLOR_RGBA !color :: `WEIGHT 600 :: hi_props props) method dehighlight () = (* as inserted in head, properties will not apply if they are already specified *) text#set (`WEIGHT 400 :: `FILL_COLOR_RGBA black_color :: props) method resize (zoom_factor:float) = let rec change = function | [] -> [] | `SIZE_POINTS f :: l -> `SIZE_POINTS (zoom_factor*.original_size) :: change l | `FONT _ :: l -> change l | p :: l -> p :: change l in self#set (change props) initializer text#set props end (* Constructor copied and adapted from gnoCanvas.ml *) let graph_text ?x ?y ?text ?font ?anchor ~size_points ?(props=[]) p = let add_prop props f x = match x with None -> props | Some x -> f x :: props in let props = add_prop props (fun x -> `ANCHOR x) anchor in let props = add_prop props (fun x -> `FONT x) font in let props = add_prop props (fun x -> `TEXT x) text in let props = add_prop props (fun x -> `Y x) y in let props = add_prop props (fun x -> `X x) x in let i = GnomeCanvas.Item.new_item p#as_group GnomeCanvas.Types.text in new graph_text i ~size_points ~props (** FROM DOT LAYOUT TO VIEW ITEMS *) (* Shape properties. Used when initializing items *) let pen_color draw_st = convert_outline_color draw_st.XDotDraw.pen_color let fill_color draw_st = convert_fill_color draw_st.XDotDraw.fill_color (* Flattens an array of pair of coordinates into an array of coordinates *) let flatten_points pts = let convert i = let x, y = pts.(i / 2) in if i mod 2 = 0 then x else y in Array.init (2 * Array.length pts) convert (* SHAPE CONSTRUCTORS *) (* Ellipse, polygon and bpath canvas items do not share the same type in lablgtk2 They are kept in separate type constructors along with their initial properties. *) type shape_t = | SEllipse of GnoCanvas.ellipse | SPolygon of GnoCanvas.polygon | SBSpline of GnoCanvas.bpath let shape_item = function | SEllipse e -> e#as_item | SPolygon p -> p#as_item | SBSpline b -> b#as_item (* Shape properties (used by canvas items ellipse, polygon and bpath) *) type shape_p = [ `FILL_COLOR_RGBA of int32 | `OUTLINE_COLOR_RGBA of int32 | `WIDTH_UNITS of float | `DASH of float * float array ] let to_p = function | #shape_p as p -> p | _ -> invalid_arg "to_p" (* Property list completion *) (* In the initial property list of a shape, we need all the properties to hold a value, so that we can refer to them when unsetting property changes *) let complete_props props = let rec what_props (fill, width, outline, dash as acc) = function | [] -> acc | `FILL_COLOR_RGBA _ :: l -> what_props (true, width, outline, dash) l | `WIDTH_UNITS _ :: l -> what_props (fill, true, outline, dash) l | `OUTLINE_COLOR_RGBA _ :: l -> what_props (fill, width, true, dash) l | `DASH _ :: l -> what_props (fill, width, outline, true) l in let fill, width, outline, dash = what_props (false, false, false, false) props in let props = if fill then props else `FILL_COLOR_RGBA black_color :: props in let props = if width then props else `WIDTH_UNITS 1. :: props in let props = if outline then props else `OUTLINE_COLOR_RGBA black_color :: props in if dash then props else `DASH (0., [| |]) :: props (* Shape class (either a rect, an ellipse, a polygon or a path). Uses a properties queue to undo changes *) class shape ~fill shape init_props = object (self) inherit GnoCanvas.base_item (shape_item shape) method private set_props props = match shape with | SPolygon p -> p#set (props :> GnomeCanvas.polygon_p list) | SEllipse e -> e#set (props :> GnomeCanvas.re_p list) | SBSpline b -> b#set (props :> GnomeCanvas.bpath_p list) (* Properties queue *) val mutable props = [] method set p = props <- p; self#set_props p method highlight ?(color=red_color,green_color) () = let primary, secondary = color in let color = ref primary in let rec hi_props = function | [] -> [] | `WIDTH_UNITS u :: l -> `WIDTH_UNITS (max 3. (u *. 3.)) :: hi_props l | `FILL_COLOR_RGBA c :: l when fill -> if c = primary then color := secondary; hi_props l | `OUTLINE_COLOR_RGBA c :: l -> if c = primary then color := secondary; hi_props l | p :: l -> p :: hi_props l in (* as inserted in head, `WIDTH_UNITS 3. will not apply if there is already a specified weight *) let props = hi_props props in let props = if fill then `FILL_COLOR_RGBA !color :: props else props in self#set_props (`OUTLINE_COLOR_RGBA !color :: `WIDTH_UNITS 3. :: props) method dehighlight () = (* as inserted in head, `WIDTH_UNITS 1. will not apply if there is already a specified weight *) let props = if fill then `FILL_COLOR_RGBA black_color :: props else props in self#set_props (`WIDTH_UNITS 1. :: `OUTLINE_COLOR_RGBA black_color :: props) initializer self#set (complete_props init_props) end let get_props draw_st = let base_props = [ pen_color draw_st; fill_color draw_st ] in let fold_sty_attr props = function | Dashed -> `DASH (0., [|10.|]) :: props | Dotted -> `DASH (0., [|2.; 10.|]) :: props | _ -> props in List.fold_left fold_sty_attr base_props draw_st.style let ellipse ~fill draw_st group pos w h = let((x1,y1), (x2,y2)) = XDot.bounding_box pos w h in let props = get_props draw_st in let ellip = GnoCanvas.ellipse group ~x1 ~y1 ~x2 ~y2 ~props in new shape ~fill (SEllipse ellip) props let polygon ~fill draw_st group pts = let props = get_props draw_st in let points = flatten_points pts in let poly = GnoCanvas.polygon group ~points ~props in new shape ~fill (SPolygon poly) props let pathdef pts = if List.length pts mod 3 = 1 then (* Starting point *) let pathdef = GnomeCanvas.PathDef.new_path () in let (x0,y0) = List.hd pts in GnomeCanvas.PathDef.moveto pathdef x0 y0; (* Rest of the spline *) let rec curveto = function | (x1,y1) :: (x2,y2) :: (x3,y3) :: t -> GnomeCanvas.PathDef.curveto pathdef x1 y1 x2 y2 x3 y3; curveto t | _ -> () in curveto (List.tl pts); pathdef else (* failwith "Cannot build pathdef" *) assert false let bspline ~fill draw_st group pts = let path = pathdef (Array.fold_right (fun p acc -> p :: acc) pts []) in let props = get_props draw_st in let bpath = GnoCanvas.bpath group ~bpath:path ~props in new shape ~fill (SBSpline bpath) props let text draw_st group (x,y) align anchor label = let size_points, font = draw_st.XDotDraw.font in let props = [ convert_fill_color draw_st.XDotDraw.pen_color ] in let anchor = if anchor = -. 1. then `WEST else if anchor = 1.0 then `EAST else `CENTER in let size_points,height = XDotDraw.string_scale_size font size_points label in (* y-height/4 because the base line of the text is 1/4th from the bottom *) graph_text group ~x ~y:(y-.height/.4.) ~text:label ~props ~anchor ~font ~size_points class type common_view = object inherit GnoCanvas.canvas method zoom_factor : float method adapt_zoom : unit -> unit end (* ITEMS *) class type textshape = object method highlight: ?color:int32 * int32 -> unit -> unit method dehighlight: unit -> unit method hide: unit -> unit method show: unit -> unit method lower_to_bottom: unit -> unit method connect: < event : callback:(GnoCanvas.item_event -> bool) -> GtkSignal.id; after : GnoCanvas.item_signals; destroy : callback:(unit -> unit) -> GtkSignal.id; > end (* DGraph item Node and edge derive from this class Contains shapes and texts Can be : highlighted and/or selected ~pos : center of the container ~ops_list : list of list of operations ~hl_vip : highlight properties, set when method highlight is called *) class [ 'a ] view_item ~fill ~delay ~(view: common_view) ~pos ~ops_list ~(item:'a) = object (self) inherit GnoCanvas.group view#root#as_group val mutable hilighted = false val mutable texts = [] val mutable shapes = [] val mutable computed = not delay val mutable cached_events = [] method item = item method private cache : 'a. ('a -> unit) -> 'a -> unit = fun f x -> if computed then f x else cached_events <- (fun () -> f x) :: cached_events method zoom_text (zf:float) = self#cache (fun zf -> List.iter (fun t -> t#resize zf) texts) zf method private iter f = List.iter (fun t -> f (t :> textshape)) texts; List.iter f (shapes :> textshape list) method highlight ?color () = self#cache (fun () -> if not hilighted then begin hilighted <- true; self#iter (fun s -> s#highlight ?color ()); List.iter (fun t -> t#raise_to_top ()) texts; end) () method dehighlight () = self#cache (fun () -> if hilighted then begin hilighted <- false; self#iter (fun s -> s#dehighlight ()); end) () method hide () = self#cache (fun () -> self#iter (fun s -> s#hide ())) () method show () = self#cache (fun () -> self#iter (fun s -> s#show ())) () method connect_event ~callback = self#cache (fun () -> self#iter (fun s -> ignore (s#connect#event ~callback))) () method center () = self#cache(fun () -> let x, y = pos in let w = view#hadjustment#page_size /. view#zoom_factor in let h = view#vadjustment#page_size /. view#zoom_factor in let sx = x -. (w /. 2.) in let sy = y -. (h /. 2.) in let sx, sy = view#w2c ~wx:sx ~wy:sy in ignore $ view#scroll_to ~x:sx ~y:sy) () method lower_to_bottom () = self#cache (fun () -> self#iter (fun s -> s#lower_to_bottom ())) () (* Reads a list of list of operations Updates the shapes and texts lists *) method private read_operations () = let read_op draw_st = function (* Create shapes *) | XDotDraw.Filled_ellipse (pos, w, h) | XDotDraw.Unfilled_ellipse (pos, w, h) -> shapes <- ellipse ~fill draw_st self pos w h :: shapes | XDotDraw.Filled_polygon pts | XDotDraw.Unfilled_polygon pts -> shapes <- polygon ~fill draw_st self pts :: shapes | XDotDraw.Bspline pts | XDotDraw.Filled_bspline pts -> shapes <- bspline ~fill draw_st self pts :: shapes | XDotDraw.Text (pos, align, anchor, label) -> texts <- text draw_st self pos align anchor label :: texts | _ -> () in List.iter (draw_with read_op) ops_list; List.iter (fun t -> t#raise_to_top ()) texts; List.fold_right (* preserve order *) (fun f () -> f ()) cached_events () method compute () = if not computed then begin computed <- true; self#read_operations () end initializer if delay then let prio = Glib.int_of_priority `LOW in ignore (Glib.Idle.add ~prio (fun () -> self#compute (); false)) else self#read_operations () end let view_node ~delay ~view ~vertex ~layout () = let pos = layout.n_pos in let ops_list = [ layout.n_ldraw; layout.n_draw ] in new view_item ~fill:false ~delay ~view ~pos ~ops_list ~item:vertex let view_edge ~delay ~view ~edge ~layout () = let pos = 0., 0. in let ops_list = [ layout.e_draw; layout.e_ldraw; layout.e_tldraw; layout.e_hldraw; layout.e_tdraw; layout.e_hdraw ] in new view_item ~fill:true ~delay ~view ~pos ~ops_list ~item:edge let view_cluster ~delay ~view ~cluster ~layout () = let pos = layout.c_pos in let ops_list = [ layout.c_ldraw; layout.c_draw ] in let view = new view_item ~fill:false ~delay ~pos ~ops_list ~view ~item:cluster in view#lower_to_bottom (); view ocamlgraph-1.8.3/dgraph/xDot.mli0000644000175000017500000001252412133565071015473 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (** Reads layout information from xdot ASTs *) open Graph (** Simple layout types *) (** 2D coordinates *) type pos = float * float (** upper-left and bottom-right corners *) type bounding_box = pos * pos (** Layout informations are parsed from xdot files (dot files with graphviz layout). Each node or edge layout thus contains several lists of drawing operations. See http://www.graphviz.org/doc/info/output.html#d:xdot to understand the details of the layout informations. *) (** Each node has at least a position and a bounding box. *) type node_layout = { n_name : string; (** Dot label *) n_pos : pos; (** Center position *) n_bbox : bounding_box; (** Bounding box *) n_draw : XDotDraw.operation list; (** Shape drawing *) n_ldraw : XDotDraw.operation list; (** Label drawing *) } type cluster_layout = { c_pos : pos; c_bbox : bounding_box; c_draw : XDotDraw.operation list; c_ldraw : XDotDraw.operation list; } type edge_layout = { e_draw : XDotDraw.operation list; (** Shapes and curves *) e_ldraw : XDotDraw.operation list; (** Label drawing *) e_hdraw : XDotDraw.operation list; (** Head arrowhead drawing *) e_tdraw : XDotDraw.operation list; (** Tail arrowhead drawing *) e_hldraw : XDotDraw.operation list; (** Head label drawing *) e_tldraw : XDotDraw.operation list; (** Tail label drawing *) } (** Creates a node layout *) val mk_node_layout : name:string -> pos:pos -> bbox:bounding_box -> draw:XDotDraw.operation list -> ldraw:XDotDraw.operation list -> node_layout (** Creates a cluster layout *) val mk_cluster_layout : pos:pos -> bbox:bounding_box -> draw:XDotDraw.operation list -> ldraw:XDotDraw.operation list -> cluster_layout (** Creates an edge layout *) val mk_edge_layout : draw:XDotDraw.operation list -> ldraw:XDotDraw.operation list -> hdraw:XDotDraw.operation list -> tdraw:XDotDraw.operation list -> hldraw:XDotDraw.operation list -> tldraw:XDotDraw.operation list -> edge_layout (** Parsing and reading XDot *) exception ParseError of string (** Instantiates a module which creates graph layouts from xdot files *) module Make(G : Graph.Graphviz.GraphWithDotAttrs) : sig module HV: Hashtbl.S with type key = G.V.t module HE: Hashtbl.S with type key = G.E.t (** Main layout type *) type graph_layout = { vertex_layouts : node_layout HV.t; edge_layouts : edge_layout HE.t; cluster_layouts : (string, cluster_layout) Hashtbl.t; bbox : bounding_box } exception DotError of string (** Extracts a layout of an xdot file *) val layout_of_xdot: xdot_file:string -> G.t -> graph_layout (** Using the dot file and graphviz, create an xdot and extracts its layout. *) val layout_of_dot: ?cmd:string -> dot_file:string -> G.t -> graph_layout end (** Converts and reads various layout informations *) (** [bounding_box pos w h] converts a bounding box of center [pos], width [w] and height [h] from a Dot file to a pair of corners (lower left and upper right) in the world coordinate system. @param pos position of the center of the node @param w width of the node @param h height of the node *) val bounding_box : (float * float) -> float -> float -> bounding_box val read_bounding_box : string -> bounding_box (** Reads xdot layouts from the dot ast *) val read_node_layout : Dot_ast.node_id -> Dot_ast.attr list -> node_layout val read_edge_layout : Dot_ast.attr list -> edge_layout val read_cluster_layout : Dot_ast.attr list -> cluster_layout ocamlgraph-1.8.3/dgraph/dGraphViewer.ml0000644000175000017500000001233212133565071016770 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 open Dgraph open Printf let ($) f x = f x let get_some = function Some t -> t | None -> assert false let debug = false module Content = DGraphContainer.Dot type state = { mutable file: string option; mutable window: GWindow.window; mutable content: (GPack.table * Content.view_container) option } let init_state () = let window = GWindow.window ~width:1280 ~height:1024 ~title:"Graph Widget" ~allow_shrink:true ~allow_grow:true () in let status = GMisc.label ~markup:"" () in status#set_use_markup true; let file = ref None in for i=1 to Array.length Sys.argv - 1 do file := Some Sys.argv.(i) done; { file = !file; window = window; content = None } (* Top menu *) let menu_desc = "\ \ \ \ \ \ \ " let update_state state ~packing = (match state.content with None -> () | Some (t, _) -> t#destroy ()); try let _, view as content = match state.file with | Some file -> if debug then printf "Building Model...\n"; state.file <- Some file; Content.from_dot_with_commands ~packing file | None -> raise Not_found in state.content <- Some content; state.window#show (); view#adapt_zoom () with Not_found -> if debug then printf "No model\n" let all_files () = let f = GFile.filter ~name:"All" () in f#add_pattern "*" ; f let open_file state ~packing () = let dialog = GWindow.file_chooser_dialog ~action:`OPEN ~title:"Open File" ~parent:state.window () in dialog#add_button_stock `CANCEL `CANCEL ; dialog#add_select_button_stock `OPEN `OPEN ; dialog#add_filter (all_files ()) ; match dialog#run () with | `OPEN -> state.file <- dialog#filename; dialog#destroy (); update_state state ~packing | `DELETE_EVENT | `CANCEL -> dialog#destroy () let create_menu state ~packing = let ui_m = GAction.ui_manager () in let actions = GAction.action_group ~name:"Actions" () in GAction.add_actions actions [ GAction.add_action "FileMenu" ~label:"File" ; GAction.add_action "Open" ~label:"Open" ~accel:"o" ~stock:`OPEN ~callback:(fun _ -> open_file state ~packing ()); GAction.add_action "Zoom fit" ~label:"Zoom fit" ~accel:"t" ~stock:`ZOOM_FIT ~callback:(fun _ -> match state.content with |None -> () |Some (_,v) -> v#adapt_zoom ()); GAction.add_action "Quit" ~label:"Quit" ~accel:"q" ~stock:`QUIT ~callback:(fun _ -> GMain.Main.quit ()); ]; ui_m#insert_action_group actions 0 ; ignore $ ui_m#add_ui_from_string menu_desc; ui_m (* Main loop *) let main () = (* GUI *) let state = init_state () in let vbox = GPack.vbox ~border_width:4 ~spacing:4 ~packing:state.window#add () in let packing = vbox#pack ~expand:true ~fill:true in (* Menu *) let ui_m = create_menu state ~packing in state.window#add_accel_group ui_m#get_accel_group ; vbox#pack ~expand:false (ui_m#get_widget "/MenuBar"); ignore $ state.window#connect#destroy ~callback:GMain.Main.quit; if debug then printf "GUI built, time: %f\n" (Sys.time ()); update_state state ~packing; state.window#show (); GMain.Main.main () (* [JS 2009/09/21] Printexc.print prevents to use ocaml < 3.11 *) let _ = (*Printexc.print*) main () ocamlgraph-1.8.3/dgraph/dGraphTreeModel.ml0000755000175000017500000001670712133565071017424 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 S = sig module Tree: Graphviz.GraphWithDotAttrs module TreeManipulation : sig type t val get_structure : t -> Tree.t val get_tree_vertices : Tree.V.label -> t -> Tree.V.t list val get_graph_vertex : Tree.V.t -> t -> Tree.V.label val is_ghost_node : Tree.V.t -> t -> bool val is_ghost_edge : Tree.E.t -> t -> bool end type cluster = string class tree_model : XDot.Make(Tree).graph_layout -> TreeManipulation.t -> [Tree.V.t, Tree.E.t, cluster] DGraphModel.abstract_model val tree : unit -> TreeManipulation.t end module Build (G: Sig.G) (T: Graphviz.GraphWithDotAttrs with type V.label = G.V.t) (TM: DGraphSubTree.S with type Tree.t = T.t and type Tree.V.t = T.V.t and type Tree.E.t = T.E.t) = struct module TreeManipulation = TM type cluster = string module X = XDot.Make(T) class tree_model layout tree : [ T.V.t, T.E.t, cluster ] DGraphModel.abstract_model = let tree_structure = TM.get_structure tree in object (* Iterators *) method iter_edges f = T.iter_edges (fun v1 v2 -> if not (TM.is_ghost_node v1 tree && TM.is_ghost_node v2 tree) then f v1 v2) tree_structure method iter_edges_e f = T.iter_edges_e (fun e -> if not (TM.is_ghost_edge e tree) then f e) tree_structure method iter_pred f v = T.iter_pred (fun v -> if not (TM.is_ghost_node v tree) then f v) tree_structure v method iter_pred_e f v = T.iter_pred_e (fun e -> if not (TM.is_ghost_edge e tree) then f e) tree_structure v method iter_succ f = T.iter_succ (fun v -> if not (TM.is_ghost_node v tree) then f v) tree_structure method iter_succ_e f = T.iter_succ_e (fun e -> if not (TM.is_ghost_edge e tree) then f e) tree_structure method iter_vertex f = T.iter_vertex (fun v -> if not (TM.is_ghost_node v tree) then f v) tree_structure method iter_associated_vertex f v = let origin_vertex = TM.get_graph_vertex v tree in List.iter (fun v -> if not (TM.is_ghost_node v tree) then f v) (TM.get_tree_vertices origin_vertex tree) method iter_clusters f = Hashtbl.iter (fun k _ -> f k) layout.X.cluster_layouts (* Membership functions *) method find_edge = try T.find_edge tree_structure with Not_found -> assert false method mem_edge = T.mem_edge tree_structure method mem_edge_e = T.mem_edge_e tree_structure method mem_vertex = T.mem_vertex tree_structure method src = T.E.src method dst = T.E.dst (* Layout *) method bounding_box = layout.X.bbox method get_vertex_layout v = try X.HV.find layout.X.vertex_layouts v with Not_found -> assert false method get_edge_layout e = try X.HE.find layout.X.edge_layouts e with Not_found -> assert false method get_cluster_layout c = try Hashtbl.find layout.X.cluster_layouts c with Not_found -> assert false end end module SubTreeMake(G: Graphviz.GraphWithDotAttrs) = struct module T = Imperative.Digraph.Abstract(G.V) module TM = DGraphSubTree.Make(G)(T) let tree_ref : TM.t option ref = ref None let tree () = match !tree_ref with None -> assert false | Some t -> t let graph_ref: G.t option ref = ref None let graph () = match !graph_ref with None -> assert false | Some g -> g module Tree = struct include T let graph_attributes _ = G.graph_attributes (graph ()) let default_vertex_attributes _ = G.default_vertex_attributes (graph ()) let default_edge_attributes _ = G.default_edge_attributes (graph ()) let cpt = ref 0 let name_table = Hashtbl.create 97 let vertex_name v = try Hashtbl.find name_table v with Not_found -> incr cpt; Hashtbl.add name_table v (string_of_int !cpt); string_of_int !cpt let vertex_attributes v = let t = tree () in if TM.is_ghost_node v t then [ `Style `Invis ] else G.vertex_attributes (TM.get_graph_vertex v t) let edge_attributes e = let t = tree () in if TM.is_ghost_node (T.E.src e) t || TM.is_ghost_node (T.E.dst e) t then [ `Style `Dashed; `Dir `None ] else G.edge_attributes (G.find_edge (graph ()) (TM.get_graph_vertex (T.E.src e) t) (TM.get_graph_vertex (T.E.dst e) t)) let get_subgraph v = let t = tree () in if TM.is_ghost_node v t then None else G.get_subgraph (TM.get_graph_vertex v t) end include Build(G)(Tree)(TM) module TreeLayout = DGraphTreeLayout.Make (Tree) (struct let is_ghost_node v = TM.is_ghost_node v (tree ()) end) let from_graph ?(depth_forward=2) ?(depth_backward=2) context g v = (* Generate subtree *) let t = TM.make g v depth_forward depth_backward in tree_ref := Some t; graph_ref := Some g; let layout = TreeLayout.from_tree context (TM.get_structure t) (TM.get_root t) in new tree_model layout t end module SubTreeDotModelMake = struct module T = Imperative.Digraph.Abstract(DGraphModel.DotG.V) module TM = DGraphSubTree.Make_from_dot_model(T) let tree_ref : TM.t option ref = ref None let tree () = match !tree_ref with None -> assert false | Some t -> t module TreeLayout = DGraphTreeLayout.MakeFromDotModel (T) (struct let is_ghost_node v = TM.is_ghost_node v (tree ()) end) include TreeLayout include Build(DGraphModel.DotG)(Tree)(TM) let from_model ?(depth_forward=2) ?(depth_backward=2) model v = let t = TM.make model v depth_forward depth_backward in tree_ref := Some t; let tree_structure = TM.get_structure t in let layout = from_model tree_structure (TM.get_root t) model in new tree_model layout t end ocamlgraph-1.8.3/dgraph/dGraphTreeModel.mli0000755000175000017500000000574012133565071017570 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 S = sig module Tree: Graph.Graphviz.GraphWithDotAttrs module TreeManipulation : sig type t val get_structure : t -> Tree.t val get_tree_vertices : Tree.V.label -> t -> Tree.V.t list val get_graph_vertex : Tree.V.t -> t -> Tree.V.label val is_ghost_node : Tree.V.t -> t -> bool val is_ghost_edge : Tree.E.t -> t -> bool end type cluster = string class tree_model : XDot.Make(Tree).graph_layout -> TreeManipulation.t -> [ Tree.V.t, Tree.E.t, cluster ] DGraphModel.abstract_model val tree : unit -> TreeManipulation.t end (** This functor creates a model centered on a vertex from a graph *) module SubTreeMake(G : Graph.Graphviz.GraphWithDotAttrs) : sig include S with type Tree.V.label = G.V.t val from_graph : ?depth_forward:int -> ?depth_backward:int -> [> `widget] Gtk.obj -> G.t -> G.V.t -> tree_model end (** Creates a model centered on a vertex from a dot model *) module SubTreeDotModelMake : sig include S with type Tree.V.label = DGraphModel.DotG.V.t val from_model : ?depth_forward:int -> ?depth_backward:int -> DGraphModel.dotg_model -> DGraphModel.DotG.V.t -> tree_model end ocamlgraph-1.8.3/dgraph/dGraphSubTree.ml0000755000175000017500000002311212133565071017101 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) ocamlgraph-1.8.3/dgraph/dGraphTreeLayout.mli0000755000175000017500000000472012133565071020002 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 type cluster = string module Make (Tree: Graphviz.GraphWithDotAttrs) (TreeManipulation: sig val is_ghost_node: Tree.V.t -> bool end): sig val from_tree: [> `widget] Gtk.obj -> Tree.t -> Tree.V.t -> XDot.Make(Tree).graph_layout end module MakeFromDotModel (Tree : Sig.G with type V.label = DGraphModel.DotG.V.t and type E.label = unit) (TreeManipulation: sig val is_ghost_node: Tree.V.t -> bool end): sig module Tree: Graphviz.GraphWithDotAttrs with module V = Tree.V and module E = Tree.E and type t = Tree.t val from_model: Tree.t -> Tree.V.t -> DGraphModel.dotg_model -> XDot.Make(Tree).graph_layout end ocamlgraph-1.8.3/dgraph/xDot.ml0000644000175000017500000003156112133565071015324 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (** Reading XDot files *) open Graph open GnomeCanvas open Dot_ast open Printf (* Layout types *) (* This file is responsible for converting the coordinates from dot coordinates to GnomeCanvas world coordinates. The matrix transformation to apply is: (1 0) (0 -1) Care must be taken to exchange max and min values on the y axis. Outside this module all coordinates are assumed to be in canvas world coordinates. *) type pos = float * float (* coordinates *) type bounding_box = pos * pos (* bounding box *) type node_layout = { n_name : string; n_pos : pos; n_bbox : bounding_box; n_draw : XDotDraw.operation list; n_ldraw : XDotDraw.operation list; } type cluster_layout = { c_pos : pos; c_bbox : bounding_box; c_draw : XDotDraw.operation list; c_ldraw : XDotDraw.operation list; } type edge_layout = { e_draw : XDotDraw.operation list; e_ldraw : XDotDraw.operation list; e_hdraw : XDotDraw.operation list; e_tdraw : XDotDraw.operation list; e_hldraw : XDotDraw.operation list; e_tldraw : XDotDraw.operation list; } let mk_node_layout ~name ~pos ~bbox ~draw ~ldraw = { n_name = name; n_pos = pos; n_bbox = bbox; n_draw = draw; n_ldraw = ldraw } let mk_cluster_layout ~pos ~bbox ~draw ~ldraw = { c_pos = pos; c_bbox = bbox; c_draw = draw; c_ldraw = ldraw } let mk_edge_layout ~draw ~ldraw ~hdraw ~tdraw ~hldraw ~tldraw = { e_draw = draw; e_ldraw = ldraw; e_hdraw = hdraw; e_tdraw = tdraw; e_hldraw = hldraw; e_tldraw = tldraw; } exception ParseError of string (* MISCELLANEOUS FUNCTIONS *) let rec take n = function | [] -> [] | l when n = 0 -> [] | h::t -> h::(take (n-1) t) let suffix s i = try String.sub s i ((String.length s)-i) with Invalid_argument("String.sub") -> "" let rec group_tuples = function | [] -> [] | [x] -> [] | h1::h2::t -> (h1, h2) :: group_tuples t (** Splits a string with a separator returns a list of strings *) let split c s = let rec split_from n = try let p = String.index_from s n c in (String.sub s n (p-n)) :: (split_from (p+1)) with Not_found -> [ suffix s n ] in if s="" then [] else split_from 0 let read_pos s = Scanf.sscanf s "%f,%f" (fun x y -> x, -.y) let bounding_box (x, y) w h = let lower_left = x -. w , y -. h in let upper_right = x+.w,y+.h in lower_left,upper_right let get_dot_string = function | Dot_ast.String s -> s | Dot_ast.Ident s -> s | Dot_ast.Number s -> s | Dot_ast.Html s -> s (* READING VERTEX LAYOUTS *) let read_node_label = function | Dot_ast.Ident s | Dot_ast.Number s | Dot_ast.String s | Dot_ast.Html s -> s let read_points c s = let s' = suffix s (String.index s c) in let tokens = List.filter (fun s -> s <> "") (List.tl (split ' ' s')) in try match tokens with | [] -> None | n::t -> let n = int_of_string n in let floats = List.map float_of_string (take (n*2) t) in let points = group_tuples floats in Some points with Failure "int_of_string" -> None (** Finds the attributes [pos], [width] and [height] of a node in the attribute list *) let read_common_layout mk_layout attr_list = (* Iter on the attributes *) (* shape, position, width, height, color, filled *) let fold ((p,w,h, draw,ldraw) as attrs) = function | (Dot_ast.Ident "pos"), Some (Dot_ast.String s) -> (Some s), w, h, draw,ldraw | (Dot_ast.Ident "width"), Some (Dot_ast.String s) -> p, (Some s), h, draw,ldraw | (Dot_ast.Ident "height"), Some (Dot_ast.String s) -> p, w, (Some s), draw,ldraw | (Dot_ast.Ident "_draw_"), Some (Dot_ast.String draw) -> p,w,h, XDotDraw.parse draw, ldraw | (Dot_ast.Ident "_ldraw_"), Some (Dot_ast.String ldraw) -> p,w,h, draw, XDotDraw.parse ldraw | _ -> attrs in let fold_attr acc attr_list = List.fold_left fold acc attr_list in let attrs = List.fold_left fold_attr (None, None, None, [], []) attr_list in (* Check if we have position, width and height *) match attrs with | Some pos, Some w, Some h, draw,ldraw-> let pos = read_pos pos in let coord = bounding_box pos (float_of_string w) (-.(float_of_string h)) in (* Return the node model *) mk_layout ~pos ~bbox:coord ~draw ~ldraw | _,_,_, draw, ldraw -> let pos = (0.,0.) in let bbox = (0.,0.),(0.,0.) in mk_layout ~pos ~bbox ~draw ~ldraw let read_node_layout (id,_) attrs = let f = read_common_layout (fun ~pos ~bbox ~draw ~ldraw -> mk_node_layout ~pos ~bbox ~draw ~ldraw) attrs in f ~name:(get_dot_string id) let read_cluster_layout = read_common_layout mk_cluster_layout (* READING EDGE LAYOUTS *) (** Reads the spline control points of a curve in an xdot file example : "c 5 -black B 4 65 296 65 288 65 279 65 270 " *) (* The edge drawing operations are in the following attributes : _hdraw_ Head arrowhead _tdraw_ Tail arrowhead _hldraw_ Head label _tldraw_ Tail label *) (** Gets the layout of an edge out of the dot ast *) let read_edge_layout attr_list = let draw = ref [] in let ldraw = ref [] in let hdraw = ref [] in let tdraw = ref [] in let hldraw = ref [] in let tldraw = ref [] in let fill_draw_ops = function | (Dot_ast.Ident "_draw_"), Some (Dot_ast.String s) -> draw := XDotDraw.parse s | (Dot_ast.Ident "_ldraw_"), Some (Dot_ast.String s) -> ldraw := XDotDraw.parse s | (Dot_ast.Ident "_hdraw_"), Some (Dot_ast.String s) -> hdraw := XDotDraw.parse s | (Dot_ast.Ident "_tdraw_"), Some (Dot_ast.String s) -> tdraw := XDotDraw.parse s | (Dot_ast.Ident "_hldraw_"), Some (Dot_ast.String s) -> hldraw := XDotDraw.parse s | (Dot_ast.Ident "_tldraw_"), Some (Dot_ast.String s) -> tldraw := XDotDraw.parse s | _ -> () in List.iter (List.iter fill_draw_ops) attr_list; let draw, ldraw = !draw, !ldraw in let hdraw, tdraw, hldraw, tldraw = !hdraw, !tdraw, !hldraw, !tldraw in mk_edge_layout ~draw ~ldraw ~hdraw ~tdraw ~hldraw ~tldraw (* Computes the bounding box *) let read_bounding_box str = let x1,y1,x2,y2 = Scanf.sscanf str "%f,%f,%f,%f" (fun a b c d -> a,b,c,d) in (* Convert coordinates to the world canvas coordinates *) let lower_left = (x1, -.y2) and upper_right = x2, -.y1 in lower_left,upper_right module Make(G : Graph.Graphviz.GraphWithDotAttrs) = struct module HV = Hashtbl.Make(G.V) module HE = Hashtbl.Make (struct type t = G.E.t let equal x y = G.E.compare x y = 0 let hash = Hashtbl.hash end) module HT = Hashtbl.Make (Util.HTProduct (Util.HTProduct(G.V)(G.V)) (struct type t = string let equal = (=) let hash = Hashtbl.hash end)) type graph_layout = { vertex_layouts : node_layout HV.t; edge_layouts : edge_layout HE.t; cluster_layouts : (string, cluster_layout) Hashtbl.t; bbox : bounding_box } exception Found of string let get_edge_comment e = let al = G.edge_attributes e in try List.iter (function `Comment c -> raise (Found c) | _ -> ()) al; None with Found c -> Some c let get_dot_comment (al : Dot_ast.attr list) = try List.iter (List.iter (function | Ident "comment", Some c -> raise (Found (get_dot_string c)) | _ -> ())) al; "" with Found c -> c let strip_quotes = function | "" -> "" | s -> let len = String.length s in if s.[0] = '"' && s.[len -1] = '"' then String.sub s 1 (len - 2) else s (* Parses the graph attribute named id, and converts it with conv *) let parse_graph_attr id conv stmts = let read_attr = function | Ident ident , Some (String attr) when ident = id -> raise (Found attr) | _ -> () in let read_stmt = function | Attr_graph attrs -> List.iter (List.iter read_attr) attrs | _ -> () in try List.iter read_stmt stmts; failwith ("Could not find the graph attribute named " ^ id) with Found attr -> conv attr let parse_bounding_box = parse_graph_attr "bb" read_bounding_box (*let parse_bgcolor = parse_graph_attr "bgcolor" XDotDraw.normalize_color*) let parse_layouts g stmts = let name_to_vertex = Hashtbl.create 97 in let vertices_comment_to_edge = HT.create 97 in let vertex_layouts = HV.create 97 in let edge_layouts = HE.create 97 in let cluster_layouts = Hashtbl.create 97 in G.iter_vertex (fun v -> let name = strip_quotes (G.vertex_name v) in Hashtbl.add name_to_vertex name v) g; G.iter_edges_e (fun e -> let comment = match get_edge_comment e with | Some c -> strip_quotes c | None -> "" in let vs = G.E.src e, G.E.dst e in HT.add vertices_comment_to_edge (vs, comment) e) g; let find_vertex (id,_) = let name = get_dot_string id in try Hashtbl.find name_to_vertex name with Not_found -> failwith ("Could not find vertex named " ^ name) in let find_edge v v' comment = try HT.find vertices_comment_to_edge ((v, v'), comment) with Not_found -> (* Printf.printf "Did not find edge from %s to %s with comment %s\n" (G.vertex_name v) (G.vertex_name v') (match comment with Some c -> c | None -> "none");*) raise Not_found in let rec collect_layouts cluster stmt = try match stmt with | Node_stmt (node_id, al) -> let v = find_vertex node_id in HV.add vertex_layouts v (read_node_layout node_id al) | Edge_stmt (NodeId id, [NodeId id'], al) -> let v = find_vertex id in let v' = find_vertex id' in let comment = get_dot_comment al in let e = find_edge v v' comment in HE.add edge_layouts e (read_edge_layout al) | Subgraph (SubgraphDef (Some id, stmts)) -> let cluster = get_dot_string id in List.iter (collect_layouts (Some cluster)) stmts (* Anonymous subgraph *) | Subgraph (SubgraphDef (_, stmts)) -> List.iter (collect_layouts cluster) stmts | Attr_graph al -> (match cluster with | Some c -> Hashtbl.add cluster_layouts c (read_cluster_layout al) | None -> ()) | _ -> () with Not_found -> () in List.iter (collect_layouts None) stmts; vertex_layouts, edge_layouts, cluster_layouts let parse g dot_ast = let v_layouts, e_layouts, c_layouts = parse_layouts g dot_ast.stmts in let bbox = parse_bounding_box dot_ast.stmts in (* let bgcolor = parse_bgcolor dot_ast.stmts in*) { vertex_layouts = v_layouts; edge_layouts = e_layouts; cluster_layouts = c_layouts; bbox = bbox } exception DotError of string let layout_of_xdot ~xdot_file g = let dot_ast = Dot.parse_dot_ast xdot_file in parse g dot_ast let layout_of_dot ?(cmd="dot") ~dot_file g = let base_name = try Filename.basename (Filename.chop_extension dot_file) with Invalid_argument _ -> dot_file in let xdot_file = Filename.temp_file base_name ".xdot" in (* Run graphviz to get xdot file *) let dot_cmd = sprintf "%s -Txdot %s > %s" cmd dot_file xdot_file in match Sys.command dot_cmd with | 0 -> let l = layout_of_xdot ~xdot_file g in Sys.remove xdot_file; l | _ -> Sys.remove xdot_file; raise (DotError "Error during dot execution") end ocamlgraph-1.8.3/dgraph/xDotDraw.ml0000644000175000017500000003003312133565071016133 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (* This module parses _draw_ attributes in XDot *) type pos = float * float type width = float type height = float type size = int type align = Left | Center | Right type style_attr = | Filled | Invisible | Diagonals | Rounded | Dashed | Dotted | Solid | Bold | StyleString of string (* Drawing operations *) type operation = | Filled_ellipse of pos * width * height | Unfilled_ellipse of pos * width * height | Filled_polygon of pos array | Unfilled_polygon of pos array | Polyline of pos array | Bspline of pos array | Filled_bspline of pos array | Text of pos * align * width * string | Fill_color of string | Pen_color of string | Font of float * string | Style of style_attr list (* Drawing state *) type draw_state = { mutable fill_color : string; mutable pen_color : string; mutable font : float * string; mutable style : style_attr list } let copy_draw_st ds = { ds with fill_color = ds.fill_color } let default_draw_state () = { fill_color = "#FFFFFF"; pen_color = "#000000"; font = 0., ""; style = [] } let set_fill_color st c = st.fill_color <- c let set_pen_color st c = st.pen_color <- c let set_font st c = st.font <- c let set_style st s = st.style <- s (* STRING OPERATIONS *) let suffix s i = try String.sub s i ((String.length s)-i) with Invalid_argument("String.sub") -> "" (** Splits a string with a separator returns a list of strings *) let split c s = let rec split_from n = try let p = String.index_from s n c in (String.sub s n (p-n)) :: (split_from (p+1)) with Not_found -> [ suffix s n ] in if s="" then [] else split_from 0 ;; let string_scale_size font size s = let context = Gdk.Screen.get_pango_context () in let font_description = Pango.Font.from_string font in Pango.Font.modify font_description ~size:(int_of_float (size *. (float Pango.scale))) (); Pango.Context.set_font_description context font_description; let layout = Pango.Layout.create context in Pango.Layout.set_text layout s; let width, height = Pango.Layout.get_pixel_size layout in let width = float width in let linear_width = size*. (float (String.length s)) in size*.width/.linear_width, float height (* HSV TO RGB CONVERSION *) (* If color string in hsv format, convert to hex *) let normalize_color s = try let h,s,v = Scanf.sscanf s "%f %f %f"(fun a b c -> (a,b,c)) in let h' = 360. *. h /. 60. in let hi = truncate h' mod 6 in let f = h' -. floor h' in let p = v *. (1. -. s) in let q = v *. (1. -. f*.s) in let t = v *. (1. -. (1. -. f) *. s) in let r,g,b = match hi with | 0 -> v,t,p | 1 -> q,v,p | 2 -> p,v,t | 3 -> p,q,v | 4 -> t,p,v | 5 -> v,p,q | _ -> 1.,1.,1. in let to_hex x = Printf.sprintf "%02X" (truncate (x *. 255.)) in "#" ^ to_hex r ^ to_hex g ^ to_hex b with Scanf.Scan_failure _ -> s (* PARSE STATE *) type state = { mutable operations : operation list; mutable cur : int; str : string; } exception ParseError of string exception NoOperationId let mk_state s = { operations = []; cur = 0; str = s } let char state = state.str.[state.cur] let incr state = state.cur <- state.cur + 1 (* No more characters *) let over state = state.cur >= String.length state.str let add_operation i state = state.operations <- i :: state.operations (* GET TOKENS *) let get_n n st = let s = String.sub st.str st.cur n in st.cur <- st.cur + n; s let is_space = function | ' ' | '\t' | '\n' -> true | _ -> false let is_token = function | "E" | "e" | "P" | "p" | "L" | "B" | "b" | "T" | "C" | "c" | "F" | "S" -> true | _ -> false let skip_spaces state = let rec loop () = if not (over state) then if is_space (char state) then begin incr state; loop () end in loop () (* Gets a word *) let get_word state = skip_spaces state; let start = state.cur in let rec get' () = if over state then if start = String.length state.str then None else Some (String.sub state.str start (state.cur - start)) else if not (is_space (char state)) then begin incr state; get' () end else Some (String.sub state.str start (state.cur - start)) in get' () (* Gets a rendering or attribute operation *) let rec get_op_id state = let tok = get_word state in match tok with | None -> raise NoOperationId | Some tok' -> if is_token tok' then tok' else raise NoOperationId let filter_int s = let is_int = function | '0' | '1' .. '9' -> true | _ -> false in let buf = Buffer.create 30 in String.iter (fun c -> if is_int c then Buffer.add_char buf c) s; Buffer.contents buf let rec get_int state = match get_word state with | Some w -> begin (*let w' = filter_int w in*) try int_of_string w with Failure "int_of_string" -> raise (ParseError "Cannot parse int") end | None -> raise (ParseError "Cannot parse int") let rec get_float state = match get_word state with | Some w -> begin try float_of_string w with Failure "float_of_string" -> raise (ParseError "Cannot parse float") end | None -> raise (ParseError "Cannot parse float") let rec get_pos state = try let x0 = get_float state in let y0 = get_float state in (x0, y0) with ParseError _ -> raise (ParseError "Cannot parse point in position") (* PARSING *) let get_anchor state = let i = get_int state in match i with | -1 -> Left | 0 -> Center | 1 -> Right | _ -> raise (ParseError "Cannot parse anchor") let parse_bytes st = skip_spaces st; let n = get_int st in skip_spaces st; if char st <> '-' then raise (ParseError "Cannot parse bytes") else begin incr st; get_n n st end let parse_ellipse constr state = (* pos width height *) let pos = get_pos state in let w = get_float state in let h = get_float state in constr (pos, w, h) let invert_y_pos (x,y) = (x,-.y) let parse_filled_ellipse = parse_ellipse (fun (p,w,h) -> Filled_ellipse (invert_y_pos p,w,h)) let parse_unfilled_ellipse = parse_ellipse (fun (p,w,h) -> Unfilled_ellipse (invert_y_pos p,w,h)) let parse_points state = let n = get_int state in Array.init n (fun _ -> invert_y_pos (get_pos state)) let parse_filled_polygon state = Filled_polygon (parse_points state) let parse_unfilled_polygon state = Unfilled_polygon (parse_points state) let parse_polyline state = Polyline (parse_points state) let parse_bspline state = Bspline (parse_points state) let parse_filled_bspline state = Filled_bspline (parse_points state) let parse_text state = let pos = invert_y_pos (get_pos state) in let anchor = get_anchor state in let width = get_float state in let str = parse_bytes state in Text (pos, anchor, width, str) let parse_fill_color state = Fill_color (normalize_color (parse_bytes state)) let parse_pen_color state = Pen_color (normalize_color (parse_bytes state)) let parse_font state = let size = get_float state in let font = parse_bytes state in Font (size, font) let parse_style state = let read = function | "filled" -> Filled | "invisible" -> Invisible | "diagonals" -> Diagonals | "rounded" -> Rounded | "dashed" -> Dashed | "dotted" -> Dotted | "solid" -> Solid | "bold" -> Bold | s -> StyleString s in let str = parse_bytes state in Style (List.map read (split ',' str)) let parse_operation state = let operation () = match get_op_id state with | "E" -> parse_filled_ellipse state | "e" -> parse_unfilled_ellipse state | "P" -> parse_filled_polygon state | "p" -> parse_unfilled_polygon state | "L" -> parse_polyline state | "B" -> parse_bspline state | "b" -> parse_filled_bspline state | "T" -> parse_text state | "C" -> parse_fill_color state | "c" -> parse_pen_color state | "F" -> parse_font state | "S" -> parse_style state | _ -> raise (ParseError "Cannot parse operation") in try add_operation (operation ()) state with NoOperationId -> () let parse_with_state state = let rec loop () = parse_operation state; if over state then state.operations else loop () in try List.rev (loop ()) with NoOperationId -> List.rev state.operations (* Long drawing operation strings sometimes contain useless backslashes We get rid of them to avoid problems with the parser *) let remove_backslashes s = let buf = Buffer.create 30 in let rec loop i = if i = String.length s then () else if s.[i] = '\\' && i < String.length s - 1 && s.[i+1] = '\n' then loop (i+2) else begin Buffer.add_char buf s.[i]; loop (i+1) end in loop 0; Buffer.contents buf let parse s = parse_with_state (mk_state (remove_backslashes s)) let draw_with (f : draw_state -> operation -> unit) operations = let st = default_draw_state () in let draw_op = function (* The 4 following instructions modify the drawing state *) | Fill_color c as op -> set_fill_color st c; f st op | Pen_color c as op -> set_pen_color st c; f st op | Font (sty,font) as op -> set_font st (sty,font); f st op | Style stys as op -> set_style st stys; f st op (* No state effects on the other operations *) | op -> f st op in List.iter draw_op operations (* let d1 = parse "c 5 -white C 5 -white P 4 0 0 0 409 228 409 228 0 " *) (* let d2 = parse "S 6 -filled c 9 -lightgrey C 9 -lightgrey P 4 8 72 8 365 101 365 101 72 " *) (* let d3 = parse "S 6 -filled c 5 -white C 5 -white E 65 314 27 18 " *) (* let d4 = parse "F 14.000000 11 -Times-Roman c 5 -black T 39 109 0 35 4 -LR_0 " *) (* let d5 = parse "S 6 -filled c 5 -white C 5 -white E 64 98 27 18 " *) (* let d6 = parse "S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 69 270 65 260 62 270 " *) (* let d7 = parse "S 6 -filled c 7 -salmon2 C 7 -salmon2 P 9 865 1177 877 1193 841 1200 760 1192 695 1178 700 1167 756 1161 810 1160 841 1165 " *) (* let d8 = parse "F 14.000000 17 -Helvetica-Outline c 5 -black T 529 1005 0 65 9 -Mini Unix " *) (* let d9 = parse "S 6 -filled c 11 -greenyellow C 11 -greenyellow P 10 1254 819 1263 834 1247 843 1197 841 1137 830 1110 817 1131 808 1177 805 121\ *) (* 6 804 1238 809 " *) (* let d10 = parse "S 6 -filled c 11 -greenyellow C 11 -greenyellow P 10 255 282 264 297 248 306 198 304 138 293 111 280 132 271 178 268 217 267 239\\\n 272 " *) ocamlgraph-1.8.3/dgraph/dGraphViewItem.mli0000644000175000017500000001206612133565071017435 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (** View items for the different elements of a graph. *) (* ********************************************************************** *) (** {2 Shape} *) (* ********************************************************************** *) (** Shape properties *) type shape_p = [ `FILL_COLOR_RGBA of int32 | `OUTLINE_COLOR_RGBA of int32 | `WIDTH_UNITS of float | `DASH of float * float array ] class type textshape = object method highlight: ?color:int32 * int32 -> unit -> unit (** Change the color of the text. May be cancelled by [dehighlight]. If [color] is [primary,secondary], then [primary] is used except if the current color is [primary]. In this case, [secondary] is used. *) method dehighlight: unit -> unit (** Cancel [highlight]. *) method hide: unit -> unit method show: unit -> unit method lower_to_bottom: unit -> unit method connect: < event : callback:(GnoCanvas.item_event -> bool) -> GtkSignal.id; after : GnoCanvas.item_signals; destroy : callback:(unit -> unit) -> GtkSignal.id; > end class type shape = object inherit GnoCanvas.base_item inherit textshape val obj : GnomeCanvas.item Gtk.obj method set: shape_p list -> unit end (* ********************************************************************** *) (** {2 Text} *) (* ********************************************************************** *) (** Derived text class. *) class graph_text : GnomeCanvas.text Gtk.obj -> size_points:float -> props:GnomeCanvas.text_p list -> object inherit GnoCanvas.text inherit textshape method resize: float -> unit end (* ********************************************************************** *) (** {2 View items} *) (* ********************************************************************** *) class type common_view = object inherit GnoCanvas.canvas method zoom_factor : float method adapt_zoom : unit -> unit end (** ViewItem class. Group of shapes and texts *) class ['a ] view_item : fill:bool -> delay:bool (** May the item be displayed non instantaneously? *) -> view:common_view -> pos:float * float -> ops_list:XDotDraw.operation list list -> item:'a -> object inherit GnoCanvas.group method item: 'a method zoom_text: float -> unit method highlight: ?color: int32 * int32 -> unit -> unit (** Change the color of the item. May be cancelled by [dehighlight]. If [color] is [primary,secondary], then [primary] is used except if the current color is [primary]. In this case, [secondary] is used. *) method dehighlight: unit -> unit (** Cancel [highlight]. *) method show : unit -> unit method hide : unit -> unit method center : unit -> unit method connect_event: callback:(GnoCanvas.item_event -> bool) -> unit method compute: unit -> unit (** apply all delayed operations *) method lower_to_bottom: unit -> unit end exception Cannot_convert_color of string val view_node: delay:bool -> view:common_view -> vertex:'vertex -> layout:XDot.node_layout -> unit -> 'vertex view_item val view_edge: delay:bool -> view:common_view -> edge:'edge -> layout:XDot.edge_layout -> unit -> 'edge view_item val view_cluster: delay:bool -> view:common_view -> cluster:'cluster -> layout:XDot.cluster_layout -> unit -> 'cluster view_item ocamlgraph-1.8.3/dgraph/dGraphModel.mli0000644000175000017500000000753712133565071016753 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (** Abstract graph model *) open XDot open Graph exception DotError of string (** Immutable graph model. Layout accessors, iterators and membership functions. *) class type ['vertex, 'edge, 'cluster] abstract_model = object method iter_edges : ('vertex -> 'vertex -> unit) -> unit method iter_edges_e : ('edge -> unit) -> unit method iter_pred : ('vertex -> unit) -> 'vertex -> unit method iter_pred_e : ('edge -> unit) -> 'vertex -> unit method iter_succ : ('vertex -> unit) -> 'vertex -> unit method iter_succ_e : ('edge -> unit) -> 'vertex -> unit method iter_vertex : ('vertex -> unit) -> unit method iter_clusters : ('cluster -> unit) -> unit method iter_associated_vertex : ('vertex -> unit) -> 'vertex -> unit (** Membership functions *) method find_edge : 'vertex -> 'vertex -> 'edge method mem_edge : 'vertex -> 'vertex -> bool method mem_edge_e : 'edge -> bool method mem_vertex : 'vertex -> bool method src : 'edge -> 'vertex method dst : 'edge -> 'vertex (** Dot layout *) method bounding_box : bounding_box method get_edge_layout : 'edge -> edge_layout method get_vertex_layout : 'vertex -> node_layout method get_cluster_layout : 'cluster -> cluster_layout end (** This functor creates a model from a graph *) module Make(G : Graph.Graphviz.GraphWithDotAttrs) : sig open G type cluster = string class model: XDot.Make(G).graph_layout -> G.t -> [G.V.t, G.E.t, cluster] abstract_model val from_graph : ?cmd:string -> ?tmp_name:string -> G.t -> model (** Creates a model using graphviz. [tmp_name] is the name of the temporary dot files. @raise DotError if issue occurs with the generated dot file *) end module DotG : Sig.G with type V.label = XDot.node_layout and type E.label = XDot.edge_layout type cluster = string type dotg_model = (DotG.vertex, DotG.edge, cluster) abstract_model (** Creates a model from a dot file. *) val read_dot : ?cmd:string -> string -> dotg_model (** Creates a model from an xdot file (the layout is not recomputed)*) val read_xdot : string -> dotg_model ocamlgraph-1.8.3/dgraph/dGraphContainer.ml0000755000175000017500000003342312133565071017460 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 let ($) f x = f x type cluster = string type status = Global | Tree | Both (* ABSTRACT CLASS *) class type ['vertex, 'edge, 'cluster, 'tree_vertex, 'tree_edge, 'tree_cluster] view_container_type = object method global_view : ('vertex, 'edge, 'cluster) DGraphView.view option method tree_view: ('tree_vertex, 'tree_edge, 'tree_cluster) DGraphView.view option method tree_root: 'vertex option method depth_backward : int method depth_forward : int method status : status method set_depth_backward : int -> unit method set_depth_forward : int -> unit method set_tree_root: 'vertex -> unit method switch : status -> unit method adapt_zoom: unit -> unit end module type S = sig type graph type vertex type edge module Tree: Sig.G with type V.label = vertex module GView: DGraphView.S with type vertex = vertex and type edge = edge and type cluster = cluster module TView: DGraphView.S with type vertex = Tree.V.t and type edge = Tree.E.t and type cluster = cluster type global_view = (vertex, edge, cluster) DGraphView.view type tree_view = (Tree.V.t, Tree.E.t, cluster) DGraphView.view class view_container : ?packing:(GObj.widget -> unit) -> ?status:status -> ?default_callbacks:bool -> mk_global_view: (unit -> global_view) -> mk_tree_view: (depth_backward:int -> depth_forward:int -> Gtk.widget Gtk.obj -> vertex -> tree_view) -> vertex option -> [ vertex, edge, cluster, Tree.V.t, Tree.E.t, cluster] view_container_type end (* CONTAINER *) let with_commands ?packing mk_view model = let main_table = GPack.table ~columns:2 ~rows:2 ?packing () in let view = let packing w = main_table#attach ~left:0 ~right:2 ~top:1 ~expand:`BOTH w in mk_view ~packing model in (* Buttons box *) let buttons_box = GPack.button_box `HORIZONTAL ~border_width:3 ~child_height:10 ~child_width:85 ~spacing:10 ~layout:`START ~packing:(main_table#attach ~top:0 ~left:0 ~expand:`X) () in let view_label = GMisc.label ~markup:"View" () in buttons_box#pack ~expand:false view_label#coerce; let add_button label mode = let b = GButton.button ~label ~packing:buttons_box#pack () in ignore (b#connect#clicked ~callback:(fun _ -> view#switch mode)) in add_button "Global" Global; add_button "Tree" Tree; add_button "Both" Both; (* Depth of exploration controls *) let depth_hbox = GPack.hbox ~packing:(main_table#attach ~expand:`X ~top:0 ~left:1) () in let depth_forward_adj = GData.adjustment ~lower:0. ~page_size:0. () in let depth_backward_adj = GData.adjustment ~lower:0. ~page_size:0. () in let change_depth_forward adj content () = content#set_depth_forward (int_of_float adj#value); in let change_depth_backward adj content () = content#set_depth_backward (int_of_float adj#value) in ignore $ depth_forward_adj#connect#value_changed ~callback:(change_depth_forward depth_forward_adj view); ignore $ depth_backward_adj#connect#value_changed ~callback:(change_depth_backward depth_backward_adj view); let depth_label = GMisc.label ~markup:"Depth" () in let depth_forward_label = GMisc.label ~text:" forward: " () in let depth_backward_label = GMisc.label ~text:" backward: " () in let depth_forward_spin = GEdit.spin_button ~value:2. ~adjustment:depth_forward_adj () in let depth_backward_spin = GEdit.spin_button ~value:2. ~adjustment:depth_backward_adj () in depth_hbox#pack ~from:`END depth_backward_spin#coerce; depth_hbox#pack ~from:`END depth_backward_label#coerce; depth_hbox#pack ~from:`END depth_forward_spin#coerce; depth_hbox#pack ~from:`END depth_forward_label#coerce; depth_hbox#pack ~from:`END depth_label#coerce; main_table, view (* FROM GRAPH *) module HString = struct type t = string let equal = (=) let hash = Hashtbl.hash end module Build (G: Sig.G) (T: DGraphTreeModel.S with type Tree.V.label = G.V.t) = struct type graph = G.t type vertex = G.V.t type edge = G.E.t module TreeModel = T module Tree = T.Tree module HE(E: sig type t val compare: t -> t -> int end) = struct type t = E.t let equal x y = E.compare x y = 0 let hash = Hashtbl.hash end module GView = DGraphView.Make(G.V)(HE(G.E))(HString) module TView = DGraphView.Make(Tree.V)(HE(Tree.E))(HString) type global_view = (G.V.t, G.E.t, string) DGraphView.view type tree_view = (Tree.V.t, Tree.E.t, string) DGraphView.view class view_container ?packing ?(status=Global) ?(default_callbacks=true) ~mk_global_view ~mk_tree_view default_tree_root = (* widgets *) let paned_box = GPack.paned `VERTICAL ?packing () in let global_frame = GBin.frame ~label:"Global View" () in let tree_frame = GBin.frame ~label:"Tree View" () in (* Callback functions *) let connect_tree_callback view node = let item = node#item in let callback ev = let apply f = match view#global_view with | None -> false | Some gview -> let tree = T.tree () in let vlist = T.TreeManipulation.get_graph_vertex item tree in f (gview:global_view) (gview#get_node vlist); false in match ev with | `BUTTON_PRESS _ -> (* clicking on a node of the tree view *) view#set_tree_root (T.Tree.V.label item); apply (fun v -> v#dehighlight) | `MOTION_NOTIFY _ -> apply (fun v n -> v#highlight n) | `LEAVE_NOTIFY _ -> apply (fun v -> v#dehighlight) | _ -> false in node#connect_event ~callback in let connect_global_callback view node = let item = node#item in let callback ev = let apply f = match view#tree_view with | None -> false | Some tview -> let tree = T.tree () in let vlist = T.TreeManipulation.get_tree_vertices item tree in List.iter (fun v -> f (tview:tree_view) (tview#get_node v)) vlist; false in match ev with | `BUTTON_PRESS _ -> (* clicking on a node of the global view *) (* Update the root of the tree view *) view#set_tree_root node#item; (* Center the global view on the selected node *) begin match view#global_view with | None -> () | Some w -> w#center_node node end; false | `MOTION_NOTIFY _ -> apply (fun v n -> v#highlight n) | `LEAVE_NOTIFY _ -> apply (fun v -> v#dehighlight) |_ -> false in node#connect_event ~callback in object (self) val mutable global_view: global_view option = None val mutable tree_view: tree_view option = None val mutable tree_change = false (* must recompute the tree? *) val mutable tree_root = default_tree_root val mutable status = status val mutable depth_forward = 2 val mutable depth_backward = 2 (* Getters *) method status = status method global_view = global_view method tree_view = tree_view method tree_root = tree_root method depth_forward = depth_forward method depth_backward = depth_backward (* Setters *) method set_depth_forward i = depth_forward <- i; tree_change <- true; self#update () method set_depth_backward i = depth_backward <- i; tree_change <- true; self#update () method set_tree_root v = tree_root <- Some v; tree_change <- true; self#update () method switch s = status <- s; self#update () (* Compute the views *) method private memo_tree_view () = if tree_change then begin (match tree_view with | None -> () | Some view -> match view#misc#parent with | Some parent -> tree_frame#remove parent | None -> () ); match tree_root with | None -> assert false | Some r -> let view = mk_tree_view ~depth_backward ~depth_forward paned_box#as_widget r in tree_view <- Some view; if default_callbacks then begin view#connect_highlighting_event(); view#iter_nodes (connect_tree_callback self); end; let scroll = GBin.scrolled_window ~hpolicy:`AUTOMATIC ~vpolicy:`AUTOMATIC ~packing:tree_frame#add () in scroll#add view#coerce end method private memo_global_view () = match global_view with | None -> let view = mk_global_view () in global_view <- Some view; if default_callbacks then begin view#connect_highlighting_event (); view#iter_nodes (connect_global_callback self); end; let scroll = GBin.scrolled_window ~hpolicy:`AUTOMATIC ~vpolicy:`AUTOMATIC ~packing:global_frame#add () in scroll#add view#coerce | Some _ -> () method adapt_zoom () = let az = function | None -> () | Some w -> w#adapt_zoom () in az tree_view; az global_view method private add_global_view () = self#memo_global_view (); paned_box#pack1 global_frame#coerce method private add_tree_view () = self#memo_tree_view (); paned_box#pack2 tree_frame#coerce method private update () = List.iter paned_box#remove paned_box#all_children; (match status, tree_root with | Global, _ | _, None -> self#add_global_view () | Tree, Some _ -> self#add_tree_view () | Both, Some _ -> self#add_global_view (); self#add_tree_view ()) initializer self#update () end end module Make(G: Graphviz.GraphWithDotAttrs) = struct module FullTreeModel = DGraphTreeModel.SubTreeMake(G) include Build(G)(FullTreeModel) module GlobalModel = DGraphModel.Make(G) let from_graph ?packing ?status ?(default_callbacks=true) ?(mk_global_view = fun model -> GView.view ~aa:true model) ?(mk_tree_view = fun model -> TView.view ~aa:true model) ?root g = let status = match status with | None -> if G.nb_vertex g < 500 && G.nb_edges g < 2500 then Global else Tree | Some s -> s in new view_container ?packing ~default_callbacks ~status ~mk_global_view:(fun () -> mk_global_view (GlobalModel.from_graph g)) ~mk_tree_view:(fun ~depth_backward ~depth_forward w v -> let model = FullTreeModel.from_graph ~depth_forward ~depth_backward w g v in mk_tree_view model) root let from_graph_with_commands ?packing ?status ?(default_callbacks=true) ?mk_global_view ?mk_tree_view ?root g = with_commands ?packing (fun ~packing g -> from_graph ~packing ?status ~default_callbacks ?mk_global_view ?mk_tree_view ?root g) g end (* FROM DOT *) module Dot = struct include Build(DGraphModel.DotG)(DGraphTreeModel.SubTreeDotModelMake) exception Found of DGraphModel.DotG.V.t let from_dot ?packing ?status ?(default_callbacks=true) ?(mk_global_view = fun model -> GView.view ~aa:true model) ?(mk_tree_view = fun model -> TView.view ~aa:true model) dot_file = let gmodel = if Filename.check_suffix dot_file "xdot" then DGraphModel.read_xdot dot_file else DGraphModel.read_dot dot_file in let one_vertex = try gmodel#iter_vertex (fun v -> raise (Found v)); None with Found v -> Some v in let status = match status with | None -> let nb f = let cpt = ref 0 in f gmodel (fun _ -> incr cpt); !cpt in if nb (fun g -> g#iter_vertex) < 500 && nb (fun g -> g#iter_edges_e) < 2500 then Global else Tree | Some s -> s in new view_container ?packing ~status ~default_callbacks ~mk_global_view:(fun () -> mk_global_view gmodel) ~mk_tree_view:(fun ~depth_backward ~depth_forward _ v -> mk_tree_view (DGraphTreeModel.SubTreeDotModelMake.from_model ~depth_forward ~depth_backward gmodel v)) one_vertex let from_dot_with_commands ?packing ?status ?(default_callbacks=true) ?mk_global_view ?mk_tree_view dot_file = with_commands ?packing (fun ~packing d -> from_dot ~packing ?status ~default_callbacks ?mk_global_view ?mk_tree_view d) dot_file end ocamlgraph-1.8.3/dgraph/dGraphRandModel.ml0000644000175000017500000000614612133565071017402 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 open DGraphView open Printf let ($) f x = f x let element = function | [] -> invalid_arg "empty list in element" | l -> Random.self_init (); List.nth l (Random.int (List.length l)) let black = 0x000000 and white = 0xFFFFFF and red = 0xFF0000 and green = 0x00FF00 and blue = 0x0000FF and yellow = 0xFFFF00 and cyan = 0x00FFFF and magenta = 0xFF00FF module Vertex = struct type t = int end module Edge = struct type t = int let compare : int -> int -> int = Pervasives.compare let default = 0 end module G = Imperative.Digraph.AbstractLabeled(Vertex)(Edge) module R = Rand.I(G) module GraphAttrs = struct include G let graph_attributes _ = [] let default_vertex_attributes _ = [] let vertex_name v = string_of_int (G.V.label v) let vertex_attributes _ = let shape = element [`Ellipse; `Box; `Circle; `Doublecircle; `Diamond] in let color = element [black; white; red; green; blue; yellow; cyan; magenta] in [`Shape shape; `Color color] let default_edge_attributes _ = [] let edge_attributes _ = [] let get_subgraph _ = None end module Model = DGraphModel.Make(GraphAttrs) let create () = (* State *) Random.self_init (); let v = 100 in let e = Random.int (v*2) in let g = R.graph ~loops:true ~v ~e () in Model.from_graph g ocamlgraph-1.8.3/dgraph/dGraphMake.ml0000644000175000017500000000357112133565071016411 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 open XDot open Printf exception DotError of string ocamlgraph-1.8.3/dgraph/dGraphSubTree.mli0000755000175000017500000000650712133565071017263 0ustar mehdimehdi(**************************************************************************) (* *) (* 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 Make (G : G) (Tree : Tree with type V.label = G.V.t and type E.label = unit) : sig include S with module Tree = Tree val make : G.t -> G.V.t -> int -> int -> t end module Make_from_dot_model (Tree : Tree with type V.label = DGraphModel.DotG.V.t and type E.label = unit) : sig include S with module Tree = Tree val make: (Tree.V.label, DGraphModel.DotG.E.t, string) DGraphModel.abstract_model -> Tree.V.label -> int -> int -> t end ocamlgraph-1.8.3/dgraph/dGraphView.mli0000644000175000017500000001261312133565071016614 0ustar mehdimehdi(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) (** View classes. Each optional function [delay_node], [delay_edge] and [delay_cluster] of this module may be used to indicate whether an element must be displayed instantaneously (if the function returns [false]) or may be delayed for latter display (if the function returns [true]). By default, each function always returns [false]. It may be set for returning [true] from time to time, improving efficiency. *) open DGraphViewItem (** Graph widget derived from [GnoCanvas.canvas]. Support zooming and scrolling. *) class type ['vertex, 'edge, 'cluster] view = object inherit GnoCanvas.canvas method model : ('vertex, 'edge, 'cluster) DGraphModel.abstract_model (** {2 Getters} *) method get_node : 'vertex -> 'vertex view_item method get_edge : 'edge -> 'edge view_item method get_cluster : 'cluster -> 'cluster view_item (** {2 Iterators} *) method iter_nodes: ('vertex view_item -> unit) -> unit method iter_edges: ('vertex view_item -> 'vertex view_item -> unit) -> unit method iter_edges_e: ('edge view_item -> unit) -> unit method iter_clusters: ('cluster view_item -> unit) -> unit method iter_succ: ('vertex view_item -> unit) -> 'vertex view_item -> unit method iter_pred: ('vertex view_item -> unit) -> 'vertex view_item -> unit method iter_succ_e: ('edge view_item -> unit) -> 'vertex view_item -> unit method iter_pred_e: ('edge view_item -> unit) -> 'vertex view_item -> unit (* Benoit Bataille's method: is it really useful? *) method iter_associated_vertex: ('vertex view_item -> unit) -> 'vertex view_item -> unit (** {2 Membership functions} *) method mem_edge: 'vertex view_item -> 'vertex view_item -> bool method find_edge: 'vertex view_item -> 'vertex view_item -> 'edge view_item method src: 'edge view_item -> 'vertex view_item method dst: 'edge view_item -> 'vertex view_item (** {2 Zooming} *) method zoom_factor : float (** The current zoom factor.*) method zoom_to : float -> unit (** Set an absolute zoom factor.*) method zoom_in : unit -> unit (** Increase [zoom_factor] by [zoom_factor*zoom_padding].*) method zoom_out : unit -> unit (** Decrease [zoom_factor] by [zoom_factor*zoom_padding].*) method adapt_zoom : unit -> unit (** Zoom in order to view the whole graph (bird eye view). *) method set_zoom_padding: float -> unit (** Set the zoom padding used by [zoom_in] and [zoom_out]. It defaults to 0.1. *) method center_node: 'vertex view_item -> unit (** Center canvas on a node. *) (** {2 Highlighting} *) method connect_highlighting_event: unit -> unit method highlight: ?color: int32 * int32 -> 'vertex view_item -> unit (** Change the color of the given vertex item. May be cancelled by [dehighlight]. If [color] is [primary,secondary], then [primary] is used except if the current color is [primary]. In this case, [secondary] is used. *) method dehighlight: 'vertex view_item -> unit (** Cancel [highlight]. *) end module type S = sig type vertex type edge type cluster val view: ?aa:bool (** Anti-aliasing *) -> ?delay_node:(vertex -> bool) -> ?delay_edge:(edge -> bool) -> ?delay_cluster:(cluster -> bool) -> ?border_width:int -> ?width:int -> ?height:int -> ?packing:(GObj.widget -> unit) -> ?show:bool -> (vertex, edge, cluster) DGraphModel.abstract_model -> (vertex, edge, cluster) view (** View as a Gnome Canvas. Support zooming and scrolling. *) end module Make(V: Sig.HASHABLE)(E: Sig.HASHABLE)(C: Sig.HASHABLE) : S with type vertex = V.t and type edge = E.t and type cluster = C.t ocamlgraph-1.8.3/bin/0000755000175000017500000000000012133565070013350 5ustar mehdimehdiocamlgraph-1.8.3/configure0000755000175000017500000031336012133565071014516 0ustar mehdimehdi#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="src/sig.mli" ac_subst_vars='LTLIBOBJS LIBOBJS INCLUDEGTK2 OBJEXT LIBEXT EXE OCAMLWIN32 LABLGNOMECANVAS LABLGTK2 OCAMLLIB OCAMLVERSION OCAMLBEST OCAMLFIND OCAMLWEB OCAMLDOCOPT OCAMLDOC OCAMLYACC OCAMLLEXDOTOPT OCAMLLEX OCAMLDEP OCAMLOPTDOTOPT OCAMLCDOTOPT OCAMLOPT OCAMLC target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Check for Ocaml compilers # we first look for ocamlc in the path; if not present, we fail # Extract the first word of "ocamlc", so it can be a program name with args. set dummy ocamlc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLC"; then ac_cv_prog_OCAMLC="$OCAMLC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLC="ocamlc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLC" && ac_cv_prog_OCAMLC="no" fi fi OCAMLC=$ac_cv_prog_OCAMLC if test -n "$OCAMLC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLC" >&5 $as_echo "$OCAMLC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLC" = no ; then as_fn_error $? "Cannot find ocamlc." "$LINENO" 5 fi # we extract Ocaml version number and library path OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` echo "ocaml version is $OCAMLVERSION" case $OCAMLVERSION in 0.*|1.*|2.*|3.0*) as_fn_error $? "ocamlgraph needs ocaml version 3.10.0 or higher" "$LINENO" 5;; *) ;; esac # OCAMLLIB=`$OCAMLC -v | tail -n 1 | cut -f 4 -d " "` # OCAMLLIB=`$OCAMLC -v | tail -n 1 | sed -e 's|[[^:]]*: \(.*\)|\1|' ` OCAMLLIB=`$OCAMLC -where | tr -d '\r'` echo "ocaml library path is $OCAMLLIB" # then we look for ocamlopt; if not present, we issue a warning # if the version is not the same, we also discard it # we set OCAMLBEST to "opt" or "byte", whether ocamlopt is available or not # Extract the first word of "ocamlopt", so it can be a program name with args. set dummy ocamlopt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLOPT"; then ac_cv_prog_OCAMLOPT="$OCAMLOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLOPT="ocamlopt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLOPT" && ac_cv_prog_OCAMLOPT="no" fi fi OCAMLOPT=$ac_cv_prog_OCAMLOPT if test -n "$OCAMLOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLOPT" >&5 $as_echo "$OCAMLOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi OCAMLBEST=byte if test "$OCAMLOPT" = no ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find ocamlopt; bytecode compilation only." >&5 $as_echo "$as_me: WARNING: Cannot find ocamlopt; bytecode compilation only." >&2;} else { $as_echo "$as_me:${as_lineno-$LINENO}: checking ocamlopt version" >&5 $as_echo_n "checking ocamlopt version... " >&6; } TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: differs from ocamlc; ocamlopt discarded." >&5 $as_echo "differs from ocamlc; ocamlopt discarded." >&6; } OCAMLOPT=no else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } OCAMLBEST=opt fi fi # checking for ocamlc.opt # Extract the first word of "ocamlc.opt", so it can be a program name with args. set dummy ocamlc.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLCDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLCDOTOPT"; then ac_cv_prog_OCAMLCDOTOPT="$OCAMLCDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLCDOTOPT="ocamlc.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLCDOTOPT" && ac_cv_prog_OCAMLCDOTOPT="no" fi fi OCAMLCDOTOPT=$ac_cv_prog_OCAMLCDOTOPT if test -n "$OCAMLCDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLCDOTOPT" >&5 $as_echo "$OCAMLCDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLCDOTOPT" != no ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking ocamlc.opt version" >&5 $as_echo_n "checking ocamlc.opt version... " >&6; } TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: differs from ocamlc; ocamlc.opt discarded." >&5 $as_echo "differs from ocamlc; ocamlc.opt discarded." >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != no ; then # Extract the first word of "ocamlopt.opt", so it can be a program name with args. set dummy ocamlopt.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLOPTDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLOPTDOTOPT"; then ac_cv_prog_OCAMLOPTDOTOPT="$OCAMLOPTDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLOPTDOTOPT="ocamlopt.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLOPTDOTOPT" && ac_cv_prog_OCAMLOPTDOTOPT="no" fi fi OCAMLOPTDOTOPT=$ac_cv_prog_OCAMLOPTDOTOPT if test -n "$OCAMLOPTDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLOPTDOTOPT" >&5 $as_echo "$OCAMLOPTDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLOPTDOTOPT" != no ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking ocamlc.opt version" >&5 $as_echo_n "checking ocamlc.opt version... " >&6; } TMPVER=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVER" != "$OCAMLVERSION" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: differs from ocamlc; ocamlopt.opt discarded." >&5 $as_echo "differs from ocamlc; ocamlopt.opt discarded." >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi # ocamldep, ocamllex and ocamlyacc should also be present in the path # Extract the first word of "ocamldep", so it can be a program name with args. set dummy ocamldep; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLDEP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLDEP"; then ac_cv_prog_OCAMLDEP="$OCAMLDEP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLDEP="ocamldep" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLDEP" && ac_cv_prog_OCAMLDEP="no" fi fi OCAMLDEP=$ac_cv_prog_OCAMLDEP if test -n "$OCAMLDEP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLDEP" >&5 $as_echo "$OCAMLDEP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLDEP" = no ; then as_fn_error $? "Cannot find ocamldep." "$LINENO" 5 fi # Extract the first word of "ocamllex", so it can be a program name with args. set dummy ocamllex; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLLEX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLLEX"; then ac_cv_prog_OCAMLLEX="$OCAMLLEX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLLEX="ocamllex" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLLEX" && ac_cv_prog_OCAMLLEX="no" fi fi OCAMLLEX=$ac_cv_prog_OCAMLLEX if test -n "$OCAMLLEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLLEX" >&5 $as_echo "$OCAMLLEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLLEX" = no ; then as_fn_error $? "Cannot find ocamllex." "$LINENO" 5 else # Extract the first word of "ocamllex.opt", so it can be a program name with args. set dummy ocamllex.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLLEXDOTOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLLEXDOTOPT"; then ac_cv_prog_OCAMLLEXDOTOPT="$OCAMLLEXDOTOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLLEXDOTOPT="ocamllex.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLLEXDOTOPT" && ac_cv_prog_OCAMLLEXDOTOPT="no" fi fi OCAMLLEXDOTOPT=$ac_cv_prog_OCAMLLEXDOTOPT if test -n "$OCAMLLEXDOTOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLLEXDOTOPT" >&5 $as_echo "$OCAMLLEXDOTOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLLEXDOTOPT" != no ; then OCAMLLEX=$OCAMLLEXDOTOPT fi fi # Extract the first word of "ocamlyacc", so it can be a program name with args. set dummy ocamlyacc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLYACC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLYACC"; then ac_cv_prog_OCAMLYACC="$OCAMLYACC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLYACC="ocamlyacc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLYACC" && ac_cv_prog_OCAMLYACC="no" fi fi OCAMLYACC=$ac_cv_prog_OCAMLYACC if test -n "$OCAMLYACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLYACC" >&5 $as_echo "$OCAMLYACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLYACC" = no ; then as_fn_error $? "Cannot find ocamlyacc." "$LINENO" 5 fi # Extract the first word of "ocamldoc", so it can be a program name with args. set dummy ocamldoc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLDOC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLDOC"; then ac_cv_prog_OCAMLDOC="$OCAMLDOC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLDOC="ocamldoc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLDOC" && ac_cv_prog_OCAMLDOC="true" fi fi OCAMLDOC=$ac_cv_prog_OCAMLDOC if test -n "$OCAMLDOC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLDOC" >&5 $as_echo "$OCAMLDOC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLDOC" = true ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Cannot find ocamldoc" >&5 $as_echo "$as_me: WARNING: Cannot find ocamldoc" >&2;} else # Extract the first word of "ocamldoc.opt", so it can be a program name with args. set dummy ocamldoc.opt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLDOCOPT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLDOCOPT"; then ac_cv_prog_OCAMLDOCOPT="$OCAMLDOCOPT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLDOCOPT="ocamldoc.opt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLDOCOPT" && ac_cv_prog_OCAMLDOCOPT="no" fi fi OCAMLDOCOPT=$ac_cv_prog_OCAMLDOCOPT if test -n "$OCAMLDOCOPT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLDOCOPT" >&5 $as_echo "$OCAMLDOCOPT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLDOCOPT" != no ; then OCAMLDOC=$OCAMLDOCOPT fi fi # Extract the first word of "ocamlweb", so it can be a program name with args. set dummy ocamlweb; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLWEB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLWEB"; then ac_cv_prog_OCAMLWEB="$OCAMLWEB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLWEB="ocamlweb" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_OCAMLWEB" && ac_cv_prog_OCAMLWEB="true" fi fi OCAMLWEB=$ac_cv_prog_OCAMLWEB if test -n "$OCAMLWEB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLWEB" >&5 $as_echo "$OCAMLWEB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "ocamlfind", so it can be a program name with args. set dummy ocamlfind; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OCAMLFIND+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OCAMLFIND"; then ac_cv_prog_OCAMLFIND="$OCAMLFIND" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OCAMLFIND="ocamlfind" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OCAMLFIND=$ac_cv_prog_OCAMLFIND if test -n "$OCAMLFIND"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCAMLFIND" >&5 $as_echo "$OCAMLFIND" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$OCAMLFIND" = "" ; then echo "No ocamlfind detected" else OCAMLLIB_BY_FINDLIB=`ocamlfind query stdlib | tr -d '\\r'` if test "$OCAMLLIB_BY_FINDLIB" = "$OCAMLLIB" ; then echo "OCamlfind detected and enabled" else echo "OCamlfind detected but disabled. Standard libraries differ." OCAMLFIND="" fi fi if test "$OCAMLBEST" = "opt"; then SUFFIX=cmxa; else SUFFIX=cma; fi # checking for lablgtk2 and lablgnomecanvas ########################################### # lablgtk2 now uses ocamlfind while older version uses `ocamlc -where ` # its installation path is not the same if test "$OCAMLFIND" = "" ; then LABLGTK_PATH=+lablgtk2 LABLGTKPATH_FOR_CONFIGURE=$OCAMLLIB/lablgtk2 else LABLGTK_PATH=`ocamlfind query lablgtk2 | tr -d '\\r\\n'` if test "$LABLGTK_PATH" = "" -o "$LABLGTK_PATH" -ef "$OCAMLLIB/lablgtk2" ; \ then LABLGTK_PATH=+lablgtk2 LABLGTKPATH_FOR_CONFIGURE=$OCAMLLIB/lablgtk2 else LABLGTKPATH_FOR_CONFIGURE=$LABLGTK_PATH fi fi as_ac_File=`$as_echo "ac_cv_file_$LABLGTKPATH_FOR_CONFIGURE/lablgtk.$SUFFIX" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LABLGTKPATH_FOR_CONFIGURE/lablgtk.$SUFFIX" >&5 $as_echo_n "checking for $LABLGTKPATH_FOR_CONFIGURE/lablgtk.$SUFFIX... " >&6; } if eval \${$as_ac_File+:} false; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$LABLGTKPATH_FOR_CONFIGURE/lablgtk.$SUFFIX"; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes"; then : LABLGTK2=yes else LABLGTK2=no fi if test "$LABLGTK2" = yes ; then INCLUDEGTK2="-I $LABLGTK_PATH" as_ac_File=`$as_echo "ac_cv_file_$LABLGTKPATH_FOR_CONFIGURE/lablgnomecanvas.$SUFFIX" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LABLGTKPATH_FOR_CONFIGURE/lablgnomecanvas.$SUFFIX" >&5 $as_echo_n "checking for $LABLGTKPATH_FOR_CONFIGURE/lablgnomecanvas.$SUFFIX... " >&6; } if eval \${$as_ac_File+:} false; then : $as_echo_n "(cached) " >&6 else test "$cross_compiling" = yes && as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 if test -r "$LABLGTKPATH_FOR_CONFIGURE/lablgnomecanvas.$SUFFIX"; then eval "$as_ac_File=yes" else eval "$as_ac_File=no" fi fi eval ac_res=\$$as_ac_File { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_File"\" = x"yes"; then : LABLGNOMECANVAS=yes else LABLGNOMECANVAS=no fi else LABLGTK2=no LABLGNOMECANVAS=no fi # platform { $as_echo "$as_me:${as_lineno-$LINENO}: checking Win32 platform" >&5 $as_echo_n "checking Win32 platform... " >&6; } echo "print_endline Sys.os_type" > check_arch.ml if ocaml check_arch.ml | grep -q Win32; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } OCAMLWIN32=yes EXE=.exe else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } OCAMLWIN32=no EXE= fi rm -f check_arch.ml LIBEXT=`ocamlc -config | grep ext_lib | sed -e 's/.*\(\..*\)/\1/' ` OBJEXT=`ocamlc -config | grep ext_obj | sed -e 's/.*\(\..*\)/\1/' ` if test "$LABLGNOMECANVAS" = no ; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: lablgnomecanvas not found: the graph editor and view_graph will not be compiled" >&5 $as_echo "$as_me: WARNING: lablgnomecanvas not found: the graph editor and view_graph will not be compiled" >&2;} fi # substitutions to perform # Finally create the Makefile from Makefile.in ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi chmod a-w Makefile ocamlgraph-1.8.3/Makefile.in0000644000175000017500000003770212133565071014657 0ustar mehdimehdi########################################################################## # # # Ocamlgraph: a generic graph library for OCaml # # Copyright (C) 2004-2010 # # Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles # # # # This software is free software; you can redistribute it and/or # # modify it under the terms of the GNU Library General Public # # License version 2.1, with the special exception on linking # # described in file LICENSE. # # # # This software 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. # # # ########################################################################## # Where to install the binaries DESTDIR = prefix =@prefix@ exec_prefix=@exec_prefix@ datarootdir=@datarootdir@ BINDIR =$(DESTDIR)@bindir@ # Where to install the man page MANDIR=@mandir@ # Other variables set by ./configure OCAMLC = @OCAMLC@ OCAMLOPT = @OCAMLOPT@ OCAMLDEP = @OCAMLDEP@ -slash OCAMLDOC = @OCAMLDOC@ OCAMLLEX = @OCAMLLEX@ OCAMLYACC= @OCAMLYACC@ -v OCAMLLIB = @OCAMLLIB@ OCAMLBEST= @OCAMLBEST@ OCAMLVERSION = @OCAMLVERSION@ OCAMLWEB = @OCAMLWEB@ OCAMLWIN32 = @OCAMLWIN32@ OCAMLFIND = @OCAMLFIND@ EXE = @EXE@ LIBEXT = @LIBEXT@ OBJEXT = @OBJEXT@ # Others global variables SRCDIR = src LIBDIR = lib INCLUDES= -I $(SRCDIR) -I $(LIBDIR) BFLAGS = $(INCLUDES) -g -dtypes OFLAGS = $(INCLUDES) # main target ############# NAME=ocamlgraph ifeq (@LABLGNOMECANVAS@,yes) all: byte $(OCAMLBEST) viewer dgraph editor else all: byte $(OCAMLBEST) endif # bytecode and native-code compilation ###################################### LIB= unionfind heap bitv LIB:=$(patsubst %, $(LIBDIR)/%.cmo, $(LIB)) CMO = version util blocks persistent imperative \ delaunay builder classic rand oper \ components path nonnegative traverse coloring topological kruskal flow \ dominator graphviz gml dot_parser dot_lexer dot pack \ gmap minsep cliquetree mcs_m md strat fixpoint leaderlist contraction \ graphml merge CMO := $(LIB) $(patsubst %, $(SRCDIR)/%.cmo, $(CMO)) CMX = $(CMO:.cmo=.cmx) CMA = graph.cma CMXA = graph.cmxa CMI = sig sig_pack dot_ast CMI := $(patsubst %, src/%.cmi, $(CMI)) GENERATED = META \ src/gml.ml src/version.ml \ src/dot_parser.ml src/dot_parser.mli src/dot_lexer.ml $(CMX): OFLAGS += -for-pack Graph byte: $(CMA) opt: $(CMXA) graph.cma: graph.cmo $(OCAMLC) $(INCLUDES) -a -g -o $@ $^ graph.cmxa: graph.cmx $(OCAMLOPT) $(INCLUDES) -a -o $@ $^ graph.cmi: graph.cmo graph.o: graph.cmx graph.cmo: $(CMI) $(CMO) $(OCAMLC) $(INCLUDES) -pack -g -o $@ $^ graph.cmx: $(CMI) $(CMX) $(OCAMLOPT) $(INCLUDES) -pack -o $@ $^ VERSION=1.8.3 src/version.ml: Makefile rm -f $@ echo "let version = \""$(VERSION)"\"" > $@ echo "let date = \""`date`"\"" >> $@ # gtk2 graph editor ################### ED_DIR=editor editor: $(ED_DIR)/editor.byte $(ED_DIR)/editor.$(OCAMLBEST) ED_CMO = ed_hyper ed_graph ed_draw ed_display ed_main ED_CMO:= $(patsubst %, $(ED_DIR)/%.cmo, $(ED_CMO)) ED_CMX = $(ED_CMO:.cmo=.cmx) ED_CMI = $(ED_CMO:.cmo=.cmi) ED_INCLUDES = @INCLUDEGTK2@ -I +threads -I $(ED_DIR) $(INCLUDES) -I . $(ED_CMI) $(ED_CMO): BFLAGS+= $(ED_INCLUDES) $(ED_CMI) $(ED_CMO): $(CMA) $(ED_CMX): OFLAGS+= $(ED_INCLUDES) $(ED_CMX): $(CMXA) $(ED_DIR)/editor.byte: $(CMA) $(ED_CMO) $(OCAMLC) -g -o $@ $(ED_INCLUDES) \ lablgtk.cma lablgnomecanvas.cma unix.cma $^ $(ED_DIR)/editor.opt: $(CMXA) $(ED_CMX) $(OCAMLOPT) -o $@ $(ED_INCLUDES) \ lablgtk.cmxa lablgnomecanvas.cmxa unix.cmxa $^ # gtk2 graph viewer (deprecated) ################### VIEWER_DIR=view_graph viewer: $(VIEWER_DIR)/viewgraph.byte $(VIEWER_DIR)/viewgraph.$(OCAMLBEST) VIEWER_CMO=viewGraph_core viewGraph_select viewGraph_utils viewGraph_test VIEWER_CMO:=$(patsubst %,$(VIEWER_DIR)/%.cmo, $(VIEWER_CMO)) VIEWER_CMX=$(VIEWER_CMO:.cmo=.cmx) VIEWER_CMI=$(VIEWER_CMO:.cmo=.cmi) VIEWER_MLI=$(VIEWER_CMI:.cmi=.mli) VIEWER_INCLUDES= @INCLUDEGTK2@ -I $(VIEWER_DIR) $(INCLUDES) -I . $(VIEWER_CMI) $(VIEWER_CMO): BFLAGS+= $(VIEWER_INCLUDES) $(VIEWER_CMX): OFLAGS+= $(VIEWER_INCLUDES) -for-pack Viewgraph $(VIEWER_CMI) $(VIEWER_CMO): $(CMA) $(VIEWER_CMX): $(CMXA) VIEWER_CMOLIB = $(VIEWER_DIR)/viewgraph.cmo VIEWER_CMILIB = $(VIEWER_DIR)/viewgraph.cmi VIEWER_CMXLIB = $(VIEWER_DIR)/viewgraph.cmx $(VIEWER_CMOLIB): $(filter-out $(VIEWER_DIR)/viewGraph_test.cmo, $(VIEWER_CMO)) $(OCAMLC) -o $@ $(VIEWER_INCLUDES) -pack $^ $(VIEWER_CMXLIB): $(filter-out $(VIEWER_DIR)/viewGraph_test.cmx, $(VIEWER_CMX)) $(OCAMLOPT) -o $@ $(VIEWER_INCLUDES) -pack $^ $(VIEWER_DIR)/viewgraph.byte: $(CMA) $(VIEWER_CMOLIB) $(OCAMLC) -g -o $@ $(VIEWER_INCLUDES) \ lablgtk.cma gtkInit.cmo lablgnomecanvas.cma unix.cma $^ $(VIEWER_DIR)/viewgraph.opt: $(CMXA) $(VIEWER_CMXLIB) $(OCAMLOPT) -o $@ $(VIEWER_INCLUDES) \ lablgtk.cmxa gtkInit.cmx lablgnomecanvas.cmxa unix.cmxa $^ # new gtk2 graph viewer: dgraph ############################### DGRAPH_DIR=dgraph dgraph: $(DGRAPH_DIR)/dgraph.byte $(DGRAPH_DIR)/dgraph.$(OCAMLBEST) DGRAPH_CMO=xDotDraw xDot \ dGraphModel \ dGraphTreeLayout dGraphSubTree dGraphTreeModel \ dGraphViewItem dGraphView \ dGraphRandModel dGraphContainer \ dGraphViewer DGRAPH_CMO:=$(patsubst %,$(DGRAPH_DIR)/%.cmo, $(DGRAPH_CMO)) DGRAPH_CMX=$(DGRAPH_CMO:.cmo=.cmx) DGRAPH_CMI=$(filter-out dgraph/dGraphViewer.cmi, $(DGRAPH_CMO:.cmo=.cmi)) DGRAPH_INCLUDES= @INCLUDEGTK2@ -I $(DGRAPH_DIR) $(INCLUDES) -I . $(DGRAPH_CMI) $(DGRAPH_CMO): BFLAGS+= $(DGRAPH_INCLUDES) $(DGRAPH_CMX): OFLAGS+= $(DGRAPH_INCLUDES) -for-pack Dgraph $(DGRAPH_CMI) $(DGRAPH_CMO): $(CMA) $(DGRAPH_CMX): $(CMXA) DGRAPH_CMOLIB = $(DGRAPH_DIR)/dgraph.cmo DGRAPH_CMILIB = $(DGRAPH_DIR)/dgraph.cmi DGRAPH_CMXLIB = $(DGRAPH_DIR)/dgraph.cmx dgraph/dGraphViewer.cmo: $(DGRAPH_CMOLIB) dgraph/dGraphViewer.cmx: $(DGRAPH_CMXLIB) $(DGRAPH_CMOLIB): $(filter-out dgraph/dGraphViewer.cmo, $(DGRAPH_CMO)) $(OCAMLC) -o $@ $(DGRAPH_INCLUDES) -pack $^ $(DGRAPH_CMXLIB): $(filter-out dgraph/dGraphViewer.cmx, $(DGRAPH_CMX)) $(OCAMLOPT) -o $@ $(DGRAPH_INCLUDES) -pack $^ $(DGRAPH_DIR)/dgraph.byte: $(CMA) $(DGRAPH_CMOLIB) \ $(DGRAPH_DIR)/dGraphViewer.cmo $(OCAMLC) -g -o $@ $(DGRAPH_INCLUDES) \ lablgtk.cma gtkInit.cmo lablgnomecanvas.cma $^ $(DGRAPH_DIR)/dgraph.opt: $(CMXA) $(DGRAPH_CMXLIB) \ $(DGRAPH_DIR)/dGraphViewer.cmx $(OCAMLOPT) -o $@ $(DGRAPH_INCLUDES) \ lablgtk.cmxa gtkInit.cmx lablgnomecanvas.cmxa $^ # Examples ########## EXAMPLESBIN=bin/demo.$(OCAMLBEST) bin/demo_planar.$(OCAMLBEST) \ bin/bench.$(OCAMLBEST) bin/color.$(OCAMLBEST) bin/sudoku.$(OCAMLBEST) \ bin/test.$(OCAMLBEST) .PHONY: examples examples: $(EXAMPLESBIN) .PHONY: demo demo: bin/demo.$(OCAMLBEST) bin/demo.byte: $(CMA) examples/demo.cmo $(OCAMLC) -o $@ $^ bin/demo.opt: $(CMXA) examples/demo.cmx $(OCAMLOPT) -o $@ $^ bin/demo_planar.byte: $(CMA) examples/demo_planar.cmo $(OCAMLC) -o $@ graphics.cma unix.cma $^ bin/demo_planar.opt: $(CMXA) examples/demo_planar.cmx $(OCAMLOPT) -o $@ graphics.cmxa unix.cmxa $^ bin/color.byte: $(CMA) examples/color.cmo $(OCAMLC) -o $@ graphics.cma unix.cma $^ bin/color.opt: $(CMXA) examples/color.cmx $(OCAMLOPT) -o $@ graphics.cmxa unix.cmxa $^ bin/sudoku.byte: $(CMA) examples/sudoku.cmo $(OCAMLC) -o $@ graphics.cma unix.cma $^ bin/sudoku.opt: $(CMXA) examples/sudoku.cmx $(OCAMLOPT) -o $@ graphics.cmxa unix.cmxa $^ test: $(CMA) tests/test.ml ocaml unix.cma graphics.cma $^ test-bf: $(CMA) tests/test_bf.ml ocaml unix.cma graphics.cma $^ bin/test-ts: $(CMXA) tests/test_topsort.ml $(OCAMLOPT) -o $@ unix.cmxa $^ test-ts: bin/test-ts bin/test-ts 10 nonneg: $(CMA) tests/nonneg.ml ocaml unix.cma graphics.cma $^ test-graphml: $(CMA) tests/testgraphml.ml ocaml unix.cma $^ bin/test.byte: $(CMA) tests/test.cmo $(OCAMLC) -g -unsafe -o $@ unix.cma graphics.cma $^ bin/test.opt: $(CMXA) tests/test.cmx $(OCAMLOPT) -unsafe -inline 100 -o $@ unix.cmxa graphics.cmxa $^ bin/test_bf.byte: $(CMA) tests/test_bf.ml $(OCAMLC) -g -o $@ unix.cma graphics.cma $^ bin/nonneg.byte: $(CMA) tests/nonneg.ml $(OCAMLC) -g -o $@ unix.cma graphics.cma $^ bench: bin/bench.$(OCAMLBEST) bin/bench.opt bin/bench.opt: $(CMXA) tests/bench.ml $(OCAMLOPT) -unsafe -inline 100 -o $@ unix.cmxa $^ check: $(CMA) tests/check.ml bin/test-ts ocaml $(CMA) tests/check.ml bin/test-ts 10 # Additional rules ################## EXAMPLES = demo color demo_planar sudoku EXAMPLESBIN:=$(patsubst %, bin/%.opt, $(EXAMPLES)) EXAMPLES:= $(patsubst %, examples/%.ml, $(EXAMPLES)) examples: $(EXAMPLESBIN) TESTS = test check TESTS := $(patsubst %, tests/%.ml, $(TESTS)) DPD_GRAPH_ML= $(TESTS) $(EXAMPLES) $(DPD_GRAPH_ML:.ml=.cmo): $(CMA) $(DPD_GRAPH_ML:.ml=.cmx): $(CMXA) # installation ############## INSTALL_LIBDIR=$(DESTDIR)$(OCAMLLIB)/ocamlgraph install: install-$(OCAMLBEST) install-byte mkdir -p $(BINDIR) ifeq (@LABLGNOMECANVAS@,yes) ifeq ($(OCAMLBEST),byte) cp -f $(BINDIR)/graph-editor.byte $(BINDIR)/graph-editor$(EXE) cp -f $(BINDIR)/graph-viewer.byte $(BINDIR)/graph-viewer$(EXE) else cp -f $(BINDIR)/graph-editor.opt $(BINDIR)/graph-editor$(EXE) cp -f $(BINDIR)/graph-viewer.opt $(BINDIR)/graph-viewer$(EXE) endif endif install-byte: mkdir -p $(INSTALL_LIBDIR) cp -f graph.cmo graph.cmi $(CMA) $(INSTALL_LIBDIR) cp -f $(SRCDIR)/*.mli $(INSTALL_LIBDIR) ifeq (@LABLGNOMECANVAS@,yes) mkdir -p $(BINDIR) cp -f $(ED_DIR)/editor.byte $(BINDIR)/graph-editor.byte cp -f $(VIEWER_CMILIB) $(VIEWER_CMOLIB) $(INSTALL_LIBDIR) cp -f $(DGRAPH_CMILIB) $(DGRAPH_CMOLIB) $(INSTALL_LIBDIR) cp -f $(VIEWER_DIR)/*.mli $(DGRAPH_DIR)/*.mli $(INSTALL_LIBDIR) cp -f $(DGRAPH_DIR)/dgraph.byte $(BINDIR)/graph-viewer.byte endif install-opt: install-byte mkdir -p $(INSTALL_LIBDIR) cp -f graph$(LIBEXT) graph.cmi graph.cmx $(CMXA) $(INSTALL_LIBDIR) cp -f $(SRCDIR)/*.mli $(INSTALL_LIBDIR) ifeq (@LABLGNOMECANVAS@,yes) mkdir -p $(BINDIR) cp -f $(ED_DIR)/editor.opt $(BINDIR)/graph-editor.opt cp -f $(VIEWER_CMILIB) $(VIEWER_CMXLIB) $(VIEWER_CMXLIB:.cmx=.o) \ $(INSTALL_LIBDIR) cp -f $(DGRAPH_CMILIB) $(DGRAPH_CMXLIB) $(DGRAPH_CMXLIB:.cmx=.o) \ $(INSTALL_LIBDIR) cp -f $(DGRAPH_DIR)/dgraph.opt $(BINDIR)/graph-viewer.opt cp -f $(VIEWER_DIR)/*.mli $(DGRAPH_DIR)/*.mli $(INSTALL_LIBDIR) endif install-findlib: META ifdef OCAMLFIND ifeq (@LABLGNOMECANVAS@,yes) $(OCAMLFIND) install ocamlgraph META \ $(SRCDIR)/*.mli $(VIEWER_DIR)/*.mli $(DGRAPH_DIR)/*.mli \ graph$(LIBEXT) graph.cmx graph.cmo graph.cmi $(CMA) $(CMXA) \ $(VIEWER_CMXLIB) $(VIEWER_CMOLIB) $(DGRAPH_CMXLIB) \ $(DGRAPH_CMOLIB) else $(OCAMLFIND) install ocamlgraph META \ $(SRCDIR)/*.mli $(VIEWER_DIR)/*.mli $(DGRAPH_DIR)/*.mli \ graph$(LIBEXT) graph.cmx graph.cmo graph.cmi $(CMA) $(CMXA) endif endif META: META.in Makefile sed -e s/VERSION/$(VERSION)/ -e s/CMA/$(CMA)/ -e s/CMXA/$(CMXA)/ \ $@.in > $@ # documentation ############### DOCFILES=$(NAME).ps $(NAME).html NODOC = blocks dot_parser dot_lexer version NODOC := $(patsubst %, $(SRCDIR)/%.cmo, $(NODOC)) DOC_CMO = $(filter-out $(NODOC) $(LIB), $(CMO)) DOC_SRC = $(CMI:.cmi=.mli) $(DOC_CMO:.cmo=.mli) $(DOC_CMO:.cmo=.ml) ifeq (@LABLGNOMECANVAS@,yes) DOC_SRC := $(DOC_SRC) $(DGRAPH_CMI:.cmi=.mli) endif .PHONY: doc doc: $(DOC_CMO) mkdir -p doc rm -f doc/* $(OCAMLDOC) -d doc -html $(DGRAPH_INCLUDES) $(DOC_SRC) # literate programming $(NAME).tex: $(DOC_SRC) $(OCAMLWEB) -o $@ $^ wc: ocamlwc -p $(SRCDIR)/*.mli $(SRCDIR)/*.ml # file headers ############## headers: headache \ -c misc/headache_config.txt \ -h misc/header.txt \ Makefile.in configure.in README \ $(LIBDIR)/*.ml $(LIBDIR)/*.ml[ily] \ $(SRCDIR)/*.ml $(SRCDIR)/*.ml[ily] \ $(ED_DIR)/*.ml $(ED_DIR)/*.mli headache \ -c misc/headache_config.txt \ -h $(DGRAPH_DIR)/headers/CEA_LGPL \ $(DGRAPH_DIR)/*.ml $(DGRAPH_DIR)/*.mli # export ######## EXPORTDIR=$(NAME)-$(VERSION) TAR=$(EXPORTDIR).tar FTP = /users/www-perso/projets/ocamlgraph/download WWW = /users/www-perso/projets/ocamlgraph FILES = src/*.ml* lib/*.ml* Makefile.in configure configure.in META.in \ .depend editor/ed_*.ml* editor/Makefile \ editor/tests/*.dot editor/tests/*.gml \ view_graph/*.ml view_graph/*.mli \ view_graph/README view_graph/Makefile \ dgraph/*.ml dgraph/*.mli \ examples/*.ml tests/*.ml \ README FAQ CREDITS INSTALL COPYING LICENSE CHANGES export: source export-doc export-web export-delaunay source: mkdir -p export cd export; rm -rf $(EXPORTDIR) mkdir -p export/$(EXPORTDIR)/bin cp --parents $(FILES) export/$(EXPORTDIR) cd export ; tar cf $(TAR) $(EXPORTDIR) ; gzip -f --best $(TAR) cp export/$(TAR).gz $(FTP) cp README FAQ CREDITS COPYING LICENSE CHANGES $(EXAMPLES) $(FTP) # Build and install the .tar.gz requiered by Frama-C framac: EXPORTDIR=ocamlgraph framac: FTP=$$HOME/frama-c framac: mkdir -p export cd export; rm -rf $(EXPORTDIR) mkdir -p export/$(EXPORTDIR)/bin cp --parents $(FILES) export/$(EXPORTDIR) cd export ; tar cf $(TAR) $(EXPORTDIR) ; gzip -f --best $(TAR) cp export/$(TAR).gz $(FTP) make -C $(FTP) force-ocamlgraph www/version.prehtml: Makefile.in echo "<#def version>$(VERSION)" > www/version.prehtml export-web: www/version.prehtml make -C www install export-doc: $(DOC_CMO) rm -f $(WWW)/doc/* -$(OCAMLDOC) -d $(WWW)/doc -html $(DGRAPH_INCLUDES) $(DOC_SRC) MISCFTP = $(HOME)/WWW/ftp/ocaml/misc DELAUNAY=delaunay.ml delaunay.mli export-delaunay: cd src; cp -f $(DELAUNAY) $(MISCFTP) cd src; rm -f delaunay.annot; caml2html -noannot -d $(MISCFTP) $(DELAUNAY) # generic rules ############### .SUFFIXES: .mli .ml .cmi .cmo .cmx .mll .mly .tex .dvi .ps .html .mli.cmi: $(OCAMLC) -c $(BFLAGS) $< .ml.cmo: $(OCAMLC) -c $(BFLAGS) $< .ml.o: $(OCAMLOPT) -c $(OFLAGS) $< .ml.cmx: $(OCAMLOPT) -c $(OFLAGS) $< .mll.ml: $(OCAMLLEX) $< .mly.ml: $(OCAMLYACC) -v $< .mly.mli: $(OCAMLYACC) -v $< .tex.dvi: latex $< && latex $< .dvi.ps: dvips $< -o $@ .tex.html: hevea $< # Emacs tags ############ otags: otags -r src editor view_graph tags: find . -name "*.ml*" | sort -r | xargs \ etags "--regex=/let[ \t]+\([^ \t]+\)/\1/" \ "--regex=/let[ \t]+rec[ \t]+\([^ \t]+\)/\1/" \ "--regex=/and[ \t]+\([^ \t]+\)/\1/" \ "--regex=/type[ \t]+\([^ \t]+\)/\1/" \ "--regex=/exception[ \t]+\([^ \t]+\)/\1/" \ "--regex=/val[ \t]+\([^ \t]+\)/\1/" \ "--regex=/module[ \t]+\([^ \t]+\)/\1/" # Makefile is rebuilt whenever Makefile.in or configure.in is modified ###################################################################### Makefile: Makefile.in config.status if test -e $@; then chmod a+w $@; fi ./config.status chmod a-w $@ config.status: configure ./config.status --recheck configure: configure.in autoconf # clean ####### clean: rm -f *~ for d in $(SRCDIR) $(LIBDIR) $(ED_DIR) $(VIEWER_DIR) $(DGRAPH_DIR) \ tests examples; \ do \ rm -f $$d/*.cm[iox] $$d/*$(OBJEXT) $$d/*~ $$d/*.annot; \ done rm -f $(GENERATED) $(SRCDIR)/dot_parser.output rm -f graph.*a graph.cm* graph.o graph$(LIBEXT) rm -f $(ED_DIR)/editor.byte $(ED_DIR)/editor.opt rm -f $(VIEWER_DIR)/viewgraph.byte $(VIEWER_DIR)/viewgraph.opt rm -f $(DGRAPH_DIR)/dgraph.byte $(DGRAPH_DIR)/dgraph.opt rm -f $(DGRAPH_DIR)/dgraph rm -f *.haux *.aux *.log $(NAME).tex $(NAME).dvi $(DOCFILES) rm -f $(EXAMPLESBIN) dist-clean distclean:: clean rm -f Makefile config.cache config.log config.status *.byte *.opt svnclean svn-clean:: dist-clean rm -f config.* configure configure.lineno # depend ######## .PHONY: depend .depend depend: $(GENERATED) rm -f .depend $(OCAMLDEP) $(INCLUDES) -I $(ED_DIR) -I $(VIEWER_DIR) -I $(DGRAPH_DIR)\ $(LIBDIR)/*.ml $(LIBDIR)/*.mli \ $(SRCDIR)/*.ml $(SRCDIR)/*.mli \ $(ED_DIR)/*.mli $(ED_DIR)/*.ml \ $(VIEWER_DIR)/*.mli $(VIEWER_DIR)/*.ml \ $(DGRAPH_DIR)/*.mli $(DGRAPH_DIR)/*.ml > .depend include .depend ocamlgraph-1.8.3/CHANGES0000644000175000017500000003022612133565072013600 0ustar mehdimehdi version 1.8.3, April 17, 2013 --------------------------- o new module Merge implementing several different of merges of vertices and edges into a graph (contributed by Emmanuel Haucourt) o fixed DOT parser (contributed by Alex Reece) o Topological: fixed bug in presence of disjoint cycles; new implementation o new module [Graphml] to export graphs into the graphml format (contributed by Pietro Abate) o Builder.S now contains functions remove_*. o modified Fixpoint module so that it also works with unlabeled graphs (contributed by Markus W. Weissmann) o support of lablgtk2 installed with findlib (contributed by B. Monate) o new module [Dominator] to compute dominators (contributed by David Brumley and Ivan Jager) version 1.8.2, May 12, 2012 --------------------------- o new module [Path.BellmanFord] implementing Bellman-Ford algorithm (contributed by Yuto Takei) o new module Contraction implementing edge contraction (contributed by Markus W. Weissmann) o Gmap: new function [filter_map] (contributed by Markus W. Weissmann) o Topological: fix bug when a cycle depends on another cycle. That breaks compatibility: the input graph must implement Sig.COMPARABLE instead of Sig.HASHABLE o new module Topological.Make_stable to iterate over a graph in a **stable** topological order. Stable means that the provided ordering only depends on the graph topology and on the user's vertices ordering. o new module Leaderlist to compute the leader list algorithm (see the Dragon) (contributed by Markus W. Weissmann ) version 1.8.1, October 17, 2011 ------------------------------- o module Gmap now has a signature for edges (E_SRC) compatible with Sig, so that it is easier to apply functor Gmap.Edge (contributed by Markus W. Weissmann ) o new module Fixpoint to compute fixpoints using the work-list algorithm, e.g. for data flow analysis (contributed by Markus W. Weissmann ) version 1.8, October 4, 2011 ---------------------------- o removed ocamlyacc shift/reduce conflict in dot_parser.mly (patch contributed by Till Varoquaux) o Dgraph: Correct height and width-related problems with text o DGraph: many bug fixes. Patch by Benjamin Monate o Sig.G: new function [find_all_edges] for each graph implementation o Oper: fixed bug with function [intersect]: now use G.E.compare instead of (=) o fixed "make install-findlib" version 1.7, February 23, 2011 ------------------------------ o Makefile: fixed bug when installing ocamlgraph with ocamlfind o DGraph: fixed bug with colors on some windows manager o Configure: fixed issue with automatic detection of extension under Windows/Mingw version 1.6, December 13, 2010 ------------------------------ o DGraph: new viewer mode (called `tree') which focus on a subset part of the graph centered on a given node o Graphviz: fixed bug with attribute `Constraint (was `Constraints) (patch by Boris Yakobowski) o DGraph: fixed font size issue when zooming o DGraph: now interpret text anchors and espaced sequences correctly o DGraph: offer possibility to disable the default callbacks on nodes o 'make -j' works again o new implementation Persistent.Digraph.ConcreteBidirectionalLabeled o new implementation Persistent.Digraph.ConcreteBidirectional o Makefile: bug fixed when ocamlc (resp. ocamlopt) and ocamlc.opt (resp. ocamlopt.opt) are unconsistent version 1.5, April 29, 2010 --------------------------- o Makefile: bug fixed when installing ocamlgraph with ocamlfind (patch by Virgile Prevosto) o DGraph: new method set_zoom_padding in DgraphView.view o Traverse.Dfs.has_cycle: can now be used on undirected graphs as well, and is now tail recursive o DGraph: handle dotted ellipse version 1.4, March 24, 2010 --------------------------- o new function [clear] for imperative graphs o new implementation Imperative.Digraph.ConcreteBidirectionalLabeled (contribution of Jaap Boender) o Dgraph displays graphs faster o DGraph: several bugs fixed o DGraph: several API changes (may break compatibility with existing development) version 1.3, October 2, 2009 ---------------------------- o Oper.mirror: undirected graphs are not copied anymore o Oper.mirror: fixed bug (isolated vertices were lost) o Graphviz: new signature GraphWithDotAttrs o Improvements of Dgraph o Configure: better test for detecting lablgtk o OcamlGraph is now installed by default in `ocamlc -where`/ocamlgraph o Viewgraph is now packed in a single module Viewgraph (break compatibility with previous version) o Dgraph is now packed in a single module Dgraph (break compatibility with previous version) o Makefile: fixed bug when the installation directory of binaries does not exist o Makefile: fixed bug of ocamldep under Windows version 1.2, August 31, 2009 ---------------------------- o experimental: new GTK-based graph viewer called Dgraph (viewGraph is now deprecated) o added Delaunay.iter_triangles (not of use in Ocamlgraph, actually) version 1.1, June 23, 2009 -------------------------- o added constraint "type E.label = unit" to unlabeled graph data structure o viewGraph: new module viewGraph_utils; fixed compilation (gtkInit was missing; patch by Mehdi Dogguy) o configure: fixed bug under Cygwin (patch by Julien Bernet) o configure: look for lablgnomecanvas.cmxa when compiling in native code o Makefile: fixed make install-findlib when lablgtk and/or lablgnomecanvas not installed (patch by Peter Hawkins) version 1.0, October 14, 2008 ----------------------------- o license: LGPL updated to version 2.1 o ocamlgraph now requires ocaml 3.10 or higher o experimental: GTK-based graph viewer based on dot (contribution of Anne Pacalet) o Makefile: - fixed bug when lablgnomecanvas is not installed - fixed bug when ocamlfind is installed - patch to the build system for a DESTDIR (patch by Igor Galic) - "make -j" compliant o new function Blocks.after_unserialization in order to be able to safely serialize abstract vertices (see the FAQ) o Dot: - fixed bug in the parsing of attributes - fixed bug in the parsing of subgraphs (patch by Anne Pacalet) o Oper: fixed bug in intersect o Path: improved efficiency of Dijkstra o Topological: - fixed bug in Make.{iter,fold} - folding is now tail-recursive (patch by Michael Furr) version 0.99c, April 3rd, 2008 ------------------------------ o replicated a bug fix of Bitv (could not affect Matrix, though) o fixed DFS traversal in Traverse.Dfs.{prefix,prefix_component,iterator} version 0.99b, December 18th, 2007 ---------------------------------- o fixed link bug with ocaml 3.09 (see http://caml.inria.fr/mantis/view.php?id=4124) version 0.99a, November 21st, 2007 --------------------------------- o fixed bug in Makefile when lablgtk2 is not installed o Sig.I.create and Sig_pack.create are now of type ?size:int -> unit -> t (instead of unit -> t) to indicate an initial guess on the graph size version 0.99, June 27th, 2007 ----------------------------- o experimental: GTK-based graph editor based on hyperbolic geometry; to build it and test it, cd to editor/ and type make o [Components.Make] functor: function [scc] as a new profile and a more precise specification. New function [scc_array]. o fixed configure to set ocaml's standard library using "ocamlc -where" o new module Dot to parse files in Graphviz's DOT format o slight change in the license (no more clause 6 of the LGPL; see LICENSE) o new module Strat implementing simple game strategies o Graphviz: little refactoring and improved documentation version 0.98, Sep 27th, 2006 ---------------------------- o rename Sig.IA to Sig.IM o add subgraph support in Graphviz (breaks ascendent compatibility if you use Graphviz: by default add let get_subgraph _ = None in the argument of Graphviz.Dot and Graphviz.Neato) version 0.97, July 20th, 2006 ----------------------------- o fixed compilation under Windows/Cygwin (contributed by Denis Berthod) o fixed bug with escaped string in Graphviz version 0.96, May 2nd, 2006 --------------------------- o new demo program: sudoku.ml (solving the Sudoku using graph coloring) o new module Coloring for (rather brute force) graph coloring o new implementation Imperative.Digraph.ConcreteBidirectional that maintains the set of ingoing edges for each node, thus improving the efficiency of functions such as iter_pred, pred, in_degree, etc. (contributed by Ted Kremenek) version 0.95, November 2nd, 2005 -------------------------------- o compatibility with ocaml 3.09 o new module Path.Check to check for paths version 0.94, July 6th, 2005 ---------------------------- o new module Gml to parse and print graphs in GML file format (see http://www.infosun.fmi.uni-passau.de/Graphlet/GML) corresponding functions parse_gml_file and print_gml_file in Pack o added display_with_gv in Pack o improved implementation of Unionfind (patch by Marc Lasson) version 0.93, March 31st, 2005 ------------------------------ o fixed bug in Rand (integer overflow causing Invalid_argument "random"); improved code in Rand o bug fixed in the META file o add find_edge in Sig.G (and so in all graph implementations) version 0.92, January 18th, 2005 -------------------------------- o fixed escaped labels in Graphviz output (patch by Boris Yakobowski) o new Graphviz option OrderingOut (patch by Boris Yakobowski) o fixed sharing bugs in Oper (patch by Boris Yakobowski) o fixed bug in nb_edges for undirected graphs o improvement of iterators of undirected concrete graphs version 0.91, December 16th, 2004 --------------------------------- o more precise specifications of remove_edge and shortest_path. o bug fixed in mem_edge_e of labelled graphs o generation of random graphs improved o add Rand.Make and Rand.Planar.Make (generic functors) o add signatures Persistent.S and Imperative.S version 0.90, November 30th, 2004 --------------------------------- o graph.cma graph.cmxa o version.ml and META files are now writable o add interfaces Sig.VERTEX and Sig.EDGE o "sig.ml" and "sig_pack.ml" removed; ocamlgraph now requires ocaml 3.08.0 o improvement of Minsep o add Components.scc_list o Oper.Neighbourhood replaces Neighborhood o Gmap replaces Copy o add types Sig_pack.vertex and Sig_pack.edge o fixed bug in Ford-Fulkerson: G.V.equal instead of = in two asserts version 0.81, July 13th, 2004 ----------------------------- o compatibility with ocaml 3.08 o Oper.Choose.choose_edge: choose an edge in a graph o add types Sig.G.edge and Sig.G.vertex resp. equal to Sig.G.V.t and Sig.G.E.t o fixed typos in invalid_arg arguments (in Bitv) version 0.80, June 28th, 2004 ----------------------------- o major contribution by Matthieu Sozeau and Pierre-Loïc Garoche. New modules are: - Md: Minimum Degree algorithm - Cliquetree: the clique tree of a graph - Mcs_m: Maximal Cardinality Search (MCS-M) algorithm - Minsep: Minimal separators of a graph - Neighborhood: compute the neighborhood of a vertex/some vertices - Oper.Difference: subgraphs induced by the elimination of some vertices - Oper.Choose: choose a vertex in a graph - Copy: graphs copying - Util.DataV: create a vertex type with data attached to it o out_degree: raises Invalid_argument if v not in g (instead of Not_found) o Pack.Graph: golberg/ford_fulkerson fail ("not a directed graph") version 0.70, Feb 27th, 2004 ---------------------------- o Makefile.in: dependences ("make -j" works) o union and intersection (see Oper.S.union and Oper.S.intersection) o Golberg/Ford_fulkerson algorithms in a single module Flow o step-by-step iterators in Traverse.{Dfs,Bfs} o Ford_fulkerson: maxflow now returns a flow function over edges version 0.60, Feb 18th, 2004 ---------------------------- o fixed bug in Ford-Fulkerson o random planar graphs (see Rand.Planar) o Delaunay triangulation (see Delaunay) o implementations with adjacency matrices (see Imperative.Matrix) o operations on predecessors for undirected graphs optimized o Traverse.Dfs.{prefix,prefix_component} optimized (now tail recursive) version 0.50, Feb 4th, 2004 --------------------------- o first release Local Variables: mode: text End: ocamlgraph-1.8.3/CREDITS0000644000175000017500000000023412133565071013620 0ustar mehdimehdi Contributors, in alphabetic order Sylvain Conchon Jean-Christophe Filliâtre François Pottier Julien Signoles Vincent Simonet Matthieu Sozeau ocamlgraph-1.8.3/editor/0000755000175000017500000000000012133565071014067 5ustar mehdimehdiocamlgraph-1.8.3/editor/ed_draw.ml0000644000175000017500000001214112133565071016025 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This file is a contribution of Benjamin Vadon *) open Graph open Ed_hyper open Ed_graph let make_subgraph l = let gl = G.create () in List.iter (fun v -> G.add_vertex gl v) l; List.iter (fun v -> List.iter (fun w -> if edge v w then G.add_edge gl v w) l) l; (* TODO: efficacite *) gl let order_children l = let gl = make_subgraph l in let scc = Components.scc_list gl in let order_component c = let gc = make_subgraph c in (* choose a vertex v of minimal out degree *) let v = match c with | v :: l -> List.fold_left (fun m v -> if G.out_degree gc v < G.out_degree gc m then v else m) v l | [] -> assert false in let l = ref [] in Dfs.prefix_component (fun w -> l := w :: !l) gc v; !l in let scc = List.map order_component scc in List.flatten scc (* Depth First Search drawing *) let rec draw_dfs depth node turtle = let lab = G.V.label node in lab.turtle <- turtle; lab.depth <- depth; if hspace_dist_sqr turtle <= rlimit_sqr then begin lab.visible <- Visible; let l = G.succ !graph node in let l = List.filter (fun x -> (G.V.label x).visible = Hidden) l in List.iter (fun w -> (G.V.label w).visible <- BorderNode) l; let l = order_children l in let n = List.length l in if n > 0 then begin let distance = step_from (if depth = 0 then max 3 n else 2 * max 3 n) and angle = (if depth = 0 then 2. else 1.) *. pi /. (float_of_int n) in let turtle = if depth = 0 then turtle else turn_right turtle ((pi -. angle) /. 2.) in let _ = draw_edges_dfs node (depth+1) turtle distance angle l in () end end and draw_edges_dfs node depth turtle distance angle = function | [] -> [] | v :: l -> let e = G.E.label (G.find_edge !graph node v) in e.visited <- true; e.edge_turtle <- turtle; e.edge_distance <- distance; let steps = 10 in e.edge_steps <- steps; let tv = advance_many turtle distance steps in let turtle = turn_left turtle angle in let l = (v,tv) :: draw_edges_dfs node depth turtle distance angle l in draw_dfs depth v tv; l (* Breadth First Search drawing *) let draw_bfs root turtle = let q = Queue.create () in let add v n t = Queue.push v q; let lab = G.V.label v in lab.turtle <- t; lab.depth <- n in add root 0 turtle; while not (Queue.is_empty q) do let v = Queue.pop q in let lab = G.V.label v in let depth = lab.depth in let tv = lab.turtle in let dist = hspace_dist_sqr tv in (* Format.eprintf"le noeud : %s la val presente apres :%f \n@."lab.label dist;*) if dist <= rlimit_sqr then begin lab.visible <- Visible; let l = try G.succ !graph v with Invalid_argument _ -> [] in let l = List.filter (fun x -> (G.V.label x).visible = Hidden) l in List.iter (fun w -> (G.V.label w).visible <- BorderNode) l; let l = order_children l in let n = List.length l in if n > 0 then begin let distance = step_from (if depth = 0 then max 3 n else 2 * max 3 n) and angle = (if depth = 0 then 2. else 1.) *. pi /. (float_of_int n) in let turtle = ref (if depth = 0 then tv else turn_right tv ((pi -. angle) /. 2.)) in List.iter (fun w -> let e = G.E.label (G.find_edge !graph v w) in e.visited <- true; e.edge_turtle <- !turtle; e.edge_distance <- distance; let steps = 10 in e.edge_steps <- steps; let tw = advance_many !turtle distance steps in add w (depth + 1) tw; turtle := turn_left !turtle angle) l end end done (* Drawing graph function *) let draw_graph root turtle = G.iter_vertex (fun v -> let l = G.V.label v in l.visible <- Hidden) !graph; G.iter_edges_e (fun e -> let l = G.E.label e in l.visited <- false) !graph; (if !dfs then draw_dfs 0 else draw_bfs) root turtle ocamlgraph-1.8.3/editor/ed_main.ml0000644000175000017500000007354612133565071016034 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This file is a contribution of Benjamin Vadon *) open Format open Graph open Ed_hyper open Ed_graph open Ed_display open Ed_draw let debug = ref false let trace f x = try f x with e -> eprintf "TRACE: %s@." (Printexc.to_string e); raise e let _ = GMain.Main.init () (* Model for the treeview on the left *) module Model = struct open Gobject.Data let cols = new GTree.column_list let name = cols#add string let vertex = cols#add caml let model = GTree.tree_store cols let rows = H.create 97 let find_row v = try H.find rows v with Not_found -> Format.eprintf "anomaly: no model row for %s@." (string_of_label v); raise Not_found let add_vertex v = let row = model#append () in model#set ~row ~column:name (string_of_label v); model#set ~row ~column:vertex v; H.add rows v row; row let add_edge_1 row_v w = let row = model#append ~parent:row_v () in model#set ~row ~column:name (string_of_label w); model#set ~row ~column:vertex w let add_edge v w = let row_v = find_row v in add_edge_1 row_v w; if not G.is_directed then let row_w = find_row w in add_edge_1 row_w v let find_children row_v w = let nb_child = model#iter_n_children (Some row_v) in let rec find n = let child = model#iter_children ~nth:(n-1) (Some row_v) in let child_vertex = model#get ~row:child ~column:vertex in match n with | 0 -> raise Not_found | n -> if (G.V.equal child_vertex w) then child else find (n-1) in find nb_child let remove_edge_1 row_v w = ignore (model#remove (find_children row_v w)) let remove_edge v w = let row_v = find_row v in remove_edge_1 row_v w; if not G.is_directed then let row_w = find_row w in remove_edge_1 row_w v let remove_vertex vertex = G.iter_succ (fun w -> remove_edge w vertex) !graph vertex; let row = find_row vertex in model#remove row let reset () = H.clear rows; model#clear (); G.iter_vertex (fun v -> let row = add_vertex v in G.iter_succ (add_edge_1 row) !graph v) !graph end let () = Model.reset () open GtkTree let ed_name = "Ocamlgraph's Editor" (* Main GTK window *) let window = GWindow.window ~border_width: 10 ~position: `CENTER () (* usual function to change window title *) let set_window_title () = window#set_title (match !graph_name with | None -> ed_name | Some name -> ed_name^" : "^(Filename.chop_extension (Filename.basename name))) (* menu bar *) let v_box = GPack.vbox ~homogeneous:false ~spacing:30 ~packing:window#add () let menu_bar_box = GPack.vbox ~packing:v_box#pack () (* treeview on the left, canvas on the right *) let h_box = GPack.hbox ~homogeneous:false ~spacing:30 ~packing:v_box#add () let sw = GBin.scrolled_window ~shadow_type:`ETCHED_IN ~hpolicy:`NEVER ~vpolicy:`AUTOMATIC ~packing:h_box#add () let canvas = GnoCanvas.canvas ~aa:!aa ~width:(truncate w) ~height:(truncate h) ~packing:h_box#add () (* unit circle as root of graph drawing *) let canvas_root = let circle_group = GnoCanvas.group ~x:300.0 ~y:300.0 canvas#root in circle_group#lower_to_bottom (); let w2 = 2. in let circle = GnoCanvas.ellipse ~props:[ `X1 (-.w/.2. +.w2); `Y1 (-.h/.2. +.w2); `X2 (w/.2. -.w2) ; `Y2 ( h/.2. -.w2) ; `FILL_COLOR color_circle ; `OUTLINE_COLOR "black" ; `WIDTH_PIXELS (truncate w2) ] circle_group in circle_group#lower_to_bottom (); circle#show(); let graph_root = GnoCanvas.group ~x:(-.300.0) ~y:(-.300.0) circle_group in graph_root#raise_to_top (); set_window_title (); graph_root (* current root used for drawing *) let root = ref (choose_root ()) let load_graph f = Ed_graph.load_graph f; Model.reset (); set_window_title (); root := choose_root () (* refresh rate *) let refresh = ref 0 let do_refresh () = !refresh mod !refresh_rate = 0 (* graph drawing *) let draw tortue canvas = match !root with | None -> () | Some root -> Ed_draw.draw_graph root tortue; Ed_display.draw_graph root canvas; if do_refresh () then canvas_root#canvas#update_now () let refresh_draw () = refresh := 0; let tor = make_turtle !origine 0.0 in draw tor canvas_root let refresh_display () = Ed_display.draw_graph !root canvas_root let root_change vertex ()= root := vertex; origine := start_point; let turtle = make_turtle_origine () in draw turtle canvas_root let node_selection ~(model : GTree.tree_store) path = let row = model#get_iter path in let vertex = model#get ~row ~column: Model.vertex in root_change (Some vertex) () (* usual function ref, for vertex event *) let set_vertex_event_fun = ref (fun _ -> ()) (* type to select nature of modification *) type modification = Add | Remove (* add a vertex with no successor *) let add_node () = let window = GWindow.window ~title: "Choose vertex label" ~width: 300 ~height: 50 ~position: `MOUSE () in let vbox = GPack.vbox ~packing: window#add () in let entry = GEdit.entry ~max_length: 50 ~packing: vbox#add () in entry#set_text "Label"; entry#select_region ~start:0 ~stop:entry#text_length; (*two check buttons allowing to add node to selection list and to choose this node as root*) let hbox = GPack.hbox ~packing: vbox#add () in let is_in_selection = ref false in let in_selection = GButton.check_button ~label: "Add to selection" ~active:!is_in_selection ~packing: hbox#add () in ignore (in_selection#connect#toggled ~callback:(fun () ->is_in_selection := in_selection#active )); let is_as_root = ref ((G.nb_vertex !graph)=0) in let as_root = GButton.check_button ~label:"Choose as root" ~active:!is_as_root ~packing:hbox#add () in ignore (as_root#connect#toggled ~callback:(fun () ->is_as_root := as_root#active )); window#show (); (*entry's callback*) ignore( entry#connect#activate ~callback: (fun () -> let text = entry#text in window#destroy (); (* new vertex *) let vertex = G.V.create (make_node_info text) in G.add_vertex !graph vertex ; ignore (Model.add_vertex vertex); Ed_display.add_node canvas_root vertex; !set_vertex_event_fun vertex; if !is_as_root then root_change (Some vertex) () ; if !is_in_selection then update_vertex vertex Select; let tor = make_turtle !origine 0.0 in draw tor canvas_root)) (* add an edge between n1 and n2 , add link in column and re-draw *) let add_edge n1 n2 ()= if not (edge n1 n2) then begin G.add_edge_e !graph (G.E.create n1 (make_edge_info ()) n2); Model.add_edge n1 n2; let tor = make_turtle !origine 0.0 in draw tor canvas_root; end let add_edge_no_refresh n1 n2 ()= if not (edge n1 n2) then begin G.add_edge_e !graph (G.E.create n1 (make_edge_info ()) n2); Model.add_edge n1 n2 end (* remove an edge between n1 and n2 , add un-link in column and re-draw *) let remove_edge n1 n2 ()= if (edge n1 n2) then begin G.remove_edge !graph n1 n2; Model.remove_edge n1 n2; begin try let _,n = H2.find intern_edges (n1,n2) in n#destroy (); H2.remove intern_edges (n1,n2) with Not_found -> () end; begin try let _,n = H2.find intern_edges (n2,n1) in n#destroy (); H2.remove intern_edges (n2,n1) with Not_found -> () end; begin try let n = H2.find successor_edges (n1,n2) in n#destroy (); H2.remove successor_edges (n1,n2) with Not_found -> () end; begin try let n = H2.find successor_edges (n2,n1) in n#destroy (); H2.remove successor_edges (n2,n1) with Not_found -> () end; let tor = make_turtle !origine 0.0 in draw tor canvas_root; end let remove_edge_no_refresh n1 n2 ()= if (edge n1 n2) then begin G.remove_edge !graph n1 n2; Model.remove_edge n1 n2 end (* add successor node to selected node *) let add_successor node () = let window = GWindow.window ~title: "Choose label name" ~width: 300 ~height: 50 ~position: `MOUSE () in let vbox = GPack.vbox ~packing: window#add () in let entry = GEdit.entry ~max_length: 50 ~packing: vbox#add () in entry#set_text "Label"; entry#select_region ~start:0 ~stop:entry#text_length; window#show (); ignore (entry#connect#activate ~callback:(fun () -> let text = entry#text in window#destroy (); (* new vertex *) let vertex = G.V.create (make_node_info text) in G.add_vertex !graph vertex ; ignore (Model.add_vertex vertex); Ed_display.add_node canvas_root vertex; !set_vertex_event_fun vertex; (* new edge *) G.add_edge_e !graph (G.E.create node (make_edge_info()) vertex); Model.add_edge node vertex; (* redraw *) let tor = make_turtle !origine 0.0 in draw tor canvas_root ) ) let remove_vertex vertex () = G.iter_succ (fun w -> begin try let _,n = H2.find intern_edges (vertex,w) in n#destroy (); H2.remove intern_edges (vertex,w) with Not_found -> () end; begin try let _,n = H2.find intern_edges (w,vertex) in n#destroy (); H2.remove intern_edges (w,vertex) with Not_found -> () end; begin try let n = H2.find successor_edges (vertex,w) in n#destroy (); H2.remove successor_edges (vertex,w) with Not_found -> () end; begin try let n = H2.find successor_edges (w,vertex) in n#destroy (); H2.remove successor_edges (w,vertex) with Not_found -> () end; ) !graph vertex; let (n,_,_) = H.find nodes vertex in n#destroy (); H.remove nodes vertex; ignore (Model.remove_vertex vertex); G.remove_vertex !graph vertex; begin match !root with | None -> () | Some root_v -> if (G.V.equal root_v vertex) then root := choose_root(); end; refresh_draw () let sub_edge_to modif_type vertex list = let ll = List.length list in let nb_sub_menu = (ll - 1)/10 + 1 in let nb_edge = ll / nb_sub_menu -1 in let menu = new GMenu.factory (GMenu.menu()) in let sub_menu =ref (new GMenu.factory (GMenu.menu())) in let add_menu_edge vertex v2 = if not (G.V.equal v2 vertex) then begin match modif_type with | Add -> ignore((!sub_menu)#add_item (string_of_label v2) ~callback:( add_edge v2 vertex)); | Remove -> ignore((!sub_menu)#add_item (string_of_label v2) ~callback:(remove_edge v2 vertex)); end; in let rec make_sub_menu vertex list nb = match list with | [] -> () | v::list -> match nb with | 0 -> begin sub_menu :=new GMenu.factory (GMenu.menu()) ; add_menu_edge vertex v; let string = string_of_label v in ignore (menu#add_item (String.sub string 0 (min (String.length string) 3)^"...") ~submenu: !sub_menu#menu); make_sub_menu vertex list (nb+1); end | n when n= nb_edge-> begin add_menu_edge vertex v; make_sub_menu vertex list 0 end | _ -> begin add_menu_edge vertex v; make_sub_menu vertex list (nb+1) end in if ll > 10 then begin make_sub_menu vertex list 0; menu end else begin let rec make_sub_bis list = match list with | [] -> (); | v::list ->add_menu_edge vertex v; make_sub_bis list in make_sub_bis list; !sub_menu end let edge_to modif_type vertex list = (* add an edge between current vertex and one of selected vertex*) sub_edge_to modif_type vertex list let all_edges (edge_menu :#GMenu.menu GMenu.factory) vertex list = (*add all edges as possible from current vertex to selected vertices*) begin let add_all_edge vertex list () = List.iter (fun v -> if not (G.V.equal v vertex) then add_edge_no_refresh v vertex() ) list ; refresh := 0; let tor = make_turtle !origine 0.0 in draw tor canvas_root in ignore (edge_menu#add_item "Add all edges" ~callback:( add_all_edge vertex list)) end let contextual_menu vertex ev = let menu = new GMenu.factory (GMenu.menu ()) in (* change root*) ignore (menu#add_item "As root" ~callback:(root_change (Some vertex))); (*vertex menu*) let vertex_menu = new GMenu.factory (GMenu.menu ()) in begin (* successor *) ignore (vertex_menu#add_item "Add successor" ~callback:(add_successor vertex)); ignore (vertex_menu#add_separator ()); (* remove vertex *) ignore(vertex_menu#add_item "Remove vertex" ~callback:(remove_vertex vertex)); end; ignore(menu#add_item "Vertex ops" ~submenu: vertex_menu#menu); (*edge menu*) begin let add_list = selected_list (ADD_FROM vertex) in let rem_list = selected_list (REMOVE_FROM vertex) in let al =List.length add_list in let rl =List.length rem_list in let isel = is_selected vertex in let menu_bool = ref false in let edge_menu = new GMenu.factory (GMenu.menu ()) in begin (* add menu *) if isel && al=2 || not isel && al=1 then begin ignore (edge_menu#add_item "Add edge with" ~submenu: (edge_to Add vertex add_list)#menu); menu_bool := true; end else begin if isel && al>2 || not isel && al>1 then begin ignore (edge_menu#add_item "Add edge with" ~submenu: (edge_to Add vertex add_list)#menu); all_edges edge_menu vertex add_list; menu_bool := true; end end; (* remove menu *) if isel && rl>=2 || not isel && rl>=1 then begin if !menu_bool then ignore (edge_menu#add_separator ()); ignore (edge_menu#add_item "Remove edge with" ~submenu: (edge_to Remove vertex rem_list)#menu); menu_bool := true; end; if !menu_bool then ignore(menu#add_item "Edge ops" ~submenu: edge_menu#menu); end; end; menu#menu#popup ~button:3 ~time:(GdkEvent.Button.time ev) (* unit circle callback *) let circle_event ev = begin match ev with | `BUTTON_PRESS ev -> if (GdkEvent.Button.button ev) = 3 then begin let menu = new GMenu.factory (GMenu.menu ()) in ignore (menu#add_item " Add node" ~callback:(add_node)); menu#menu#popup ~button:3 ~time:(GdkEvent.Button.time ev) end | _ ->() end; true (* event for each vertex of canvas *) let vertex_event vertex item ellispe ev = (* let vertex_info = G.V.label vertex in*) begin match ev with | `ENTER_NOTIFY _ -> item#grab_focus (); update_vertex vertex Focus; refresh_display () | `LEAVE_NOTIFY ev -> if not (Gdk.Convert.test_modifier `BUTTON1 (GdkEvent.Crossing.state ev)) then begin update_vertex vertex Unfocus; refresh_display () end | `BUTTON_RELEASE ev -> ellispe#parent#ungrab (GdkEvent.Button.time ev); | `MOTION_NOTIFY ev -> incr refresh; let state = GdkEvent.Motion.state ev in if Gdk.Convert.test_modifier `BUTTON1 state then begin let curs = Gdk.Cursor.create `FLEUR in ellispe#parent#grab [`POINTER_MOTION; `BUTTON_RELEASE] curs (GdkEvent.Button.time ev); if do_refresh () then begin let old_origin = !origine in let turtle = motion_turtle ellispe ev in if hspace_dist_sqr turtle <= rlimit_sqr then begin draw turtle canvas_root end else begin origine := old_origin; let turtle = { turtle with pos = old_origin } in draw turtle canvas_root end end end | `BUTTON_PRESS ev -> if (GdkEvent.Button.button ev) = 3 then begin contextual_menu vertex ev end | `TWO_BUTTON_PRESS ev-> if (GdkEvent.Button.button ev) = 1 then begin if (Gdk.Convert.test_modifier `CONTROL (GdkEvent.Button.state ev)) then begin if ( !nb_selected =0) then begin select_all (); update_vertex vertex Focus end else begin unselect_all (); update_vertex vertex Focus end end else begin if (is_selected vertex) then update_vertex vertex Unselect else update_vertex vertex Select; end; refresh_draw (); end; | _ -> () end; true let set_vertex_event vertex = let item,ell,_ = H.find nodes vertex in ignore (item#connect#event (vertex_event vertex item ell)) let () = set_vertex_event_fun := set_vertex_event let set_canvas_event () = (* circle event *) ignore(canvas_root#parent#connect#event (circle_event)); (* vertex event *) G.iter_vertex set_vertex_event !graph (* treeview *) let add_columns ~(view : GTree.view) ~model = let renderer = GTree.cell_renderer_text [`XALIGN 0.] in let vc = GTree.view_column ~title:"Nodes" ~renderer:(renderer, ["text", Model.name]) () in ignore (view#append_column vc); vc#set_sizing `FIXED; vc#set_fixed_width 100; (* vc#set_resizable true;*) vc#set_sizing `AUTOSIZE; view#selection#connect#after#changed ~callback: begin fun () -> List.iter (fun p -> node_selection ~model p) view#selection#get_selected_rows; end let _ = window#connect#destroy~callback:GMain.Main.quit let treeview = GTree.view ~model:Model.model ~packing:sw#add () let () = treeview#set_rules_hint true let () = treeview#selection#set_mode `MULTIPLE let _ = add_columns ~view:treeview ~model:Model.model (* reset *) let reset_table_and_canvas () = let l = canvas_root#get_items in List.iter (fun v -> trace v#destroy ()) l; H2.clear intern_edges; H2.clear successor_edges; reset_display canvas_root; origine := start_point; nb_selected:=0 (* menu action functions *) (* choose a file to load or save to *) let ask_for_file (mode: [< `OPEN | `SAVE]) = let default_file d = function | None -> d | Some v -> v in let all_files () = let f = GFile.filter ~name:"All" () in f#add_pattern "*" ; f in let graph_filter () = GFile.filter ~name:"Fichier de graphes" ~patterns:[ "*.dot"; "*.gml" ] () in let dialog = begin match mode with | `OPEN -> let dialog = GWindow.file_chooser_dialog ~action: `OPEN ~title:"Open graph file" ~parent: window () in dialog#add_button_stock `CANCEL `CANCEL ; dialog#add_select_button_stock `OPEN `OPEN; dialog | `SAVE -> let dialog = GWindow.file_chooser_dialog ~action: `SAVE ~title: "Save graph as..." ~parent: window () in dialog#set_current_name "my_graph.dot"; dialog#add_button_stock `CANCEL `CANCEL ; dialog#add_select_button_stock `SAVE `SAVE; dialog end; in dialog#add_filter (graph_filter ()) ; dialog#add_filter (all_files ()) ; let f = match dialog#run () with | `OPEN -> default_file "" dialog#filename | `SAVE -> default_file "my_graph.dot" dialog#filename | `DELETE_EVENT | `CANCEL -> "" in dialog#destroy (); f (* menu action new graph *) let new_graph () = let alert_window = GWindow.message_dialog ~message:("Are you sure you want to start" ^" a new graph and discard all" ^" unsaved changes to :\n\n" ^"\t" ^(match !graph_name with | None -> "unamed" | Some name -> name) ^"") ~use_markup:true ~title:"New graph ?" ~message_type:`QUESTION ~buttons:GWindow.Buttons.yes_no ~parent:window ~resizable:false ~position:`CENTER_ON_PARENT () in begin match alert_window#run () with | `YES -> begin graph := G.create (); Model.reset(); reset_table_and_canvas (); graph_name := None; set_window_title () end | `DELETE_EVENT | `NO -> () end; alert_window#destroy () (* menu action open graph *) let open_graph () = let file = ask_for_file `OPEN in if file <> "" then begin load_graph file; reset_table_and_canvas (); let turtle = make_turtle_origine () in draw turtle canvas_root; set_canvas_event () end (* menu action save graph as *) let save_graph_as () = let file = ask_for_file `SAVE in if file <> "" then begin save_graph file; set_window_title () end (* menu action save graph *) let save_graph () = match !graph_name with | None -> () | Some name -> begin save_graph name; set_window_title () end (* menu action quit *) let quit () = let alert_window = GWindow.message_dialog ~message:("Are you sure you want to quit" ^" and discard all" ^" unsaved changes to :\n\n" ^"\t" ^(match !graph_name with | None -> "unamed" | Some name -> name) ^"") ~use_markup:true ~title:"Quit ?" ~message_type:`QUESTION ~buttons:GWindow.Buttons.yes_no ~parent:window ~resizable:false ~position:`CENTER_ON_PARENT () in begin match alert_window#run () with | `YES -> window#destroy () | `DELETE_EVENT | `NO -> () end (* menu action about *) let about () = let dialog = GWindow.about_dialog ~authors:["Ocamlgraph :"; " Sylvain Conchon"; " Jean-Christophe Filliatre"; " Julien Signoles"; ""; ed_name^" :"; " Vadon Benjamin"] ~comments:" Ocamlgraph: a generic graph library for OCaml" ~copyright:"Copyright (C) 2004-2007 Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles" ~license:" This software is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2, with the special exception on linking described in file LICENSE. This software 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." ~logo:(GdkPixbuf.from_file"ed_icon.xpm" ) ~name:ed_name ~version:"0.99" ~website:"http://ocamlgraph.lri.fr/" ~parent:window ~title:"About" ~resizable:false ~position:`CENTER_ON_PARENT () in try ignore( dialog#run ()) with Not_found -> dialog#destroy () let handbook_text (view:GText.view) = let buffer = view#buffer in (* text's tags *) ignore (buffer#create_tag ~name:"annotation" [`LEFT_MARGIN 10; `RIGHT_MARGIN 10; `SIZE (7*Pango.scale)]); ignore (buffer#create_tag ~name:"center" [`JUSTIFICATION `CENTER]); ignore (buffer#create_tag ~name:"heading" [`UNDERLINE `SINGLE; `WEIGHT `BOLD; `SIZE (14*Pango.scale)]); ignore (buffer#create_tag ~name:"italic" [`LEFT_MARGIN 10; `RIGHT_MARGIN 10; `STYLE `ITALIC]); ignore (buffer#create_tag ~name:"item" [`LEFT_MARGIN 20; `RIGHT_MARGIN 10]); ignore (buffer#create_tag ~name:"subsection" [`LEFT_MARGIN 10; `RIGHT_MARGIN 10]); ignore (buffer#create_tag ~name:"title" [`WEIGHT `BOLD; `SIZE (17*Pango.scale);`JUSTIFICATION `CENTER]); ignore (buffer#create_tag ~name:"word_wrap" [`WRAP_MODE `WORD; `EDITABLE false]); let iter = buffer#get_iter_at_char 0 in (* title *) buffer#insert ~iter ~tag_names:["title"] (ed_name^" Handbook\n"); (* editor's icon *) let image_anchor = buffer#create_child_anchor iter in let image = GMisc.image ~pixbuf:(GdkPixbuf.from_file_at_size "ed_icon.xpm" ~width:70 ~height:70) () in view#add_child_at_anchor image#coerce image_anchor; buffer#insert ~iter "\n\n\n"; let start,stop = buffer#bounds in buffer#apply_tag_by_name "center" ~start ~stop ; (* buffer's text *) buffer#insert ~iter ~tag_names:["heading"] "First words\n"; buffer#insert ~iter ~tag_names:["subsection"] ("\tFirst of all, you have to know this is an experimental application. " ^"If you find a bug, please report it to developpers. " ^"This application have only basic fonctionnalities on graphs, so if you want a new fonctionnality, send it too.\n"); buffer#insert ~iter ~tag_names:["subsection"] (ed_name^" represents a graph in hyperbolic geometry, and precisely in Poincaré's disk representation.\n\n" ^ed_name^" is organized in four parts :\n"); buffer#insert ~iter ~tag_names:["item"] "- a menu bar\n"; buffer#insert ~iter ~tag_names:["item"] "- a vertices list, on the left side\n"; buffer#insert ~iter ~tag_names:["item"] "- the Poincaré's disk\n"; buffer#insert ~iter ~tag_names:["item"] "- and an associated contextual menu\n\n"; buffer#insert ~iter ~tag_names:["heading"] "Menu bar\n"; buffer#insert ~iter ~tag_names:["subsection"] "\t It gives standard fonctionnalities. You can create a new graph, open and save graphs from/to Gml and Dot formats.\n"; buffer#insert ~iter ~tag_names:["italic"] "Don't forget to save your changes before create or load a new graph.\n\n"; buffer#insert ~iter ~tag_names:["heading"] "Vertices list\n"; buffer#insert ~iter ~tag_names:["subsection"] "\t You can change root of graph drawing by clicking on a vertex name. If you expand one, you can see successors of it.\n\n"; buffer#insert ~iter ~tag_names:["heading"] "Poincaré's disk\n"; buffer#insert ~iter ~tag_names:["subsection"] ("\t The graph is displayed in a disk. You can drag a vertex."); buffer#insert ~iter ~tag_names:["annotation"] "[1]\n"; buffer#insert ~iter ~tag_names:["subsection"] ("By double-clicking on a node, you add/remove it to selection.\nWith a +double-click you select all nodes, or unselect all (if one or more node is already selected)" ^"\n\n"); buffer#insert ~iter ~tag_names:["heading"] "Contextual menu\n"; buffer#insert ~iter ~tag_names:["subsection"] ("\t This is the main way (and the only for the moment) to edit a graph. There are two differents menus, but it is transparent for your use.\n" ^"The first is only composed by an adding node menu, and appear when you click in the disk.\n" ^"The second menu appears when you click on a vertex." ^" You can change root of graph drawing, add a successor or remove focused vertex." ^" Rest of menu depends of selected nodes. You can add or remove an edge with one of selected, or with all." ^"\n\n"); buffer#insert ~iter ~tag_names:["annotation"] "[1] :"; buffer#insert ~iter ~tag_names:["subsection"] " a bug still remains, you can't drag root to much on the right-side, but on the left-side it is infinite"; let start,stop = buffer#bounds in buffer#apply_tag_by_name "word_wrap" ~start ~stop ; () (* menu action handbook *) let handbook () = let dialog = GWindow.dialog ~width:450 ~height:450 ~title:"Handbook" () in let view = GText.view () in let sw = GBin.scrolled_window ~packing:dialog#vbox#add () in sw#add view#coerce; handbook_text view; dialog#add_button_stock `CLOSE `CLOSE; match dialog#run () with | `CLOSE | `DELETE_EVENT -> dialog#destroy () (* menu bar, based on ui_manager *) let ui_info = "\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ " (* choose right menu action *) let activ_action ac = let name = ac#name in match name with | "New graph" -> new_graph () | "Open graph"-> open_graph () | "Save graph" -> save_graph () | "Save graph as..." -> save_graph_as () | "Quit" -> quit () | "About" -> about () | "Handbook" -> handbook () | _ -> Format.eprintf "%s menu is not yet implemented @." name let setup_ui window = let add_action = GAction.add_action in let actions = GAction.action_group ~name:"Actions" () in GAction.add_actions actions [ add_action "FileMenu" ~label:"_File" ; add_action "HelpMenu" ~label:"_Help" ; add_action "New graph" ~stock:`NEW ~tooltip:"Create a new graph" ~callback:activ_action ; add_action "Open graph" ~stock:`OPEN ~tooltip:"Open a graph file" ~callback:activ_action ; add_action "Save graph" ~stock:`SAVE ~tooltip:"Save current graph" ~callback:activ_action ; add_action "Save graph as..." ~stock:`SAVE_AS ~accel:"S" ~tooltip:"Save current graph to specified file" ~callback:activ_action ; add_action "Quit" ~stock:`QUIT ~tooltip:"Quit" ~callback:activ_action ; add_action "About" ~label:"_About" ~tooltip:"Who build this" ~callback:activ_action; add_action "Handbook" ~label:"_Handbook" ~accel:"H" ~tooltip:"How to.." ~callback:activ_action; ] ; let ui_m = GAction.ui_manager () in ui_m#insert_action_group actions 0 ; window#add_accel_group ui_m#get_accel_group ; ignore (ui_m#add_ui_from_string ui_info) ; menu_bar_box#pack (ui_m#get_widget "/MenuBar") let () = reset_table_and_canvas (); draw (make_turtle_origine ()) canvas_root; set_canvas_event (); canvas#set_scroll_region 0. 0. w h ; setup_ui window; ignore (window#show ()); GMain.Main.main () ocamlgraph-1.8.3/editor/ed_graph.ml0000644000175000017500000002070312133565071016174 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This file is a contribution of Benjamin Vadon *) open Graph open Ed_hyper type visibility = Visible | BorderNode | Hidden type mode = Normal | Selected | Focused | Selected_Focused type node_info = { label : string; mutable visible : visibility; mutable depth : int; mutable vertex_mode : mode; mutable turtle : turtle; } let make_node_info s = { label = s; visible = Hidden; depth = 0; vertex_mode = Normal; turtle = dummy_turtle } type edge_info = { mutable visited : bool; mutable edge_mode : mode; mutable edge_turtle : turtle; mutable edge_distance : float; mutable edge_steps : int; } let make_edge_info () = { visited = false; edge_mode = Normal; edge_turtle = dummy_turtle; edge_distance = 0.; edge_steps = 0; } module EDGE = struct type t = edge_info let compare : t -> t -> int = Pervasives.compare let default = make_edge_info () end module G = Imperative.Graph.AbstractLabeled(struct type t = node_info end)(EDGE) module B = Builder.I(G) (* current graph *) let graph = ref (G.create ()) type name = string option let graph_name = ref (None: name) (* useful functions for vertex and edge *) let string_of_label x = (G.V.label x).label let edge v w = G.mem_edge !graph v w || G.mem_edge !graph w v (* two Parser modules *) module GmlParser = Gml.Parse (B) (struct let node l = make_node_info (try match List.assoc "id" l with Gml.Int n -> string_of_int n | _ -> "" with Not_found -> "") let edge _ = make_edge_info () end) module DotParser = Dot.Parse (B) (struct let node (id,_) _ = match id with | Dot_ast.Ident s | Dot_ast.Number s | Dot_ast.String s | Dot_ast.Html s -> make_node_info s let edge _ = make_edge_info () end) (* a parsing file function *) let parse_file f = if Filename.check_suffix f ".gml" then GmlParser.parse f else DotParser.parse f (* two Printer Modules *) module GmlPrinter = Gml.Print (G) (struct let node (v: G.V.label) = ["label", Gml.Int (int_of_string v.label)] let edge (e: G.E.label) = [] end) module DotPrinter = Graphviz.Dot ( struct include G let vertex_name vertex = string_of_label vertex let graph_attributes _ = [] let default_vertex_attributes _ = [] let vertex_attributes _ = [] let default_edge_attributes _ = [] let edge_attributes _ = [] let get_subgraph _ = None end ) (* two outputs functions, and a save graph function *) let gml_output g f = let c = open_out f in let fmt = Format.formatter_of_out_channel c in Format.fprintf fmt "%a@." GmlPrinter.print g; close_out c let dot_output g f = let oc = open_out f in DotPrinter.output_graph oc g; close_out oc let save_graph name = if Filename.check_suffix name "gml" then ( gml_output !graph name; graph_name := Some name) else if Filename.check_suffix name "dot" then ( dot_output !graph name; graph_name := Some name) else ( let name = name^".dot" in dot_output !graph name; graph_name := Some name ) module Components = Components.Make(G) module Dfs = Traverse.Dfs(G) exception Choose of G.V.t let choose_root () = try G.iter_vertex (fun v -> raise (Choose v)) !graph; None with Choose v -> Some v (* Parsing of the command line *) let load_graph f = graph := parse_file f; graph_name := Some f let dfs = ref false let refresh_rate = ref 10 let aa = ref true let () = Arg.parse ["-dfs", Arg.Set dfs, "DFS drawing strategy"; "-bfs", Arg.Clear dfs, "BFS drawing strategy"; "-rr", Arg.Set_int refresh_rate, "set the refresh rate, must be greater than 0"; "-aa", Arg.Clear aa, "turn off anti-aliased mode"; ] load_graph "editor [options] " (* successor edges *) module H2 = Hashtbl.Make (struct type t = G.V.t * G.V.t let hash (v,w) = Hashtbl.hash (G.V.hash v, G.V.hash w) let equal (v1,w1) (v2,w2) = G.V.equal v1 v2 && G.V.equal w1 w2 end) module H = Hashtbl.Make(G.V) (* vertex select and unselect *) (* a counter for selected vertices *) let nb_selected = ref 0 (* a belonging test to selection *) let is_selected (x:G.V.t) = let mode =(G.V.label x).vertex_mode in mode = Selected || mode = Selected_Focused type mode_select_list = REMOVE_FROM of G.V.t | ADD_FROM of G.V.t | NONE let selected_list mode = let vertex_selection =ref [] in G.iter_vertex (fun v -> if (is_selected v) && (match mode with | ADD_FROM vertex -> not (edge v vertex) | REMOVE_FROM vertex -> (edge v vertex) | NONE -> true) then vertex_selection := v::(!vertex_selection)) !graph; let compare s1 s2 = String.compare (string_of_label s1) (string_of_label s2) in List.sort compare !vertex_selection type ed_event = Select | Unselect | Focus | Unfocus let update_vertex vertex event = let vertex_info = G.V.label vertex in begin match vertex_info.vertex_mode, event with | Normal, Select -> vertex_info.vertex_mode <- Selected; incr nb_selected | Normal, Focus -> vertex_info.vertex_mode <- Focused | Normal, _ -> () | Selected, Focus -> vertex_info.vertex_mode <- Selected_Focused | Selected, Unselect -> vertex_info.vertex_mode <- Normal; decr nb_selected | Selected, _ -> () | Focused, Select -> vertex_info.vertex_mode <- Selected_Focused; incr nb_selected | Focused, Unfocus -> vertex_info.vertex_mode <- Normal | Focused, _ -> () | Selected_Focused, Unselect -> vertex_info.vertex_mode <- Focused; decr nb_selected | Selected_Focused, Unfocus -> vertex_info.vertex_mode <- Selected | Selected_Focused, _ -> () end; G.iter_succ_e ( fun edge -> let edge_info = G.E.label edge in let dest_vertex = G.E.dst edge in begin match edge_info.edge_mode, event with | Normal, Select -> edge_info.edge_mode <- Selected | Normal, Focus -> edge_info.edge_mode <- Focused | Normal, _ -> () | Selected, Focus -> edge_info.edge_mode <- Selected_Focused | Selected, Unselect -> if not(is_selected dest_vertex) then edge_info.edge_mode <- Normal | Selected, _ -> () | Focused, Select -> edge_info.edge_mode <- Selected_Focused | Focused, Unfocus -> edge_info.edge_mode <- Normal | Focused, _ -> () | Selected_Focused, Unselect -> if not(is_selected dest_vertex) then edge_info.edge_mode <- Focused; decr nb_selected | Selected_Focused, Unfocus -> edge_info.edge_mode <- Selected | Selected_Focused, _ -> () end; ) !graph vertex (* to select and unselect all vertices *) let select_all () = G.iter_vertex (fun v -> if not(is_selected v) then begin let v = G.V.label v in v.vertex_mode <- Selected; incr nb_selected end ) !graph; G.iter_edges_e (fun e -> let e = G.E.label e in e.edge_mode <- Selected) !graph let unselect_all () = G.iter_vertex (fun v -> if (is_selected v) then begin let l = G.V.label v in l.vertex_mode <- Normal; decr nb_selected end ) !graph; G.iter_edges_e (fun e -> let e = G.E.label e in e.edge_mode <- Normal) !graph ocamlgraph-1.8.3/editor/ed_display.ml0000644000175000017500000003036012133565071016540 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This file is a contribution of Benjamin Vadon *) open Format open Ed_hyper open Ed_graph let debug = ref false (* Original window size *) let (w,h)= (600.,600.) (* light mode (* differents definitions *) let color_circle = "grey99" let color_intern_edge = "grey69" let color_successor_edge = "black" (*"grey38"*) let color_vertex = "grey75" let color_selected_intern_edge = "#9f1a1a" (* "#74885e"*) let color_selected_successor_edge = "#9f1a1a" let color_selected_vertex = "#9f1a1a" let color_focused_intern_edge = "#4d51a9" let color_focused_successor_edge = "#4d51a9" let color_focused_vertex = "#4d51a9" let color_selected_focused_intern_edge = "LightCoral" let color_selected_focused_vertex ="LightCoral" let color_selected_focused_successor_edge = "LightCoral" let color_text = "black" let width_successor_edge = 2 let width_intern_edge = 2 let point_size_text = 12.*) (* dark mode (* differents definitions *) let color_circle = "grey99" let color_intern_edge = "black" let color_successor_edge ="black" let color_vertex = "grey58" let color_selected_intern_edge = "OrangeRed4" let color_selected_successor_edge = "OrangeRed4" let color_selected_vertex = "OrangeRed4" let color_focused_intern_edge = "blue" let color_focused_successor_edge = "blue" let color_focused_vertex = "blue" let color_selected_focused_intern_edge = "dark magenta" let color_selected_focused_vertex ="dark magenta" let color_selected_focused_successor_edge = "dark magenta" let color_text = "white" let width_successor_edge = 2 let width_intern_edge = 2 let point_size_text = 12. *) (* guizmode *) (* differents definitions *) let color_circle = "grey99" let color_intern_edge = "grey69" let color_successor_edge = "black" (*"grey38"*) let color_vertex = "grey75" let color_selected_intern_edge = "#9f1a1a" (* "#74885e"*) let color_selected_successor_edge = "#9f1a1a" let color_selected_vertex = "#9f1a1a" let color_focused_intern_edge = "#4d51a9" let color_focused_successor_edge = "#4d51a9" let color_focused_vertex = "#4d51a9" let color_selected_focused_intern_edge = "#e80000" let color_selected_focused_vertex ="#e80000" let color_selected_focused_successor_edge = "#e80000" let color_text = "black" let width_successor_edge = 2 let width_intern_edge = 2 let point_size_text = 12. (* two tables for two types of edge : successor_edges = edges with successor of root intern_edges = edges between successors of root *) let successor_edges = H2.create 97 let intern_edges = H2.create 97 (* table of all nodes *) let nodes = H.create 97 (* GTK to hyperbolic coordinates *) let to_turtle(x,y)= let zx,zy as r = ((float x*.(2./.w) -. 1.),(1. -. float y *.(2./.h))) in let zn = sqrt(zx*.zx +. zy*.zy) in if zn > rlimit then (rlimit*.zx/.zn, rlimit*.zy/.zn) else r (* Hyperbolic to GTK coordinates *) let from_turtle (x,y) = let xzoom = (w/.2.) and yzoom = (h/.2.) in (truncate (x*.xzoom +. xzoom), truncate(yzoom -. y*.yzoom)) (* the middle of the screen used when init a graoh drawing *) let start_point = to_turtle (truncate(w/.2.), truncate(h/.2.)) (* origine is a reference to the start point drawing for the graph in GTK coordinates *) let origine = ref start_point (* Current point in Hyperbolic view with an initialization in center of hyperbolic circle *) let current_point = ref (0,0) (* Change hyperbolic current point *) let moveto_gtk x y = current_point := (x,y) (* Change hyperbolic current point with turtle coordinates *) let tmoveto_gtk turtle = let (x,y)= from_turtle turtle.pos in moveto_gtk x y (* Create a turtle with origine's coordinates *) let make_turtle_origine () = let (x,y) = let (x,y) = !origine in (truncate x, truncate y) in moveto_gtk x y; make_turtle !origine 0.0 (* Append turtle coordinates to line, set current point and return the "new" line *) let tlineto_gtk turtle line = tmoveto_gtk turtle; let (x,y) = !current_point in List.append line [(float x); (float y) ] (* Set line points for a distance with a number of steps, set current point to last line's point, by side-effect of tlineto_gtk, and return the final turtle *) let set_successor_edge turtle distance steps line = let d = distance /. (float steps) in let rec list_points turtle liste = function | 0 -> (turtle,liste) | n ->let turt = advance turtle d in list_points turt (tlineto_gtk turt liste) (n-1) in let start = let (x,y) = from_turtle turtle.pos in [(float x); (float y)] in let turtle,lpoints = list_points turtle start steps in let points = Array.of_list lpoints in line#set [`POINTS points] type polaire = { radius : float; angle : float} type cartesien = { x : float; y: float} let pol_to_cart p = { x = p.radius *. (cos p.angle); y = p.radius *. (sin p.angle) } let cart_to_pol p = let radius = sqrt((p.x *. p.x) +.(p.y *. p.y)) in { radius = radius; angle = 2. *. ath ((p.y /. radius) /. (1. +. p.x /. radius)) } (* Set Bpath between turtles tv and tw where line is a gtk widget *) let set_intern_edge tv tw bpath line = let (x,y) = let (x ,y ) = from_turtle tv.pos in ((float_of_int x),(float_of_int y)) in let (x',y') = let (x',y') = from_turtle tw.pos in ((float_of_int x'),(float_of_int y')) in let rate = 1.95 in GnomeCanvas.PathDef.reset bpath; GnomeCanvas.PathDef.moveto bpath x y ; GnomeCanvas.PathDef.curveto bpath ((x+. x')/.rate) ((y +. y')/.rate) ((x +.x')/.rate) ((y +. y')/.rate) x' y'; line#set [`BPATH bpath] (* Set ellipse coordinate to turtle's and set current point too *) let tdraw_string_gtk v turtle = let node,ellipse,texte = H.find nodes v in tmoveto_gtk turtle; let factor = (shrink_factor ((G.V.label v).turtle.pos)) in let factor = if factor < 0.5 then 0.5 else factor in let w = factor*. point_size_text in texte#set [`SIZE_POINTS w ]; let w = texte#text_width in let h = texte#text_height in ellipse#set [ `X1 (-.( w+.8.)/.2.); `X2 ((w+.8.)/.2.); `Y1 (-.( h+.6.)/.2.); `Y2 ((h+.6.)/.2.)]; let (x,y) = !current_point in node#move ~x:(float x) ~y:(float y); node#set [`X (float x); `Y (float y)]; node let add_node canvas v = let s = string_of_label v in let node_group = GnoCanvas.group ~x:0.0 ~y:0.0 canvas in let ellipse = GnoCanvas.ellipse ~props:[ `FILL_COLOR color_vertex ; `OUTLINE_COLOR "black" ; `WIDTH_PIXELS 0 ] node_group in let texte = GnoCanvas.text ~props:[`X 0.0; `Y 0.0 ; `TEXT s; `FILL_COLOR color_text] node_group in node_group#hide(); H.add nodes v (node_group,ellipse,texte) let init_nodes canvas = H.clear nodes; G.iter_vertex (add_node canvas) !graph (* change color for a vertex *) let color_change_vertex item color n = item#set [ `FILL_COLOR color ; `WIDTH_PIXELS n ] (* change color for a successor edge *) let color_change_intern_edge (line:GnoCanvas.bpath) color = line#set [`OUTLINE_COLOR color] (* change color for an intern edge *) let color_change_successor_edge (line:GnoCanvas.line) color = line#set [`FILL_COLOR color] (* draws but don't show intern edges, and return a couple bpath (gtk_object), and line (gtw_widget)*) let draw_intern_edge vw edge tv tw canvas = let bpath,line = try let _,line as pl = H2.find intern_edges vw in pl with Not_found -> let bpath = GnomeCanvas.PathDef.new_path () in let line = GnoCanvas.bpath canvas ~props:[ `BPATH bpath ; `WIDTH_PIXELS width_intern_edge ] in line#lower_to_bottom (); H2.add intern_edges vw (bpath,line); let v,w = vw in if (is_selected w) || (is_selected v) then edge.edge_mode <- Selected; bpath,line in set_intern_edge tv tw bpath line; bpath,line let draw_successor_edge vw edge canvas = let line = try H2.find successor_edges vw with Not_found -> let line = GnoCanvas.line canvas ~props:[ `FILL_COLOR color_successor_edge ; `WIDTH_PIXELS width_successor_edge; `SMOOTH true] in line#lower_to_bottom (); H2.add successor_edges vw line; let v,w = vw in if (is_selected w) || (is_selected v) then edge.edge_mode <- Selected; line in set_successor_edge edge.edge_turtle edge.edge_distance edge.edge_steps line; line (* set origine to new mouse position and return associated turtle *) let motion_turtle item ev = let bounds = item#parent#get_bounds in let z1 = to_turtle(truncate((bounds.(0)+. bounds.(2))/.2.), truncate((bounds.(1)+. bounds.(3))/.2.)) in let z2 = to_turtle (truncate (GdkEvent.Motion.x ev), truncate (GdkEvent.Motion.y ev)) in let (x,y) = drag_origin !origine z1 z2 in origine := (x,y); make_turtle !origine 0.0 let hide_intern_edge vw = try let _,line = H2.find intern_edges vw in line#hide () with Not_found -> () let hide_succesor_edge vw = try let line = H2.find successor_edges vw in line#hide () with Not_found -> () (* graph drawing *) let draw_graph root canvas = (* vertexes *) G.iter_vertex (fun v -> let ( l : node_info) = G.V.label v in if l.visible = Visible then begin let node = tdraw_string_gtk v l.turtle in node#raise_to_top(); node#show(); let _,item,_=H.find nodes v in match l.vertex_mode with | Normal -> color_change_vertex item color_vertex 0; | Selected -> color_change_vertex item color_selected_vertex 0; | Focused -> color_change_vertex item color_focused_vertex 3; | Selected_Focused -> color_change_vertex item color_selected_focused_vertex 3; end else let node,_,_= H.find nodes v in node#hide() ) !graph; (* edges *) G.iter_edges_e (fun e -> let edge = G.E.label e in let v = G.E.src e in let w = G.E.dst e in let vw = (v,w) in if edge.visited then (* successor edge *) begin let line = draw_successor_edge vw edge canvas in begin match edge.edge_mode with | Normal -> color_change_successor_edge line color_successor_edge; | Selected -> color_change_successor_edge line color_selected_successor_edge; | Focused -> color_change_successor_edge line color_focused_successor_edge; | Selected_Focused -> color_change_successor_edge line color_selected_focused_successor_edge; end; line#show (); hide_intern_edge vw end else (* intern edges *) begin hide_succesor_edge vw; let labv = G.V.label v in let labw = G.V.label w in let turv = labv.turtle in let turw = labw.turtle in if labv.visible = Visible && labw.visible = Visible && v!=w then begin let _,line = draw_intern_edge vw edge turv turw canvas in begin match edge.edge_mode with | Normal -> color_change_intern_edge line color_intern_edge; | Selected -> color_change_intern_edge line color_selected_intern_edge; | Focused -> color_change_intern_edge line color_focused_intern_edge; | Selected_Focused -> color_change_intern_edge line color_selected_focused_intern_edge; end; line#show() end else hide_intern_edge vw end) !graph let reset_display canvas = init_nodes canvas ocamlgraph-1.8.3/editor/Makefile0000644000175000017500000000141212133565071015525 0ustar mehdimehdi test: editor.opt ./editor.opt -rr 15 tests/divisors12.gml editor.opt: ed_*.ml make -C .. editor/editor.opt editor.byte: ed_*.ml make -C .. editor/editor.byte # tortuegpoint: tortue.ml # ocamlopt outils_math.ml # ocamlopt -o $@ graphics.cmxa outils_math.cmx $^ # graphEd.opt : outils_math.ml outils_tort.ml graphEd.ml # ocamlopt -o $@ graphics.cmxa -I .. ../graph.cmxa $^ # graphEdGTK : outils_math.ml outils_tort.ml graphEdGTK.ml # ocamlopt.opt -o $@ -I +lablgtk2 lablgtk.cmxa lablgnomecanvas.cmxa unix.cmxa -I .. ../graph.cmxa $^ # graphEdGTK.byte : outils_math.ml outils_tort.ml graphEdGTK.ml # ocamlc.opt -g -o $@ -I +lablgtk2 lablgtk.cma lablgnomecanvas.cma unix.cma -I .. ../graph.cma $^ # editor.opt: # make -C .. clean: rm -f *.opt rm -f *.cm[iox] ocamlgraph-1.8.3/editor/ed_hyper.ml0000644000175000017500000001314112133565071016220 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This code is from Alexandre Miquel's Htree (http://www.pps.jussieu.fr/~miquel/soft.html) *) (*** Complex numbers *) let ( ~-& ) (x, y) = (-.x, -.y) let ( ~& ) (x, y) = (x, -.y) let ( +& ) (x1, y1) (x2, y2) = (x1 +. x2, y1 +. y2) let ( -& ) (x1, y1) (x2, y2) = (x1 +. x2, y1 +. y2) let ( *& ) (x1, y1) (x2, y2) = (x1*.x2 -. y1*.y2, x1*.y2 +. y1*.x2) let ( /& ) (x1, y1) (x2, y2) = let n2 = x2*.x2 +. y2*.y2 in ((x1*.x2 +. y1*.y2)/.n2, (-.x1*.y2 +. y1*.x2)/.n2) let ( *.& ) f (x, y) = (f*.x, f*.y) let norm_sqr (x, y) = x*.x +. y*.y let norm (x, y) = sqrt(x*.x +. y*.y) let normalize (x, y) = let n = sqrt(x*.x +. y*.y) in (x/.n, y/.n) let expi t = (cos t, sin t) (*** Hyperbolic geometry ***) let th t = let ept = exp t and emt = exp (-.t) in (ept -. emt)/.(ept +. emt) let ath x = 0.5*.log((1.0 +. x)/.(1.0 -. x)) let pi = 3.14159265358979323846 let pi_over_2 = pi/.2.0 let pi_over_4 = pi/.4.0 let one = (1.0, 0.0) let translate a z = (a +& z)/&(one +& (~&a) *& z) let gamma a u t = let utht = th t *.& u in (a +& utht) /& (one +& (~&a) *& utht) let delta a u t = let atht = th t *.& a and utht = th t *.& u in (u +& atht) /& (one +& (~&a) *& utht) (* solving a Cramer system *) let cramer a1 a2 b1 b2 c1 c2 = let cdet = a1*.b2 -. a2*.b1 and xdet = c1*.b2 -. c2*.b1 and ydet = a1*.c2 -. a2*.c1 in (xdet/.cdet, ydet/.cdet) ;; let drag_origin (x0, y0) (x1, y1) (x2, y2) = let (x1, y1) = translate (-.x0, -.y0) (x1, y1) in let x3 = x1*.x2 -. y1*.y2 in let y3 = x1*.y2 +. y1*.x2 in cramer (1.0 -. x3) (-.y3) (-.y3) (1.0 +. x3) (x2 -. x1) (y2 -. y1) let shrink_factor (x, y) = 1.0 -. (x*.x +. y*.y) (*** Hyperbolic turtle ***) type coord = float * float type turtle = { pos : coord ; (* with |pos| < 1 *) dir : coord (* with |dir| = 1 *) } let make_turtle pos angle = { pos = pos ; dir = expi angle } let make_turtle_dir pos dir = { pos = pos ; dir = dir } let dist tdep tdest = let a = tdep.pos in let b = tdest.pos in ath (norm ( (a -& b) /& (one -& (~&a) *& b))) let dir_to tdep tdest t = let a = tdep.pos in let d = tdest.pos in ((d -& a) /& (th t *.&( one -& (~&a) *& d))) (* return a turtle for a distance from original *) let advance turtle step = { pos = gamma turtle.pos turtle.dir step ; dir = delta turtle.pos turtle.dir step } (* return a turtle for a distance d from original with steps *) let advance_many turtle d steps = let d = d /. (float steps) in let rec adv t = function | 0 -> t | n -> adv (advance t d) (n-1) in adv turtle steps (* return a list of turtle along distance d from original turtle with steps *) let list_advance_many turtle d steps = let d = d /. (float steps) in let rec adv t = function | 0 -> [] | n -> t :: adv (advance t d) (n-1) in adv turtle steps let turn turtle u = { turtle with dir = turtle.dir *& u } let turn_left turtle angle = turn turtle (expi angle) (*** a comprendre pourquoi je dois inverser + et - de l'angle ***) let turn_right turtle angle = turn turtle (expi (-.angle)) (*** a comprendre pourquoi je dois inverser + et - de l'angle ***) let dummy_turtle = { pos = (0., 0.); dir = (0., 0.) } (* [step_from n] computes the best `distance' for solving the dictator's problem in the complex hyperbolic plane for [n] dictators. In a half-plane, we have to use the distance given by [step_from (2*n)] or, better, the distance given by [step_from (2*max(3 n))]. *) let step_from n = ath (tan (pi_over_4 -. pi/.float(2*n))) (* [hspace_dist_sqr turtle] computes the square of the distance between the origin and the half-space in front of [turtle]. *) let hspace_dist_sqr turtle = let (ax, ay) = turtle.pos and (dx, dy) = turtle.dir in if ax*.dx +. ay*.dy < 0.0 then begin 0.0 end else begin let ux = dy and uy = -.dx in let alpha = ax*.ax +. ay*.ay and beta = 2.0*.(ax*.ux +. ay*.uy) in if beta = 0.0 then alpha else begin let gamma = (1.0 +. alpha)/.beta in let delta = gamma*.gamma -. 1.0 in let sol = if beta > 0.0 then -.gamma +. sqrt(delta) else -.gamma -. sqrt(delta) in let (zx, zy) = translate (ax, ay) (ux*.sol, uy*.sol) in let res = zx*.zx +. zy*.zy in res end end (* Limit of visibility for nodes *) let rlimit = 0.98 let rlimit_sqr = rlimit *. rlimit ocamlgraph-1.8.3/editor/tests/0000755000175000017500000000000012133565071015231 5ustar mehdimehdiocamlgraph-1.8.3/editor/tests/rand_100_300.gml0000644000175000017500000004576712133565071017643 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] node [ id 11 label 10 ] node [ id 12 label 11 ] node [ id 13 label 12 ] node [ id 14 label 13 ] node [ id 15 label 14 ] node [ id 16 label 15 ] node [ id 17 label 16 ] node [ id 18 label 17 ] node [ id 19 label 18 ] node [ id 20 label 19 ] node [ id 21 label 20 ] node [ id 22 label 21 ] node [ id 23 label 22 ] node [ id 24 label 23 ] node [ id 25 label 24 ] node [ id 26 label 25 ] node [ id 27 label 26 ] node [ id 28 label 27 ] node [ id 29 label 28 ] node [ id 30 label 29 ] node [ id 31 label 30 ] node [ id 32 label 31 ] node [ id 33 label 32 ] node [ id 34 label 33 ] node [ id 35 label 34 ] node [ id 36 label 35 ] node [ id 37 label 36 ] node [ id 38 label 37 ] node [ id 39 label 38 ] node [ id 40 label 39 ] node [ id 41 label 40 ] node [ id 42 label 41 ] node [ id 43 label 42 ] node [ id 44 label 43 ] node [ id 45 label 44 ] node [ id 46 label 45 ] node [ id 47 label 46 ] node [ id 48 label 47 ] node [ id 49 label 48 ] node [ id 50 label 49 ] node [ id 51 label 50 ] node [ id 52 label 51 ] node [ id 53 label 52 ] node [ id 54 label 53 ] node [ id 55 label 54 ] node [ id 56 label 55 ] node [ id 57 label 56 ] node [ id 58 label 57 ] node [ id 59 label 58 ] node [ id 60 label 59 ] node [ id 61 label 60 ] node [ id 62 label 61 ] node [ id 63 label 62 ] node [ id 64 label 63 ] node [ id 65 label 64 ] node [ id 66 label 65 ] node [ id 67 label 66 ] node [ id 68 label 67 ] node [ id 69 label 68 ] node [ id 70 label 69 ] node [ id 71 label 70 ] node [ id 72 label 71 ] node [ id 73 label 72 ] node [ id 74 label 73 ] node [ id 75 label 74 ] node [ id 76 label 75 ] node [ id 77 label 76 ] node [ id 78 label 77 ] node [ id 79 label 78 ] node [ id 80 label 79 ] node [ id 81 label 80 ] node [ id 82 label 81 ] node [ id 83 label 82 ] node [ id 84 label 83 ] node [ id 85 label 84 ] node [ id 86 label 85 ] node [ id 87 label 86 ] node [ id 88 label 87 ] node [ id 89 label 88 ] node [ id 90 label 89 ] node [ id 91 label 90 ] node [ id 92 label 91 ] node [ id 93 label 92 ] node [ id 94 label 93 ] node [ id 95 label 94 ] node [ id 96 label 95 ] node [ id 97 label 96 ] node [ id 98 label 97 ] node [ id 99 label 98 ] node [ id 100 label 99 ] edge [ source 6 target 5 label 0 ] edge [ source 7 target 1 label 0 ] edge [ source 8 target 2 label 0 ] edge [ source 10 target 2 label 0 ] edge [ source 12 target 6 label 0 ] edge [ source 12 target 11 label 0 ] edge [ source 13 target 1 label 0 ] edge [ source 14 target 9 label 0 ] edge [ source 15 target 3 label 0 ] edge [ source 16 target 14 label 0 ] edge [ source 18 target 1 label 0 ] edge [ source 19 target 11 label 0 ] edge [ source 21 target 17 label 0 ] edge [ source 22 target 5 label 0 ] edge [ source 22 target 13 label 0 ] edge [ source 22 target 17 label 0 ] edge [ source 23 target 15 label 0 ] edge [ source 23 target 19 label 0 ] edge [ source 27 target 22 label 0 ] edge [ source 28 target 4 label 0 ] edge [ source 28 target 19 label 0 ] edge [ source 29 target 12 label 0 ] edge [ source 29 target 15 label 0 ] edge [ source 29 target 19 label 0 ] edge [ source 29 target 20 label 0 ] edge [ source 29 target 28 label 0 ] edge [ source 31 target 10 label 0 ] edge [ source 31 target 24 label 0 ] edge [ source 32 target 3 label 0 ] edge [ source 32 target 22 label 0 ] edge [ source 32 target 28 label 0 ] edge [ source 34 target 3 label 0 ] edge [ source 35 target 26 label 0 ] edge [ source 35 target 29 label 0 ] edge [ source 36 target 16 label 0 ] edge [ source 37 target 23 label 0 ] edge [ source 37 target 28 label 0 ] edge [ source 38 target 32 label 0 ] edge [ source 38 target 33 label 0 ] edge [ source 39 target 4 label 0 ] edge [ source 39 target 15 label 0 ] edge [ source 39 target 33 label 0 ] edge [ source 40 target 4 label 0 ] edge [ source 40 target 6 label 0 ] edge [ source 40 target 7 label 0 ] edge [ source 40 target 20 label 0 ] edge [ source 40 target 29 label 0 ] edge [ source 40 target 34 label 0 ] edge [ source 41 target 25 label 0 ] edge [ source 43 target 22 label 0 ] edge [ source 44 target 4 label 0 ] edge [ source 44 target 9 label 0 ] edge [ source 44 target 28 label 0 ] edge [ source 44 target 32 label 0 ] edge [ source 45 target 17 label 0 ] edge [ source 45 target 30 label 0 ] edge [ source 46 target 19 label 0 ] edge [ source 46 target 43 label 0 ] edge [ source 47 target 37 label 0 ] edge [ source 47 target 43 label 0 ] edge [ source 48 target 28 label 0 ] edge [ source 48 target 35 label 0 ] edge [ source 49 target 5 label 0 ] edge [ source 49 target 26 label 0 ] edge [ source 50 target 9 label 0 ] edge [ source 51 target 13 label 0 ] edge [ source 51 target 30 label 0 ] edge [ source 52 target 3 label 0 ] edge [ source 52 target 11 label 0 ] edge [ source 52 target 13 label 0 ] edge [ source 52 target 46 label 0 ] edge [ source 52 target 48 label 0 ] edge [ source 53 target 9 label 0 ] edge [ source 53 target 14 label 0 ] edge [ source 53 target 23 label 0 ] edge [ source 53 target 24 label 0 ] edge [ source 53 target 25 label 0 ] edge [ source 53 target 36 label 0 ] edge [ source 53 target 41 label 0 ] edge [ source 53 target 46 label 0 ] edge [ source 53 target 47 label 0 ] edge [ source 54 target 7 label 0 ] edge [ source 54 target 9 label 0 ] edge [ source 54 target 26 label 0 ] edge [ source 55 target 3 label 0 ] edge [ source 55 target 4 label 0 ] edge [ source 55 target 19 label 0 ] edge [ source 55 target 39 label 0 ] edge [ source 56 target 23 label 0 ] edge [ source 56 target 40 label 0 ] edge [ source 56 target 42 label 0 ] edge [ source 57 target 3 label 0 ] edge [ source 57 target 24 label 0 ] edge [ source 57 target 25 label 0 ] edge [ source 57 target 44 label 0 ] edge [ source 57 target 51 label 0 ] edge [ source 57 target 55 label 0 ] edge [ source 58 target 1 label 0 ] edge [ source 58 target 4 label 0 ] edge [ source 58 target 37 label 0 ] edge [ source 60 target 37 label 0 ] edge [ source 61 target 4 label 0 ] edge [ source 61 target 27 label 0 ] edge [ source 62 target 2 label 0 ] edge [ source 62 target 14 label 0 ] edge [ source 62 target 43 label 0 ] edge [ source 63 target 17 label 0 ] edge [ source 63 target 32 label 0 ] edge [ source 64 target 23 label 0 ] edge [ source 64 target 27 label 0 ] edge [ source 64 target 48 label 0 ] edge [ source 64 target 61 label 0 ] edge [ source 65 target 7 label 0 ] edge [ source 65 target 9 label 0 ] edge [ source 65 target 19 label 0 ] edge [ source 65 target 42 label 0 ] edge [ source 65 target 49 label 0 ] edge [ source 66 target 11 label 0 ] edge [ source 66 target 43 label 0 ] edge [ source 66 target 50 label 0 ] edge [ source 66 target 51 label 0 ] edge [ source 66 target 58 label 0 ] edge [ source 67 target 23 label 0 ] edge [ source 67 target 24 label 0 ] edge [ source 67 target 28 label 0 ] edge [ source 67 target 29 label 0 ] edge [ source 67 target 31 label 0 ] edge [ source 67 target 49 label 0 ] edge [ source 67 target 56 label 0 ] edge [ source 68 target 1 label 0 ] edge [ source 68 target 27 label 0 ] edge [ source 70 target 2 label 0 ] edge [ source 70 target 35 label 0 ] edge [ source 70 target 53 label 0 ] edge [ source 71 target 15 label 0 ] edge [ source 71 target 24 label 0 ] edge [ source 71 target 29 label 0 ] edge [ source 71 target 39 label 0 ] edge [ source 72 target 33 label 0 ] edge [ source 72 target 71 label 0 ] edge [ source 73 target 26 label 0 ] edge [ source 73 target 56 label 0 ] edge [ source 73 target 62 label 0 ] edge [ source 74 target 22 label 0 ] edge [ source 74 target 28 label 0 ] edge [ source 74 target 60 label 0 ] edge [ source 75 target 15 label 0 ] edge [ source 75 target 18 label 0 ] edge [ source 75 target 26 label 0 ] edge [ source 75 target 33 label 0 ] edge [ source 75 target 53 label 0 ] edge [ source 75 target 54 label 0 ] edge [ source 76 target 73 label 0 ] edge [ source 76 target 74 label 0 ] edge [ source 77 target 61 label 0 ] edge [ source 77 target 65 label 0 ] edge [ source 77 target 76 label 0 ] edge [ source 78 target 12 label 0 ] edge [ source 78 target 14 label 0 ] edge [ source 78 target 19 label 0 ] edge [ source 78 target 35 label 0 ] edge [ source 78 target 48 label 0 ] edge [ source 78 target 76 label 0 ] edge [ source 79 target 24 label 0 ] edge [ source 79 target 25 label 0 ] edge [ source 79 target 35 label 0 ] edge [ source 79 target 67 label 0 ] edge [ source 80 target 9 label 0 ] edge [ source 80 target 23 label 0 ] edge [ source 80 target 56 label 0 ] edge [ source 80 target 57 label 0 ] edge [ source 80 target 67 label 0 ] edge [ source 81 target 61 label 0 ] edge [ source 82 target 39 label 0 ] edge [ source 82 target 41 label 0 ] edge [ source 82 target 44 label 0 ] edge [ source 82 target 52 label 0 ] edge [ source 82 target 63 label 0 ] edge [ source 82 target 65 label 0 ] edge [ source 82 target 72 label 0 ] edge [ source 82 target 77 label 0 ] edge [ source 83 target 7 label 0 ] edge [ source 83 target 36 label 0 ] edge [ source 83 target 46 label 0 ] edge [ source 83 target 47 label 0 ] edge [ source 83 target 54 label 0 ] edge [ source 83 target 81 label 0 ] edge [ source 83 target 82 label 0 ] edge [ source 84 target 10 label 0 ] edge [ source 84 target 67 label 0 ] edge [ source 84 target 68 label 0 ] edge [ source 84 target 76 label 0 ] edge [ source 85 target 20 label 0 ] edge [ source 85 target 21 label 0 ] edge [ source 85 target 27 label 0 ] edge [ source 85 target 31 label 0 ] edge [ source 85 target 59 label 0 ] edge [ source 86 target 13 label 0 ] edge [ source 86 target 15 label 0 ] edge [ source 86 target 39 label 0 ] edge [ source 86 target 54 label 0 ] edge [ source 86 target 64 label 0 ] edge [ source 86 target 79 label 0 ] edge [ source 87 target 34 label 0 ] edge [ source 87 target 37 label 0 ] edge [ source 87 target 46 label 0 ] edge [ source 87 target 50 label 0 ] edge [ source 87 target 60 label 0 ] edge [ source 87 target 76 label 0 ] edge [ source 88 target 29 label 0 ] edge [ source 88 target 40 label 0 ] edge [ source 88 target 41 label 0 ] edge [ source 88 target 44 label 0 ] edge [ source 88 target 48 label 0 ] edge [ source 88 target 61 label 0 ] edge [ source 88 target 78 label 0 ] edge [ source 88 target 85 label 0 ] edge [ source 89 target 4 label 0 ] edge [ source 89 target 9 label 0 ] edge [ source 89 target 13 label 0 ] edge [ source 89 target 43 label 0 ] edge [ source 89 target 49 label 0 ] edge [ source 89 target 81 label 0 ] edge [ source 90 target 16 label 0 ] edge [ source 90 target 17 label 0 ] edge [ source 90 target 54 label 0 ] edge [ source 90 target 89 label 0 ] edge [ source 91 target 1 label 0 ] edge [ source 91 target 4 label 0 ] edge [ source 91 target 14 label 0 ] edge [ source 91 target 48 label 0 ] edge [ source 91 target 59 label 0 ] edge [ source 91 target 63 label 0 ] edge [ source 91 target 70 label 0 ] edge [ source 91 target 74 label 0 ] edge [ source 92 target 1 label 0 ] edge [ source 92 target 3 label 0 ] edge [ source 92 target 23 label 0 ] edge [ source 92 target 32 label 0 ] edge [ source 92 target 42 label 0 ] edge [ source 92 target 53 label 0 ] edge [ source 92 target 55 label 0 ] edge [ source 92 target 58 label 0 ] edge [ source 92 target 61 label 0 ] edge [ source 92 target 81 label 0 ] edge [ source 92 target 84 label 0 ] edge [ source 93 target 19 label 0 ] edge [ source 93 target 21 label 0 ] edge [ source 93 target 25 label 0 ] edge [ source 93 target 38 label 0 ] edge [ source 93 target 53 label 0 ] edge [ source 93 target 60 label 0 ] edge [ source 93 target 81 label 0 ] edge [ source 94 target 39 label 0 ] edge [ source 94 target 53 label 0 ] edge [ source 94 target 56 label 0 ] edge [ source 94 target 70 label 0 ] edge [ source 94 target 83 label 0 ] edge [ source 95 target 6 label 0 ] edge [ source 95 target 18 label 0 ] edge [ source 95 target 35 label 0 ] edge [ source 95 target 54 label 0 ] edge [ source 95 target 71 label 0 ] edge [ source 96 target 6 label 0 ] edge [ source 96 target 17 label 0 ] edge [ source 96 target 21 label 0 ] edge [ source 96 target 32 label 0 ] edge [ source 96 target 38 label 0 ] edge [ source 96 target 52 label 0 ] edge [ source 96 target 59 label 0 ] edge [ source 96 target 60 label 0 ] edge [ source 96 target 93 label 0 ] edge [ source 97 target 3 label 0 ] edge [ source 97 target 17 label 0 ] edge [ source 97 target 30 label 0 ] edge [ source 97 target 51 label 0 ] edge [ source 97 target 52 label 0 ] edge [ source 97 target 80 label 0 ] edge [ source 97 target 81 label 0 ] edge [ source 97 target 85 label 0 ] edge [ source 97 target 93 label 0 ] edge [ source 98 target 4 label 0 ] edge [ source 98 target 10 label 0 ] edge [ source 98 target 11 label 0 ] edge [ source 98 target 50 label 0 ] edge [ source 98 target 56 label 0 ] edge [ source 98 target 63 label 0 ] edge [ source 98 target 68 label 0 ] edge [ source 98 target 74 label 0 ] edge [ source 98 target 91 label 0 ] edge [ source 99 target 13 label 0 ] edge [ source 99 target 32 label 0 ] edge [ source 99 target 67 label 0 ] edge [ source 99 target 73 label 0 ] edge [ source 100 target 2 label 0 ] edge [ source 100 target 25 label 0 ] edge [ source 100 target 27 label 0 ] edge [ source 100 target 31 label 0 ] edge [ source 100 target 86 label 0 ] edge [ source 100 target 87 label 0 ] ] ocamlgraph-1.8.3/editor/tests/test.gml0000644000175000017500000000165312133565071016716 0ustar mehdimehdigraph [ comment "This is a sample graph" directed 1 id 42 label "Hello, I am a graph" node [ id 1 label "Node 1" ] node [ id 2 label "node 2" ] node [ id 3 label "node 3" ] node [ id 4 label "node 3" ] node [ id 5 label "node 3" ] node [ id 6 label "node 3" ] node [ id 7 label "node 3" ] node [ id 8 label "node 3" ] node [ id 9 label "node 3" ] node [ id 10 label "node 3" ] node [ id 11 label "node 3" ] node [ id 12 label "node 3" ] edge [ source 1 target 2 ] edge [ source 1 target 4 ] edge [ source 1 target 5 ] edge [ source 1 target 6 ] edge [ source 1 target 7 ] edge [ source 2 target 7 ] edge [ source 3 target 7 ] edge [ source 1 target 8 ] edge [ source 2 target 3 ] edge [ source 3 target 1 ] edge [ source 8 target 9 ] edge [ source 8 target 10 ] edge [ source 8 target 11 ] edge [ source 8 target 12 ] ]ocamlgraph-1.8.3/editor/tests/rand_100_10.gml0000644000175000017500000001003212133565071017532 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] node [ id 11 label 10 ] node [ id 12 label 11 ] node [ id 13 label 12 ] node [ id 14 label 13 ] node [ id 15 label 14 ] node [ id 16 label 15 ] node [ id 17 label 16 ] node [ id 18 label 17 ] node [ id 19 label 18 ] node [ id 20 label 19 ] node [ id 21 label 20 ] node [ id 22 label 21 ] node [ id 23 label 22 ] node [ id 24 label 23 ] node [ id 25 label 24 ] node [ id 26 label 25 ] node [ id 27 label 26 ] node [ id 28 label 27 ] node [ id 29 label 28 ] node [ id 30 label 29 ] node [ id 31 label 30 ] node [ id 32 label 31 ] node [ id 33 label 32 ] node [ id 34 label 33 ] node [ id 35 label 34 ] node [ id 36 label 35 ] node [ id 37 label 36 ] node [ id 38 label 37 ] node [ id 39 label 38 ] node [ id 40 label 39 ] node [ id 41 label 40 ] node [ id 42 label 41 ] node [ id 43 label 42 ] node [ id 44 label 43 ] node [ id 45 label 44 ] node [ id 46 label 45 ] node [ id 47 label 46 ] node [ id 48 label 47 ] node [ id 49 label 48 ] node [ id 50 label 49 ] node [ id 51 label 50 ] node [ id 52 label 51 ] node [ id 53 label 52 ] node [ id 54 label 53 ] node [ id 55 label 54 ] node [ id 56 label 55 ] node [ id 57 label 56 ] node [ id 58 label 57 ] node [ id 59 label 58 ] node [ id 60 label 59 ] node [ id 61 label 60 ] node [ id 62 label 61 ] node [ id 63 label 62 ] node [ id 64 label 63 ] node [ id 65 label 64 ] node [ id 66 label 65 ] node [ id 67 label 66 ] node [ id 68 label 67 ] node [ id 69 label 68 ] node [ id 70 label 69 ] node [ id 71 label 70 ] node [ id 72 label 71 ] node [ id 73 label 72 ] node [ id 74 label 73 ] node [ id 75 label 74 ] node [ id 76 label 75 ] node [ id 77 label 76 ] node [ id 78 label 77 ] node [ id 79 label 78 ] node [ id 80 label 79 ] node [ id 81 label 80 ] node [ id 82 label 81 ] node [ id 83 label 82 ] node [ id 84 label 83 ] node [ id 85 label 84 ] node [ id 86 label 85 ] node [ id 87 label 86 ] node [ id 88 label 87 ] node [ id 89 label 88 ] node [ id 90 label 89 ] node [ id 91 label 90 ] node [ id 92 label 91 ] node [ id 93 label 92 ] node [ id 94 label 93 ] node [ id 95 label 94 ] node [ id 96 label 95 ] node [ id 97 label 96 ] node [ id 98 label 97 ] node [ id 99 label 98 ] node [ id 100 label 99 ] edge [ source 18 target 1 label 0 ] edge [ source 29 target 15 label 0 ] edge [ source 48 target 35 label 0 ] edge [ source 49 target 26 label 0 ] edge [ source 66 target 58 label 0 ] edge [ source 75 target 33 label 0 ] edge [ source 77 target 61 label 0 ] edge [ source 84 target 76 label 0 ] edge [ source 89 target 13 label 0 ] edge [ source 93 target 21 label 0 ] ] ocamlgraph-1.8.3/editor/tests/test2,1_3.gml0000644000175000017500000000114712133565071017355 0ustar mehdimehdigraph [ comment "This is a sample graph" directed 1 id 42 label "Hello, I am a graph" node [ id 1 label "Node 1" ] node [ id 2 label "node 2" ] node [ id 3 label "node 3" ] node [ id 4 label "node 4" ] node [ id 5 label "node 5" ] node [ id 6 label "node 6" ] node [ id 7 label "node 7" ] edge [ source 1 target 2 ] edge [ source 1 target 3 ] edge [ source 1 target 4 ] edge [ source 1 target 6 ] edge [ source 1 target 5 ] edge [ source 1 target 7 ] edge [ source 2 target 4 ] edge [ source 6 target 5 ] edge [ source 5 target 7 ] ] ocamlgraph-1.8.3/editor/tests/test2,1_2.gml0000644000175000017500000000100712133565071017347 0ustar mehdimehdigraph [ comment "This is a sample graph" directed 1 id 42 label "Hello, I am a graph" node [ id 1 label "Node 1" ] node [ id 2 label "node 2" ] node [ id 3 label "node 3" ] node [ id 4 label "node 4" ] node [ id 5 label "node 5" ] node [ id 6 label "node 6" ] edge [ source 1 target 2 ] edge [ source 1 target 3 ] edge [ source 1 target 4 ] edge [ source 1 target 5 ] edge [ source 1 target 6 ] edge [ source 2 target 4 ] edge [ source 5 target 6] ] ocamlgraph-1.8.3/editor/tests/de_bruijn4.gml0000644000175000017500000000420012133565071017753 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] node [ id 11 label 10 ] node [ id 12 label 11 ] node [ id 13 label 12 ] node [ id 14 label 13 ] node [ id 15 label 14 ] node [ id 16 label 15 ] edge [ source 1 target 1 label 0 ] edge [ source 2 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 4 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 6 target 3 label 0 ] edge [ source 7 target 4 label 0 ] edge [ source 8 target 4 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 10 target 3 label 0 ] edge [ source 10 target 4 label 0 ] edge [ source 10 target 5 label 0 ] edge [ source 11 target 5 label 0 ] edge [ source 11 target 6 label 0 ] edge [ source 12 target 6 label 0 ] edge [ source 12 target 7 label 0 ] edge [ source 12 target 8 label 0 ] edge [ source 13 target 7 label 0 ] edge [ source 13 target 9 label 0 ] edge [ source 13 target 10 label 0 ] edge [ source 14 target 7 label 0 ] edge [ source 14 target 11 label 0 ] edge [ source 14 target 12 label 0 ] edge [ source 15 target 8 label 0 ] edge [ source 15 target 13 label 0 ] edge [ source 15 target 14 label 0 ] edge [ source 16 target 8 label 0 ] edge [ source 16 target 15 label 0 ] edge [ source 16 target 16 label 0 ] ] ocamlgraph-1.8.3/editor/tests/transparency.dot0000644000175000017500000000345412133565071020460 0ustar mehdimehdigraph G { graph [splines=true overlap=false] graph [truecolor bgcolor="#ff00005f"] node [style=filled fillcolor="#00ff005f"] 1 -- 30 [f=1]; 1 -- 40 [f=14]; 8 -- 46 [f=1]; 8 -- 16 [f=18]; 10 -- 25 [f=1]; 10 -- 19 [f=5]; 10 -- 33 [f=1]; 12 -- 8 [f=1]; 12 -- 36 [f=5]; 12 -- 17 [f=16]; 13 -- 38 [f=1]; 13 -- 24 [f=19]; 24 -- 49 [f=1]; 24 -- 13 [f=1]; 24 -- 47 [f=12]; 24 -- 12 [f=19]; 25 -- 27 [f=1]; 25 -- 12 [f=1]; 27 -- 12 [f=1]; 27 -- 14 [f=8]; 29 -- 10 [f=1]; 29 -- 8 [f=17]; 30 -- 24 [f=1]; 30 -- 44 [f=15]; 38 -- 29 [f=1]; 38 -- 35 [f=15]; 2 -- 42 [f=2]; 2 -- 35 [f=3]; 2 -- 11 [f=19]; 14 -- 18 [f=2]; 14 -- 24 [f=15]; 14 -- 38 [f=18]; 18 -- 49 [f=2]; 18 -- 47 [f=20]; 26 -- 41 [f=2]; 26 -- 42 [f=15]; 31 -- 39 [f=2]; 31 -- 47 [f=17]; 31 -- 25 [f=14]; 37 -- 26 [f=2]; 37 -- 16 [f=14]; 39 -- 50 [f=2]; 39 -- 14 [f=2]; 39 -- 18 [f=17]; 39 -- 47 [f=10]; 41 -- 31 [f=2]; 41 -- 8 [f=16]; 42 -- 44 [f=2]; 42 -- 29 [f=12]; 44 -- 37 [f=2]; 44 -- 32 [f=15]; 3 -- 20 [f=2]; 3 -- 28 [f=19]; 6 -- 45 [f=2]; 6 -- 28 [f=10]; 9 -- 6 [f=2]; 9 -- 16 [f=1]; 15 -- 16 [f=2]; 15 -- 48 [f=2]; 16 -- 50 [f=2]; 16 -- 32 [f=14]; 16 -- 39 [f=8]; 20 -- 33 [f=2]; 33 -- 9 [f=2]; 33 -- 46 [f=3]; 33 -- 48 [f=17]; 45 -- 15 [f=2]; 4 -- 17 [f=4]; 4 -- 15 [f=6]; 4 -- 12 [f=16]; 17 -- 21 [f=4]; 19 -- 35 [f=4]; 19 -- 15 [f=9]; 19 -- 43 [f=4]; 21 -- 19 [f=4]; 21 -- 50 [f=4]; 23 -- 36 [f=4]; 34 -- 23 [f=4]; 34 -- 24 [f=11]; 35 -- 34 [f=4]; 35 -- 16 [f=6]; 35 -- 18 [f=16]; 36 -- 46 [f=4]; 5 -- 7 [f=1]; 5 -- 36 [f=6]; 7 -- 32 [f=1]; 7 -- 11 [f=2]; 7 -- 14 [f=17]; 11 -- 40 [f=1]; 11 -- 50 [f=1]; 22 -- 46 [f=1]; 28 -- 43 [f=1]; 28 -- 8 [f=18]; 32 -- 28 [f=1]; 32 -- 39 [f=13]; 32 -- 42 [f=15]; 40 -- 22 [f=1]; 40 -- 47 [f=1]; 43 -- 11 [f=1]; 43 -- 17 [f=19]; } ocamlgraph-1.8.3/editor/tests/full50.gml0000644000175000017500000020645512133565071017055 0ustar mehdimehdigraph [ node [ id 1 label 1 ] node [ id 2 label 2 ] node [ id 3 label 3 ] node [ id 4 label 4 ] node [ id 5 label 5 ] node [ id 6 label 6 ] node [ id 7 label 7 ] node [ id 8 label 8 ] node [ id 9 label 9 ] node [ id 10 label 10 ] node [ id 11 label 11 ] node [ id 12 label 12 ] node [ id 13 label 13 ] node [ id 14 label 14 ] node [ id 15 label 15 ] node [ id 16 label 16 ] node [ id 17 label 17 ] node [ id 18 label 18 ] node [ id 19 label 19 ] node [ id 20 label 20 ] node [ id 21 label 21 ] node [ id 22 label 22 ] node [ id 23 label 23 ] node [ id 24 label 24 ] node [ id 25 label 25 ] node [ id 26 label 26 ] node [ id 27 label 27 ] node [ id 28 label 28 ] node [ id 29 label 29 ] node [ id 30 label 30 ] node [ id 31 label 31 ] node [ id 32 label 32 ] node [ id 33 label 33 ] node [ id 34 label 34 ] node [ id 35 label 35 ] node [ id 36 label 36 ] node [ id 37 label 37 ] node [ id 38 label 38 ] node [ id 39 label 39 ] node [ id 40 label 40 ] node [ id 41 label 41 ] node [ id 42 label 42 ] node [ id 43 label 43 ] node [ id 44 label 44 ] node [ id 45 label 45 ] node [ id 46 label 46 ] node [ id 47 label 47 ] node [ id 48 label 48 ] node [ id 49 label 49 ] node [ id 50 label 50 ] edge [ source 1 target 1 label 0 ] edge [ source 2 target 1 label 0 ] edge [ source 2 target 2 label 0 ] edge [ source 3 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 3 target 3 label 0 ] edge [ source 4 target 1 label 0 ] edge [ source 4 target 2 label 0 ] edge [ source 4 target 3 label 0 ] edge [ source 4 target 4 label 0 ] edge [ source 5 target 1 label 0 ] edge [ source 5 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 5 target 4 label 0 ] edge [ source 5 target 5 label 0 ] edge [ source 6 target 1 label 0 ] edge [ source 6 target 2 label 0 ] edge [ source 6 target 3 label 0 ] edge [ source 6 target 4 label 0 ] edge [ source 6 target 5 label 0 ] edge [ source 6 target 6 label 0 ] edge [ source 7 target 1 label 0 ] edge [ source 7 target 2 label 0 ] edge [ source 7 target 3 label 0 ] edge [ source 7 target 4 label 0 ] edge [ source 7 target 5 label 0 ] edge [ source 7 target 6 label 0 ] edge [ source 7 target 7 label 0 ] edge [ source 8 target 1 label 0 ] edge [ source 8 target 2 label 0 ] edge [ source 8 target 3 label 0 ] edge [ source 8 target 4 label 0 ] edge [ source 8 target 5 label 0 ] edge [ source 8 target 6 label 0 ] edge [ source 8 target 7 label 0 ] edge [ source 8 target 8 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 3 label 0 ] edge [ source 9 target 4 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 9 target 6 label 0 ] edge [ source 9 target 7 label 0 ] edge [ source 9 target 8 label 0 ] edge [ source 9 target 9 label 0 ] edge [ source 10 target 1 label 0 ] edge [ source 10 target 2 label 0 ] edge [ source 10 target 3 label 0 ] edge [ source 10 target 4 label 0 ] edge [ source 10 target 5 label 0 ] edge [ source 10 target 6 label 0 ] edge [ source 10 target 7 label 0 ] edge [ source 10 target 8 label 0 ] edge [ source 10 target 9 label 0 ] edge [ source 10 target 10 label 0 ] edge [ source 11 target 1 label 0 ] edge [ source 11 target 2 label 0 ] edge [ source 11 target 3 label 0 ] edge [ source 11 target 4 label 0 ] edge [ source 11 target 5 label 0 ] edge [ source 11 target 6 label 0 ] edge [ source 11 target 7 label 0 ] edge [ source 11 target 8 label 0 ] edge [ source 11 target 9 label 0 ] edge [ source 11 target 10 label 0 ] edge [ source 11 target 11 label 0 ] edge [ source 12 target 1 label 0 ] edge [ source 12 target 2 label 0 ] edge [ source 12 target 3 label 0 ] edge [ source 12 target 4 label 0 ] edge [ source 12 target 5 label 0 ] edge [ source 12 target 6 label 0 ] edge [ source 12 target 7 label 0 ] edge [ source 12 target 8 label 0 ] edge [ source 12 target 9 label 0 ] edge [ source 12 target 10 label 0 ] edge [ source 12 target 11 label 0 ] edge [ source 12 target 12 label 0 ] edge [ source 13 target 1 label 0 ] edge [ source 13 target 2 label 0 ] edge [ source 13 target 3 label 0 ] edge [ source 13 target 4 label 0 ] edge [ source 13 target 5 label 0 ] edge [ source 13 target 6 label 0 ] edge [ source 13 target 7 label 0 ] edge [ source 13 target 8 label 0 ] edge [ source 13 target 9 label 0 ] edge [ source 13 target 10 label 0 ] edge [ source 13 target 11 label 0 ] edge [ source 13 target 12 label 0 ] edge [ source 13 target 13 label 0 ] edge [ source 14 target 1 label 0 ] edge [ source 14 target 2 label 0 ] edge [ source 14 target 3 label 0 ] edge [ source 14 target 4 label 0 ] edge [ source 14 target 5 label 0 ] edge [ source 14 target 6 label 0 ] edge [ source 14 target 7 label 0 ] edge [ source 14 target 8 label 0 ] edge [ source 14 target 9 label 0 ] edge [ source 14 target 10 label 0 ] edge [ source 14 target 11 label 0 ] edge [ source 14 target 12 label 0 ] edge [ source 14 target 13 label 0 ] edge [ source 14 target 14 label 0 ] edge [ source 15 target 1 label 0 ] edge [ source 15 target 2 label 0 ] edge [ source 15 target 3 label 0 ] edge [ source 15 target 4 label 0 ] edge [ source 15 target 5 label 0 ] edge [ source 15 target 6 label 0 ] edge [ source 15 target 7 label 0 ] edge [ source 15 target 8 label 0 ] edge [ source 15 target 9 label 0 ] edge [ source 15 target 10 label 0 ] edge [ source 15 target 11 label 0 ] edge [ source 15 target 12 label 0 ] edge [ source 15 target 13 label 0 ] edge [ source 15 target 14 label 0 ] edge [ source 15 target 15 label 0 ] edge [ source 16 target 1 label 0 ] edge [ source 16 target 2 label 0 ] edge [ source 16 target 3 label 0 ] edge [ source 16 target 4 label 0 ] edge [ source 16 target 5 label 0 ] edge [ source 16 target 6 label 0 ] edge [ source 16 target 7 label 0 ] edge [ source 16 target 8 label 0 ] edge [ source 16 target 9 label 0 ] edge [ source 16 target 10 label 0 ] edge [ source 16 target 11 label 0 ] edge [ source 16 target 12 label 0 ] edge [ source 16 target 13 label 0 ] edge [ source 16 target 14 label 0 ] edge [ source 16 target 15 label 0 ] edge [ source 16 target 16 label 0 ] edge [ source 17 target 1 label 0 ] edge [ source 17 target 2 label 0 ] edge [ source 17 target 3 label 0 ] edge [ source 17 target 4 label 0 ] edge [ source 17 target 5 label 0 ] edge [ source 17 target 6 label 0 ] edge [ source 17 target 7 label 0 ] edge [ source 17 target 8 label 0 ] edge [ source 17 target 9 label 0 ] edge [ source 17 target 10 label 0 ] edge [ source 17 target 11 label 0 ] edge [ source 17 target 12 label 0 ] edge [ source 17 target 13 label 0 ] edge [ source 17 target 14 label 0 ] edge [ source 17 target 15 label 0 ] edge [ source 17 target 16 label 0 ] edge [ source 17 target 17 label 0 ] edge [ source 18 target 1 label 0 ] edge [ source 18 target 2 label 0 ] edge [ source 18 target 3 label 0 ] edge [ source 18 target 4 label 0 ] edge [ source 18 target 5 label 0 ] edge [ source 18 target 6 label 0 ] edge [ source 18 target 7 label 0 ] edge [ source 18 target 8 label 0 ] edge [ source 18 target 9 label 0 ] edge [ source 18 target 10 label 0 ] edge [ source 18 target 11 label 0 ] edge [ source 18 target 12 label 0 ] edge [ source 18 target 13 label 0 ] edge [ source 18 target 14 label 0 ] edge [ source 18 target 15 label 0 ] edge [ source 18 target 16 label 0 ] edge [ source 18 target 17 label 0 ] edge [ source 18 target 18 label 0 ] edge [ source 19 target 1 label 0 ] edge [ source 19 target 2 label 0 ] edge [ source 19 target 3 label 0 ] edge [ source 19 target 4 label 0 ] edge [ source 19 target 5 label 0 ] edge [ source 19 target 6 label 0 ] edge [ source 19 target 7 label 0 ] edge [ source 19 target 8 label 0 ] edge [ source 19 target 9 label 0 ] edge [ source 19 target 10 label 0 ] edge [ source 19 target 11 label 0 ] edge [ source 19 target 12 label 0 ] edge [ source 19 target 13 label 0 ] edge [ source 19 target 14 label 0 ] edge [ source 19 target 15 label 0 ] edge [ source 19 target 16 label 0 ] edge [ source 19 target 17 label 0 ] edge [ source 19 target 18 label 0 ] edge [ source 19 target 19 label 0 ] edge [ source 20 target 1 label 0 ] edge [ source 20 target 2 label 0 ] edge [ source 20 target 3 label 0 ] edge [ source 20 target 4 label 0 ] edge [ source 20 target 5 label 0 ] edge [ source 20 target 6 label 0 ] edge [ source 20 target 7 label 0 ] edge [ source 20 target 8 label 0 ] edge [ source 20 target 9 label 0 ] edge [ source 20 target 10 label 0 ] edge [ source 20 target 11 label 0 ] edge [ source 20 target 12 label 0 ] edge [ source 20 target 13 label 0 ] edge [ source 20 target 14 label 0 ] edge [ source 20 target 15 label 0 ] edge [ source 20 target 16 label 0 ] edge [ source 20 target 17 label 0 ] edge [ source 20 target 18 label 0 ] edge [ source 20 target 19 label 0 ] edge [ source 20 target 20 label 0 ] edge [ source 21 target 1 label 0 ] edge [ source 21 target 2 label 0 ] edge [ source 21 target 3 label 0 ] edge [ source 21 target 4 label 0 ] edge [ source 21 target 5 label 0 ] edge [ source 21 target 6 label 0 ] edge [ source 21 target 7 label 0 ] edge [ source 21 target 8 label 0 ] edge [ source 21 target 9 label 0 ] edge [ source 21 target 10 label 0 ] edge [ source 21 target 11 label 0 ] edge [ source 21 target 12 label 0 ] edge [ source 21 target 13 label 0 ] edge [ source 21 target 14 label 0 ] edge [ source 21 target 15 label 0 ] edge [ source 21 target 16 label 0 ] edge [ source 21 target 17 label 0 ] edge [ source 21 target 18 label 0 ] edge [ source 21 target 19 label 0 ] edge [ source 21 target 20 label 0 ] edge [ source 21 target 21 label 0 ] edge [ source 22 target 1 label 0 ] edge [ source 22 target 2 label 0 ] edge [ source 22 target 3 label 0 ] edge [ source 22 target 4 label 0 ] edge [ source 22 target 5 label 0 ] edge [ source 22 target 6 label 0 ] edge [ source 22 target 7 label 0 ] edge [ source 22 target 8 label 0 ] edge [ source 22 target 9 label 0 ] edge [ source 22 target 10 label 0 ] edge [ source 22 target 11 label 0 ] edge [ source 22 target 12 label 0 ] edge [ source 22 target 13 label 0 ] edge [ source 22 target 14 label 0 ] edge [ source 22 target 15 label 0 ] edge [ source 22 target 16 label 0 ] edge [ source 22 target 17 label 0 ] edge [ source 22 target 18 label 0 ] edge [ source 22 target 19 label 0 ] edge [ source 22 target 20 label 0 ] edge [ source 22 target 21 label 0 ] edge [ source 22 target 22 label 0 ] edge [ source 23 target 1 label 0 ] edge [ source 23 target 2 label 0 ] edge [ source 23 target 3 label 0 ] edge [ source 23 target 4 label 0 ] edge [ source 23 target 5 label 0 ] edge [ source 23 target 6 label 0 ] edge [ source 23 target 7 label 0 ] edge [ source 23 target 8 label 0 ] edge [ source 23 target 9 label 0 ] edge [ source 23 target 10 label 0 ] edge [ source 23 target 11 label 0 ] edge [ source 23 target 12 label 0 ] edge [ source 23 target 13 label 0 ] edge [ source 23 target 14 label 0 ] edge [ source 23 target 15 label 0 ] edge [ source 23 target 16 label 0 ] edge [ source 23 target 17 label 0 ] edge [ source 23 target 18 label 0 ] edge [ source 23 target 19 label 0 ] edge [ source 23 target 20 label 0 ] edge [ source 23 target 21 label 0 ] edge [ source 23 target 22 label 0 ] edge [ source 23 target 23 label 0 ] edge [ source 24 target 1 label 0 ] edge [ source 24 target 2 label 0 ] edge [ source 24 target 3 label 0 ] edge [ source 24 target 4 label 0 ] edge [ source 24 target 5 label 0 ] edge [ source 24 target 6 label 0 ] edge [ source 24 target 7 label 0 ] edge [ source 24 target 8 label 0 ] edge [ source 24 target 9 label 0 ] edge [ source 24 target 10 label 0 ] edge [ source 24 target 11 label 0 ] edge [ source 24 target 12 label 0 ] edge [ source 24 target 13 label 0 ] edge [ source 24 target 14 label 0 ] edge [ source 24 target 15 label 0 ] edge [ source 24 target 16 label 0 ] edge [ source 24 target 17 label 0 ] edge [ source 24 target 18 label 0 ] edge [ source 24 target 19 label 0 ] edge [ source 24 target 20 label 0 ] edge [ source 24 target 21 label 0 ] edge [ source 24 target 22 label 0 ] edge [ source 24 target 23 label 0 ] edge [ source 24 target 24 label 0 ] edge [ source 25 target 1 label 0 ] edge [ source 25 target 2 label 0 ] edge [ source 25 target 3 label 0 ] edge [ source 25 target 4 label 0 ] edge [ source 25 target 5 label 0 ] edge [ source 25 target 6 label 0 ] edge [ source 25 target 7 label 0 ] edge [ source 25 target 8 label 0 ] edge [ source 25 target 9 label 0 ] edge [ source 25 target 10 label 0 ] edge [ source 25 target 11 label 0 ] edge [ source 25 target 12 label 0 ] edge [ source 25 target 13 label 0 ] edge [ source 25 target 14 label 0 ] edge [ source 25 target 15 label 0 ] edge [ source 25 target 16 label 0 ] edge [ source 25 target 17 label 0 ] edge [ source 25 target 18 label 0 ] edge [ source 25 target 19 label 0 ] edge [ source 25 target 20 label 0 ] edge [ source 25 target 21 label 0 ] edge [ source 25 target 22 label 0 ] edge [ source 25 target 23 label 0 ] edge [ source 25 target 24 label 0 ] edge [ source 25 target 25 label 0 ] edge [ source 26 target 1 label 0 ] edge [ source 26 target 2 label 0 ] edge [ source 26 target 3 label 0 ] edge [ source 26 target 4 label 0 ] edge [ source 26 target 5 label 0 ] edge [ source 26 target 6 label 0 ] edge [ source 26 target 7 label 0 ] edge [ source 26 target 8 label 0 ] edge [ source 26 target 9 label 0 ] edge [ source 26 target 10 label 0 ] edge [ source 26 target 11 label 0 ] edge [ source 26 target 12 label 0 ] edge [ source 26 target 13 label 0 ] edge [ source 26 target 14 label 0 ] edge [ source 26 target 15 label 0 ] edge [ source 26 target 16 label 0 ] edge [ source 26 target 17 label 0 ] edge [ source 26 target 18 label 0 ] edge [ source 26 target 19 label 0 ] edge [ source 26 target 20 label 0 ] edge [ source 26 target 21 label 0 ] edge [ source 26 target 22 label 0 ] edge [ source 26 target 23 label 0 ] edge [ source 26 target 24 label 0 ] edge [ source 26 target 25 label 0 ] edge [ source 26 target 26 label 0 ] edge [ source 27 target 1 label 0 ] edge [ source 27 target 2 label 0 ] edge [ source 27 target 3 label 0 ] edge [ source 27 target 4 label 0 ] edge [ source 27 target 5 label 0 ] edge [ source 27 target 6 label 0 ] edge [ source 27 target 7 label 0 ] edge [ source 27 target 8 label 0 ] edge [ source 27 target 9 label 0 ] edge [ source 27 target 10 label 0 ] edge [ source 27 target 11 label 0 ] edge [ source 27 target 12 label 0 ] edge [ source 27 target 13 label 0 ] edge [ source 27 target 14 label 0 ] edge [ source 27 target 15 label 0 ] edge [ source 27 target 16 label 0 ] edge [ source 27 target 17 label 0 ] edge [ source 27 target 18 label 0 ] edge [ source 27 target 19 label 0 ] edge [ source 27 target 20 label 0 ] edge [ source 27 target 21 label 0 ] edge [ source 27 target 22 label 0 ] edge [ source 27 target 23 label 0 ] edge [ source 27 target 24 label 0 ] edge [ source 27 target 25 label 0 ] edge [ source 27 target 26 label 0 ] edge [ source 27 target 27 label 0 ] edge [ source 28 target 1 label 0 ] edge [ source 28 target 2 label 0 ] edge [ source 28 target 3 label 0 ] edge [ source 28 target 4 label 0 ] edge [ source 28 target 5 label 0 ] edge [ source 28 target 6 label 0 ] edge [ source 28 target 7 label 0 ] edge [ source 28 target 8 label 0 ] edge [ source 28 target 9 label 0 ] edge [ source 28 target 10 label 0 ] edge [ source 28 target 11 label 0 ] edge [ source 28 target 12 label 0 ] edge [ source 28 target 13 label 0 ] edge [ source 28 target 14 label 0 ] edge [ source 28 target 15 label 0 ] edge [ source 28 target 16 label 0 ] edge [ source 28 target 17 label 0 ] edge [ source 28 target 18 label 0 ] edge [ source 28 target 19 label 0 ] edge [ source 28 target 20 label 0 ] edge [ source 28 target 21 label 0 ] edge [ source 28 target 22 label 0 ] edge [ source 28 target 23 label 0 ] edge [ source 28 target 24 label 0 ] edge [ source 28 target 25 label 0 ] edge [ source 28 target 26 label 0 ] edge [ source 28 target 27 label 0 ] edge [ source 28 target 28 label 0 ] edge [ source 29 target 1 label 0 ] edge [ source 29 target 2 label 0 ] edge [ source 29 target 3 label 0 ] edge [ source 29 target 4 label 0 ] edge [ source 29 target 5 label 0 ] edge [ source 29 target 6 label 0 ] edge [ source 29 target 7 label 0 ] edge [ source 29 target 8 label 0 ] edge [ source 29 target 9 label 0 ] edge [ source 29 target 10 label 0 ] edge [ source 29 target 11 label 0 ] edge [ source 29 target 12 label 0 ] edge [ source 29 target 13 label 0 ] edge [ source 29 target 14 label 0 ] edge [ source 29 target 15 label 0 ] edge [ source 29 target 16 label 0 ] edge [ source 29 target 17 label 0 ] edge [ source 29 target 18 label 0 ] edge [ source 29 target 19 label 0 ] edge [ source 29 target 20 label 0 ] edge [ source 29 target 21 label 0 ] edge [ source 29 target 22 label 0 ] edge [ source 29 target 23 label 0 ] edge [ source 29 target 24 label 0 ] edge [ source 29 target 25 label 0 ] edge [ source 29 target 26 label 0 ] edge [ source 29 target 27 label 0 ] edge [ source 29 target 28 label 0 ] edge [ source 29 target 29 label 0 ] edge [ source 30 target 1 label 0 ] edge [ source 30 target 2 label 0 ] edge [ source 30 target 3 label 0 ] edge [ source 30 target 4 label 0 ] edge [ source 30 target 5 label 0 ] edge [ source 30 target 6 label 0 ] edge [ source 30 target 7 label 0 ] edge [ source 30 target 8 label 0 ] edge [ source 30 target 9 label 0 ] edge [ source 30 target 10 label 0 ] edge [ source 30 target 11 label 0 ] edge [ source 30 target 12 label 0 ] edge [ source 30 target 13 label 0 ] edge [ source 30 target 14 label 0 ] edge [ source 30 target 15 label 0 ] edge [ source 30 target 16 label 0 ] edge [ source 30 target 17 label 0 ] edge [ source 30 target 18 label 0 ] edge [ source 30 target 19 label 0 ] edge [ source 30 target 20 label 0 ] edge [ source 30 target 21 label 0 ] edge [ source 30 target 22 label 0 ] edge [ source 30 target 23 label 0 ] edge [ source 30 target 24 label 0 ] edge [ source 30 target 25 label 0 ] edge [ source 30 target 26 label 0 ] edge [ source 30 target 27 label 0 ] edge [ source 30 target 28 label 0 ] edge [ source 30 target 29 label 0 ] edge [ source 30 target 30 label 0 ] edge [ source 31 target 1 label 0 ] edge [ source 31 target 2 label 0 ] edge [ source 31 target 3 label 0 ] edge [ source 31 target 4 label 0 ] edge [ source 31 target 5 label 0 ] edge [ source 31 target 6 label 0 ] edge [ source 31 target 7 label 0 ] edge [ source 31 target 8 label 0 ] edge [ source 31 target 9 label 0 ] edge [ source 31 target 10 label 0 ] edge [ source 31 target 11 label 0 ] edge [ source 31 target 12 label 0 ] edge [ source 31 target 13 label 0 ] edge [ source 31 target 14 label 0 ] edge [ source 31 target 15 label 0 ] edge [ source 31 target 16 label 0 ] edge [ source 31 target 17 label 0 ] edge [ source 31 target 18 label 0 ] edge [ source 31 target 19 label 0 ] edge [ source 31 target 20 label 0 ] edge [ source 31 target 21 label 0 ] edge [ source 31 target 22 label 0 ] edge [ source 31 target 23 label 0 ] edge [ source 31 target 24 label 0 ] edge [ source 31 target 25 label 0 ] edge [ source 31 target 26 label 0 ] edge [ source 31 target 27 label 0 ] edge [ source 31 target 28 label 0 ] edge [ source 31 target 29 label 0 ] edge [ source 31 target 30 label 0 ] edge [ source 31 target 31 label 0 ] edge [ source 32 target 1 label 0 ] edge [ source 32 target 2 label 0 ] edge [ source 32 target 3 label 0 ] edge [ source 32 target 4 label 0 ] edge [ source 32 target 5 label 0 ] edge [ source 32 target 6 label 0 ] edge [ source 32 target 7 label 0 ] edge [ source 32 target 8 label 0 ] edge [ source 32 target 9 label 0 ] edge [ source 32 target 10 label 0 ] edge [ source 32 target 11 label 0 ] edge [ source 32 target 12 label 0 ] edge [ source 32 target 13 label 0 ] edge [ source 32 target 14 label 0 ] edge [ source 32 target 15 label 0 ] edge [ source 32 target 16 label 0 ] edge [ source 32 target 17 label 0 ] edge [ source 32 target 18 label 0 ] edge [ source 32 target 19 label 0 ] edge [ source 32 target 20 label 0 ] edge [ source 32 target 21 label 0 ] edge [ source 32 target 22 label 0 ] edge [ source 32 target 23 label 0 ] edge [ source 32 target 24 label 0 ] edge [ source 32 target 25 label 0 ] edge [ source 32 target 26 label 0 ] edge [ source 32 target 27 label 0 ] edge [ source 32 target 28 label 0 ] edge [ source 32 target 29 label 0 ] edge [ source 32 target 30 label 0 ] edge [ source 32 target 31 label 0 ] edge [ source 32 target 32 label 0 ] edge [ source 33 target 1 label 0 ] edge [ source 33 target 2 label 0 ] edge [ source 33 target 3 label 0 ] edge [ source 33 target 4 label 0 ] edge [ source 33 target 5 label 0 ] edge [ source 33 target 6 label 0 ] edge [ source 33 target 7 label 0 ] edge [ source 33 target 8 label 0 ] edge [ source 33 target 9 label 0 ] edge [ source 33 target 10 label 0 ] edge [ source 33 target 11 label 0 ] edge [ source 33 target 12 label 0 ] edge [ source 33 target 13 label 0 ] edge [ source 33 target 14 label 0 ] edge [ source 33 target 15 label 0 ] edge [ source 33 target 16 label 0 ] edge [ source 33 target 17 label 0 ] edge [ source 33 target 18 label 0 ] edge [ source 33 target 19 label 0 ] edge [ source 33 target 20 label 0 ] edge [ source 33 target 21 label 0 ] edge [ source 33 target 22 label 0 ] edge [ source 33 target 23 label 0 ] edge [ source 33 target 24 label 0 ] edge [ source 33 target 25 label 0 ] edge [ source 33 target 26 label 0 ] edge [ source 33 target 27 label 0 ] edge [ source 33 target 28 label 0 ] edge [ source 33 target 29 label 0 ] edge [ source 33 target 30 label 0 ] edge [ source 33 target 31 label 0 ] edge [ source 33 target 32 label 0 ] edge [ source 33 target 33 label 0 ] edge [ source 34 target 1 label 0 ] edge [ source 34 target 2 label 0 ] edge [ source 34 target 3 label 0 ] edge [ source 34 target 4 label 0 ] edge [ source 34 target 5 label 0 ] edge [ source 34 target 6 label 0 ] edge [ source 34 target 7 label 0 ] edge [ source 34 target 8 label 0 ] edge [ source 34 target 9 label 0 ] edge [ source 34 target 10 label 0 ] edge [ source 34 target 11 label 0 ] edge [ source 34 target 12 label 0 ] edge [ source 34 target 13 label 0 ] edge [ source 34 target 14 label 0 ] edge [ source 34 target 15 label 0 ] edge [ source 34 target 16 label 0 ] edge [ source 34 target 17 label 0 ] edge [ source 34 target 18 label 0 ] edge [ source 34 target 19 label 0 ] edge [ source 34 target 20 label 0 ] edge [ source 34 target 21 label 0 ] edge [ source 34 target 22 label 0 ] edge [ source 34 target 23 label 0 ] edge [ source 34 target 24 label 0 ] edge [ source 34 target 25 label 0 ] edge [ source 34 target 26 label 0 ] edge [ source 34 target 27 label 0 ] edge [ source 34 target 28 label 0 ] edge [ source 34 target 29 label 0 ] edge [ source 34 target 30 label 0 ] edge [ source 34 target 31 label 0 ] edge [ source 34 target 32 label 0 ] edge [ source 34 target 33 label 0 ] edge [ source 34 target 34 label 0 ] edge [ source 35 target 1 label 0 ] edge [ source 35 target 2 label 0 ] edge [ source 35 target 3 label 0 ] edge [ source 35 target 4 label 0 ] edge [ source 35 target 5 label 0 ] edge [ source 35 target 6 label 0 ] edge [ source 35 target 7 label 0 ] edge [ source 35 target 8 label 0 ] edge [ source 35 target 9 label 0 ] edge [ source 35 target 10 label 0 ] edge [ source 35 target 11 label 0 ] edge [ source 35 target 12 label 0 ] edge [ source 35 target 13 label 0 ] edge [ source 35 target 14 label 0 ] edge [ source 35 target 15 label 0 ] edge [ source 35 target 16 label 0 ] edge [ source 35 target 17 label 0 ] edge [ source 35 target 18 label 0 ] edge [ source 35 target 19 label 0 ] edge [ source 35 target 20 label 0 ] edge [ source 35 target 21 label 0 ] edge [ source 35 target 22 label 0 ] edge [ source 35 target 23 label 0 ] edge [ source 35 target 24 label 0 ] edge [ source 35 target 25 label 0 ] edge [ source 35 target 26 label 0 ] edge [ source 35 target 27 label 0 ] edge [ source 35 target 28 label 0 ] edge [ source 35 target 29 label 0 ] edge [ source 35 target 30 label 0 ] edge [ source 35 target 31 label 0 ] edge [ source 35 target 32 label 0 ] edge [ source 35 target 33 label 0 ] edge [ source 35 target 34 label 0 ] edge [ source 35 target 35 label 0 ] edge [ source 36 target 1 label 0 ] edge [ source 36 target 2 label 0 ] edge [ source 36 target 3 label 0 ] edge [ source 36 target 4 label 0 ] edge [ source 36 target 5 label 0 ] edge [ source 36 target 6 label 0 ] edge [ source 36 target 7 label 0 ] edge [ source 36 target 8 label 0 ] edge [ source 36 target 9 label 0 ] edge [ source 36 target 10 label 0 ] edge [ source 36 target 11 label 0 ] edge [ source 36 target 12 label 0 ] edge [ source 36 target 13 label 0 ] edge [ source 36 target 14 label 0 ] edge [ source 36 target 15 label 0 ] edge [ source 36 target 16 label 0 ] edge [ source 36 target 17 label 0 ] edge [ source 36 target 18 label 0 ] edge [ source 36 target 19 label 0 ] edge [ source 36 target 20 label 0 ] edge [ source 36 target 21 label 0 ] edge [ source 36 target 22 label 0 ] edge [ source 36 target 23 label 0 ] edge [ source 36 target 24 label 0 ] edge [ source 36 target 25 label 0 ] edge [ source 36 target 26 label 0 ] edge [ source 36 target 27 label 0 ] edge [ source 36 target 28 label 0 ] edge [ source 36 target 29 label 0 ] edge [ source 36 target 30 label 0 ] edge [ source 36 target 31 label 0 ] edge [ source 36 target 32 label 0 ] edge [ source 36 target 33 label 0 ] edge [ source 36 target 34 label 0 ] edge [ source 36 target 35 label 0 ] edge [ source 36 target 36 label 0 ] edge [ source 37 target 1 label 0 ] edge [ source 37 target 2 label 0 ] edge [ source 37 target 3 label 0 ] edge [ source 37 target 4 label 0 ] edge [ source 37 target 5 label 0 ] edge [ source 37 target 6 label 0 ] edge [ source 37 target 7 label 0 ] edge [ source 37 target 8 label 0 ] edge [ source 37 target 9 label 0 ] edge [ source 37 target 10 label 0 ] edge [ source 37 target 11 label 0 ] edge [ source 37 target 12 label 0 ] edge [ source 37 target 13 label 0 ] edge [ source 37 target 14 label 0 ] edge [ source 37 target 15 label 0 ] edge [ source 37 target 16 label 0 ] edge [ source 37 target 17 label 0 ] edge [ source 37 target 18 label 0 ] edge [ source 37 target 19 label 0 ] edge [ source 37 target 20 label 0 ] edge [ source 37 target 21 label 0 ] edge [ source 37 target 22 label 0 ] edge [ source 37 target 23 label 0 ] edge [ source 37 target 24 label 0 ] edge [ source 37 target 25 label 0 ] edge [ source 37 target 26 label 0 ] edge [ source 37 target 27 label 0 ] edge [ source 37 target 28 label 0 ] edge [ source 37 target 29 label 0 ] edge [ source 37 target 30 label 0 ] edge [ source 37 target 31 label 0 ] edge [ source 37 target 32 label 0 ] edge [ source 37 target 33 label 0 ] edge [ source 37 target 34 label 0 ] edge [ source 37 target 35 label 0 ] edge [ source 37 target 36 label 0 ] edge [ source 37 target 37 label 0 ] edge [ source 38 target 1 label 0 ] edge [ source 38 target 2 label 0 ] edge [ source 38 target 3 label 0 ] edge [ source 38 target 4 label 0 ] edge [ source 38 target 5 label 0 ] edge [ source 38 target 6 label 0 ] edge [ source 38 target 7 label 0 ] edge [ source 38 target 8 label 0 ] edge [ source 38 target 9 label 0 ] edge [ source 38 target 10 label 0 ] edge [ source 38 target 11 label 0 ] edge [ source 38 target 12 label 0 ] edge [ source 38 target 13 label 0 ] edge [ source 38 target 14 label 0 ] edge [ source 38 target 15 label 0 ] edge [ source 38 target 16 label 0 ] edge [ source 38 target 17 label 0 ] edge [ source 38 target 18 label 0 ] edge [ source 38 target 19 label 0 ] edge [ source 38 target 20 label 0 ] edge [ source 38 target 21 label 0 ] edge [ source 38 target 22 label 0 ] edge [ source 38 target 23 label 0 ] edge [ source 38 target 24 label 0 ] edge [ source 38 target 25 label 0 ] edge [ source 38 target 26 label 0 ] edge [ source 38 target 27 label 0 ] edge [ source 38 target 28 label 0 ] edge [ source 38 target 29 label 0 ] edge [ source 38 target 30 label 0 ] edge [ source 38 target 31 label 0 ] edge [ source 38 target 32 label 0 ] edge [ source 38 target 33 label 0 ] edge [ source 38 target 34 label 0 ] edge [ source 38 target 35 label 0 ] edge [ source 38 target 36 label 0 ] edge [ source 38 target 37 label 0 ] edge [ source 38 target 38 label 0 ] edge [ source 39 target 1 label 0 ] edge [ source 39 target 2 label 0 ] edge [ source 39 target 3 label 0 ] edge [ source 39 target 4 label 0 ] edge [ source 39 target 5 label 0 ] edge [ source 39 target 6 label 0 ] edge [ source 39 target 7 label 0 ] edge [ source 39 target 8 label 0 ] edge [ source 39 target 9 label 0 ] edge [ source 39 target 10 label 0 ] edge [ source 39 target 11 label 0 ] edge [ source 39 target 12 label 0 ] edge [ source 39 target 13 label 0 ] edge [ source 39 target 14 label 0 ] edge [ source 39 target 15 label 0 ] edge [ source 39 target 16 label 0 ] edge [ source 39 target 17 label 0 ] edge [ source 39 target 18 label 0 ] edge [ source 39 target 19 label 0 ] edge [ source 39 target 20 label 0 ] edge [ source 39 target 21 label 0 ] edge [ source 39 target 22 label 0 ] edge [ source 39 target 23 label 0 ] edge [ source 39 target 24 label 0 ] edge [ source 39 target 25 label 0 ] edge [ source 39 target 26 label 0 ] edge [ source 39 target 27 label 0 ] edge [ source 39 target 28 label 0 ] edge [ source 39 target 29 label 0 ] edge [ source 39 target 30 label 0 ] edge [ source 39 target 31 label 0 ] edge [ source 39 target 32 label 0 ] edge [ source 39 target 33 label 0 ] edge [ source 39 target 34 label 0 ] edge [ source 39 target 35 label 0 ] edge [ source 39 target 36 label 0 ] edge [ source 39 target 37 label 0 ] edge [ source 39 target 38 label 0 ] edge [ source 39 target 39 label 0 ] edge [ source 40 target 1 label 0 ] edge [ source 40 target 2 label 0 ] edge [ source 40 target 3 label 0 ] edge [ source 40 target 4 label 0 ] edge [ source 40 target 5 label 0 ] edge [ source 40 target 6 label 0 ] edge [ source 40 target 7 label 0 ] edge [ source 40 target 8 label 0 ] edge [ source 40 target 9 label 0 ] edge [ source 40 target 10 label 0 ] edge [ source 40 target 11 label 0 ] edge [ source 40 target 12 label 0 ] edge [ source 40 target 13 label 0 ] edge [ source 40 target 14 label 0 ] edge [ source 40 target 15 label 0 ] edge [ source 40 target 16 label 0 ] edge [ source 40 target 17 label 0 ] edge [ source 40 target 18 label 0 ] edge [ source 40 target 19 label 0 ] edge [ source 40 target 20 label 0 ] edge [ source 40 target 21 label 0 ] edge [ source 40 target 22 label 0 ] edge [ source 40 target 23 label 0 ] edge [ source 40 target 24 label 0 ] edge [ source 40 target 25 label 0 ] edge [ source 40 target 26 label 0 ] edge [ source 40 target 27 label 0 ] edge [ source 40 target 28 label 0 ] edge [ source 40 target 29 label 0 ] edge [ source 40 target 30 label 0 ] edge [ source 40 target 31 label 0 ] edge [ source 40 target 32 label 0 ] edge [ source 40 target 33 label 0 ] edge [ source 40 target 34 label 0 ] edge [ source 40 target 35 label 0 ] edge [ source 40 target 36 label 0 ] edge [ source 40 target 37 label 0 ] edge [ source 40 target 38 label 0 ] edge [ source 40 target 39 label 0 ] edge [ source 40 target 40 label 0 ] edge [ source 41 target 1 label 0 ] edge [ source 41 target 2 label 0 ] edge [ source 41 target 3 label 0 ] edge [ source 41 target 4 label 0 ] edge [ source 41 target 5 label 0 ] edge [ source 41 target 6 label 0 ] edge [ source 41 target 7 label 0 ] edge [ source 41 target 8 label 0 ] edge [ source 41 target 9 label 0 ] edge [ source 41 target 10 label 0 ] edge [ source 41 target 11 label 0 ] edge [ source 41 target 12 label 0 ] edge [ source 41 target 13 label 0 ] edge [ source 41 target 14 label 0 ] edge [ source 41 target 15 label 0 ] edge [ source 41 target 16 label 0 ] edge [ source 41 target 17 label 0 ] edge [ source 41 target 18 label 0 ] edge [ source 41 target 19 label 0 ] edge [ source 41 target 20 label 0 ] edge [ source 41 target 21 label 0 ] edge [ source 41 target 22 label 0 ] edge [ source 41 target 23 label 0 ] edge [ source 41 target 24 label 0 ] edge [ source 41 target 25 label 0 ] edge [ source 41 target 26 label 0 ] edge [ source 41 target 27 label 0 ] edge [ source 41 target 28 label 0 ] edge [ source 41 target 29 label 0 ] edge [ source 41 target 30 label 0 ] edge [ source 41 target 31 label 0 ] edge [ source 41 target 32 label 0 ] edge [ source 41 target 33 label 0 ] edge [ source 41 target 34 label 0 ] edge [ source 41 target 35 label 0 ] edge [ source 41 target 36 label 0 ] edge [ source 41 target 37 label 0 ] edge [ source 41 target 38 label 0 ] edge [ source 41 target 39 label 0 ] edge [ source 41 target 40 label 0 ] edge [ source 41 target 41 label 0 ] edge [ source 42 target 1 label 0 ] edge [ source 42 target 2 label 0 ] edge [ source 42 target 3 label 0 ] edge [ source 42 target 4 label 0 ] edge [ source 42 target 5 label 0 ] edge [ source 42 target 6 label 0 ] edge [ source 42 target 7 label 0 ] edge [ source 42 target 8 label 0 ] edge [ source 42 target 9 label 0 ] edge [ source 42 target 10 label 0 ] edge [ source 42 target 11 label 0 ] edge [ source 42 target 12 label 0 ] edge [ source 42 target 13 label 0 ] edge [ source 42 target 14 label 0 ] edge [ source 42 target 15 label 0 ] edge [ source 42 target 16 label 0 ] edge [ source 42 target 17 label 0 ] edge [ source 42 target 18 label 0 ] edge [ source 42 target 19 label 0 ] edge [ source 42 target 20 label 0 ] edge [ source 42 target 21 label 0 ] edge [ source 42 target 22 label 0 ] edge [ source 42 target 23 label 0 ] edge [ source 42 target 24 label 0 ] edge [ source 42 target 25 label 0 ] edge [ source 42 target 26 label 0 ] edge [ source 42 target 27 label 0 ] edge [ source 42 target 28 label 0 ] edge [ source 42 target 29 label 0 ] edge [ source 42 target 30 label 0 ] edge [ source 42 target 31 label 0 ] edge [ source 42 target 32 label 0 ] edge [ source 42 target 33 label 0 ] edge [ source 42 target 34 label 0 ] edge [ source 42 target 35 label 0 ] edge [ source 42 target 36 label 0 ] edge [ source 42 target 37 label 0 ] edge [ source 42 target 38 label 0 ] edge [ source 42 target 39 label 0 ] edge [ source 42 target 40 label 0 ] edge [ source 42 target 41 label 0 ] edge [ source 42 target 42 label 0 ] edge [ source 43 target 1 label 0 ] edge [ source 43 target 2 label 0 ] edge [ source 43 target 3 label 0 ] edge [ source 43 target 4 label 0 ] edge [ source 43 target 5 label 0 ] edge [ source 43 target 6 label 0 ] edge [ source 43 target 7 label 0 ] edge [ source 43 target 8 label 0 ] edge [ source 43 target 9 label 0 ] edge [ source 43 target 10 label 0 ] edge [ source 43 target 11 label 0 ] edge [ source 43 target 12 label 0 ] edge [ source 43 target 13 label 0 ] edge [ source 43 target 14 label 0 ] edge [ source 43 target 15 label 0 ] edge [ source 43 target 16 label 0 ] edge [ source 43 target 17 label 0 ] edge [ source 43 target 18 label 0 ] edge [ source 43 target 19 label 0 ] edge [ source 43 target 20 label 0 ] edge [ source 43 target 21 label 0 ] edge [ source 43 target 22 label 0 ] edge [ source 43 target 23 label 0 ] edge [ source 43 target 24 label 0 ] edge [ source 43 target 25 label 0 ] edge [ source 43 target 26 label 0 ] edge [ source 43 target 27 label 0 ] edge [ source 43 target 28 label 0 ] edge [ source 43 target 29 label 0 ] edge [ source 43 target 30 label 0 ] edge [ source 43 target 31 label 0 ] edge [ source 43 target 32 label 0 ] edge [ source 43 target 33 label 0 ] edge [ source 43 target 34 label 0 ] edge [ source 43 target 35 label 0 ] edge [ source 43 target 36 label 0 ] edge [ source 43 target 37 label 0 ] edge [ source 43 target 38 label 0 ] edge [ source 43 target 39 label 0 ] edge [ source 43 target 40 label 0 ] edge [ source 43 target 41 label 0 ] edge [ source 43 target 42 label 0 ] edge [ source 43 target 43 label 0 ] edge [ source 44 target 1 label 0 ] edge [ source 44 target 2 label 0 ] edge [ source 44 target 3 label 0 ] edge [ source 44 target 4 label 0 ] edge [ source 44 target 5 label 0 ] edge [ source 44 target 6 label 0 ] edge [ source 44 target 7 label 0 ] edge [ source 44 target 8 label 0 ] edge [ source 44 target 9 label 0 ] edge [ source 44 target 10 label 0 ] edge [ source 44 target 11 label 0 ] edge [ source 44 target 12 label 0 ] edge [ source 44 target 13 label 0 ] edge [ source 44 target 14 label 0 ] edge [ source 44 target 15 label 0 ] edge [ source 44 target 16 label 0 ] edge [ source 44 target 17 label 0 ] edge [ source 44 target 18 label 0 ] edge [ source 44 target 19 label 0 ] edge [ source 44 target 20 label 0 ] edge [ source 44 target 21 label 0 ] edge [ source 44 target 22 label 0 ] edge [ source 44 target 23 label 0 ] edge [ source 44 target 24 label 0 ] edge [ source 44 target 25 label 0 ] edge [ source 44 target 26 label 0 ] edge [ source 44 target 27 label 0 ] edge [ source 44 target 28 label 0 ] edge [ source 44 target 29 label 0 ] edge [ source 44 target 30 label 0 ] edge [ source 44 target 31 label 0 ] edge [ source 44 target 32 label 0 ] edge [ source 44 target 33 label 0 ] edge [ source 44 target 34 label 0 ] edge [ source 44 target 35 label 0 ] edge [ source 44 target 36 label 0 ] edge [ source 44 target 37 label 0 ] edge [ source 44 target 38 label 0 ] edge [ source 44 target 39 label 0 ] edge [ source 44 target 40 label 0 ] edge [ source 44 target 41 label 0 ] edge [ source 44 target 42 label 0 ] edge [ source 44 target 43 label 0 ] edge [ source 44 target 44 label 0 ] edge [ source 45 target 1 label 0 ] edge [ source 45 target 2 label 0 ] edge [ source 45 target 3 label 0 ] edge [ source 45 target 4 label 0 ] edge [ source 45 target 5 label 0 ] edge [ source 45 target 6 label 0 ] edge [ source 45 target 7 label 0 ] edge [ source 45 target 8 label 0 ] edge [ source 45 target 9 label 0 ] edge [ source 45 target 10 label 0 ] edge [ source 45 target 11 label 0 ] edge [ source 45 target 12 label 0 ] edge [ source 45 target 13 label 0 ] edge [ source 45 target 14 label 0 ] edge [ source 45 target 15 label 0 ] edge [ source 45 target 16 label 0 ] edge [ source 45 target 17 label 0 ] edge [ source 45 target 18 label 0 ] edge [ source 45 target 19 label 0 ] edge [ source 45 target 20 label 0 ] edge [ source 45 target 21 label 0 ] edge [ source 45 target 22 label 0 ] edge [ source 45 target 23 label 0 ] edge [ source 45 target 24 label 0 ] edge [ source 45 target 25 label 0 ] edge [ source 45 target 26 label 0 ] edge [ source 45 target 27 label 0 ] edge [ source 45 target 28 label 0 ] edge [ source 45 target 29 label 0 ] edge [ source 45 target 30 label 0 ] edge [ source 45 target 31 label 0 ] edge [ source 45 target 32 label 0 ] edge [ source 45 target 33 label 0 ] edge [ source 45 target 34 label 0 ] edge [ source 45 target 35 label 0 ] edge [ source 45 target 36 label 0 ] edge [ source 45 target 37 label 0 ] edge [ source 45 target 38 label 0 ] edge [ source 45 target 39 label 0 ] edge [ source 45 target 40 label 0 ] edge [ source 45 target 41 label 0 ] edge [ source 45 target 42 label 0 ] edge [ source 45 target 43 label 0 ] edge [ source 45 target 44 label 0 ] edge [ source 45 target 45 label 0 ] edge [ source 46 target 1 label 0 ] edge [ source 46 target 2 label 0 ] edge [ source 46 target 3 label 0 ] edge [ source 46 target 4 label 0 ] edge [ source 46 target 5 label 0 ] edge [ source 46 target 6 label 0 ] edge [ source 46 target 7 label 0 ] edge [ source 46 target 8 label 0 ] edge [ source 46 target 9 label 0 ] edge [ source 46 target 10 label 0 ] edge [ source 46 target 11 label 0 ] edge [ source 46 target 12 label 0 ] edge [ source 46 target 13 label 0 ] edge [ source 46 target 14 label 0 ] edge [ source 46 target 15 label 0 ] edge [ source 46 target 16 label 0 ] edge [ source 46 target 17 label 0 ] edge [ source 46 target 18 label 0 ] edge [ source 46 target 19 label 0 ] edge [ source 46 target 20 label 0 ] edge [ source 46 target 21 label 0 ] edge [ source 46 target 22 label 0 ] edge [ source 46 target 23 label 0 ] edge [ source 46 target 24 label 0 ] edge [ source 46 target 25 label 0 ] edge [ source 46 target 26 label 0 ] edge [ source 46 target 27 label 0 ] edge [ source 46 target 28 label 0 ] edge [ source 46 target 29 label 0 ] edge [ source 46 target 30 label 0 ] edge [ source 46 target 31 label 0 ] edge [ source 46 target 32 label 0 ] edge [ source 46 target 33 label 0 ] edge [ source 46 target 34 label 0 ] edge [ source 46 target 35 label 0 ] edge [ source 46 target 36 label 0 ] edge [ source 46 target 37 label 0 ] edge [ source 46 target 38 label 0 ] edge [ source 46 target 39 label 0 ] edge [ source 46 target 40 label 0 ] edge [ source 46 target 41 label 0 ] edge [ source 46 target 42 label 0 ] edge [ source 46 target 43 label 0 ] edge [ source 46 target 44 label 0 ] edge [ source 46 target 45 label 0 ] edge [ source 46 target 46 label 0 ] edge [ source 47 target 1 label 0 ] edge [ source 47 target 2 label 0 ] edge [ source 47 target 3 label 0 ] edge [ source 47 target 4 label 0 ] edge [ source 47 target 5 label 0 ] edge [ source 47 target 6 label 0 ] edge [ source 47 target 7 label 0 ] edge [ source 47 target 8 label 0 ] edge [ source 47 target 9 label 0 ] edge [ source 47 target 10 label 0 ] edge [ source 47 target 11 label 0 ] edge [ source 47 target 12 label 0 ] edge [ source 47 target 13 label 0 ] edge [ source 47 target 14 label 0 ] edge [ source 47 target 15 label 0 ] edge [ source 47 target 16 label 0 ] edge [ source 47 target 17 label 0 ] edge [ source 47 target 18 label 0 ] edge [ source 47 target 19 label 0 ] edge [ source 47 target 20 label 0 ] edge [ source 47 target 21 label 0 ] edge [ source 47 target 22 label 0 ] edge [ source 47 target 23 label 0 ] edge [ source 47 target 24 label 0 ] edge [ source 47 target 25 label 0 ] edge [ source 47 target 26 label 0 ] edge [ source 47 target 27 label 0 ] edge [ source 47 target 28 label 0 ] edge [ source 47 target 29 label 0 ] edge [ source 47 target 30 label 0 ] edge [ source 47 target 31 label 0 ] edge [ source 47 target 32 label 0 ] edge [ source 47 target 33 label 0 ] edge [ source 47 target 34 label 0 ] edge [ source 47 target 35 label 0 ] edge [ source 47 target 36 label 0 ] edge [ source 47 target 37 label 0 ] edge [ source 47 target 38 label 0 ] edge [ source 47 target 39 label 0 ] edge [ source 47 target 40 label 0 ] edge [ source 47 target 41 label 0 ] edge [ source 47 target 42 label 0 ] edge [ source 47 target 43 label 0 ] edge [ source 47 target 44 label 0 ] edge [ source 47 target 45 label 0 ] edge [ source 47 target 46 label 0 ] edge [ source 47 target 47 label 0 ] edge [ source 48 target 1 label 0 ] edge [ source 48 target 2 label 0 ] edge [ source 48 target 3 label 0 ] edge [ source 48 target 4 label 0 ] edge [ source 48 target 5 label 0 ] edge [ source 48 target 6 label 0 ] edge [ source 48 target 7 label 0 ] edge [ source 48 target 8 label 0 ] edge [ source 48 target 9 label 0 ] edge [ source 48 target 10 label 0 ] edge [ source 48 target 11 label 0 ] edge [ source 48 target 12 label 0 ] edge [ source 48 target 13 label 0 ] edge [ source 48 target 14 label 0 ] edge [ source 48 target 15 label 0 ] edge [ source 48 target 16 label 0 ] edge [ source 48 target 17 label 0 ] edge [ source 48 target 18 label 0 ] edge [ source 48 target 19 label 0 ] edge [ source 48 target 20 label 0 ] edge [ source 48 target 21 label 0 ] edge [ source 48 target 22 label 0 ] edge [ source 48 target 23 label 0 ] edge [ source 48 target 24 label 0 ] edge [ source 48 target 25 label 0 ] edge [ source 48 target 26 label 0 ] edge [ source 48 target 27 label 0 ] edge [ source 48 target 28 label 0 ] edge [ source 48 target 29 label 0 ] edge [ source 48 target 30 label 0 ] edge [ source 48 target 31 label 0 ] edge [ source 48 target 32 label 0 ] edge [ source 48 target 33 label 0 ] edge [ source 48 target 34 label 0 ] edge [ source 48 target 35 label 0 ] edge [ source 48 target 36 label 0 ] edge [ source 48 target 37 label 0 ] edge [ source 48 target 38 label 0 ] edge [ source 48 target 39 label 0 ] edge [ source 48 target 40 label 0 ] edge [ source 48 target 41 label 0 ] edge [ source 48 target 42 label 0 ] edge [ source 48 target 43 label 0 ] edge [ source 48 target 44 label 0 ] edge [ source 48 target 45 label 0 ] edge [ source 48 target 46 label 0 ] edge [ source 48 target 47 label 0 ] edge [ source 48 target 48 label 0 ] edge [ source 49 target 1 label 0 ] edge [ source 49 target 2 label 0 ] edge [ source 49 target 3 label 0 ] edge [ source 49 target 4 label 0 ] edge [ source 49 target 5 label 0 ] edge [ source 49 target 6 label 0 ] edge [ source 49 target 7 label 0 ] edge [ source 49 target 8 label 0 ] edge [ source 49 target 9 label 0 ] edge [ source 49 target 10 label 0 ] edge [ source 49 target 11 label 0 ] edge [ source 49 target 12 label 0 ] edge [ source 49 target 13 label 0 ] edge [ source 49 target 14 label 0 ] edge [ source 49 target 15 label 0 ] edge [ source 49 target 16 label 0 ] edge [ source 49 target 17 label 0 ] edge [ source 49 target 18 label 0 ] edge [ source 49 target 19 label 0 ] edge [ source 49 target 20 label 0 ] edge [ source 49 target 21 label 0 ] edge [ source 49 target 22 label 0 ] edge [ source 49 target 23 label 0 ] edge [ source 49 target 24 label 0 ] edge [ source 49 target 25 label 0 ] edge [ source 49 target 26 label 0 ] edge [ source 49 target 27 label 0 ] edge [ source 49 target 28 label 0 ] edge [ source 49 target 29 label 0 ] edge [ source 49 target 30 label 0 ] edge [ source 49 target 31 label 0 ] edge [ source 49 target 32 label 0 ] edge [ source 49 target 33 label 0 ] edge [ source 49 target 34 label 0 ] edge [ source 49 target 35 label 0 ] edge [ source 49 target 36 label 0 ] edge [ source 49 target 37 label 0 ] edge [ source 49 target 38 label 0 ] edge [ source 49 target 39 label 0 ] edge [ source 49 target 40 label 0 ] edge [ source 49 target 41 label 0 ] edge [ source 49 target 42 label 0 ] edge [ source 49 target 43 label 0 ] edge [ source 49 target 44 label 0 ] edge [ source 49 target 45 label 0 ] edge [ source 49 target 46 label 0 ] edge [ source 49 target 47 label 0 ] edge [ source 49 target 48 label 0 ] edge [ source 49 target 49 label 0 ] edge [ source 50 target 1 label 0 ] edge [ source 50 target 2 label 0 ] edge [ source 50 target 3 label 0 ] edge [ source 50 target 4 label 0 ] edge [ source 50 target 5 label 0 ] edge [ source 50 target 6 label 0 ] edge [ source 50 target 7 label 0 ] edge [ source 50 target 8 label 0 ] edge [ source 50 target 9 label 0 ] edge [ source 50 target 10 label 0 ] edge [ source 50 target 11 label 0 ] edge [ source 50 target 12 label 0 ] edge [ source 50 target 13 label 0 ] edge [ source 50 target 14 label 0 ] edge [ source 50 target 15 label 0 ] edge [ source 50 target 16 label 0 ] edge [ source 50 target 17 label 0 ] edge [ source 50 target 18 label 0 ] edge [ source 50 target 19 label 0 ] edge [ source 50 target 20 label 0 ] edge [ source 50 target 21 label 0 ] edge [ source 50 target 22 label 0 ] edge [ source 50 target 23 label 0 ] edge [ source 50 target 24 label 0 ] edge [ source 50 target 25 label 0 ] edge [ source 50 target 26 label 0 ] edge [ source 50 target 27 label 0 ] edge [ source 50 target 28 label 0 ] edge [ source 50 target 29 label 0 ] edge [ source 50 target 30 label 0 ] edge [ source 50 target 31 label 0 ] edge [ source 50 target 32 label 0 ] edge [ source 50 target 33 label 0 ] edge [ source 50 target 34 label 0 ] edge [ source 50 target 35 label 0 ] edge [ source 50 target 36 label 0 ] edge [ source 50 target 37 label 0 ] edge [ source 50 target 38 label 0 ] edge [ source 50 target 39 label 0 ] edge [ source 50 target 40 label 0 ] edge [ source 50 target 41 label 0 ] edge [ source 50 target 42 label 0 ] edge [ source 50 target 43 label 0 ] edge [ source 50 target 44 label 0 ] edge [ source 50 target 45 label 0 ] edge [ source 50 target 46 label 0 ] edge [ source 50 target 47 label 0 ] edge [ source 50 target 48 label 0 ] edge [ source 50 target 49 label 0 ] edge [ source 50 target 50 label 0 ] ] ocamlgraph-1.8.3/editor/tests/full10.gml0000644000175000017500000000614112133565071017037 0ustar mehdimehdigraph [ node [ id 1 label 1 ] node [ id 2 label 2 ] node [ id 3 label 3 ] node [ id 4 label 4 ] node [ id 5 label 5 ] node [ id 6 label 6 ] node [ id 7 label 7 ] node [ id 8 label 8 ] node [ id 9 label 9 ] node [ id 10 label 10 ] edge [ source 1 target 1 label 0 ] edge [ source 2 target 1 label 0 ] edge [ source 2 target 2 label 0 ] edge [ source 3 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 3 target 3 label 0 ] edge [ source 4 target 1 label 0 ] edge [ source 4 target 2 label 0 ] edge [ source 4 target 3 label 0 ] edge [ source 4 target 4 label 0 ] edge [ source 5 target 1 label 0 ] edge [ source 5 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 5 target 4 label 0 ] edge [ source 5 target 5 label 0 ] edge [ source 6 target 1 label 0 ] edge [ source 6 target 2 label 0 ] edge [ source 6 target 3 label 0 ] edge [ source 6 target 4 label 0 ] edge [ source 6 target 5 label 0 ] edge [ source 6 target 6 label 0 ] edge [ source 7 target 1 label 0 ] edge [ source 7 target 2 label 0 ] edge [ source 7 target 3 label 0 ] edge [ source 7 target 4 label 0 ] edge [ source 7 target 5 label 0 ] edge [ source 7 target 6 label 0 ] edge [ source 7 target 7 label 0 ] edge [ source 8 target 1 label 0 ] edge [ source 8 target 2 label 0 ] edge [ source 8 target 3 label 0 ] edge [ source 8 target 4 label 0 ] edge [ source 8 target 5 label 0 ] edge [ source 8 target 6 label 0 ] edge [ source 8 target 7 label 0 ] edge [ source 8 target 8 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 3 label 0 ] edge [ source 9 target 4 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 9 target 6 label 0 ] edge [ source 9 target 7 label 0 ] edge [ source 9 target 8 label 0 ] edge [ source 9 target 9 label 0 ] edge [ source 10 target 1 label 0 ] edge [ source 10 target 2 label 0 ] edge [ source 10 target 3 label 0 ] edge [ source 10 target 4 label 0 ] edge [ source 10 target 5 label 0 ] edge [ source 10 target 6 label 0 ] edge [ source 10 target 7 label 0 ] edge [ source 10 target 8 label 0 ] edge [ source 10 target 9 label 0 ] edge [ source 10 target 10 label 0 ] ] ocamlgraph-1.8.3/editor/tests/dep_why.dot0000644000175000017500000000502312133565071017400 0ustar mehdimehdidigraph G { size="7.5,10" ; rankdir = TB ; "Why" -> "Main" ; "Theoryreducer" -> "Logic_decl" ; "Theoryreducer" -> "Pp" ; "Theoryreducer" -> "Unionfind" ; "Theory_filtering" -> "Logic_decl" ; "Theory_filtering" -> "Pp" ; "Theory_filtering" -> "Unionfind" ; "Options" -> "Lib" ; "Options" -> "Version" ; "Main" -> "Coq" ; "Main" -> "Dispatcher" ; "Main" -> "Fastwp" ; "Main" -> "Gappa" ; "Main" -> "Hol4" ; "Main" -> "Holl" ; "Main" -> "Hypotheses_filtering" ; "Main" -> "Isabelle" ; "Main" -> "Mizar" ; "Main" -> "Monad" ; "Main" -> "Ocaml" ; "Main" -> "PredDefExpansor" ; "Main" -> "Pvs" ; "Main" -> "Wp" ; "Hypotheses_filtering" -> "Util" ; "Encoding_mono" -> "Util" ; "Zenon" -> "Encoding" ; "Zenon" -> "Ltyping" ; "Wp" -> "Typing" ; "Vcg" -> "Log" ; "Vcg" -> "Util" ; "Util" -> "Logic_decl" ; "Util" -> "Rename" ; "Typing" -> "Ltyping" ; "Types" -> "Effect" ; "Smtlib" -> "Encoding" ; "Simplify" -> "Encoding" ; "Report" -> "Lexer" ; "Report" -> "Misc" ; "Rename" -> "Pp" ; "Rename" -> "Report" ; "Regen" -> "Vcg" ; "Red" -> "Util" ; "Pvs" -> "Vcg" ; "Purify" -> "Env" ; "Ptree" -> "Loc" ; "Ptree" -> "Types" ; "Pretty" -> "Logic_decl" ; "Pretty" -> "Pp" ; "PredDefExpansor" -> "Util" ; "Parser" -> "Error" ; "Parser" -> "Float_lexer" ; "Parser" -> "Ptree" ; "Ocaml" -> "Util" ; "Monomorph" -> "Vcg" ; "Monad" -> "Typing" ; "Mlize" -> "Monad" ; "Mizar" -> "Regen" ; "Misc" -> "Ast" ; "Misc" -> "Option_misc" ; "Misc" -> "Options" ; "Ltyping" -> "Util" ; "Logic" -> "Ident" ; "Logic_decl" -> "Env" ; "Lexer" -> "Parser" ; "Isabelle" -> "Regen" ; "Holl" -> "Vcg" ; "Hol4" -> "Vcg" ; "Harvey" -> "Encoding" ; "Gappa" -> "Logic_decl" ; "Gappa" -> "Pp" ; "Fpi" -> "Misc" ; "Fpi" -> "Pp" ; "Fastwp" -> "Util" ; "Error" -> "Effect" ; "Env" -> "Report" ; "Encoding_strat" -> "Util" ; "Encoding_rec" -> "Logic_decl" ; "Encoding_pred" -> "Logic_decl" ; "Encoding" -> "Encoding_mono" ; "Encoding" -> "Encoding_pred" ; "Encoding" -> "Encoding_rec" ; "Encoding" -> "Encoding_strat" ; "Encoding" -> "Monomorph" ; "Effect" -> "Logic" ; "Dispatcher" -> "Cvcl" ; "Dispatcher" -> "Harvey" ; "Dispatcher" -> "Pretty" ; "Dispatcher" -> "Simplify" ; "Dispatcher" -> "Smtlib" ; "Dispatcher" -> "Theory_filtering" ; "Dispatcher" -> "Zenon" ; "Cvcl" -> "Encoding" ; "Cvcl" -> "Ltyping" ; "Coq" -> "Regen" ; "Cc" -> "Loc" ; "Cc" -> "Logic" ; "Ast" -> "Cc" ; "Ast" -> "Ptree" ; "Annot" -> "Util" ; } ocamlgraph-1.8.3/editor/tests/rand_10_10.gml0000644000175000017500000000154112133565071017457 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] edge [ source 3 target 1 label 0 ] edge [ source 5 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 6 target 3 label 0 ] edge [ source 7 target 3 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 9 target 6 label 0 ] edge [ source 10 target 6 label 0 ] edge [ source 10 target 7 label 0 ] edge [ source 10 target 9 label 0 ] ] ocamlgraph-1.8.3/editor/tests/parcours.dot0000644000175000017500000000041712133565071017601 0ustar mehdimehdidigraph g { r -> U; r -> D; r -> T; U -> Ua; U -> Ub; Ua -> Uaa; Ub -> Ubb; Ua -> Ubb; Ub -> Uaa; D -> Da; D -> Db; Da -> Daa; Db -> Dbb; Da -> Dbb; Db -> Daa; T -> Ta; T -> Tb; Ta -> Taa; Tb -> Tbb; Ta -> Tbb; Tb -> Taa; Ua -> Da; Db -> Ta; Tb -> Ub; }ocamlgraph-1.8.3/editor/tests/full20.gml0000644000175000017500000002660612133565071017050 0ustar mehdimehdigraph [ node [ id 1 label 1 ] node [ id 2 label 2 ] node [ id 3 label 3 ] node [ id 4 label 4 ] node [ id 5 label 5 ] node [ id 6 label 6 ] node [ id 7 label 7 ] node [ id 8 label 8 ] node [ id 9 label 9 ] node [ id 10 label 10 ] node [ id 11 label 11 ] node [ id 12 label 12 ] node [ id 13 label 13 ] node [ id 14 label 14 ] node [ id 15 label 15 ] node [ id 16 label 16 ] node [ id 17 label 17 ] node [ id 18 label 18 ] node [ id 19 label 19 ] node [ id 20 label 20 ] edge [ source 1 target 1 label 0 ] edge [ source 2 target 1 label 0 ] edge [ source 2 target 2 label 0 ] edge [ source 3 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 3 target 3 label 0 ] edge [ source 4 target 1 label 0 ] edge [ source 4 target 2 label 0 ] edge [ source 4 target 3 label 0 ] edge [ source 4 target 4 label 0 ] edge [ source 5 target 1 label 0 ] edge [ source 5 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 5 target 4 label 0 ] edge [ source 5 target 5 label 0 ] edge [ source 6 target 1 label 0 ] edge [ source 6 target 2 label 0 ] edge [ source 6 target 3 label 0 ] edge [ source 6 target 4 label 0 ] edge [ source 6 target 5 label 0 ] edge [ source 6 target 6 label 0 ] edge [ source 7 target 1 label 0 ] edge [ source 7 target 2 label 0 ] edge [ source 7 target 3 label 0 ] edge [ source 7 target 4 label 0 ] edge [ source 7 target 5 label 0 ] edge [ source 7 target 6 label 0 ] edge [ source 7 target 7 label 0 ] edge [ source 8 target 1 label 0 ] edge [ source 8 target 2 label 0 ] edge [ source 8 target 3 label 0 ] edge [ source 8 target 4 label 0 ] edge [ source 8 target 5 label 0 ] edge [ source 8 target 6 label 0 ] edge [ source 8 target 7 label 0 ] edge [ source 8 target 8 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 3 label 0 ] edge [ source 9 target 4 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 9 target 6 label 0 ] edge [ source 9 target 7 label 0 ] edge [ source 9 target 8 label 0 ] edge [ source 9 target 9 label 0 ] edge [ source 10 target 1 label 0 ] edge [ source 10 target 2 label 0 ] edge [ source 10 target 3 label 0 ] edge [ source 10 target 4 label 0 ] edge [ source 10 target 5 label 0 ] edge [ source 10 target 6 label 0 ] edge [ source 10 target 7 label 0 ] edge [ source 10 target 8 label 0 ] edge [ source 10 target 9 label 0 ] edge [ source 10 target 10 label 0 ] edge [ source 11 target 1 label 0 ] edge [ source 11 target 2 label 0 ] edge [ source 11 target 3 label 0 ] edge [ source 11 target 4 label 0 ] edge [ source 11 target 5 label 0 ] edge [ source 11 target 6 label 0 ] edge [ source 11 target 7 label 0 ] edge [ source 11 target 8 label 0 ] edge [ source 11 target 9 label 0 ] edge [ source 11 target 10 label 0 ] edge [ source 11 target 11 label 0 ] edge [ source 12 target 1 label 0 ] edge [ source 12 target 2 label 0 ] edge [ source 12 target 3 label 0 ] edge [ source 12 target 4 label 0 ] edge [ source 12 target 5 label 0 ] edge [ source 12 target 6 label 0 ] edge [ source 12 target 7 label 0 ] edge [ source 12 target 8 label 0 ] edge [ source 12 target 9 label 0 ] edge [ source 12 target 10 label 0 ] edge [ source 12 target 11 label 0 ] edge [ source 12 target 12 label 0 ] edge [ source 13 target 1 label 0 ] edge [ source 13 target 2 label 0 ] edge [ source 13 target 3 label 0 ] edge [ source 13 target 4 label 0 ] edge [ source 13 target 5 label 0 ] edge [ source 13 target 6 label 0 ] edge [ source 13 target 7 label 0 ] edge [ source 13 target 8 label 0 ] edge [ source 13 target 9 label 0 ] edge [ source 13 target 10 label 0 ] edge [ source 13 target 11 label 0 ] edge [ source 13 target 12 label 0 ] edge [ source 13 target 13 label 0 ] edge [ source 14 target 1 label 0 ] edge [ source 14 target 2 label 0 ] edge [ source 14 target 3 label 0 ] edge [ source 14 target 4 label 0 ] edge [ source 14 target 5 label 0 ] edge [ source 14 target 6 label 0 ] edge [ source 14 target 7 label 0 ] edge [ source 14 target 8 label 0 ] edge [ source 14 target 9 label 0 ] edge [ source 14 target 10 label 0 ] edge [ source 14 target 11 label 0 ] edge [ source 14 target 12 label 0 ] edge [ source 14 target 13 label 0 ] edge [ source 14 target 14 label 0 ] edge [ source 15 target 1 label 0 ] edge [ source 15 target 2 label 0 ] edge [ source 15 target 3 label 0 ] edge [ source 15 target 4 label 0 ] edge [ source 15 target 5 label 0 ] edge [ source 15 target 6 label 0 ] edge [ source 15 target 7 label 0 ] edge [ source 15 target 8 label 0 ] edge [ source 15 target 9 label 0 ] edge [ source 15 target 10 label 0 ] edge [ source 15 target 11 label 0 ] edge [ source 15 target 12 label 0 ] edge [ source 15 target 13 label 0 ] edge [ source 15 target 14 label 0 ] edge [ source 15 target 15 label 0 ] edge [ source 16 target 1 label 0 ] edge [ source 16 target 2 label 0 ] edge [ source 16 target 3 label 0 ] edge [ source 16 target 4 label 0 ] edge [ source 16 target 5 label 0 ] edge [ source 16 target 6 label 0 ] edge [ source 16 target 7 label 0 ] edge [ source 16 target 8 label 0 ] edge [ source 16 target 9 label 0 ] edge [ source 16 target 10 label 0 ] edge [ source 16 target 11 label 0 ] edge [ source 16 target 12 label 0 ] edge [ source 16 target 13 label 0 ] edge [ source 16 target 14 label 0 ] edge [ source 16 target 15 label 0 ] edge [ source 16 target 16 label 0 ] edge [ source 17 target 1 label 0 ] edge [ source 17 target 2 label 0 ] edge [ source 17 target 3 label 0 ] edge [ source 17 target 4 label 0 ] edge [ source 17 target 5 label 0 ] edge [ source 17 target 6 label 0 ] edge [ source 17 target 7 label 0 ] edge [ source 17 target 8 label 0 ] edge [ source 17 target 9 label 0 ] edge [ source 17 target 10 label 0 ] edge [ source 17 target 11 label 0 ] edge [ source 17 target 12 label 0 ] edge [ source 17 target 13 label 0 ] edge [ source 17 target 14 label 0 ] edge [ source 17 target 15 label 0 ] edge [ source 17 target 16 label 0 ] edge [ source 17 target 17 label 0 ] edge [ source 18 target 1 label 0 ] edge [ source 18 target 2 label 0 ] edge [ source 18 target 3 label 0 ] edge [ source 18 target 4 label 0 ] edge [ source 18 target 5 label 0 ] edge [ source 18 target 6 label 0 ] edge [ source 18 target 7 label 0 ] edge [ source 18 target 8 label 0 ] edge [ source 18 target 9 label 0 ] edge [ source 18 target 10 label 0 ] edge [ source 18 target 11 label 0 ] edge [ source 18 target 12 label 0 ] edge [ source 18 target 13 label 0 ] edge [ source 18 target 14 label 0 ] edge [ source 18 target 15 label 0 ] edge [ source 18 target 16 label 0 ] edge [ source 18 target 17 label 0 ] edge [ source 18 target 18 label 0 ] edge [ source 19 target 1 label 0 ] edge [ source 19 target 2 label 0 ] edge [ source 19 target 3 label 0 ] edge [ source 19 target 4 label 0 ] edge [ source 19 target 5 label 0 ] edge [ source 19 target 6 label 0 ] edge [ source 19 target 7 label 0 ] edge [ source 19 target 8 label 0 ] edge [ source 19 target 9 label 0 ] edge [ source 19 target 10 label 0 ] edge [ source 19 target 11 label 0 ] edge [ source 19 target 12 label 0 ] edge [ source 19 target 13 label 0 ] edge [ source 19 target 14 label 0 ] edge [ source 19 target 15 label 0 ] edge [ source 19 target 16 label 0 ] edge [ source 19 target 17 label 0 ] edge [ source 19 target 18 label 0 ] edge [ source 19 target 19 label 0 ] edge [ source 20 target 1 label 0 ] edge [ source 20 target 2 label 0 ] edge [ source 20 target 3 label 0 ] edge [ source 20 target 4 label 0 ] edge [ source 20 target 5 label 0 ] edge [ source 20 target 6 label 0 ] edge [ source 20 target 7 label 0 ] edge [ source 20 target 8 label 0 ] edge [ source 20 target 9 label 0 ] edge [ source 20 target 10 label 0 ] edge [ source 20 target 11 label 0 ] edge [ source 20 target 12 label 0 ] edge [ source 20 target 13 label 0 ] edge [ source 20 target 14 label 0 ] edge [ source 20 target 15 label 0 ] edge [ source 20 target 16 label 0 ] edge [ source 20 target 17 label 0 ] edge [ source 20 target 18 label 0 ] edge [ source 20 target 19 label 0 ] edge [ source 20 target 20 label 0 ] ] ocamlgraph-1.8.3/editor/tests/test2,1_3tot.gml0000644000175000017500000000120612133565071020100 0ustar mehdimehdigraph [ comment "This is a sample graph" directed 1 id 42 label "Hello, I am a graph" node [ id 1 label "Node 1" ] node [ id 2 label "node 2" ] node [ id 3 label "node 3" ] node [ id 4 label "node 4" ] node [ id 5 label "node 5" ] node [ id 6 label "node 6" ] node [ id 7 label "node 7" ] edge [ source 1 target 2 ] edge [ source 1 target 3 ] edge [ source 1 target 4 ] edge [ source 1 target 5 ] edge [ source 1 target 6 ] edge [ source 1 target 7 ] edge [ source 2 target 4 ] edge [ source 5 target 6 ] edge [ source 6 target 7 ] edge [ source 5 target 7 ] ] ocamlgraph-1.8.3/editor/tests/test2_2.gml0000644000175000017500000000071012133565071017212 0ustar mehdimehdigraph [ comment "This is a sample graph" directed 1 id 42 label "Hello, I am a graph" node [ id 1 label "Node 1" ] node [ id 2 label "node 2" ] node [ id 3 label "node 3" ] node [ id 4 label "node 4" ] node [ id 5 label "node 5" ] edge [ source 1 target 2 ] edge [ source 1 target 3 ] edge [ source 1 target 4 ] edge [ source 1 target 5 ] edge [ source 2 target 3 ] edge [ source 4 target 5 ] ] ocamlgraph-1.8.3/editor/tests/rand_50_300.gml0000644000175000017500000004224312133565071017551 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] node [ id 11 label 10 ] node [ id 12 label 11 ] node [ id 13 label 12 ] node [ id 14 label 13 ] node [ id 15 label 14 ] node [ id 16 label 15 ] node [ id 17 label 16 ] node [ id 18 label 17 ] node [ id 19 label 18 ] node [ id 20 label 19 ] node [ id 21 label 20 ] node [ id 22 label 21 ] node [ id 23 label 22 ] node [ id 24 label 23 ] node [ id 25 label 24 ] node [ id 26 label 25 ] node [ id 27 label 26 ] node [ id 28 label 27 ] node [ id 29 label 28 ] node [ id 30 label 29 ] node [ id 31 label 30 ] node [ id 32 label 31 ] node [ id 33 label 32 ] node [ id 34 label 33 ] node [ id 35 label 34 ] node [ id 36 label 35 ] node [ id 37 label 36 ] node [ id 38 label 37 ] node [ id 39 label 38 ] node [ id 40 label 39 ] node [ id 41 label 40 ] node [ id 42 label 41 ] node [ id 43 label 42 ] node [ id 44 label 43 ] node [ id 45 label 44 ] node [ id 46 label 45 ] node [ id 47 label 46 ] node [ id 48 label 47 ] node [ id 49 label 48 ] node [ id 50 label 49 ] edge [ source 8 target 1 label 0 ] edge [ source 8 target 3 label 0 ] edge [ source 8 target 5 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 4 label 0 ] edge [ source 10 target 2 label 0 ] edge [ source 12 target 2 label 0 ] edge [ source 12 target 7 label 0 ] edge [ source 13 target 1 label 0 ] edge [ source 13 target 8 label 0 ] edge [ source 13 target 9 label 0 ] edge [ source 14 target 1 label 0 ] edge [ source 14 target 4 label 0 ] edge [ source 14 target 6 label 0 ] edge [ source 14 target 9 label 0 ] edge [ source 15 target 2 label 0 ] edge [ source 15 target 3 label 0 ] edge [ source 15 target 5 label 0 ] edge [ source 15 target 6 label 0 ] edge [ source 15 target 8 label 0 ] edge [ source 15 target 13 label 0 ] edge [ source 16 target 7 label 0 ] edge [ source 16 target 12 label 0 ] edge [ source 16 target 15 label 0 ] edge [ source 17 target 1 label 0 ] edge [ source 17 target 4 label 0 ] edge [ source 17 target 8 label 0 ] edge [ source 17 target 9 label 0 ] edge [ source 17 target 11 label 0 ] edge [ source 17 target 13 label 0 ] edge [ source 17 target 16 label 0 ] edge [ source 18 target 1 label 0 ] edge [ source 18 target 2 label 0 ] edge [ source 18 target 3 label 0 ] edge [ source 18 target 9 label 0 ] edge [ source 18 target 14 label 0 ] edge [ source 18 target 17 label 0 ] edge [ source 19 target 6 label 0 ] edge [ source 19 target 9 label 0 ] edge [ source 19 target 11 label 0 ] edge [ source 19 target 12 label 0 ] edge [ source 20 target 4 label 0 ] edge [ source 20 target 10 label 0 ] edge [ source 20 target 11 label 0 ] edge [ source 20 target 12 label 0 ] edge [ source 21 target 4 label 0 ] edge [ source 21 target 6 label 0 ] edge [ source 21 target 9 label 0 ] edge [ source 21 target 11 label 0 ] edge [ source 21 target 12 label 0 ] edge [ source 22 target 7 label 0 ] edge [ source 22 target 8 label 0 ] edge [ source 22 target 9 label 0 ] edge [ source 22 target 13 label 0 ] edge [ source 23 target 1 label 0 ] edge [ source 23 target 8 label 0 ] edge [ source 23 target 9 label 0 ] edge [ source 23 target 13 label 0 ] edge [ source 23 target 16 label 0 ] edge [ source 23 target 18 label 0 ] edge [ source 23 target 19 label 0 ] edge [ source 23 target 20 label 0 ] edge [ source 23 target 21 label 0 ] edge [ source 24 target 1 label 0 ] edge [ source 24 target 2 label 0 ] edge [ source 24 target 4 label 0 ] edge [ source 24 target 6 label 0 ] edge [ source 24 target 10 label 0 ] edge [ source 24 target 12 label 0 ] edge [ source 24 target 13 label 0 ] edge [ source 24 target 14 label 0 ] edge [ source 24 target 16 label 0 ] edge [ source 24 target 18 label 0 ] edge [ source 25 target 2 label 0 ] edge [ source 25 target 3 label 0 ] edge [ source 25 target 6 label 0 ] edge [ source 25 target 8 label 0 ] edge [ source 25 target 14 label 0 ] edge [ source 25 target 24 label 0 ] edge [ source 26 target 5 label 0 ] edge [ source 26 target 9 label 0 ] edge [ source 26 target 10 label 0 ] edge [ source 26 target 14 label 0 ] edge [ source 26 target 15 label 0 ] edge [ source 26 target 23 label 0 ] edge [ source 27 target 3 label 0 ] edge [ source 27 target 8 label 0 ] edge [ source 27 target 12 label 0 ] edge [ source 27 target 18 label 0 ] edge [ source 27 target 23 label 0 ] edge [ source 28 target 2 label 0 ] edge [ source 28 target 7 label 0 ] edge [ source 28 target 10 label 0 ] edge [ source 28 target 15 label 0 ] edge [ source 28 target 18 label 0 ] edge [ source 28 target 19 label 0 ] edge [ source 28 target 20 label 0 ] edge [ source 28 target 22 label 0 ] edge [ source 28 target 27 label 0 ] edge [ source 29 target 1 label 0 ] edge [ source 29 target 7 label 0 ] edge [ source 29 target 8 label 0 ] edge [ source 29 target 9 label 0 ] edge [ source 29 target 13 label 0 ] edge [ source 29 target 14 label 0 ] edge [ source 29 target 18 label 0 ] edge [ source 29 target 19 label 0 ] edge [ source 29 target 20 label 0 ] edge [ source 30 target 1 label 0 ] edge [ source 30 target 3 label 0 ] edge [ source 30 target 4 label 0 ] edge [ source 30 target 17 label 0 ] edge [ source 30 target 20 label 0 ] edge [ source 30 target 21 label 0 ] edge [ source 30 target 26 label 0 ] edge [ source 31 target 2 label 0 ] edge [ source 31 target 4 label 0 ] edge [ source 31 target 7 label 0 ] edge [ source 31 target 8 label 0 ] edge [ source 31 target 14 label 0 ] edge [ source 31 target 18 label 0 ] edge [ source 31 target 19 label 0 ] edge [ source 31 target 26 label 0 ] edge [ source 31 target 28 label 0 ] edge [ source 32 target 13 label 0 ] edge [ source 32 target 18 label 0 ] edge [ source 32 target 22 label 0 ] edge [ source 32 target 29 label 0 ] edge [ source 33 target 7 label 0 ] edge [ source 33 target 16 label 0 ] edge [ source 33 target 18 label 0 ] edge [ source 33 target 22 label 0 ] edge [ source 33 target 24 label 0 ] edge [ source 33 target 25 label 0 ] edge [ source 33 target 27 label 0 ] edge [ source 34 target 1 label 0 ] edge [ source 34 target 3 label 0 ] edge [ source 34 target 4 label 0 ] edge [ source 34 target 5 label 0 ] edge [ source 34 target 6 label 0 ] edge [ source 34 target 8 label 0 ] edge [ source 34 target 15 label 0 ] edge [ source 34 target 16 label 0 ] edge [ source 34 target 22 label 0 ] edge [ source 34 target 23 label 0 ] edge [ source 34 target 26 label 0 ] edge [ source 35 target 2 label 0 ] edge [ source 35 target 7 label 0 ] edge [ source 35 target 8 label 0 ] edge [ source 35 target 11 label 0 ] edge [ source 35 target 14 label 0 ] edge [ source 35 target 22 label 0 ] edge [ source 35 target 32 label 0 ] edge [ source 36 target 13 label 0 ] edge [ source 36 target 16 label 0 ] edge [ source 36 target 19 label 0 ] edge [ source 36 target 23 label 0 ] edge [ source 37 target 2 label 0 ] edge [ source 37 target 3 label 0 ] edge [ source 37 target 6 label 0 ] edge [ source 37 target 7 label 0 ] edge [ source 37 target 9 label 0 ] edge [ source 37 target 16 label 0 ] edge [ source 37 target 21 label 0 ] edge [ source 37 target 23 label 0 ] edge [ source 37 target 24 label 0 ] edge [ source 37 target 26 label 0 ] edge [ source 37 target 27 label 0 ] edge [ source 37 target 29 label 0 ] edge [ source 37 target 32 label 0 ] edge [ source 37 target 33 label 0 ] edge [ source 37 target 34 label 0 ] edge [ source 38 target 2 label 0 ] edge [ source 38 target 3 label 0 ] edge [ source 38 target 4 label 0 ] edge [ source 38 target 7 label 0 ] edge [ source 38 target 9 label 0 ] edge [ source 38 target 17 label 0 ] edge [ source 38 target 18 label 0 ] edge [ source 38 target 33 label 0 ] edge [ source 38 target 34 label 0 ] edge [ source 38 target 37 label 0 ] edge [ source 39 target 4 label 0 ] edge [ source 39 target 8 label 0 ] edge [ source 39 target 15 label 0 ] edge [ source 39 target 18 label 0 ] edge [ source 39 target 19 label 0 ] edge [ source 39 target 28 label 0 ] edge [ source 39 target 29 label 0 ] edge [ source 39 target 31 label 0 ] edge [ source 40 target 3 label 0 ] edge [ source 40 target 4 label 0 ] edge [ source 40 target 7 label 0 ] edge [ source 40 target 8 label 0 ] edge [ source 40 target 14 label 0 ] edge [ source 40 target 18 label 0 ] edge [ source 40 target 19 label 0 ] edge [ source 40 target 20 label 0 ] edge [ source 40 target 23 label 0 ] edge [ source 40 target 25 label 0 ] edge [ source 40 target 35 label 0 ] edge [ source 41 target 1 label 0 ] edge [ source 41 target 2 label 0 ] edge [ source 41 target 3 label 0 ] edge [ source 41 target 5 label 0 ] edge [ source 41 target 27 label 0 ] edge [ source 41 target 29 label 0 ] edge [ source 41 target 39 label 0 ] edge [ source 42 target 1 label 0 ] edge [ source 42 target 5 label 0 ] edge [ source 42 target 20 label 0 ] edge [ source 42 target 21 label 0 ] edge [ source 42 target 35 label 0 ] edge [ source 42 target 37 label 0 ] edge [ source 43 target 3 label 0 ] edge [ source 43 target 4 label 0 ] edge [ source 43 target 13 label 0 ] edge [ source 43 target 14 label 0 ] edge [ source 43 target 20 label 0 ] edge [ source 43 target 25 label 0 ] edge [ source 43 target 32 label 0 ] edge [ source 43 target 37 label 0 ] edge [ source 43 target 41 label 0 ] edge [ source 44 target 1 label 0 ] edge [ source 44 target 7 label 0 ] edge [ source 44 target 8 label 0 ] edge [ source 44 target 14 label 0 ] edge [ source 44 target 19 label 0 ] edge [ source 44 target 20 label 0 ] edge [ source 44 target 22 label 0 ] edge [ source 44 target 30 label 0 ] edge [ source 44 target 39 label 0 ] edge [ source 44 target 40 label 0 ] edge [ source 45 target 4 label 0 ] edge [ source 45 target 17 label 0 ] edge [ source 45 target 21 label 0 ] edge [ source 45 target 30 label 0 ] edge [ source 45 target 35 label 0 ] edge [ source 45 target 38 label 0 ] edge [ source 46 target 2 label 0 ] edge [ source 46 target 6 label 0 ] edge [ source 46 target 7 label 0 ] edge [ source 46 target 20 label 0 ] edge [ source 46 target 32 label 0 ] edge [ source 46 target 34 label 0 ] edge [ source 46 target 36 label 0 ] edge [ source 46 target 37 label 0 ] edge [ source 46 target 38 label 0 ] edge [ source 46 target 39 label 0 ] edge [ source 47 target 5 label 0 ] edge [ source 47 target 6 label 0 ] edge [ source 47 target 8 label 0 ] edge [ source 47 target 10 label 0 ] edge [ source 47 target 13 label 0 ] edge [ source 47 target 15 label 0 ] edge [ source 47 target 16 label 0 ] edge [ source 47 target 17 label 0 ] edge [ source 47 target 21 label 0 ] edge [ source 47 target 23 label 0 ] edge [ source 47 target 25 label 0 ] edge [ source 47 target 26 label 0 ] edge [ source 47 target 28 label 0 ] edge [ source 47 target 31 label 0 ] edge [ source 47 target 33 label 0 ] edge [ source 47 target 38 label 0 ] edge [ source 47 target 41 label 0 ] edge [ source 47 target 43 label 0 ] edge [ source 47 target 46 label 0 ] edge [ source 48 target 3 label 0 ] edge [ source 48 target 9 label 0 ] edge [ source 48 target 11 label 0 ] edge [ source 48 target 12 label 0 ] edge [ source 48 target 15 label 0 ] edge [ source 48 target 20 label 0 ] edge [ source 48 target 22 label 0 ] edge [ source 48 target 30 label 0 ] edge [ source 48 target 33 label 0 ] edge [ source 48 target 39 label 0 ] edge [ source 48 target 43 label 0 ] edge [ source 48 target 46 label 0 ] edge [ source 48 target 47 label 0 ] edge [ source 49 target 2 label 0 ] edge [ source 49 target 13 label 0 ] edge [ source 49 target 18 label 0 ] edge [ source 49 target 28 label 0 ] edge [ source 49 target 39 label 0 ] edge [ source 49 target 43 label 0 ] edge [ source 49 target 44 label 0 ] edge [ source 49 target 47 label 0 ] edge [ source 50 target 4 label 0 ] edge [ source 50 target 13 label 0 ] edge [ source 50 target 23 label 0 ] edge [ source 50 target 26 label 0 ] edge [ source 50 target 27 label 0 ] edge [ source 50 target 28 label 0 ] edge [ source 50 target 33 label 0 ] edge [ source 50 target 39 label 0 ] edge [ source 50 target 40 label 0 ] edge [ source 50 target 45 label 0 ] ] ocamlgraph-1.8.3/editor/tests/unix.dot0000644000175000017500000000261612133565071016731 0ustar mehdimehdi/* courtesy Ian Darwin and Geoff Collyer, Softquad Inc. */ digraph unix { "5th Edition" -> "6th Edition"; "5th Edition" -> "PWB 1.0"; "6th Edition" -> "LSX"; "6th Edition" -> "1 BSD"; "6th Edition" -> "Mini Unix"; "6th Edition" -> "Wollongong"; "6th Edition" -> "Interdata"; "Interdata" -> "Unix/TS 3.0"; "Interdata" -> "PWB 2.0"; "Interdata" -> "7th Edition"; "7th Edition" -> "8th Edition"; "7th Edition" -> "32V"; "7th Edition" -> "V7M"; "7th Edition" -> "Ultrix-11"; "7th Edition" -> "Xenix"; "7th Edition" -> "UniPlus+"; "V7M" -> "Ultrix-11"; "8th Edition" -> "9th Edition"; "1 BSD" -> "2 BSD"; "2 BSD" -> "2.8 BSD"; "2.8 BSD" -> "Ultrix-11"; "2.8 BSD" -> "2.9 BSD"; "32V" -> "3 BSD"; "3 BSD" -> "4 BSD"; "4 BSD" -> "4.1 BSD"; "4.1 BSD" -> "4.2 BSD"; "4.1 BSD" -> "2.8 BSD"; "4.1 BSD" -> "8th Edition"; "4.2 BSD" -> "4.3 BSD"; "4.2 BSD" -> "Ultrix-32"; "PWB 1.0" -> "PWB 1.2"; "PWB 1.0" -> "USG 1.0"; "PWB 1.2" -> "PWB 2.0"; "USG 1.0" -> "CB Unix 1"; "USG 1.0" -> "USG 2.0"; "CB Unix 1" -> "CB Unix 2"; "CB Unix 2" -> "CB Unix 3"; "CB Unix 3" -> "Unix/TS++"; "CB Unix 3" -> "PDP-11 Sys V"; "USG 2.0" -> "USG 3.0"; "USG 3.0" -> "Unix/TS 3.0"; "PWB 2.0" -> "Unix/TS 3.0"; "Unix/TS 1.0" -> "Unix/TS 3.0"; "Unix/TS 3.0" -> "TS 4.0"; "Unix/TS++" -> "TS 4.0"; "CB Unix 3" -> "TS 4.0"; "TS 4.0" -> "System V.0"; "System V.0" -> "System V.2"; "System V.2" -> "System V.3"; } ocamlgraph-1.8.3/editor/tests/softmaint.dot0000644000175000017500000003515212133565071017753 0ustar mehdimehdidigraph G { // size="7,10" // page="8.5,11" // center="" // node[width=.25,height=.375,fontsize=9] fcfpr1_1_2t_17 -> 341411; fcfpr1_1t_1 -> 341411; rdlfpr2_0_rdlt_4 -> 341411; fpfpr1_0_1t_1 -> 341411; fpfpr1_1_2t_11 -> 341411; rtafpr1_1_2t_28 -> 341411; rtafpr1_1_3t_6 -> 341411; rdlfpr1_1t_1 -> 358866; rtafpr1_1_3t_6 -> 358866; tmfpr1_1_3t_5 -> 358930; fcfpr1_1_3t_9 -> 358930; pcfpr1_1_3t_7 -> 358930; fpfpr1_1_3g_1 -> 358930; fpfpr1_1_3t_1 -> 358930; aufpr1_1_3t_1 -> 358930; rtafpr1_0_3g_1 -> 358930; rtafpr1_1_3t_6 -> 358930; msgfpr1_1_1g_12 -> 371943; rtafpr1_1_1g_8 -> 371943; rtafpr1_1_1t_35 -> 371943; rtafpr1_1_1t_45 -> 371943; rtafpr1_1_3t_6 -> 371943; tlfpr2_0_rdlg_2 -> 374300; fcfpr1_1_3t_8 -> 374300; fcfpr1_1_3t_9 -> 374300; rtafpr1_1_3t_6 -> 374300; fcfpr1_0_5g_1 -> 371942; fcfpr1_1_1t_19 -> 371942; fcfpr1_1_3t_9 -> 371942; fcfpr1_1_3t_9 -> 374700; tymsgfpr1_1_3t_3 -> 374700; fpfpr1_1_3t_1 -> 374700; rtafpr1_1_3t_7 -> 374700; fcfpr1_1_3g_2 -> 374741; fcfpr1_1_3t_9 -> 374741; fpfpr1_1_3t_1 -> 374741; rtafpr1_1_3t_7 -> 374741; fcfpr1_1_1t_18 -> 374886; fcfpr1_1_3t_9 -> 374886; fpfpr1_1_3t_1 -> 374886; rtafpr1_1_3t_7 -> 374886; fcfpr1_1_3t_9 -> 375039; fpfpr1_1_3t_1 -> 375039; fcfpr1_1_3t_42 -> 375507; fcfpr1_1_3t_9 -> 375507; rdlfpr2_0_rdlt_158 -> 375507; rtafpr1_1_3t_7 -> 375507; rtafpr1_1_3t_71 -> 375507; dbfpr1_1_3t_2 -> 375507; fcfpr1_1_3t_9 -> 375508; rdlfpr1_1g_13 -> 375508; rtafpr1_1_3t_7 -> 375508; rtafpr2_1_rdlg_1 -> 375508; dbfpr1_1_3t_2 -> 375508; fcfpr1_1_3t_9 -> 375519; fpfpr1_1_3g_1 -> 375519; fpfpr1_1_3t_1 -> 375519; fcfpr1_1_3t_9 -> 377380; rdlfpr1_1g_16 -> 377380; rdlfpr1_1t_100 -> 377380; fcfpr1_0_2g_1 -> 377719; fcfpr1_1_3t_10 -> 377719; fcfpr1_1_3t_7 -> 377719; fcfpr1_1_3t_9 -> 377719; rdlfpr2_0_rdlg_12 -> 377719; rdlfpr2_0_rdlt_108 -> 377719; rdlfpr2_0_rdlt_27 -> 377719; rdlfpr2_0_rdlt_30 -> 377719; fcfpr1_1_3t_9 -> 377763; fcfpr1_1_3t_9 -> 379848; fpfpr1_1_3t_1 -> 379848; fcfpr1_1_3t_9 -> 380571; fcfpr1_1_3t_9 -> 380604; fpfpr1_1_3t_1 -> 380604; fcfpr1_1_3t_9 -> 381211; fpfpr1_1_3t_1 -> 381211; fcfpr1_1_3t_9 -> 381835; fcfpr1_1_3t_9 -> 381897; fcfpr1_1_3t_9 -> 381901; fpfpr1_1_3t_1 -> 381901; fcfpr1_1_3t_9 -> 382103; rtafpr1_1_3t_7 -> 382103; fcfpr1_1_3t_9 -> 382161; fcfpr1_1_3t_9 -> 383174; fpfpr1_1_3t_1 -> 383174; rtafpr1_1_3t_7 -> 383174; fpfpr1_1_3g_1 -> 352010; fpfpr1_1_3t_1 -> 352010; fpfpr1_1_3t_1 -> 382409; fpfpr1_1_3t_1 -> 382827; fpfpr1_1_3t_1 -> 382928; rtafpr1_1_3t_7 -> 382928; tlfpr1_1_1t_5 -> 358224; tymsgfpr1_1_1t_23 -> 358224; tymsgfpr1_1_3t_3 -> 358224; rcfpr0_0_1t_9 -> 358224; rcfpr1_1_1t_5 -> 358224; odfpr0_0_1t_8 -> 358224; odfpr1_1_1t_6 -> 358224; ecdsgfpr1_1_1t_4 -> 358224; tymsgfpr1_1_1t_18 -> 358900; tymsgfpr1_1_3t_3 -> 358900; rcfpr1_1_1t_100 -> 358900; rcfpr1_1_1t_22 -> 358900; rcfpr1_1_1t_37 -> 358900; odfpr1_1_1t_21 -> 358900; tymsgfpr1_1_3t_3 -> 372568; rcfpr1_1_1t_30 -> 372568; odfpr1_1_1t_31 -> 372568; tlfpr1_1_1t_20 -> 375557; tymsgfpr1_1_1t_24 -> 375557; tymsgfpr1_1_3t_3 -> 375557; rcfpr1_1_1t_11 -> 375557; odfpr1_1_1t_9 -> 375557; ecdsgfpr1_1_1t_19 -> 375557; rtafpr1_1_1g_14 -> 376956; rtafpr1_1_1t_64 -> 376956; rtafpr1_1_2t_18 -> 376956; rtafpr1_1_3t_30 -> 376956; rtafpr1_1_3t_7 -> 376956; rtafpr1_1_3t_7 -> 379339; rtafpr1_1_1t_14 -> 379422; rtafpr1_1_1t_20 -> 379422; rtafpr1_1_3t_7 -> 379422; rtafpr1_1_3t_7 -> 383039; fcfpr1_1_1t_18 -> 359471; fcfpr2_0_1t_1 -> 359471; fcfpr2_0_1t_2 -> 359471; ccsfpr2_0_1t_99 -> 359471; fcfpr1_1_3t_42 -> 384096; rtafpr1_1_3t_71 -> 384096; tlfpr1_0_4g_4 -> 354290; rcfpr0_0_1t_9 -> 354290; odfpr0_0_1t_8 -> 354290; pagfpr1_1_1t_23 -> 354290; rcfpr1_1_1t_5 -> 379864; rcfpr1_1_1t_100 -> 382574; rcfpr1_1_1t_22 -> 382574; rcfpr1_1_1t_37 -> 382574; rcfpr1_1_1t_30 -> 370706; rcfpr1_1_1t_30 -> 377908; rcfpr1_1_1t_30 -> 377924; rcfpr1_1_1t_30 -> 377971; rcfpr1_1_1t_30 -> 377980; odfpr1_1_1t_31 -> 377980; rcfpr1_1_1t_30 -> 378362; rcfpr1_1_1t_30 -> 378656; rcfpr1_1_1t_30 -> 378666; rcfpr1_1_1t_30 -> 379169; odfpr1_1_1t_31 -> 379169; rcfpr1_1_1t_110 -> 379341; rcfpr1_1_1t_30 -> 379341; rcfpr1_1_1t_62 -> 379341; odfpr1_1_1t_31 -> 379341; rcfpr1_1_1t_30 -> 379972; rcfpr1_1_1t_30 -> 380298; rcfpr1_1_1t_30 -> 380448; rcfpr1_1_1t_30 -> 380475; odfpr1_1_1t_31 -> 380475; rcfpr1_1_1t_30 -> 380526; odfpr1_1_1t_31 -> 357430; rcfpr1_1_1t_11 -> 379968; odfpr1_1_1t_9 -> 379968; ccsfpr2_0_1t_99 -> 359100; ccsfpr2_0_1t_99 -> 376529; ccsfpr2_0_1t_99 -> 377801; ccsfpr2_0_1t_99 -> 379126; ccsfpr2_0_1t_99 -> 379212; ccsfpr2_0_1t_99 -> 380285; ccsfpr2_0_1t_99 -> 380963; ccsfpr2_0_1t_99 -> 384909; tlfpr1_0_4g_4 -> 358471; odfpr0_0_1t_7 -> 358471; odfpr1_0_1t_36 -> 358471; odfpr1_0_3t_18 -> 358471; odfpr1_0_3t_21 -> 358471; tlfpr1_0_4g_4 -> 375024; tlfpr1_0_4g_4 -> 375027; rcfpr1_1_1t_110 -> 381710; rcfpr1_1_1t_62 -> 381710; rcfpr1_1_1t_110 -> 381775; rcfpr1_1_1t_62 -> 381775; rcfpr1_1_1t_110 -> 382436; fcfpr1_1_3t_34 -> 382528; rcfpr1_1_1t_110 -> 382528; rtafpr1_1_3t_48 -> 382528; rcfpr1_1_1t_110 -> 382566; rcfpr1_1_1t_110 -> 382572; odfpr0_0_1t_7 -> 353506; rcfpr1_0_1t_35 -> 370509; odfpr0_0_1t_7 -> 370509; odfpr0_0_1t_7 -> 370510; odfpr1_0_1t_38 -> 370510; tlfpr1_0_4g_5 -> 354546; rcfpr1_1_1t_61 -> 354546; odfpr1_0_3t_18 -> 354546; odfpr1_0_3t_20 -> 354546; odfpr1_0_3t_18 -> 354757; odfpr1_0_3t_20 -> 354757; odfpr1_0_3t_18 -> 354766; odfpr1_0_3t_20 -> 354766; odfpr1_0_3t_18 -> 354771; odfpr1_0_3t_20 -> 354771; odfpr1_0_3t_18 -> 354785; odfpr1_0_3t_23 -> 354785; odfpr1_0_3t_24 -> 354785; odfpr1_0_3t_18 -> 354878; odfpr1_0_3t_23 -> 354878; odfpr1_0_3t_24 -> 354878; odfpr1_0_3t_18 -> 355080; odfpr1_0_3t_23 -> 355080; odfpr1_0_3t_24 -> 355080; odfpr1_0_3t_18 -> 355288; odfpr1_0_3t_23 -> 355288; odfpr1_0_3t_24 -> 355288; odfpr2_0_03t_13 -> 355288; odfpr1_0_3t_18 -> 355800; odfpr1_0_3t_21 -> 355800; odfpr1_0_3t_18 -> 356116; odfpr1_0_3t_21 -> 356116; odfpr1_0_3t_18 -> 356741; odfpr1_0_3t_21 -> 356741; odfpr1_0_3t_18 -> 357340; odfpr1_0_3t_21 -> 357340; odfpr1_0_3t_18 -> 357538; odfpr1_0_3t_21 -> 357538; odfpr1_0_3t_18 -> 357769; odfpr1_0_3t_21 -> 357769; odfpr1_0_3t_18 -> 357793; odfpr1_0_3t_21 -> 357793; odfpr1_0_3t_18 -> 358155; odfpr1_0_3t_21 -> 358155; odfpr1_0_3t_18 -> 358157; odfpr1_0_3t_21 -> 358157; odfpr1_0_3t_18 -> 358159; odfpr1_0_3t_21 -> 358159; odfpr1_0_3t_18 -> 358584; odfpr1_0_3t_21 -> 358584; odfpr1_0_3t_18 -> 360104; odfpr1_0_3t_21 -> 360104; odfpr1_0_3t_18 -> 360144; odfpr1_0_3t_21 -> 360144; odfpr1_0_3t_18 -> 360672; odfpr1_0_3t_21 -> 360672; odfpr1_0_3t_5 -> 360672; odfpr1_0_3t_18 -> 360839; odfpr1_0_3t_21 -> 360839; odfpr1_0_3t_18 -> 371187; tlfpr1_0_3g_5 -> 373300; odfpr1_0_3t_12 -> 373300; odfpr1_0_3t_18 -> 373300; odfpr1_0_3t_18 -> 375134; odfpr1_0_5t_18 -> 375134; rcfpr0_0_1t_10 -> 375319; odfpr1_0_3t_18 -> 375319; odfpr1_0_3t_36 -> 375319; odfpr1_0_5t_17 -> 375319; odfpr1_0_5t_19 -> 375319; odfpr1_0_3t_18 -> 375499; odfpr1_0_3t_18 -> 377220; odfpr1_0_5t_21 -> 377220; tlfpr1_0_3g_7 -> 377562; tlfpr1_1_1t_3 -> 377562; odfpr1_0_3t_18 -> 377562; odfpr1_0_3t_36 -> 377562; odfpr1_0_5t_20 -> 377562; odfpr1_0_3t_18 -> 378108; odfpr1_0_3t_6 -> 378108; odfpr1_0_5t_20 -> 354221; odfpr0_0_1t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_0_3g_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr0_0_1t_8 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_61 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_0_3g_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_62 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; ccsfpr2_0_1t_99 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tymsgfpr1_1_3t_3 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr0_0_1t_9 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1t_14 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_3t_30 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_110 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; dbfpr1_1_3t_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1g_8 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_30 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_1_1t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1t_64 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr2_0_rdlg_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_2t_28 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_1_1t_3 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_1_1t_6 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fpfpr1_1_3t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; aufpr1_1_3t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3t_34 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_1t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_36 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_1_1t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_1t_19 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_1_1t_9 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_37 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3t_8 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_1_1t_21 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3t_9 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr2_0_rdlt_27 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3g_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1t_35 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_5t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fpfpr1_1_3g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_5t_21 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fpfpr1_1_2t_11 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; ecdsgfpr1_1_1t_19 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_1t_36 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1g_14 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tymsgfpr1_1_1t_23 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tymsgfpr1_1_1t_24 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_1t_38 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_0_2g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr1_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr0_0_1t_10 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_100 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr2_0_rdlt_108 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; pcfpr1_1_3t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; ecdsgfpr1_1_1t_4 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tmfpr1_1_3t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_21 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fpfpr1_0_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_23 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_22 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; pagfpr1_1_1t_23 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_3t_71 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_2t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr2_0_rdlt_158 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_3t_6 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_24 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_3t_7 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_0_3g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1t_20 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr1_1g_13 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_0_1t_35 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_2t_17 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr2_1_rdlg_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr2_0_rdlt_4 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr1_1g_16 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr2_0_1t_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr2_0_1t_2 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr1_1t_100 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; msgfpr1_1_1g_12 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr2_0_rdlt_30 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_0_4g_4 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3t_42 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_6 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tlfpr1_0_4g_5 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_3t_48 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_5t_17 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_5t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; tymsgfpr1_1_1t_18 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_5t_19 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_1_3t_10 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; fcfpr1_0_5g_1 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_0_3t_12 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr2_0_03t_13 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rcfpr1_1_1t_11 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; odfpr1_1_1t_31 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rdlfpr2_0_rdlg_12 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; rtafpr1_1_1t_45 [label="",shape=circle,height=0.12,width=0.12,fontsize=1]; } ocamlgraph-1.8.3/editor/tests/fsm.dot0000644000175000017500000000100412133565071016521 0ustar mehdimehdidigraph finite_state_machine { LR_0 -> LR_2 [ label = "SS(B)" ]; LR_0 -> LR_1 [ label = "SS(S)" ]; LR_1 -> LR_3 [ label = "S($end)" ]; LR_2 -> LR_6 [ label = "SS(b)" ]; LR_2 -> LR_5 [ label = "SS(a)" ]; LR_2 -> LR_4 [ label = "S(A)" ]; LR_5 -> LR_7 [ label = "S(b)" ]; LR_5 -> LR_5 [ label = "S(a)" ]; LR_6 -> LR_6 [ label = "S(b)" ]; LR_6 -> LR_5 [ label = "S(a)" ]; LR_7 -> LR_8 [ label = "S(b)" ]; LR_7 -> LR_5 [ label = "S(a)" ]; LR_8 -> LR_6 [ label = "S(b)" ]; LR_8 -> LR_5 [ label = "S(a)" ]; } ocamlgraph-1.8.3/editor/tests/divisors12.gml0000644000175000017500000000163112133565071017740 0ustar mehdimehdigraph [ node [ id 1 label 1 ] node [ id 2 label 2 ] node [ id 3 label 3 ] node [ id 4 label 4 ] node [ id 5 label 5 ] node [ id 6 label 6 ] node [ id 7 label 7 ] node [ id 8 label 8 ] node [ id 9 label 9 ] node [ id 10 label 10 ] node [ id 11 label 11 ] edge [ source 3 target 1 ] edge [ source 5 target 1 ] edge [ source 5 target 2 ] edge [ source 7 target 1 ] edge [ source 7 target 3 ] edge [ source 8 target 2 ] edge [ source 9 target 1 ] edge [ source 9 target 4 ] edge [ source 11 target 1 ] edge [ source 11 target 2 ] edge [ source 11 target 3 ] edge [ source 11 target 5 ] ] ocamlgraph-1.8.3/editor/tests/world.dot0000644000175000017500000000172412133565071017074 0ustar mehdimehdidigraph world { size="7,7"; {rank=same; S8 S24 S1 S35 S30;} {rank=same; T8 T24 T1 T35 T30;} {rank=same; 43 37 36 10 2;} {rank=same; 25 9 38 40 13 17 12 18;} {rank=same; 26 42 11 3 33 19 39 14 16;} {rank=same; 4 31 34 21 41 28 20;} {rank=same; 27 5 22 32 29 15;} {rank=same; 6 23;} {rank=same; 7;} S8 -> 9; S24 -> 25; S24 -> 27; S1 -> 2; S1 -> 10; S35 -> 43; S35 -> 36; S30 -> 31; S30 -> 33; 9 -> 42; 9 -> T1; 25 -> T1; 25 -> 26; 27 -> T24; 2 -> {3 ; 16 ; 17 ; T1 ; 18} 10 -> { 11 ; 14 ; T1 ; 13; 12;} 31 -> T1; 31 -> 32; 33 -> T30; 33 -> 34; 42 -> 4; 26 -> 4; 3 -> 4; 16 -> 15; 17 -> 19; 18 -> 29; 11 -> 4; 14 -> 15; 37 -> {39 ; 41 ; 38 ; 40;} 13 -> 19; 12 -> 29; 43 -> 38; 43 -> 40; 36 -> 19; 32 -> 23; 34 -> 29; 39 -> 15; 41 -> 29; 38 -> 4; 40 -> 19; 4 -> 5; 19 -> {21 ; 20 ; 28;} 5 -> {6 ; T35 ; 23;} 21 -> 22; 20 -> 15; 28 -> 29; 6 -> 7; 15 -> T1; 22 -> T35; 22 -> 23; 29 -> T30; 7 -> T8; 23 -> T24; 23 -> T1; } ocamlgraph-1.8.3/editor/tests/rand_10_40.gml0000644000175000017500000000454012133565071017464 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] edge [ source 2 target 1 label 0 ] edge [ source 3 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 4 target 1 label 0 ] edge [ source 4 target 2 label 0 ] edge [ source 5 target 1 label 0 ] edge [ source 5 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 5 target 4 label 0 ] edge [ source 6 target 1 label 0 ] edge [ source 6 target 2 label 0 ] edge [ source 6 target 5 label 0 ] edge [ source 7 target 1 label 0 ] edge [ source 7 target 2 label 0 ] edge [ source 7 target 3 label 0 ] edge [ source 7 target 4 label 0 ] edge [ source 7 target 5 label 0 ] edge [ source 7 target 6 label 0 ] edge [ source 8 target 1 label 0 ] edge [ source 8 target 2 label 0 ] edge [ source 8 target 3 label 0 ] edge [ source 8 target 4 label 0 ] edge [ source 8 target 5 label 0 ] edge [ source 8 target 6 label 0 ] edge [ source 8 target 7 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 3 label 0 ] edge [ source 9 target 4 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 9 target 6 label 0 ] edge [ source 9 target 8 label 0 ] edge [ source 10 target 1 label 0 ] edge [ source 10 target 3 label 0 ] edge [ source 10 target 4 label 0 ] edge [ source 10 target 5 label 0 ] edge [ source 10 target 6 label 0 ] edge [ source 10 target 7 label 0 ] edge [ source 10 target 8 label 0 ] edge [ source 10 target 9 label 0 ] ] ocamlgraph-1.8.3/editor/tests/twopi2.dot0000644000175000017500000043271312133565071017177 0ustar mehdimehdidigraph G { ranksep=3; ratio=auto; "1" [ label="02f5daf56e299b8a8ecea892",shape="hexagon",style="filled",color="green" ]; "189E" [ label="ca5af2",shape="box",style="filled",color="grey" ]; "790E" [ label="b4dfef6",shape="box",style="filled",color="grey" ]; "2" [ label="171192dc1f8e6ea551548a910c00",shape="hexagon",style="filled",color="green" ]; "191E" [ label="629e42",shape="box",style="filled",color="grey" ]; "3" [ label="6bce02baf91781a831e1b95",shape="hexagon",style="filled",color="green" ]; "193E" [ label="1c08373",shape="box",style="filled",color="grey" ]; "4" [ label="6236a67933a619a6a3d48",shape="hexagon",style="filled",color="green" ]; "195E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; "5" [ label="50962c93b4cb293f5beb59eb",shape="hexagon",style="filled",color="green" ]; "197E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; "6" [ label="05d4b1ed6a6135eec3abd3f2",shape="hexagon",style="filled",color="green" ]; "199E" [ label="",shape="box",style="filled",color="grey" ]; "7" [ label="08769f73d31c1a99be2d9363f",shape="hexagon",style="filled",color="green" ]; "201E" [ label="629e42",shape="box",style="filled",color="grey" ]; "8" [ label="a6a196a504c3a7657d1fa41",shape="hexagon",style="filled",color="green" ]; "203E" [ label="cd856f",shape="box",style="filled",color="grey" ]; "9" [ label="837ebf4bde22e1f1535cb662",shape="hexagon",style="filled",color="green" ]; "725E" [ label="d0eb84",shape="box",style="filled",color="grey" ]; "785E" [ label="dd2ba36",shape="box",style="filled",color="grey" ]; "10" [ label="5f865c374cb3fe976dd376b8",shape="hexagon",style="filled",color="green" ]; "205E" [ label="23ad1",shape="box",style="filled",color="grey" ]; "11" [ label="8be752bc95d436a90493bec9",shape="hexagon",style="filled",color="green" ]; "207E" [ label="ee91c97828",shape="box",style="filled",color="grey" ]; "12" [ label="969a58db14386cb9d2f51ec",shape="hexagon",style="filled",color="green" ]; "209E" [ label="7c7c",shape="box",style="filled",color="grey" ]; "13" [ label="da24f74aad2ff519009d1f38c",shape="hexagon",style="filled",color="green" ]; "211E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; "14" [ label="3124d3a6ed3381a6341c6",shape="hexagon",style="filled",color="green" ]; "213E" [ label="bbe0a8f93dc1",shape="box",style="filled",color="grey" ]; "15" [ label="71512ec7d43f958f2b6da",shape="hexagon",style="filled",color="green" ]; "215E" [ label="3f0a2b4eb62f",shape="box",style="filled",color="grey" ]; "16" [ label="3828a2c682419423cf",shape="hexagon",style="filled",color="green" ]; "727E" [ label="2",shape="box",style="filled",color="grey" ]; "784E" [ label="",shape="box",style="filled",color="grey" ]; "17" [ label="aa868f65c34cdb64f1fad19a",shape="hexagon",style="filled",color="green" ]; "217E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; "787E" [ label="1aaaab063",shape="box",style="filled",color="grey" ]; "18" [ label="dca32af03698c988b22",shape="hexagon",style="filled",color="green" ]; "219E" [ label="eb8",shape="box",style="filled",color="grey" ]; "19" [ label="d8f4a9e463a1e89217f",shape="hexagon",style="filled",color="green" ]; "221E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; "20" [ label="c96782ef56711c5d6a3f69",shape="hexagon",style="filled",color="green" ]; "223E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; "21" [ label="4f04c39708f",shape="hexagon",style="filled",color="green" ]; "225E" [ label="a49284e9",shape="box",style="filled",color="grey" ]; "22" [ label="97284d4c3a5d499853f0e",shape="hexagon",style="filled",color="green" ]; "227E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; "792E" [ label="79b69c612",shape="box",style="filled",color="grey" ]; "23" [ label="c4d32527b670afb370d643",shape="hexagon",style="filled",color="green" ]; "231E" [ label="e851f5ddd920",shape="box",style="filled",color="grey" ]; "24" [ label="5e9156098c064",shape="hexagon",style="filled",color="green" ]; "233E" [ label="",shape="box",style="filled",color="grey" ]; "25" [ label="3d475ea3aeca51b60212dd",shape="hexagon",style="filled",color="green" ]; "235E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; "26" [ label="966d271c22e75c7538",shape="hexagon",style="filled",color="green" ]; "237E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "27" [ label="b630e1af6ae1997f0e8ba750",shape="hexagon",style="filled",color="green" ]; "239E" [ label="bb828f1a326",shape="box",style="filled",color="grey" ]; "783E" [ label="499f6985db294c",shape="box",style="filled",color="grey" ]; "28" [ label="ebd8ffc2ac3a90efb8af9",shape="hexagon",style="filled",color="green" ]; "241E" [ label="1ebeec",shape="box",style="filled",color="grey" ]; "791E" [ label="c0b727",shape="box",style="filled",color="grey" ]; "29" [ label="69fdd1a1f4768c5efe7",shape="hexagon",style="filled",color="green" ]; "243E" [ label="35b8742610",shape="box",style="filled",color="grey" ]; "30" [ label="d93a80739fc1edb41a11b7294",shape="hexagon",style="filled",color="green" ]; "245E" [ label="e03b8bc0435a",shape="box",style="filled",color="grey" ]; "31" [ label="bf65cfddeb00ff847feae0c",shape="hexagon",style="filled",color="green" ]; "247E" [ label="8df",shape="box",style="filled",color="grey" ]; "32" [ label="916c686a1e82dba72524a",shape="hexagon",style="filled",color="green" ]; "249E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; "33" [ label="f496bcf0889b301d77819c",shape="hexagon",style="filled",color="green" ]; "251E" [ label="f29dfb9",shape="box",style="filled",color="grey" ]; "34" [ label="76889f7d35e",shape="hexagon",style="filled",color="green" ]; "253E" [ label="e7ef998",shape="box",style="filled",color="grey" ]; "35" [ label="668d636002",shape="hexagon",style="filled",color="green" ]; "255E" [ label="4379b5ed",shape="box",style="filled",color="grey" ]; "36" [ label="e1e4c23db39d8bd633c3a",shape="hexagon",style="filled",color="green" ]; "257E" [ label="1ed5d7f63b8c6",shape="box",style="filled",color="grey" ]; "37" [ label="842bc5775657c1e0d67",shape="hexagon",style="filled",color="green" ]; "259E" [ label="a387210a27b",shape="box",style="filled",color="grey" ]; "38" [ label="e4e2f4e6d",shape="hexagon",style="filled",color="green" ]; "261E" [ label="1f4f0fdf",shape="box",style="filled",color="grey" ]; "39" [ label="04390dec6f1779353c07f5",shape="hexagon",style="filled",color="green" ]; "263E" [ label="bac77c3f414a",shape="box",style="filled",color="grey" ]; "40" [ label="69f2611acc42c36ed7cc",shape="hexagon",style="filled",color="green" ]; "265E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "41" [ label="1562abef0d8241",shape="hexagon",style="filled",color="green" ]; "267E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; "42" [ label="e49aaa5cc4e44355d6a0",shape="hexagon",style="filled",color="green" ]; "269E" [ label="cc3f63d",shape="box",style="filled",color="grey" ]; "43" [ label="e8ebe1bf5f421c1223",shape="hexagon",style="filled",color="green" ]; "271E" [ label="96325ea",shape="box",style="filled",color="grey" ]; "44" [ label="2759e82e30d6d",shape="hexagon",style="filled",color="green" ]; "273E" [ label="ca5af2",shape="box",style="filled",color="grey" ]; "45" [ label="23c1ec53358d237c1",shape="hexagon",style="filled",color="green" ]; "275E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "46" [ label="5838586c293d455",shape="hexagon",style="filled",color="green" ]; "277E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; "47" [ label="f841118350a27b7ea29a9c9d",shape="hexagon",style="filled",color="green" ]; "279E" [ label="69f4ecb77d",shape="box",style="filled",color="grey" ]; "48" [ label="658d208447d8ec5d6de8",shape="hexagon",style="filled",color="green" ]; "281E" [ label="f7b22b9640",shape="box",style="filled",color="grey" ]; "49" [ label="11180ae7706510211bc4",shape="hexagon",style="filled",color="green" ]; "283E" [ label="052bb6e3",shape="box",style="filled",color="grey" ]; "50" [ label="5807acd8d58e006f43",shape="hexagon",style="filled",color="green" ]; "285E" [ label="",shape="box",style="filled",color="grey" ]; "51" [ label="fe4e848cb5291ee59a2",shape="hexagon",style="filled",color="green" ]; "287E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; "52" [ label="c4f31ea3844e12da27ad47c6",shape="hexagon",style="filled",color="green" ]; "289E" [ label="fb16636aae",shape="box",style="filled",color="grey" ]; "53" [ label="00cbeb87c182ca0785f",shape="hexagon",style="filled",color="green" ]; "291E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; "54" [ label="11f088bfd8",shape="hexagon",style="filled",color="green" ]; "293E" [ label="6a80cbe",shape="box",style="filled",color="grey" ]; "55" [ label="64a9ec24428099ad8ed82ba6",shape="hexagon",style="filled",color="green" ]; "745E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; "56" [ label="3c2a62e0e5e9f7",shape="hexagon",style="filled",color="green" ]; "295E" [ label="ae32701",shape="box",style="filled",color="grey" ]; "57" [ label="dd84fe6a65cfac7bca03ebd",shape="hexagon",style="filled",color="green" ]; "297E" [ label="",shape="box",style="filled",color="grey" ]; "58" [ label="b06bbfa920aa95dd",shape="hexagon",style="filled",color="green" ]; "299E" [ label="07",shape="box",style="filled",color="grey" ]; "59" [ label="6b5aaa4bdf44b2c898854",shape="hexagon",style="filled",color="green" ]; "301E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; "789E" [ label="3a0ff0",shape="box",style="filled",color="grey" ]; "60" [ label="855d26296eda4eb7",shape="hexagon",style="filled",color="green" ]; "303E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; "61" [ label="e82f47b8d4949ba4af69b38cbc19",shape="hexagon",style="filled",color="green" ]; "305E" [ label="b62cd1d0a0",shape="box",style="filled",color="grey" ]; "62" [ label="86569bffb49adf6b3d0ebac",shape="hexagon",style="filled",color="green" ]; "307E" [ label="660ffeb76fc59",shape="box",style="filled",color="grey" ]; "63" [ label="a96e47ff37983425a3e452095",shape="hexagon",style="filled",color="green" ]; "309E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "64" [ label="71a48d11b2e7e56b1df128bd",shape="hexagon",style="filled",color="green" ]; "311E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; "65" [ label="a0befe6dd1ca7b165786835",shape="hexagon",style="filled",color="green" ]; "313E" [ label="3cfae",shape="box",style="filled",color="grey" ]; "66" [ label="f33ec11db496f7bfcb024f",shape="hexagon",style="filled",color="green" ]; "315E" [ label="71e6b",shape="box",style="filled",color="grey" ]; "67" [ label="fe6be3206549f5b5564acde84783",shape="hexagon",style="filled",color="green" ]; "317E" [ label="",shape="box",style="filled",color="grey" ]; "68" [ label="e4dba079d5fcb1f165920a3bf",shape="hexagon",style="filled",color="green" ]; "319E" [ label="",shape="box",style="filled",color="grey" ]; "69" [ label="35dfbee3123dc389cba0b15",shape="hexagon",style="filled",color="green" ]; "746E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; "70" [ label="16c508ab98483d430bbe",shape="hexagon",style="filled",color="green" ]; "321E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "71" [ label="9c9e2e0f2da8758e436c",shape="hexagon",style="filled",color="green" ]; "327E" [ label="cd0d985a366cad7e",shape="box",style="filled",color="grey" ]; "72" [ label="fb039d7a2a9fe73b5f468eba9",shape="hexagon",style="filled",color="green" ]; "329E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; "73" [ label="2ef949c4a39b",shape="hexagon",style="filled",color="green" ]; "331E" [ label="617809d979f",shape="box",style="filled",color="grey" ]; "74" [ label="a9497e0757b0969bde707ed5",shape="hexagon",style="filled",color="green" ]; "333E" [ label="541ab86a2e",shape="box",style="filled",color="grey" ]; "75" [ label="230cc6bbc66b24eae94fa03d",shape="hexagon",style="filled",color="green" ]; "335E" [ label="",shape="box",style="filled",color="grey" ]; "76" [ label="1d163eac141def176461c",shape="hexagon",style="filled",color="green" ]; "337E" [ label="0acc5bb8ca4",shape="box",style="filled",color="grey" ]; "77" [ label="32979f8cf86",shape="hexagon",style="filled",color="green" ]; "339E" [ label="a7e89580",shape="box",style="filled",color="grey" ]; "78" [ label="37d80ae421dba4a70730338860",shape="hexagon",style="filled",color="green" ]; "341E" [ label="",shape="box",style="filled",color="grey" ]; "79" [ label="fbba7215e7c13173a60206",shape="hexagon",style="filled",color="green" ]; "343E" [ label="617809d979f",shape="box",style="filled",color="grey" ]; "80" [ label="2dd8cc4d693415f93c0f8fc",shape="hexagon",style="filled",color="green" ]; "345E" [ label="94da691e20e3",shape="box",style="filled",color="grey" ]; "81" [ label="00880e6f50c765ebc1f85d3e9",shape="hexagon",style="filled",color="green" ]; "347E" [ label="e7ef998",shape="box",style="filled",color="grey" ]; "82" [ label="ef13d45b1277ac9a0444adb",shape="hexagon",style="filled",color="green" ]; "349E" [ label="a7fe7",shape="box",style="filled",color="grey" ]; "83" [ label="2573e1bf51f1b307f4640",shape="hexagon",style="filled",color="green" ]; "351E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; "84" [ label="162d8039483d8",shape="hexagon",style="filled",color="green" ]; "353E" [ label="a8e9",shape="box",style="filled",color="grey" ]; "85" [ label="f490de272a7f6e4af346d40",shape="hexagon",style="filled",color="green" ]; "355E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; "788E" [ label="391256c872",shape="box",style="filled",color="grey" ]; "86" [ label="678bf739c344b9ad41da1",shape="hexagon",style="filled",color="green" ]; "357E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; "87" [ label="876d120b38b0e88817",shape="hexagon",style="filled",color="green" ]; "359E" [ label="e5",shape="box",style="filled",color="grey" ]; "88" [ label="503737b64d432c60d6ac557e0e6",shape="hexagon",style="filled",color="green" ]; "361E" [ label="9937ccba1469",shape="box",style="filled",color="grey" ]; "89" [ label="b36e0be6f67fc25286127456",shape="hexagon",style="filled",color="green" ]; "363E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; "90" [ label="4cc20a0b7651e486",shape="hexagon",style="filled",color="green" ]; "365E" [ label="e079d2c",shape="box",style="filled",color="grey" ]; "91" [ label="08dade990b2282",shape="hexagon",style="filled",color="green" ]; "367E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; "92" [ label="f8128d574c356631b8a9",shape="hexagon",style="filled",color="green" ]; "369E" [ label="",shape="box",style="filled",color="grey" ]; "93" [ label="88a4f0337c2189c3fc7b31",shape="hexagon",style="filled",color="green" ]; "729E" [ label="da0d7bbcf30",shape="box",style="filled",color="grey" ]; "94" [ label="1b13908a9f0763c0ae54af9062080",shape="hexagon",style="filled",color="green" ]; "371E" [ label="8b06a67a",shape="box",style="filled",color="grey" ]; "95" [ label="e2a5d11499b7e",shape="hexagon",style="filled",color="green" ]; "373E" [ label="66abc181ac4",shape="box",style="filled",color="grey" ]; "96" [ label="90cc275011c2013c61eb11",shape="hexagon",style="filled",color="green" ]; "375E" [ label="",shape="box",style="filled",color="grey" ]; "97" [ label="1e003bfe8fc840df0163f4c",shape="hexagon",style="filled",color="green" ]; "747E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; "98" [ label="1927c743a0d440a5a0",shape="hexagon",style="filled",color="green" ]; "377E" [ label="b12441ecff15fa12c",shape="box",style="filled",color="grey" ]; "99" [ label="155d892827c33ed3cae3",shape="hexagon",style="filled",color="green" ]; "379E" [ label="71e6b",shape="box",style="filled",color="grey" ]; "100" [ label="9f24ba80192c339a64c0",shape="hexagon",style="filled",color="green" ]; "381E" [ label="",shape="box",style="filled",color="grey" ]; "101" [ label="3e814305b42beb41b8c706",shape="hexagon",style="filled",color="green" ]; "383E" [ label="1c08373",shape="box",style="filled",color="grey" ]; "102" [ label="eccfe5ff0af70fe9fbec8b2360f90",shape="hexagon",style="filled",color="green" ]; "385E" [ label="be8f4199f",shape="box",style="filled",color="grey" ]; "103" [ label="8fa622d9f842c5572a545ed72982",shape="hexagon",style="filled",color="green" ]; "387E" [ label="4dccb",shape="box",style="filled",color="grey" ]; "104" [ label="ad9142a65f5eab78b4ca5e",shape="hexagon",style="filled",color="green" ]; "389E" [ label="f36cce089",shape="box",style="filled",color="grey" ]; "105" [ label="20f234fdcd0e1fc50261ce8",shape="hexagon",style="filled",color="green" ]; "391E" [ label="67219ef689f0146b544",shape="box",style="filled",color="grey" ]; "106" [ label="e06cc38155ff6781cf944d745",shape="hexagon",style="filled",color="green" ]; "393E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; "107" [ label="cfdf1932665dcb4cd3c",shape="hexagon",style="filled",color="green" ]; "395E" [ label="964b86fc1bba0e",shape="box",style="filled",color="grey" ]; "108" [ label="6d4a4a5a5af91b895272c30",shape="hexagon",style="filled",color="green" ]; "397E" [ label="b5e86c73d1198f",shape="box",style="filled",color="grey" ]; "109" [ label="e0ad365c2fb444358201",shape="hexagon",style="filled",color="green" ]; "399E" [ label="bb5e89c8963",shape="box",style="filled",color="grey" ]; "110" [ label="b07bbdc8cca5985d4c4",shape="hexagon",style="filled",color="green" ]; "401E" [ label="50023f6f88",shape="box",style="filled",color="grey" ]; "111" [ label="df5dba74c75b228de48c",shape="hexagon",style="filled",color="green" ]; "403E" [ label="7e493ee44b28",shape="box",style="filled",color="grey" ]; "112" [ label="0b8694c9ef9b27b9c3d8",shape="hexagon",style="filled",color="green" ]; "405E" [ label="2342b759c03",shape="box",style="filled",color="grey" ]; "113" [ label="81e20155999fa64e0ae6fd",shape="hexagon",style="filled",color="green" ]; "407E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; "114" [ label="3ef07ae75d29a707",shape="hexagon",style="filled",color="green" ]; "409E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; "115" [ label="4a36db80f1ab1e97",shape="hexagon",style="filled",color="green" ]; "411E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; "116" [ label="16da5f1301b36df4df0f",shape="hexagon",style="filled",color="green" ]; "413E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; "117" [ label="6b3f3fa236bb90592d23a",shape="hexagon",style="filled",color="green" ]; "415E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; "118" [ label="f2a57e4d4f0cec516891e3",shape="hexagon",style="filled",color="green" ]; "417E" [ label="bd2484",shape="box",style="filled",color="grey" ]; "119" [ label="deb3089920548bf1ecb23f0d",shape="hexagon",style="filled",color="green" ]; "419E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; "120" [ label="bf01c8a262",shape="hexagon",style="filled",color="green" ]; "421E" [ label="01",shape="box",style="filled",color="grey" ]; "121" [ label="23dc3a52fed9c119610b5e8",shape="hexagon",style="filled",color="green" ]; "423E" [ label="71e6b",shape="box",style="filled",color="grey" ]; "122" [ label="aff7fc220edc93572bb2",shape="hexagon",style="filled",color="green" ]; "748E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; "123" [ label="78cc16f965adc5f712ea2372c6",shape="hexagon",style="filled",color="green" ]; "425E" [ label="23ad1",shape="box",style="filled",color="grey" ]; "124" [ label="5be631dff7b97697be7dc0a2f07f2",shape="hexagon",style="filled",color="green" ]; "427E" [ label="",shape="box",style="filled",color="grey" ]; "786E" [ label="421",shape="box",style="filled",color="grey" ]; "125" [ label="48398d080dfcccced48da1980",shape="hexagon",style="filled",color="green" ]; "431E" [ label="866808df",shape="box",style="filled",color="grey" ]; "126" [ label="03716a2c341e5edaa31",shape="hexagon",style="filled",color="green" ]; "433E" [ label="21407f8a6d7",shape="box",style="filled",color="grey" ]; "127" [ label="ddfeabe456a9de5f5784",shape="hexagon",style="filled",color="green" ]; "435E" [ label="aac615ae78",shape="box",style="filled",color="grey" ]; "128" [ label="d550a7f392c787661aadd48",shape="hexagon",style="filled",color="green" ]; "437E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; "129" [ label="4c82921f4ad3f07066540",shape="hexagon",style="filled",color="green" ]; "439E" [ label="a7fe7",shape="box",style="filled",color="grey" ]; "130" [ label="0bc7f8f513e0e74b270",shape="hexagon",style="filled",color="green" ]; "441E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; "131" [ label="3b1563a23eb9",shape="hexagon",style="filled",color="green" ]; "443E" [ label="a8e9",shape="box",style="filled",color="grey" ]; "132" [ label="be233fafa38d931d894",shape="hexagon",style="filled",color="green" ]; "445E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; "133" [ label="f906dc5244ee6a371f8",shape="hexagon",style="filled",color="green" ]; "749E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; "134" [ label="e7a887d88c2318beba51",shape="hexagon",style="filled",color="green" ]; "447E" [ label="9d8988c0945d6",shape="box",style="filled",color="grey" ]; "135" [ label="be6b73bd46a7a5183e8c91a",shape="hexagon",style="filled",color="green" ]; "449E" [ label="ee91c97828",shape="box",style="filled",color="grey" ]; "769E" [ label="444189d179b5db71fe",shape="box",style="filled",color="grey" ]; "770E" [ label="1e1fbbe14ac24e0518",shape="box",style="filled",color="grey" ]; "136" [ label="644f112bb0aa452ee7040a",shape="hexagon",style="filled",color="green" ]; "451E" [ label="52f247fc3b",shape="box",style="filled",color="grey" ]; "137" [ label="010957669f3770aac",shape="hexagon",style="filled",color="green" ]; "453E" [ label="78",shape="box",style="filled",color="grey" ]; "138" [ label="0a185946ee443342b07d8e1",shape="hexagon",style="filled",color="green" ]; "455E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; "139" [ label="f66fe4df3d189e69ce10c9c",shape="hexagon",style="filled",color="green" ]; "457E" [ label="21407f8a6d7",shape="box",style="filled",color="grey" ]; "140" [ label="247e407f45b353f8",shape="hexagon",style="filled",color="green" ]; "459E" [ label="",shape="box",style="filled",color="grey" ]; "141" [ label="84907547f36d0ff7",shape="hexagon",style="filled",color="green" ]; "461E" [ label="e920b915087",shape="box",style="filled",color="grey" ]; "142" [ label="805004328dad9d315d",shape="hexagon",style="filled",color="green" ]; "463E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; "143" [ label="4f0cbd3fbf0cb1e8c",shape="hexagon",style="filled",color="green" ]; "465E" [ label="403126",shape="box",style="filled",color="grey" ]; "144" [ label="4869e993f2bb10f",shape="hexagon",style="filled",color="green" ]; "467E" [ label="ff",shape="box",style="filled",color="grey" ]; "145" [ label="665b76844ff78fc2cf66ca2",shape="hexagon",style="filled",color="green" ]; "469E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; "146" [ label="3f16509139c7dad5163b91799",shape="hexagon",style="filled",color="green" ]; "471E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; "147" [ label="01db23a60422ba93a68611cc0",shape="hexagon",style="filled",color="green" ]; "473E" [ label="",shape="box",style="filled",color="grey" ]; "148" [ label="46125fcc583c0f494a3a1d3",shape="hexagon",style="filled",color="green" ]; "475E" [ label="db6c4213a717bc",shape="box",style="filled",color="grey" ]; "149" [ label="731857fe189fb398e80a0594",shape="hexagon",style="filled",color="green" ]; "477E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; "150" [ label="6fb7a84e370ef70feac5cb",shape="hexagon",style="filled",color="green" ]; "479E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; "151" [ label="e343cea291b79a2ed4e",shape="hexagon",style="filled",color="green" ]; "481E" [ label="88d8b220746882d",shape="box",style="filled",color="grey" ]; "152" [ label="5f2592b20f13356b7fc8b42",shape="hexagon",style="filled",color="green" ]; "483E" [ label="",shape="box",style="filled",color="grey" ]; "153" [ label="275a0407e33e9b8aa9cdd051",shape="hexagon",style="filled",color="green" ]; "731E" [ label="",shape="box",style="filled",color="grey" ]; "154" [ label="011d119375cf494ca2fa8d59",shape="hexagon",style="filled",color="green" ]; "750E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; "155" [ label="173fd00917644f0f1f3e3",shape="hexagon",style="filled",color="green" ]; "485E" [ label="0acc5bb8ca4",shape="box",style="filled",color="grey" ]; "156" [ label="c72df69b40156a3254",shape="hexagon",style="filled",color="green" ]; "487E" [ label="fff03efcd",shape="box",style="filled",color="grey" ]; "157" [ label="6c632ad9c42228bb337",shape="hexagon",style="filled",color="green" ]; "489E" [ label="eb8",shape="box",style="filled",color="grey" ]; "158" [ label="bbb13dc62adf2de2a42b6",shape="hexagon",style="filled",color="green" ]; "491E" [ label="69ce90c9b2",shape="box",style="filled",color="grey" ]; "159" [ label="6282bc21f6",shape="hexagon",style="filled",color="green" ]; "495E" [ label="de34214b4c258c9333ec3",shape="box",style="filled",color="grey" ]; "160" [ label="71cf45dd4e91bcca945137b40e",shape="hexagon",style="filled",color="green" ]; "499E" [ label="65fd8495",shape="box",style="filled",color="grey" ]; "161" [ label="a3b6df27179b175c88fa4c9cf9f",shape="hexagon",style="filled",color="green" ]; "501E" [ label="6577",shape="box",style="filled",color="grey" ]; "162" [ label="284f14a259991806654e74",shape="hexagon",style="filled",color="green" ]; "503E" [ label="4280833ef80172",shape="box",style="filled",color="grey" ]; "163" [ label="a7c99ccf6ddf6f5ebbe",shape="hexagon",style="filled",color="green" ]; "505E" [ label="c4fd8",shape="box",style="filled",color="grey" ]; "164" [ label="c32d2697e8",shape="hexagon",style="filled",color="green" ]; "507E" [ label="52f247fc3b",shape="box",style="filled",color="grey" ]; "165" [ label="d12bd75c24b110ef90cdd35d3",shape="hexagon",style="filled",color="green" ]; "509E" [ label="0668",shape="box",style="filled",color="grey" ]; "166" [ label="1c07453d584f3d14b1876fdb",shape="hexagon",style="filled",color="green" ]; "511E" [ label="460aed10cc9",shape="box",style="filled",color="grey" ]; "167" [ label="f713a8b311ffa05ce3683ad10",shape="hexagon",style="filled",color="green" ]; "513E" [ label="30d6138b63eb",shape="box",style="filled",color="grey" ]; "168" [ label="3cdc90c57243373efaba65a",shape="hexagon",style="filled",color="green" ]; "515E" [ label="fa2afbd869",shape="box",style="filled",color="grey" ]; "169" [ label="e3bdbca0e2256fffa8a59018",shape="hexagon",style="filled",color="green" ]; "517E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; "170" [ label="75ba8d840070942eb4e737849",shape="hexagon",style="filled",color="green" ]; "519E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; "171" [ label="fbdc3ca37406f66635c8b226e",shape="hexagon",style="filled",color="green" ]; "521E" [ label="8cbcf5cb5",shape="box",style="filled",color="grey" ]; "172" [ label="40b49a5a9bb256c7a3286e56",shape="hexagon",style="filled",color="green" ]; "523E" [ label="f72564578be",shape="box",style="filled",color="grey" ]; "173" [ label="3b2f08d52e4bca3f9ca7bbbd6",shape="hexagon",style="filled",color="green" ]; "525E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; "174" [ label="4a38abc630c82b0c48dfbf5271",shape="hexagon",style="filled",color="green" ]; "527E" [ label="f0bd1521",shape="box",style="filled",color="grey" ]; "175" [ label="2d7b7fb6c9ad6821752651f7",shape="hexagon",style="filled",color="green" ]; "529E" [ label="47b2da3d",shape="box",style="filled",color="grey" ]; "176" [ label="910b00285f11bb90d0a15641",shape="hexagon",style="filled",color="green" ]; "531E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; "177" [ label="24431c3eb075102f07cc2c1be",shape="hexagon",style="filled",color="green" ]; "533E" [ label="",shape="box",style="filled",color="grey" ]; "178" [ label="07f8a9e55a16beddb3c9153b0",shape="hexagon",style="filled",color="green" ]; "535E" [ label="81dabfaba8",shape="box",style="filled",color="grey" ]; "179" [ label="c1c30f30d40c4f1f84924622f",shape="hexagon",style="filled",color="green" ]; "537E" [ label="c5d5be3942",shape="box",style="filled",color="grey" ]; "180" [ label="86276bb1e23f2c7ffcbe82a0",shape="hexagon",style="filled",color="green" ]; "539E" [ label="0f940646",shape="box",style="filled",color="grey" ]; "181" [ label="f78e145a127014eb43345a0c",shape="hexagon",style="filled",color="green" ]; "541E" [ label="d370c12dbc",shape="box",style="filled",color="grey" ]; "182" [ label="a27037332d9fa5c43bcfe94c0",shape="hexagon",style="filled",color="green" ]; "543E" [ label="80874aa8",shape="box",style="filled",color="grey" ]; "183" [ label="c29ce10bb8d19b498355aa04",shape="hexagon",style="filled",color="green" ]; "545E" [ label="1c08373",shape="box",style="filled",color="grey" ]; "184" [ label="4f8c642b53c349c687534bda35db",shape="hexagon",style="filled",color="green" ]; "547E" [ label="46969c4",shape="box",style="filled",color="grey" ]; "185" [ label="30cc206b1878485",shape="hexagon",style="filled",color="green" ]; "549E" [ label="23ad1",shape="box",style="filled",color="grey" ]; "186" [ label="5d69639a5e3bdd3d",shape="hexagon",style="filled",color="green" ]; "551E" [ label="6139fa6adc88d",shape="box",style="filled",color="grey" ]; "187" [ label="b656f0ed2202b8e46eb",shape="hexagon",style="filled",color="green" ]; "553E" [ label="f6e6236b48bc3",shape="box",style="filled",color="grey" ]; "188" [ label="3b566eaa70ed401479d43a9",shape="hexagon",style="filled",color="green" ]; "555E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; "189" [ label="d6125ef42bd9958",shape="hexagon",style="filled",color="green" ]; "557E" [ label="4c6c8c",shape="box",style="filled",color="grey" ]; "190" [ label="dd12f26f8d9bb55",shape="hexagon",style="filled",color="green" ]; "559E" [ label="83c397b8bf7f",shape="box",style="filled",color="grey" ]; "191" [ label="ea890ccca2f7c2107351",shape="hexagon",style="filled",color="green" ]; "561E" [ label="eb8",shape="box",style="filled",color="grey" ]; "192" [ label="84e4f1c582427a98d7b",shape="hexagon",style="filled",color="green" ]; "563E" [ label="eb8",shape="box",style="filled",color="grey" ]; "193" [ label="d378760b814eaecb6efe636e0efc4",shape="hexagon",style="filled",color="green" ]; "565E" [ label="81bcc35f82891",shape="box",style="filled",color="grey" ]; "194" [ label="f722890f70a32dce3baff371a",shape="hexagon",style="filled",color="green" ]; "567E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; "195" [ label="666f11bb45c3a8dcf26e1ed79",shape="hexagon",style="filled",color="green" ]; "569E" [ label="c90f755c8b6612d",shape="box",style="filled",color="grey" ]; "196" [ label="91ecbe29a71f00ed5a3",shape="hexagon",style="filled",color="green" ]; "571E" [ label="0a963fef9",shape="box",style="filled",color="grey" ]; "197" [ label="30c3f3bf8463d3843dc57d8e98",shape="hexagon",style="filled",color="green" ]; "573E" [ label="3089106e3b",shape="box",style="filled",color="grey" ]; "198" [ label="8ea965ab6ee8dedb6c3333e9",shape="hexagon",style="filled",color="green" ]; "575E" [ label="84e4ede82074",shape="box",style="filled",color="grey" ]; "199" [ label="3eecb304bab2136a76deda",shape="hexagon",style="filled",color="green" ]; "577E" [ label="8df",shape="box",style="filled",color="grey" ]; "200" [ label="d886e4b76537a99bc71b8a9331c94",shape="hexagon",style="filled",color="green" ]; "579E" [ label="1172dca23",shape="box",style="filled",color="grey" ]; "201" [ label="dcc5d5e9d6c4e",shape="hexagon",style="filled",color="green" ]; "581E" [ label="a8e9",shape="box",style="filled",color="grey" ]; "202" [ label="8292af691429f8d9ed481ff71ffd",shape="hexagon",style="filled",color="green" ]; "583E" [ label="212af4",shape="box",style="filled",color="grey" ]; "203" [ label="12fcb26b3de00ef98719c2ca",shape="hexagon",style="filled",color="green" ]; "585E" [ label="",shape="box",style="filled",color="grey" ]; "204" [ label="a141a557a60912051f3c135",shape="hexagon",style="filled",color="green" ]; "587E" [ label="",shape="box",style="filled",color="grey" ]; "205" [ label="64eeeddfc34489ff396",shape="hexagon",style="filled",color="green" ]; "751E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; "206" [ label="f5d636e14a6cd716362158d",shape="hexagon",style="filled",color="green" ]; "589E" [ label="32c958c9997",shape="box",style="filled",color="grey" ]; "207" [ label="84e4978afc069d5a1aecbf2b",shape="hexagon",style="filled",color="green" ]; "593E" [ label="56caa96d171a9ac2da7c",shape="box",style="filled",color="grey" ]; "208" [ label="52a6c2063bccd83110c32",shape="hexagon",style="filled",color="green" ]; "597E" [ label="",shape="box",style="filled",color="grey" ]; "209" [ label="46f754ea06f070dbc023e571a876",shape="hexagon",style="filled",color="green" ]; "599E" [ label="ffccaa9e3",shape="box",style="filled",color="grey" ]; "210" [ label="c10cb9baf4dcb43e24",shape="hexagon",style="filled",color="green" ]; "601E" [ label="ac6e99186",shape="box",style="filled",color="grey" ]; "211" [ label="3dafe1619016463f521f",shape="hexagon",style="filled",color="green" ]; "603E" [ label="b9",shape="box",style="filled",color="grey" ]; "212" [ label="0f5db6ce12751ddcc64e",shape="hexagon",style="filled",color="green" ]; "605E" [ label="bb828f1a326",shape="box",style="filled",color="grey" ]; "213" [ label="34c8c8dc0f6e41c7e7b2",shape="hexagon",style="filled",color="green" ]; "607E" [ label="2832ed5cea6",shape="box",style="filled",color="grey" ]; "214" [ label="0a49c95f107c0aa57c9b5748",shape="hexagon",style="filled",color="green" ]; "609E" [ label="",shape="box",style="filled",color="grey" ]; "215" [ label="3b4fdad8e0429d112",shape="hexagon",style="filled",color="green" ]; "611E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "216" [ label="17dafa5ebaafd48440e3",shape="hexagon",style="filled",color="green" ]; "613E" [ label="b5f038f79a3",shape="box",style="filled",color="grey" ]; "217" [ label="f4c69e5e212f89348122e8",shape="hexagon",style="filled",color="green" ]; "615E" [ label="396b16a892fe",shape="box",style="filled",color="grey" ]; "218" [ label="4f2e020854dfacce46a12",shape="hexagon",style="filled",color="green" ]; "617E" [ label="e079d2c",shape="box",style="filled",color="grey" ]; "219" [ label="6448451ac2ceade90715378b",shape="hexagon",style="filled",color="green" ]; "619E" [ label="",shape="box",style="filled",color="grey" ]; "220" [ label="7d7b14baa649330",shape="hexagon",style="filled",color="green" ]; "621E" [ label="77d145b32328880440c7a",shape="box",style="filled",color="grey" ]; "221" [ label="d7c27cc6f7b02a31eb64d",shape="hexagon",style="filled",color="green" ]; "623E" [ label="87a7e69a72412",shape="box",style="filled",color="grey" ]; "222" [ label="8f5a69ece1",shape="hexagon",style="filled",color="green" ]; "752E" [ label="eb9cf6456613d4cd06f7c0894bd6",shape="box",style="filled",color="grey" ]; "223" [ label="eccf7c722ddf",shape="hexagon",style="filled",color="green" ]; "625E" [ label="df61d5f5fc",shape="box",style="filled",color="grey" ]; "224" [ label="86633c26be93ada8b",shape="hexagon",style="filled",color="green" ]; "627E" [ label="08500a6044",shape="box",style="filled",color="grey" ]; "225" [ label="3f9ddf1ffbc0d38b",shape="hexagon",style="filled",color="green" ]; "629E" [ label="07",shape="box",style="filled",color="grey" ]; "226" [ label="e33792703",shape="hexagon",style="filled",color="green" ]; "631E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; "227" [ label="293a225dc56dd1e0564e6bb",shape="hexagon",style="filled",color="green" ]; "633E" [ label="e3aefac763",shape="box",style="filled",color="grey" ]; "228" [ label="57c77c341f94afddef07e6",shape="hexagon",style="filled",color="green" ]; "635E" [ label="5e80f85274",shape="box",style="filled",color="grey" ]; "229" [ label="3bbfc7bfdbbb1ba1bfad7517",shape="hexagon",style="filled",color="green" ]; "637E" [ label="",shape="box",style="filled",color="grey" ]; "230" [ label="a7167d5eb5408b3839903",shape="hexagon",style="filled",color="green" ]; "639E" [ label="8c8b5bde6",shape="box",style="filled",color="grey" ]; "231" [ label="34d7bb6af4fcd8d630de72500c8",shape="hexagon",style="filled",color="green" ]; "641E" [ label="32fe7eee5283",shape="box",style="filled",color="grey" ]; "232" [ label="8e69341faa4489",shape="hexagon",style="filled",color="green" ]; "643E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "233" [ label="459236f07c73814faf5",shape="hexagon",style="filled",color="green" ]; "645E" [ label="18083a711d",shape="box",style="filled",color="grey" ]; "234" [ label="c71aa521578164debd0c5",shape="hexagon",style="filled",color="green" ]; "647E" [ label="78",shape="box",style="filled",color="grey" ]; "235" [ label="a5520019b8a73bc141b5fd416a",shape="hexagon",style="filled",color="green" ]; "649E" [ label="3219b6b71443",shape="box",style="filled",color="grey" ]; "236" [ label="6c89dc59ee7aaebbbd6bb64",shape="hexagon",style="filled",color="green" ]; "651E" [ label="8c8b5bde6",shape="box",style="filled",color="grey" ]; "237" [ label="a9a36ef02f",shape="hexagon",style="filled",color="green" ]; "653E" [ label="6a80cbe",shape="box",style="filled",color="grey" ]; "238" [ label="3db761b596844f133c",shape="hexagon",style="filled",color="green" ]; "655E" [ label="e920b915087",shape="box",style="filled",color="grey" ]; "239" [ label="383db224d7508ef072bea21d0",shape="hexagon",style="filled",color="green" ]; "657E" [ label="975fedfb64df",shape="box",style="filled",color="grey" ]; "240" [ label="8e307415fb435445ced7",shape="hexagon",style="filled",color="green" ]; "659E" [ label="21dff35936370ae5f",shape="box",style="filled",color="grey" ]; "241" [ label="aff6d7896e0e142bbc3e78",shape="hexagon",style="filled",color="green" ]; "661E" [ label="d2498",shape="box",style="filled",color="grey" ]; "242" [ label="e153c6e676c7369b285b4e9033a",shape="hexagon",style="filled",color="green" ]; "663E" [ label="",shape="box",style="filled",color="grey" ]; "243" [ label="f3c4311de0e931f08c232b",shape="hexagon",style="filled",color="green" ]; "665E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; "244" [ label="0c72a426929600000f5",shape="hexagon",style="filled",color="green" ]; "667E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; "245" [ label="38fa61352f5086d2cb51",shape="hexagon",style="filled",color="green" ]; "669E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; "246" [ label="ad1dd724f1c3e",shape="hexagon",style="filled",color="green" ]; "671E" [ label="cab04b7c14a",shape="box",style="filled",color="grey" ]; "247" [ label="11bb8ed3ae227d3acefc",shape="hexagon",style="filled",color="green" ]; "673E" [ label="eb8",shape="box",style="filled",color="grey" ]; "248" [ label="f2c7b3bb4d44f977d0ab8a42351",shape="hexagon",style="filled",color="green" ]; "675E" [ label="",shape="box",style="filled",color="grey" ]; "249" [ label="51e045ca826077ae765",shape="hexagon",style="filled",color="green" ]; "679E" [ label="e842",shape="box",style="filled",color="grey" ]; "250" [ label="aa0adc8978020629574",shape="hexagon",style="filled",color="green" ]; "753E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; "251" [ label="3b6b2c549de670d7bf5fc0ee",shape="hexagon",style="filled",color="green" ]; "681E" [ label="",shape="box",style="filled",color="grey" ]; "252" [ label="5eea496cc301b2a9721",shape="hexagon",style="filled",color="green" ]; "683E" [ label="",shape="box",style="filled",color="grey" ]; "253" [ label="bfc6564cbdeeffac00a141",shape="hexagon",style="filled",color="green" ]; "685E" [ label="3b0a8a1c2e5050bd",shape="box",style="filled",color="grey" ]; "254" [ label="c360aaeb167487c9578a8f",shape="hexagon",style="filled",color="green" ]; "687E" [ label="d",shape="box",style="filled",color="grey" ]; "255" [ label="39d025b265f9790490781cb201",shape="hexagon",style="filled",color="green" ]; "689E" [ label="5e80f85274",shape="box",style="filled",color="grey" ]; "256" [ label="b4ce21e0a3df1d097277d6",shape="hexagon",style="filled",color="green" ]; "691E" [ label="a849f9d352e",shape="box",style="filled",color="grey" ]; "257" [ label="8bdb6a91c6dee925b557c705b3",shape="hexagon",style="filled",color="green" ]; "693E" [ label="53069e384a2",shape="box",style="filled",color="grey" ]; "258" [ label="ac487676a04e4",shape="hexagon",style="filled",color="green" ]; "695E" [ label="a8e9",shape="box",style="filled",color="grey" ]; "259" [ label="18115fa32ff1cb99",shape="hexagon",style="filled",color="green" ]; "697E" [ label="45827dbdd8",shape="box",style="filled",color="grey" ]; "260" [ label="b7b899dc8bc6a32b28cb098fa16",shape="hexagon",style="filled",color="green" ]; "699E" [ label="32fe7eee5283",shape="box",style="filled",color="grey" ]; "261" [ label="b69e426d974e1907e88",shape="hexagon",style="filled",color="green" ]; "703E" [ label="e842",shape="box",style="filled",color="grey" ]; "262" [ label="60d0128bdb61ae40e98638bd1391",shape="hexagon",style="filled",color="green" ]; "705E" [ label="23ad1",shape="box",style="filled",color="grey" ]; "264" [ label="8fb60d769e4c387",shape="hexagon",style="filled",color="green" ]; "709E" [ label="6a8f5bafb1",shape="box",style="filled",color="grey" ]; "265" [ label="e1fa7f549e5a0893bb42da5",shape="hexagon",style="filled",color="green" ]; "711E" [ label="6a3c6921b0aeceda3",shape="box",style="filled",color="grey" ]; "266" [ label="a77622f2ff77ffeeb2",shape="hexagon",style="filled",color="green" ]; "713E" [ label="21dff35936370ae5f",shape="box",style="filled",color="grey" ]; "267" [ label="30d9d350943c0e3ff7594b50",shape="hexagon",style="filled",color="green" ]; "715E" [ label="b5e86c73d1198f",shape="box",style="filled",color="grey" ]; "268" [ label="89ced1a7906d58d687d5a04",shape="hexagon",style="filled",color="green" ]; "717E" [ label="c0174bbe7ae8",shape="box",style="filled",color="grey" ]; "269" [ label="1de26f6b12b0d292f94184",shape="hexagon",style="filled",color="green" ]; "719E" [ label="65fd8495",shape="box",style="filled",color="grey" ]; "270" [ label="26fa7360ab81be9d4434a",shape="hexagon",style="filled",color="green" ]; "721E" [ label="af0268dddd",shape="box",style="filled",color="grey" ]; "272" [ label="4a9d79c960b8d33e39251e5f66",shape="hexagon" ]; "34E" [ label="330342f283ef2",shape="box",style="filled",color="grey" ]; "252E" [ label="3dafb9a29c00",shape="box",style="filled",color="grey" ]; "436E" [ label="8d5137b16a",shape="box",style="filled",color="grey" ]; "274" [ label="10a7d61c201c67a5e78542807cd",shape="hexagon" ]; "59E" [ label="ef6361295eba07",shape="box",style="filled",color="grey" ]; "500E" [ label="a8f0fe2eb7bc1471",shape="box",style="filled",color="grey" ]; "720E" [ label="cfff3acd8e9d",shape="box",style="filled",color="grey" ]; "275" [ label="f8ff39eab120851f143bf19",shape="hexagon" ]; "98E" [ label="4e3cfd27a",shape="box",style="filled",color="grey" ]; "278" [ label="4995c71223c9f6067324d387a2",shape="hexagon" ]; "35E" [ label="57948adb5dead",shape="box",style="filled",color="grey" ]; "488E" [ label="a738ba39",shape="box",style="filled",color="grey" ]; "598E" [ label="be7d637c50c",shape="box",style="filled",color="grey" ]; "604E" [ label="8d52f183ec",shape="box",style="filled",color="grey" ]; "628E" [ label="cef12b6",shape="box",style="filled",color="grey" ]; "279" [ label="b9ae94e6935503603341ecf4",shape="hexagon" ]; "99E" [ label="14a3c17f3d",shape="box",style="filled",color="grey" ]; "280" [ label="fd28c194a46fde909b019c52f",shape="hexagon" ]; "242E" [ label="9fe65061641",shape="box",style="filled",color="grey" ]; "270E" [ label="34d06d1ed6",shape="box",style="filled",color="grey" ]; "272E" [ label="713db1c1",shape="box",style="filled",color="grey" ]; "284E" [ label="90dccb18c0",shape="box",style="filled",color="grey" ]; "286E" [ label="e17fea65",shape="box",style="filled",color="grey" ]; "288E" [ label="aebb7b91b",shape="box",style="filled",color="grey" ]; "586E" [ label="4348f3abcb7716",shape="box",style="filled",color="grey" ]; "763E" [ label="b082f7a5ff",shape="box",style="filled",color="grey" ]; "281" [ label="7c0ab977f5a3c4ab6d625f5033",shape="hexagon" ]; "45E" [ label="20949455f573f",shape="box",style="filled",color="grey" ]; "470E" [ label="c338481d79773",shape="box",style="filled",color="grey" ]; "670E" [ label="e1d01ef89f",shape="box",style="filled",color="grey" ]; "722E" [ label="c4507c22d19",shape="box",style="filled",color="grey" ]; "282" [ label="7e0b91491c8c8566892cd9a0889",shape="hexagon" ]; "103E" [ label="de9efa12873949",shape="box",style="filled",color="grey" ]; "283" [ label="d58478d9c273ad4f4b2e091324",shape="hexagon" ]; "165E" [ label="1a220eb692c",shape="box",style="filled",color="grey" ]; "284" [ label="8be0efdd94a6383e87fbfded4f",shape="hexagon" ]; "39E" [ label="c8a6c26d4fd9f",shape="box",style="filled",color="grey" ]; "224E" [ label="8cbae42a3900",shape="box",style="filled",color="grey" ]; "268E" [ label="fc73",shape="box",style="filled",color="grey" ]; "632E" [ label="",shape="box",style="filled",color="grey" ]; "710E" [ label="102f1",shape="box",style="filled",color="grey" ]; "285" [ label="3aeb78ea51020a44f2d2615436dae",shape="hexagon" ]; "53E" [ label="96deede0c6b44119",shape="box",style="filled",color="grey" ]; "286" [ label="6bbd5b422edb8e358dcc20eecf9",shape="hexagon" ]; "38E" [ label="4f2de229621272",shape="box",style="filled",color="grey" ]; "166E" [ label="d495de0b35f6",shape="box",style="filled",color="grey" ]; "288" [ label="4856000a6802ddfc121ef40432297",shape="hexagon",style="filled",color="#ff0000" ]; "40E" [ label="04904a458422a5b9",shape="box",style="filled",color="grey" ]; "218E" [ label="8cd4d",shape="box",style="filled",color="grey" ]; "244E" [ label="",shape="box",style="filled",color="grey" ]; "246E" [ label="9be88247",shape="box",style="filled",color="grey" ]; "258E" [ label="4f05b",shape="box",style="filled",color="grey" ]; "290E" [ label="8b092",shape="box",style="filled",color="grey" ]; "292E" [ label="c3bbf4",shape="box",style="filled",color="grey" ]; "308E" [ label="6331b3f",shape="box",style="filled",color="grey" ]; "318E" [ label="",shape="box",style="filled",color="grey" ]; "388E" [ label="3711",shape="box",style="filled",color="grey" ]; "472E" [ label="c5255d",shape="box",style="filled",color="grey" ]; "478E" [ label="5c6a2",shape="box",style="filled",color="grey" ]; "566E" [ label="51ec95518d1b3",shape="box",style="filled",color="grey" ]; "570E" [ label="82a65ed4b69",shape="box",style="filled",color="grey" ]; "574E" [ label="05fed5e",shape="box",style="filled",color="grey" ]; "608E" [ label="bf",shape="box",style="filled",color="grey" ]; "614E" [ label="ce",shape="box",style="filled",color="grey" ]; "658E" [ label="1a830d9f",shape="box",style="filled",color="grey" ]; "664E" [ label="",shape="box",style="filled",color="grey" ]; "682E" [ label="",shape="box",style="filled",color="grey" ]; "289" [ label="2e31175cbd52fcd08360fe86d20",shape="hexagon" ]; "41E" [ label="4ad5d68f07981a",shape="box",style="filled",color="grey" ]; "636E" [ label="51192117f9b4",shape="box",style="filled",color="grey" ]; "642E" [ label="6bf214d9e7fa5f2df",shape="box",style="filled",color="grey" ]; "690E" [ label="558d8534f92fddfe",shape="box",style="filled",color="grey" ]; "700E" [ label="6819fd5a6cdd280dd",shape="box",style="filled",color="grey" ]; "290" [ label="3aa0ce5efcf79bc3ecced1886e89",shape="hexagon" ]; "56E" [ label="ff9d64ddf49a20f",shape="box",style="filled",color="grey" ]; "264E" [ label="6c93f24516f01d",shape="box",style="filled",color="grey" ]; "510E" [ label="32b98f11f3d01d6",shape="box",style="filled",color="grey" ]; "718E" [ label="8f7c875500073",shape="box",style="filled",color="grey" ]; "291" [ label="7c1767485953d9c2",shape="hexagon" ]; "66E" [ label="086",shape="box",style="filled",color="grey" ]; "76E" [ label="",shape="box",style="filled",color="grey" ]; "610E" [ label="450d3a2d49cbfd",shape="box",style="filled",color="grey" ]; "292" [ label="9c1305d59c37e9be9f13d7d049c",shape="hexagon" ]; "73E" [ label="817",shape="box",style="filled",color="grey" ]; "293" [ label="efe092824916a5637ee35d439589",shape="hexagon" ]; "49E" [ label="",shape="box",style="filled",color="grey" ]; "214E" [ label="",shape="box",style="filled",color="grey" ]; "216E" [ label="",shape="box",style="filled",color="grey" ]; "236E" [ label="",shape="box",style="filled",color="grey" ]; "278E" [ label="",shape="box",style="filled",color="grey" ]; "358E" [ label="",shape="box",style="filled",color="grey" ]; "398E" [ label="",shape="box",style="filled",color="grey" ]; "400E" [ label="",shape="box",style="filled",color="grey" ]; "402E" [ label="",shape="box",style="filled",color="grey" ]; "404E" [ label="",shape="box",style="filled",color="grey" ]; "406E" [ label="",shape="box",style="filled",color="grey" ]; "408E" [ label="",shape="box",style="filled",color="grey" ]; "412E" [ label="",shape="box",style="filled",color="grey" ]; "438E" [ label="",shape="box",style="filled",color="grey" ]; "448E" [ label="",shape="box",style="filled",color="grey" ]; "476E" [ label="",shape="box",style="filled",color="grey" ]; "504E" [ label="",shape="box",style="filled",color="grey" ]; "552E" [ label="",shape="box",style="filled",color="grey" ]; "634E" [ label="",shape="box",style="filled",color="grey" ]; "768E" [ label="",shape="box",style="filled",color="grey" ]; "295" [ label="70815f0352b43dc1562133ab6eb",shape="hexagon",style="filled",color="#A52A2A" ]; "44E" [ label="ef2d4636934472",shape="box",style="filled",color="grey" ]; "92E" [ label="22bd92e302816",shape="box",style="filled",color="grey" ]; "250E" [ label="74e86",shape="box",style="filled",color="grey" ]; "316E" [ label="",shape="box",style="filled",color="grey" ]; "380E" [ label="",shape="box",style="filled",color="grey" ]; "424E" [ label="c",shape="box",style="filled",color="grey" ]; "442E" [ label="a5a",shape="box",style="filled",color="grey" ]; "446E" [ label="bce",shape="box",style="filled",color="grey" ]; "454E" [ label="",shape="box",style="filled",color="grey" ]; "460E" [ label="",shape="box",style="filled",color="grey" ]; "462E" [ label="",shape="box",style="filled",color="grey" ]; "648E" [ label="",shape="box",style="filled",color="grey" ]; "656E" [ label="e9",shape="box",style="filled",color="grey" ]; "666E" [ label="b701e7",shape="box",style="filled",color="grey" ]; "692E" [ label="f2e7cc",shape="box",style="filled",color="grey" ]; "712E" [ label="8a9eb2806b0aa",shape="box",style="filled",color="grey" ]; "296" [ label="e287d497450664a4c0f4efc338",shape="hexagon",style="filled",color="#ff0000" ]; "47E" [ label="06eff1db45cdf",shape="box",style="filled",color="grey" ]; "330E" [ label="c0f34a600",shape="box",style="filled",color="grey" ]; "514E" [ label="bd7aca295ca",shape="box",style="filled",color="grey" ]; "516E" [ label="0da9135",shape="box",style="filled",color="grey" ]; "518E" [ label="fe821bce",shape="box",style="filled",color="grey" ]; "520E" [ label="e64f22a31",shape="box",style="filled",color="grey" ]; "522E" [ label="46e412a3",shape="box",style="filled",color="grey" ]; "526E" [ label="99da1f8a5",shape="box",style="filled",color="grey" ]; "528E" [ label="0f167280",shape="box",style="filled",color="grey" ]; "530E" [ label="82d201",shape="box",style="filled",color="grey" ]; "532E" [ label="1d529eb4",shape="box",style="filled",color="grey" ]; "534E" [ label="",shape="box",style="filled",color="grey" ]; "536E" [ label="bf141dbce",shape="box",style="filled",color="grey" ]; "538E" [ label="e3fd0c7b3",shape="box",style="filled",color="grey" ]; "540E" [ label="c96cb3",shape="box",style="filled",color="grey" ]; "542E" [ label="0fabab47",shape="box",style="filled",color="grey" ]; "544E" [ label="1b82200",shape="box",style="filled",color="grey" ]; "297" [ label="2ced414a91575a48f2dd29a",shape="hexagon" ]; "46E" [ label="85221d5e9e",shape="box",style="filled",color="grey" ]; "93E" [ label="97a7eea3f",shape="box",style="filled",color="grey" ]; "206E" [ label="4d22e1",shape="box",style="filled",color="grey" ]; "426E" [ label="e65185ca",shape="box",style="filled",color="grey" ]; "550E" [ label="",shape="box",style="filled",color="grey" ]; "706E" [ label="a9012b7bb5",shape="box",style="filled",color="grey" ]; "298" [ label="38f162cf917ce7298663a1f1c607",shape="hexagon" ]; "36E" [ label="a031c9192ae8e75",shape="box",style="filled",color="grey" ]; "95E" [ label="062fc905b9eb35",shape="box",style="filled",color="grey" ]; "364E" [ label="c8fc17180bea86",shape="box",style="filled",color="grey" ]; "394E" [ label="09e64744536c5e1",shape="box",style="filled",color="grey" ]; "420E" [ label="af4a1fac3e2076",shape="box",style="filled",color="grey" ]; "456E" [ label="238805e2194c3",shape="box",style="filled",color="grey" ]; "624E" [ label="73e6ed83012",shape="box",style="filled",color="grey" ]; "299" [ label="549fa15d68f0b3bee6192f888cd8",shape="hexagon" ]; "48E" [ label="d17f8f4eeb8e63d",shape="box",style="filled",color="grey" ]; "168E" [ label="cca7040e47789",shape="box",style="filled",color="grey" ]; "260E" [ label="47ebc3f17",shape="box",style="filled",color="grey" ]; "282E" [ label="cf5a6049ad",shape="box",style="filled",color="grey" ]; "554E" [ label="2a47a6a27",shape="box",style="filled",color="grey" ]; "590E" [ label="eff3468631dd4",shape="box",style="filled",color="grey" ]; "767E" [ label="efb52b499303115c33fd",shape="box",style="filled",color="grey" ]; "300" [ label="8593dcf973b110d00cecdc1e756",shape="hexagon",style="filled",color="#ff7f00" ]; "62E" [ label="472a156cf2b55f",shape="box",style="filled",color="grey" ]; "190E" [ label="647",shape="box",style="filled",color="grey" ]; "226E" [ label="",shape="box",style="filled",color="grey" ]; "238E" [ label="8a",shape="box",style="filled",color="grey" ]; "254E" [ label="",shape="box",style="filled",color="grey" ]; "256E" [ label="",shape="box",style="filled",color="grey" ]; "262E" [ label="",shape="box",style="filled",color="grey" ]; "266E" [ label="e8b",shape="box",style="filled",color="grey" ]; "274E" [ label="",shape="box",style="filled",color="grey" ]; "276E" [ label="f",shape="box",style="filled",color="grey" ]; "294E" [ label="",shape="box",style="filled",color="grey" ]; "296E" [ label="",shape="box",style="filled",color="grey" ]; "310E" [ label="1b34fb150",shape="box",style="filled",color="grey" ]; "320E" [ label="",shape="box",style="filled",color="grey" ]; "322E" [ label="a7d2",shape="box",style="filled",color="grey" ]; "332E" [ label="",shape="box",style="filled",color="grey" ]; "340E" [ label="",shape="box",style="filled",color="grey" ]; "344E" [ label="f55670",shape="box",style="filled",color="grey" ]; "346E" [ label="1ed67841",shape="box",style="filled",color="grey" ]; "348E" [ label="07283",shape="box",style="filled",color="grey" ]; "374E" [ label="73ba1714ee",shape="box",style="filled",color="grey" ]; "378E" [ label="27709106",shape="box",style="filled",color="grey" ]; "452E" [ label="93ea0",shape="box",style="filled",color="grey" ]; "508E" [ label="",shape="box",style="filled",color="grey" ]; "524E" [ label="1d792d81",shape="box",style="filled",color="grey" ]; "612E" [ label="a",shape="box",style="filled",color="grey" ]; "626E" [ label="",shape="box",style="filled",color="grey" ]; "638E" [ label="",shape="box",style="filled",color="grey" ]; "644E" [ label="",shape="box",style="filled",color="grey" ]; "654E" [ label="",shape="box",style="filled",color="grey" ]; "672E" [ label="",shape="box",style="filled",color="grey" ]; "302" [ label="23f94655294d3ff537f2915fa",shape="hexagon" ]; "797E" [ label="",shape="box",style="filled",color="grey" ]; "798E" [ label="a2eab7c9fa641e5f",shape="box",style="filled",color="grey" ]; "303" [ label="a9058241db5b6b6c25569acdf5",shape="hexagon" ]; "52E" [ label="b2babf3244213",shape="box",style="filled",color="grey" ]; "650E" [ label="b354cd9e9dbb0bfa",shape="box",style="filled",color="grey" ]; "304" [ label="bdbdb31bd777fb65dd6dd2d0e7",shape="hexagon" ]; "50E" [ label="3bec1c012b498",shape="box",style="filled",color="grey" ]; "640E" [ label="c54f0fc1e05",shape="box",style="filled",color="grey" ]; "646E" [ label="9ab6c66dc",shape="box",style="filled",color="grey" ]; "652E" [ label="699e3db878047",shape="box",style="filled",color="grey" ]; "306" [ label="1d4ea80c7194689d69f9592186",shape="hexagon" ]; "55E" [ label="8066f87a88f4e",shape="box",style="filled",color="grey" ]; "220E" [ label="3a8173d6c",shape="box",style="filled",color="grey" ]; "338E" [ label="24dfe1a997a",shape="box",style="filled",color="grey" ]; "368E" [ label="65a1",shape="box",style="filled",color="grey" ]; "486E" [ label="59a8b435ccd",shape="box",style="filled",color="grey" ]; "490E" [ label="86e9b0428",shape="box",style="filled",color="grey" ]; "562E" [ label="5a7a610a8a",shape="box",style="filled",color="grey" ]; "564E" [ label="8f143077e",shape="box",style="filled",color="grey" ]; "600E" [ label="6472c2861e0e0dd681",shape="box",style="filled",color="grey" ]; "668E" [ label="f0f45e707",shape="box",style="filled",color="grey" ]; "674E" [ label="95e93c4a13",shape="box",style="filled",color="grey" ]; "698E" [ label="33e1de",shape="box",style="filled",color="grey" ]; "307" [ label="7204950f6233bf9c9e1f00d4a870",shape="hexagon" ]; "107E" [ label="ccceeef40edda78",shape="box",style="filled",color="grey" ]; "308" [ label="a2c4b1d72e2da483a86ae0c62e5",shape="hexagon" ]; "108E" [ label="eedc819a68add6",shape="box",style="filled",color="grey" ]; "309" [ label="f603819d560c5603259aa05dca",shape="hexagon" ]; "109E" [ label="acacfc83af504",shape="box",style="filled",color="grey" ]; "310" [ label="2f43cba12702078b4e0d3bfdae2bc",shape="hexagon" ]; "110E" [ label="3c1edc8de4795936",shape="box",style="filled",color="grey" ]; "311" [ label="8f9cdc26798117dd3e9ee4a8770",shape="hexagon" ]; "58E" [ label="881d373",shape="box",style="filled",color="grey" ]; "234E" [ label="",shape="box",style="filled",color="grey" ]; "300E" [ label="",shape="box",style="filled",color="grey" ]; "306E" [ label="8c7cd9b93b1cbe48e1",shape="box",style="filled",color="grey" ]; "314E" [ label="616d8a7b",shape="box",style="filled",color="grey" ]; "342E" [ label="",shape="box",style="filled",color="grey" ]; "354E" [ label="",shape="box",style="filled",color="grey" ]; "370E" [ label="",shape="box",style="filled",color="grey" ]; "382E" [ label="",shape="box",style="filled",color="grey" ]; "422E" [ label="",shape="box",style="filled",color="grey" ]; "444E" [ label="",shape="box",style="filled",color="grey" ]; "582E" [ label="",shape="box",style="filled",color="grey" ]; "620E" [ label="",shape="box",style="filled",color="grey" ]; "630E" [ label="",shape="box",style="filled",color="grey" ]; "684E" [ label="",shape="box",style="filled",color="grey" ]; "696E" [ label="",shape="box",style="filled",color="grey" ]; "801E" [ label="",shape="box",style="filled",color="grey" ]; "312" [ label="97c9d726e27304311901a52ce",shape="hexagon",style="filled",color="#ff0000" ]; "42E" [ label="1112164c2f7a",shape="box",style="filled",color="grey" ]; "192E" [ label="5c609b12c",shape="box",style="filled",color="grey" ]; "194E" [ label="00265",shape="box",style="filled",color="grey" ]; "196E" [ label="04767",shape="box",style="filled",color="grey" ]; "198E" [ label="f0d99f16",shape="box",style="filled",color="grey" ]; "200E" [ label="",shape="box",style="filled",color="grey" ]; "202E" [ label="6e186b",shape="box",style="filled",color="grey" ]; "204E" [ label="d382",shape="box",style="filled",color="grey" ]; "312E" [ label="c6b5321a",shape="box",style="filled",color="grey" ]; "336E" [ label="",shape="box",style="filled",color="grey" ]; "376E" [ label="",shape="box",style="filled",color="grey" ]; "384E" [ label="aeb8",shape="box",style="filled",color="grey" ]; "386E" [ label="2e53009d4a375",shape="box",style="filled",color="grey" ]; "428E" [ label="",shape="box",style="filled",color="grey" ]; "474E" [ label="",shape="box",style="filled",color="grey" ]; "484E" [ label="",shape="box",style="filled",color="grey" ]; "546E" [ label="dea1d1",shape="box",style="filled",color="grey" ]; "548E" [ label="5a0b4b906a",shape="box",style="filled",color="grey" ]; "314" [ label="1727041c622518c9dd24f7c211",shape="hexagon" ]; "113E" [ label="49704867bee95",shape="box",style="filled",color="grey" ]; "315" [ label="31f2f9aef958979f9f3532b9b",shape="hexagon",style="filled",color="#ff0000" ]; "43E" [ label="47cd70f",shape="box",style="filled",color="grey" ]; "240E" [ label="248df40dae",shape="box",style="filled",color="grey" ]; "298E" [ label="",shape="box",style="filled",color="grey" ]; "334E" [ label="9dd5bf47f",shape="box",style="filled",color="grey" ]; "360E" [ label="",shape="box",style="filled",color="grey" ]; "390E" [ label="28533c",shape="box",style="filled",color="grey" ]; "418E" [ label="",shape="box",style="filled",color="grey" ]; "492E" [ label="a4c7d0",shape="box",style="filled",color="grey" ]; "502E" [ label="4f6f7f",shape="box",style="filled",color="grey" ]; "584E" [ label="7ab64a969",shape="box",style="filled",color="grey" ]; "588E" [ label="",shape="box",style="filled",color="grey" ]; "602E" [ label="69",shape="box",style="filled",color="grey" ]; "606E" [ label="67513d",shape="box",style="filled",color="grey" ]; "662E" [ label="cf",shape="box",style="filled",color="grey" ]; "316" [ label="a54092a3033f7d5e41e0a76c1",shape="hexagon" ]; "51E" [ label="1467f017b74e",shape="box",style="filled",color="grey" ]; "317" [ label="2043b477ac0393676a4309514d0",shape="hexagon" ]; "116E" [ label="bdec8c86db51b9",shape="box",style="filled",color="grey" ]; "318" [ label="ab48d1f65812bc0f8ab6941c3b5",shape="hexagon" ]; "74E" [ label="81",shape="box",style="filled",color="grey" ]; "319" [ label="ca3d67754cf62fdafbf0a1e0",shape="hexagon" ]; "57E" [ label="75b14f1719d",shape="box",style="filled",color="grey" ]; "94E" [ label="62f36ea98a",shape="box",style="filled",color="grey" ]; "350E" [ label="e3a76d31ca59a",shape="box",style="filled",color="grey" ]; "440E" [ label="b3cadc253f7",shape="box",style="filled",color="grey" ]; "466E" [ label="fb58e11",shape="box",style="filled",color="grey" ]; "676E" [ label="8606837526d81cdec",shape="box",style="filled",color="grey" ]; "320" [ label="a7a7f3681dad1250b01cf80bc17",shape="hexagon" ]; "60E" [ label="2c514b0cd8f7d3",shape="box",style="filled",color="grey" ]; "366E" [ label="7e494b",shape="box",style="filled",color="grey" ]; "434E" [ label="15d44ab97",shape="box",style="filled",color="grey" ]; "458E" [ label="78b2d75d00166",shape="box",style="filled",color="grey" ]; "618E" [ label="761e0f72f95",shape="box",style="filled",color="grey" ]; "321" [ label="275afb2b215b966d9fac51b96b9",shape="hexagon" ]; "72E" [ label="ac284d73563",shape="box",style="filled",color="grey" ]; "362E" [ label="7e74e1587f3a4d208",shape="box",style="filled",color="grey" ]; "372E" [ label="ffd1b1af3b6864078f3",shape="box",style="filled",color="grey" ]; "572E" [ label="b38049e00",shape="box",style="filled",color="grey" ]; "322" [ label="c3c93c700edc0cb4f95f03c04",shape="hexagon" ]; "54E" [ label="99237fce1358",shape="box",style="filled",color="grey" ]; "222E" [ label="3dcf8f454",shape="box",style="filled",color="grey" ]; "302E" [ label="c5acd20cad2",shape="box",style="filled",color="grey" ]; "556E" [ label="6c998bf2a5edd",shape="box",style="filled",color="grey" ]; "558E" [ label="4b683",shape="box",style="filled",color="grey" ]; "323" [ label="63a3d4fb9d38a0182be6e39e76",shape="hexagon" ]; "37E" [ label="bba6e6e194ccf",shape="box",style="filled",color="grey" ]; "208E" [ label="01938827",shape="box",style="filled",color="grey" ]; "210E" [ label="9",shape="box",style="filled",color="grey" ]; "352E" [ label="64ef1d545",shape="box",style="filled",color="grey" ]; "450E" [ label="b473716",shape="box",style="filled",color="grey" ]; "568E" [ label="7c13bf753da",shape="box",style="filled",color="grey" ]; "576E" [ label="4e4a79111d",shape="box",style="filled",color="grey" ]; "686E" [ label="af4abb0d6a99",shape="box",style="filled",color="grey" ]; "324" [ label="4399cf78123dedd0dfe9776104",shape="hexagon" ]; "228E" [ label="af9c489df53",shape="box",style="filled",color="grey" ]; "248E" [ label="3703059dbc5a8",shape="box",style="filled",color="grey" ]; "304E" [ label="8a46e6",shape="box",style="filled",color="grey" ]; "468E" [ label="f9d09",shape="box",style="filled",color="grey" ]; "578E" [ label="cd1e9af3dec2",shape="box",style="filled",color="grey" ]; "660E" [ label="9e650e89bb",shape="box",style="filled",color="grey" ]; "688E" [ label="f62b136b2171",shape="box",style="filled",color="grey" ]; "694E" [ label="4727c415d06bcbef",shape="box",style="filled",color="grey" ]; "714E" [ label="38b3b0d9",shape="box",style="filled",color="grey" ]; "766E" [ label="a153512d982",shape="box",style="filled",color="grey" ]; "325" [ label="40f253cd228f7ac2d0aee",shape="hexagon" ]; "97E" [ label="a3ff993",shape="box",style="filled",color="grey" ]; "506E" [ label="7528dd86b",shape="box",style="filled",color="grey" ]; "326" [ label="89a2505da6179a80202d4a6c3",shape="hexagon" ]; "61E" [ label="75eea05672a5",shape="box",style="filled",color="grey" ]; "175E" [ label="3b0c08dd2ca",shape="box",style="filled",color="grey" ]; "482E" [ label="a3781072b",shape="box",style="filled",color="grey" ]; "328" [ label="2601085bde1b2450d64509f36",shape="hexagon" ]; "75E" [ label="0efbd",shape="box",style="filled",color="grey" ]; "580E" [ label="bb92d1da1f38d52f8ff",shape="box",style="filled",color="grey" ]; "329" [ label="5c81103c751345d0ee0f4bd",shape="hexagon" ]; "96E" [ label="b23526044",shape="box",style="filled",color="grey" ]; "330" [ label="fcbd9ad14139718bc6fcc8b4",shape="hexagon" ]; "100E" [ label="73ca543bf1",shape="box",style="filled",color="grey" ]; "170E" [ label="c2f32e2cf9",shape="box",style="filled",color="grey" ]; "333" [ label="44cbb41a9cfc15497eacd294",color="yellow",style="filled",shape="doubleoctagon" ]; "63E" [ label="6a91",shape="box",style="filled",color="grey" ]; "67E" [ label="b074e",shape="box",style="filled",color="grey" ]; "68E" [ label="06209",shape="box",style="filled",color="grey" ]; "69E" [ label="58e3dcc618",shape="box",style="filled",color="grey" ]; "70E" [ label="eee44624da",shape="box",style="filled",color="grey" ]; "71E" [ label="6a91",shape="box",style="filled",color="grey" ]; "802E" [ label="e1e8c",shape="box",style="filled",color="grey" ]; "793E" [ label="",shape="box",style="filled",color="grey" ]; "334" [ label="b46b0756dba915943839e90a55",color="yellow",style="filled",shape="doubleoctagon" ]; "64E" [ label="5fdf",shape="box",style="filled",color="grey" ]; "81E" [ label="3eca1f94dc181",shape="box",style="filled",color="grey" ]; "82E" [ label="6b1bb9b0e",shape="box",style="filled",color="grey" ]; "83E" [ label="a54d477232",shape="box",style="filled",color="grey" ]; "84E" [ label="a164d9f60fbbdd",shape="box",style="filled",color="grey" ]; "85E" [ label="78c8463ea",shape="box",style="filled",color="grey" ]; "86E" [ label="c110ba7",shape="box",style="filled",color="grey" ]; "87E" [ label="3b63cdc0f",shape="box",style="filled",color="grey" ]; "88E" [ label="6f578c5128",shape="box",style="filled",color="grey" ]; "89E" [ label="3e048573fd",shape="box",style="filled",color="grey" ]; "336" [ URL="tes hi",area="test",label="825c7994d5da13afe519861818",color="#ff0000",style="filled",shape="tripleoctagon" ]; "1E" [ label="f4bef37b6a94bfd00",shape="box",style="filled",color="grey" ]; "2E" [ label="d2647f8b6d8661d08",shape="box",style="filled",color="grey" ]; "3E" [ label="964cb56d8f69ff058",shape="box",style="filled",color="grey" ]; "4E" [ label="4f35e206816c3bd22",shape="box",style="filled",color="grey" ]; "5E" [ label="affb2d716803a2d3e",shape="box",style="filled",color="grey" ]; "6E" [ label="e4ae306d9bd669c70",shape="box",style="filled",color="grey" ]; "7E" [ label="4dbf4395236fb03ed",shape="box",style="filled",color="grey" ]; "8E" [ label="15b3ad672cd2f713a",shape="box",style="filled",color="grey" ]; "9E" [ label="8d6e6e0cd9b842a47",shape="box",style="filled",color="grey" ]; "10E" [ label="00d0dd018fe879f96",shape="box",style="filled",color="grey" ]; "11E" [ label="f28b78d4803c",shape="box",style="filled",color="grey" ]; "12E" [ label="2d886da042b5384b4",shape="box",style="filled",color="grey" ]; "13E" [ label="548c0081a62132b44",shape="box",style="filled",color="grey" ]; "14E" [ label="52126553e52385d16",shape="box",style="filled",color="grey" ]; "15E" [ label="9fe716e738eaea34e",shape="box",style="filled",color="grey" ]; "16E" [ label="5782807b5f575e0a8",shape="box",style="filled",color="grey" ]; "17E" [ label="792fd6f9df1fa1e33",shape="box",style="filled",color="grey" ]; "18E" [ label="c471b6fdbfb852661",shape="box",style="filled",color="grey" ]; "19E" [ label="a84844dfd0052b3b5",shape="box",style="filled",color="grey" ]; "20E" [ label="724dabdce9744d061",shape="box",style="filled",color="grey" ]; "21E" [ label="57f7fd2eecec93c8b",shape="box",style="filled",color="grey" ]; "22E" [ label="baba65f670ee34a88",shape="box",style="filled",color="grey" ]; "23E" [ label="ac34ec0f0488b17ec",shape="box",style="filled",color="grey" ]; "24E" [ label="51e74bec5513083bb",shape="box",style="filled",color="grey" ]; "25E" [ label="8e2d970b2f820ee35",shape="box",style="filled",color="grey" ]; "26E" [ label="19398d3cd6b9c674f",shape="box",style="filled",color="grey" ]; "27E" [ label="6505e29f4a11d9530",shape="box",style="filled",color="grey" ]; "28E" [ label="bc4824f07a9d2bba6",shape="box",style="filled",color="grey" ]; "29E" [ label="3acbf8a1537e4e1a1",shape="box",style="filled",color="grey" ]; "30E" [ label="536264e787cf70469",shape="box",style="filled",color="grey" ]; "31E" [ label="d",shape="box",style="filled",color="grey" ]; "65E" [ label="d4b2",shape="box",style="filled",color="grey" ]; "119E" [ label="2a9caef7",shape="box",style="filled",color="grey" ]; "150E" [ label="73d12",shape="box",style="filled",color="grey" ]; "176E" [ label="8896166adc0",shape="box",style="filled",color="grey" ]; "743E" [ label="9f",shape="box",style="filled",color="grey" ]; "744E" [ label="2e1313c",shape="box",style="filled",color="grey" ]; "764E" [ label="cd6",shape="box",style="filled",color="grey" ]; "337" [ label="8304a439f91fc90b3fe8dd35be8",color="yellow",style="filled",shape="doubleoctagon" ]; "120E" [ label="345d26b3f821fe",shape="box",style="filled",color="grey" ]; "121E" [ label="357679fea1e2f",shape="box",style="filled",color="grey" ]; "122E" [ label="c71043819b6a79",shape="box",style="filled",color="grey" ]; "123E" [ label="f9df653b86fb8df",shape="box",style="filled",color="grey" ]; "124E" [ label="020df871874cd",shape="box",style="filled",color="grey" ]; "125E" [ label="4c52fdd8e396692",shape="box",style="filled",color="grey" ]; "126E" [ label="8b98c3ddbe0b336",shape="box",style="filled",color="grey" ]; "127E" [ label="d9f4abac731a9e",shape="box",style="filled",color="grey" ]; "128E" [ label="50f4d9b97aefe",shape="box",style="filled",color="grey" ]; "129E" [ label="ea920d9f5b295119",shape="box",style="filled",color="grey" ]; "130E" [ label="ff5c9b242337c",shape="box",style="filled",color="grey" ]; "131E" [ label="4e12f7ff0918",shape="box",style="filled",color="grey" ]; "132E" [ label="ee3b6be71d59b",shape="box",style="filled",color="grey" ]; "133E" [ label="615cd6b5e3d21c",shape="box",style="filled",color="grey" ]; "134E" [ label="6d52dd1b198bb",shape="box",style="filled",color="grey" ]; "135E" [ label="8c932e1e502dca",shape="box",style="filled",color="grey" ]; "136E" [ label="e84330eef281284a",shape="box",style="filled",color="grey" ]; "137E" [ label="85fc23f1c88b4",shape="box",style="filled",color="grey" ]; "138E" [ label="5997cb0c083422",shape="box",style="filled",color="grey" ]; "339" [ label="b1ffbabb24d71f67d1e0ce23c51",color="yellow",style="filled",shape="doubleoctagon" ]; "151E" [ label="",shape="box",style="filled",color="grey" ]; "153E" [ label="41a8b095c7fd3",shape="box",style="filled",color="grey" ]; "154E" [ label="151bcc2a8de7ea634",shape="box",style="filled",color="grey" ]; "155E" [ label="6c541cad8de1b15",shape="box",style="filled",color="grey" ]; "156E" [ label="c935c7f4d1090ac",shape="box",style="filled",color="grey" ]; "157E" [ label="5ce1fcfb042b",shape="box",style="filled",color="grey" ]; "158E" [ label="531806429433",shape="box",style="filled",color="grey" ]; "159E" [ label="d285240b89cb",shape="box",style="filled",color="grey" ]; "160E" [ label="f22c27c0f0a54e",shape="box",style="filled",color="grey" ]; "161E" [ label="8d0d8314d211d80",shape="box",style="filled",color="grey" ]; "162E" [ label="",shape="box",style="filled",color="grey" ]; "347" [ label="9652ab8b55fdb2a36d1f3fe020",shape="hexagon" ]; "139E" [ label="ef8b68bb5772f3",shape="box",style="filled",color="grey" ]; "795E" [ label="16c3ae29c0bc713",shape="box",style="filled",color="grey" ]; "348" [ label="676bbe7d1c1fb71742df534ce8",shape="hexagon" ]; "799E" [ label="a78eb40ae56aaa9",shape="box",style="filled",color="grey" ]; "800E" [ label="6aae8d25951",shape="box",style="filled",color="grey" ]; "349" [ label="66c0220688a999aaf7f1702d1",shape="hexagon" ]; "141E" [ label="67b6a4dca3a6d",shape="box",style="filled",color="grey" ]; "350" [ label="1322fb0818783e6f9a4f173d47c52",shape="hexagon" ]; "142E" [ label="9696c0950295d8cb5",shape="box",style="filled",color="grey" ]; "678E" [ label="b5c747cc9",shape="box",style="filled",color="grey" ]; "351" [ label="ff07977fca5513098d220d1eb3a",shape="hexagon" ]; "143E" [ label="89a36b13f8c344b",shape="box",style="filled",color="grey" ]; "232E" [ label="56292d076643",shape="box",style="filled",color="grey" ]; "680E" [ label="b5c747cc9",shape="box",style="filled",color="grey" ]; "704E" [ label="431430c49",shape="box",style="filled",color="grey" ]; "352" [ label="a97ef281eafc34b1630d450a1df",shape="hexagon" ]; "144E" [ label="4ff4e275c710c3b",shape="box",style="filled",color="grey" ]; "432E" [ label="d13da6273c9b4da",shape="box",style="filled",color="grey" ]; "353" [ label="72cbb37db85ed3c6eda5dcf8",shape="hexagon" ]; "145E" [ label="33ff9e43d5ab",shape="box",style="filled",color="grey" ]; "354" [ label="0f6784e49852c0be0da23b16",shape="hexagon" ]; "146E" [ label="d4f958b03a98",shape="box",style="filled",color="grey" ]; "396E" [ label="8e24e9b4e",shape="box",style="filled",color="grey" ]; "355" [ label="383f5c65cc6c25aa0a0e6dbb",shape="hexagon" ]; "147E" [ label="1ff8ff951ee9",shape="box",style="filled",color="grey" ]; "356" [ label="f52a45620969f0df4e6ae1dcd7",shape="hexagon" ]; "148E" [ label="5256925081c812",shape="box",style="filled",color="grey" ]; "357" [ label="1f5df34ad75a55a76ef4afa0a47",shape="hexagon" ]; "149E" [ label="26a185dde9a93dd",shape="box",style="filled",color="grey" ]; "358" [ label="45ba4d4c61c9601a26d59e47e0260",shape="hexagon" ]; "167E" [ label="99bd3e7feeb710",shape="box",style="filled",color="grey" ]; "359" [ label="f95344b0ae31693f3a2746597d4",shape="hexagon" ]; "169E" [ label="4e8259973f1f",shape="box",style="filled",color="grey" ]; "360" [ label="b79798b186d6b82288e8be4017d",shape="hexagon" ]; "171E" [ label="63b079bd5847",shape="box",style="filled",color="grey" ]; "361" [ label="47e0067f4d853afd2012f04daa8",shape="hexagon" ]; "172E" [ label="92fb5d4a0805",shape="box",style="filled",color="grey" ]; "362" [ label="f2b6201774de40a29b504b1f716",shape="hexagon" ]; "173E" [ label="d7203571944b",shape="box",style="filled",color="grey" ]; "363" [ label="800422ab81d804eef3e7b91dfba91",shape="hexagon" ]; "174E" [ label="952316a1a5a785",shape="box",style="filled",color="grey" ]; "364" [ label="35b941379e1af658078cffb83a2",shape="hexagon" ]; "101E" [ label="331675c046693f",shape="box",style="filled",color="grey" ]; "365" [ label="d4f7b7fba7afcf7a72397353ec",shape="hexagon" ]; "102E" [ label="32c4684b55361",shape="box",style="filled",color="grey" ]; "367" [ label="e4b45b7a2f884d3734bfd5985656",shape="hexagon" ]; "104E" [ label="1333074979f2d0b",shape="box",style="filled",color="grey" ]; "368" [ label="02c2ba83680ab57f236a33d702",shape="hexagon" ]; "105E" [ label="084d4bfa5853e",shape="box",style="filled",color="grey" ]; "369" [ label="9ccd974150a18260b207b6584caa",shape="hexagon" ]; "106E" [ label="28f7bfc40c88e6a",shape="box",style="filled",color="grey" ]; "374" [ label="653ae44d45dcadeb481b53027d",shape="hexagon" ]; "111E" [ label="8f95518f48528",shape="box",style="filled",color="grey" ]; "375" [ label="d66f542ef1ce4d02c59bec65e",shape="hexagon" ]; "112E" [ label="2ef209509e2a",shape="box",style="filled",color="grey" ]; "377" [ label="a2984b7a11e49440420058c1d80",shape="hexagon" ]; "114E" [ label="ef42184297591d",shape="box",style="filled",color="grey" ]; "378" [ label="31055116421c96b37f72a262bb",shape="hexagon" ]; "115E" [ label="be9c5958196ed",shape="box",style="filled",color="grey" ]; "380" [ label="8462bb2eec1a62d19a15865e57c92",shape="hexagon" ]; "117E" [ label="16a795a1d63f30df",shape="box",style="filled",color="grey" ]; "392E" [ label="85a34bc9616ff",shape="box",style="filled",color="grey" ]; "381" [ label="c21eb96fe100a1efaa128181b7",shape="hexagon" ]; "118E" [ label="f1b0d754353a6",shape="box",style="filled",color="grey" ]; "382" [ label="e3e284d0cc803d98d674f9c3f6d",color="yellow",style="filled",shape="doubleoctagon" ]; "177E" [ label="30417faf916",shape="box",style="filled",color="grey" ]; "178E" [ label="e618df70814a",shape="box",style="filled",color="grey" ]; "179E" [ label="fa90ddf10bd574",shape="box",style="filled",color="grey" ]; "180E" [ label="815cc0b83d733",shape="box",style="filled",color="grey" ]; "181E" [ label="f787d827958c",shape="box",style="filled",color="grey" ]; "182E" [ label="f20f7f513e",shape="box",style="filled",color="grey" ]; "183E" [ label="290907417e13",shape="box",style="filled",color="grey" ]; "184E" [ label="e8386a8e1c8a",shape="box",style="filled",color="grey" ]; "185E" [ label="319bc900218b",shape="box",style="filled",color="grey" ]; "186E" [ label="3ba7afb0e48ae1",shape="box",style="filled",color="grey" ]; "187E" [ label="6ba0776fc8e",shape="box",style="filled",color="grey" ]; "188E" [ label="09847696ae",shape="box",style="filled",color="grey" ]; "383" [ label="908f9ad506eae9ab6ada185e3",color="yellow",style="filled",shape="doubleoctagon" ]; "730E" [ label="65694ca6d575",shape="box",style="filled",color="grey" ]; "732E" [ label="37f57e81ebed95",shape="box",style="filled",color="grey" ]; "741E" [ label="9b6c",shape="box",style="filled",color="grey" ]; "765E" [ label="88ebe2e8782c",shape="box",style="filled",color="grey" ]; "796E" [ label="901b2105a902ee7791",shape="box",style="filled",color="grey" ]; "384" [ label="593caebf2037317648bb451aa79",color="yellow",style="filled",shape="doubleoctagon" ]; "726E" [ label="351dd0aefe480c",shape="box",style="filled",color="grey" ]; "728E" [ label="56e1a896",shape="box",style="filled",color="grey" ]; "742E" [ label="5ba4693031",shape="box",style="filled",color="grey" ]; "385" [ label="717c254aeffbb527dabfc",shape="hexagon" ]; "328E" [ label="123cc6d1ac",shape="box",style="filled",color="grey" ]; "496E" [ label="",shape="box",style="filled",color="grey" ]; "594E" [ label="7f8c557bcf3889",shape="box",style="filled",color="grey" ]; "622E" [ label="da3d5",shape="box",style="filled",color="grey" ]; "754E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; "755E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; "756E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; "757E" [ label="68d8993e61d8c82cd29e8d0182b0",shape="box",style="filled",color="grey" ]; "758E" [ label="4c865eec228e41e7f4e5fc68a9a6",shape="box",style="filled",color="grey" ]; "759E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; "760E" [ label="8983ffbc30deb364dd92c3ad85c9",shape="box",style="filled",color="grey" ]; "761E" [ label="eb9cf6456613d4cd06f7c0894bd6",shape="box",style="filled",color="grey" ]; "762E" [ label="1e2298c4bb",shape="box",style="filled",color="grey" ]; "1" -> "189E" [ label=" ",color="blue",arrowhead="dot" ]; "1" -> "790E" [ label=" ",color="blue",arrowhead="dot" ]; "2" -> "191E" [ label=" ",color="blue",arrowhead="dot" ]; "3" -> "193E" [ label=" ",color="blue",arrowhead="dot" ]; "4" -> "195E" [ label=" ",color="blue",arrowhead="dot" ]; "5" -> "197E" [ label=" ",color="blue",arrowhead="dot" ]; "6" -> "199E" [ label=" ",color="blue",arrowhead="dot" ]; "7" -> "201E" [ label=" ",color="blue",arrowhead="dot" ]; "8" -> "203E" [ label=" ",color="blue",arrowhead="dot" ]; "9" -> "725E" [ label=" ",color="blue",arrowhead="dot" ]; "9" -> "785E" [ label=" ",color="blue",arrowhead="dot" ]; "10" -> "205E" [ label=" ",color="blue",arrowhead="dot" ]; "11" -> "207E" [ label=" ",color="blue",arrowhead="dot" ]; "12" -> "209E" [ label=" ",color="blue",arrowhead="dot" ]; "13" -> "211E" [ label=" ",color="blue",arrowhead="dot" ]; "14" -> "213E" [ label=" ",color="blue",arrowhead="dot" ]; "15" -> "215E" [ label=" ",color="blue",arrowhead="dot" ]; "16" -> "727E" [ label=" ",color="blue",arrowhead="dot" ]; "16" -> "784E" [ label=" ",color="blue",arrowhead="dot" ]; "17" -> "217E" [ label=" ",color="blue",arrowhead="dot" ]; "17" -> "787E" [ label=" ",color="blue",arrowhead="dot" ]; "18" -> "219E" [ label=" ",color="blue",arrowhead="dot" ]; "19" -> "221E" [ label=" ",color="blue",arrowhead="dot" ]; "20" -> "223E" [ label=" ",color="blue",arrowhead="dot" ]; "21" -> "225E" [ label=" ",color="blue",arrowhead="dot" ]; "22" -> "227E" [ label=" ",color="blue",arrowhead="dot" ]; "22" -> "792E" [ label=" ",color="blue",arrowhead="dot" ]; "23" -> "231E" [ label=" ",color="blue",arrowhead="dot" ]; "24" -> "233E" [ label=" ",color="blue",arrowhead="dot" ]; "25" -> "235E" [ label=" ",color="blue",arrowhead="dot" ]; "26" -> "237E" [ label=" ",color="blue",arrowhead="dot" ]; "27" -> "239E" [ label=" ",color="blue",arrowhead="dot" ]; "27" -> "783E" [ label=" ",color="blue",arrowhead="dot" ]; "28" -> "241E" [ label=" ",color="blue",arrowhead="dot" ]; "28" -> "791E" [ label=" ",color="blue",arrowhead="dot" ]; "29" -> "243E" [ label=" ",color="blue",arrowhead="dot" ]; "30" -> "245E" [ label=" ",color="blue",arrowhead="dot" ]; "31" -> "247E" [ label=" ",color="blue",arrowhead="dot" ]; "32" -> "249E" [ label=" ",color="blue",arrowhead="dot" ]; "33" -> "251E" [ label=" ",color="blue",arrowhead="dot" ]; "34" -> "253E" [ label=" ",color="blue",arrowhead="dot" ]; "35" -> "255E" [ label=" ",color="blue",arrowhead="dot" ]; "36" -> "257E" [ label=" ",color="blue",arrowhead="dot" ]; "37" -> "259E" [ label=" ",color="blue",arrowhead="dot" ]; "38" -> "261E" [ label=" ",color="blue",arrowhead="dot" ]; "39" -> "263E" [ label=" ",color="blue",arrowhead="dot" ]; "40" -> "265E" [ label=" ",color="blue",arrowhead="dot" ]; "41" -> "267E" [ label=" ",color="blue",arrowhead="dot" ]; "42" -> "269E" [ label=" ",color="blue",arrowhead="dot" ]; "43" -> "271E" [ label=" ",color="blue",arrowhead="dot" ]; "44" -> "273E" [ label=" ",color="blue",arrowhead="dot" ]; "45" -> "275E" [ label=" ",color="blue",arrowhead="dot" ]; "46" -> "277E" [ label=" ",color="blue",arrowhead="dot" ]; "47" -> "279E" [ label=" ",color="blue",arrowhead="dot" ]; "48" -> "281E" [ label=" ",color="blue",arrowhead="dot" ]; "49" -> "283E" [ label=" ",color="blue",arrowhead="dot" ]; "50" -> "285E" [ label=" ",color="blue",arrowhead="dot" ]; "51" -> "287E" [ label=" ",color="blue",arrowhead="dot" ]; "52" -> "289E" [ label=" ",color="blue",arrowhead="dot" ]; "53" -> "291E" [ label=" ",color="blue",arrowhead="dot" ]; "54" -> "293E" [ label=" ",color="blue",arrowhead="dot" ]; "55" -> "745E" [ label=" ",color="blue",arrowhead="dot" ]; "56" -> "295E" [ label=" ",color="blue",arrowhead="dot" ]; "57" -> "297E" [ label=" ",color="blue",arrowhead="dot" ]; "58" -> "299E" [ label=" ",color="blue",arrowhead="dot" ]; "59" -> "301E" [ label=" ",color="blue",arrowhead="dot" ]; "59" -> "789E" [ label=" ",color="blue",arrowhead="dot" ]; "60" -> "303E" [ label=" ",color="blue",arrowhead="dot" ]; "61" -> "305E" [ label=" ",color="blue",arrowhead="dot" ]; "62" -> "307E" [ label=" ",color="blue",arrowhead="dot" ]; "63" -> "309E" [ label=" ",color="blue",arrowhead="dot" ]; "64" -> "311E" [ label=" ",color="blue",arrowhead="dot" ]; "65" -> "313E" [ label=" ",color="blue",arrowhead="dot" ]; "66" -> "315E" [ label=" ",color="blue",arrowhead="dot" ]; "67" -> "317E" [ label=" ",color="blue",arrowhead="dot" ]; "68" -> "319E" [ label=" ",color="blue",arrowhead="dot" ]; "69" -> "746E" [ label=" ",color="blue",arrowhead="dot" ]; "70" -> "321E" [ label=" ",color="blue",arrowhead="dot" ]; "71" -> "327E" [ label=" ",color="blue",arrowhead="dot" ]; "72" -> "329E" [ label=" ",color="blue",arrowhead="dot" ]; "73" -> "331E" [ label=" ",color="blue",arrowhead="dot" ]; "74" -> "333E" [ label=" ",color="blue",arrowhead="dot" ]; "75" -> "335E" [ label=" ",color="blue",arrowhead="dot" ]; "76" -> "337E" [ label=" ",color="blue",arrowhead="dot" ]; "77" -> "339E" [ label=" ",color="blue",arrowhead="dot" ]; "78" -> "341E" [ label=" ",color="blue",arrowhead="dot" ]; "79" -> "343E" [ label=" ",color="blue",arrowhead="dot" ]; "80" -> "345E" [ label=" ",color="blue",arrowhead="dot" ]; "81" -> "347E" [ label=" ",color="blue",arrowhead="dot" ]; "82" -> "349E" [ label=" ",color="blue",arrowhead="dot" ]; "83" -> "351E" [ label=" ",color="blue",arrowhead="dot" ]; "84" -> "353E" [ label=" ",color="blue",arrowhead="dot" ]; "85" -> "355E" [ label=" ",color="blue",arrowhead="dot" ]; "85" -> "788E" [ label=" ",color="blue",arrowhead="dot" ]; "86" -> "357E" [ label=" ",color="blue",arrowhead="dot" ]; "87" -> "359E" [ label=" ",color="blue",arrowhead="dot" ]; "88" -> "361E" [ label=" ",color="blue",arrowhead="dot" ]; "89" -> "363E" [ label=" ",color="blue",arrowhead="dot" ]; "90" -> "365E" [ label=" ",color="blue",arrowhead="dot" ]; "91" -> "367E" [ label=" ",color="blue",arrowhead="dot" ]; "92" -> "369E" [ label=" ",color="blue",arrowhead="dot" ]; "93" -> "729E" [ label=" ",color="blue",arrowhead="dot" ]; "94" -> "371E" [ label=" ",color="blue",arrowhead="dot" ]; "95" -> "373E" [ label=" ",color="blue",arrowhead="dot" ]; "96" -> "375E" [ label=" ",color="blue",arrowhead="dot" ]; "97" -> "747E" [ label=" ",color="blue",arrowhead="dot" ]; "98" -> "377E" [ label=" ",color="blue",arrowhead="dot" ]; "99" -> "379E" [ label=" ",color="blue",arrowhead="dot" ]; "100" -> "381E" [ label=" ",color="blue",arrowhead="dot" ]; "101" -> "383E" [ label=" ",color="blue",arrowhead="dot" ]; "102" -> "385E" [ label=" ",color="blue",arrowhead="dot" ]; "103" -> "387E" [ label=" ",color="blue",arrowhead="dot" ]; "104" -> "389E" [ label=" ",color="blue",arrowhead="dot" ]; "105" -> "391E" [ label=" ",color="blue",arrowhead="dot" ]; "106" -> "393E" [ label=" ",color="blue",arrowhead="dot" ]; "107" -> "395E" [ label=" ",color="blue",arrowhead="dot" ]; "108" -> "397E" [ label=" ",color="blue",arrowhead="dot" ]; "109" -> "399E" [ label=" ",color="blue",arrowhead="dot" ]; "110" -> "401E" [ label=" ",color="blue",arrowhead="dot" ]; "111" -> "403E" [ label=" ",color="blue",arrowhead="dot" ]; "112" -> "405E" [ label=" ",color="blue",arrowhead="dot" ]; "113" -> "407E" [ label=" ",color="blue",arrowhead="dot" ]; "114" -> "409E" [ label=" ",color="blue",arrowhead="dot" ]; "115" -> "411E" [ label=" ",color="blue",arrowhead="dot" ]; "116" -> "413E" [ label=" ",color="blue",arrowhead="dot" ]; "117" -> "415E" [ label=" ",color="blue",arrowhead="dot" ]; "118" -> "417E" [ label=" ",color="blue",arrowhead="dot" ]; "119" -> "419E" [ label=" ",color="blue",arrowhead="dot" ]; "120" -> "421E" [ label=" ",color="blue",arrowhead="dot" ]; "121" -> "423E" [ label=" ",color="blue",arrowhead="dot" ]; "122" -> "748E" [ label=" ",color="blue",arrowhead="dot" ]; "123" -> "425E" [ label=" ",color="blue",arrowhead="dot" ]; "124" -> "427E" [ label=" ",color="blue",arrowhead="dot" ]; "124" -> "786E" [ label=" ",color="blue",arrowhead="dot" ]; "125" -> "431E" [ label=" ",color="blue",arrowhead="dot" ]; "126" -> "433E" [ label=" ",color="blue",arrowhead="dot" ]; "127" -> "435E" [ label=" ",color="blue",arrowhead="dot" ]; "128" -> "437E" [ label=" ",color="blue",arrowhead="dot" ]; "129" -> "439E" [ label=" ",color="blue",arrowhead="dot" ]; "130" -> "441E" [ label=" ",color="blue",arrowhead="dot" ]; "131" -> "443E" [ label=" ",color="blue",arrowhead="dot" ]; "132" -> "445E" [ label=" ",color="blue",arrowhead="dot" ]; "133" -> "749E" [ label=" ",color="blue",arrowhead="dot" ]; "134" -> "447E" [ label=" ",color="blue",arrowhead="dot" ]; "135" -> "449E" [ label=" ",color="blue",arrowhead="dot" ]; "135" -> "769E" [ label=" ",color="blue",arrowhead="dot" ]; "135" -> "770E" [ label=" ",color="blue",arrowhead="dot" ]; "136" -> "451E" [ label=" ",color="blue",arrowhead="dot" ]; "137" -> "453E" [ label=" ",color="blue",arrowhead="dot" ]; "138" -> "455E" [ label=" ",color="blue",arrowhead="dot" ]; "139" -> "457E" [ label=" ",color="blue",arrowhead="dot" ]; "140" -> "459E" [ label=" ",color="blue",arrowhead="dot" ]; "141" -> "461E" [ label=" ",color="blue",arrowhead="dot" ]; "142" -> "463E" [ label=" ",color="blue",arrowhead="dot" ]; "143" -> "465E" [ label=" ",color="blue",arrowhead="dot" ]; "144" -> "467E" [ label=" ",color="blue",arrowhead="dot" ]; "145" -> "469E" [ label=" ",color="blue",arrowhead="dot" ]; "146" -> "471E" [ label=" ",color="blue",arrowhead="dot" ]; "147" -> "473E" [ label=" ",color="blue",arrowhead="dot" ]; "148" -> "475E" [ label=" ",color="blue",arrowhead="dot" ]; "149" -> "477E" [ label=" ",color="blue",arrowhead="dot" ]; "150" -> "479E" [ label=" ",color="blue",arrowhead="dot" ]; "151" -> "481E" [ label=" ",color="blue",arrowhead="dot" ]; "152" -> "483E" [ label=" ",color="blue",arrowhead="dot" ]; "153" -> "731E" [ label=" ",color="blue",arrowhead="dot" ]; "154" -> "750E" [ label=" ",color="blue",arrowhead="dot" ]; "155" -> "485E" [ label=" ",color="blue",arrowhead="dot" ]; "156" -> "487E" [ label=" ",color="blue",arrowhead="dot" ]; "157" -> "489E" [ label=" ",color="blue",arrowhead="dot" ]; "158" -> "491E" [ label=" ",color="blue",arrowhead="dot" ]; "159" -> "495E" [ label=" ",color="blue",arrowhead="dot" ]; "160" -> "499E" [ label=" ",color="blue",arrowhead="dot" ]; "161" -> "501E" [ label=" ",color="blue",arrowhead="dot" ]; "162" -> "503E" [ label=" ",color="blue",arrowhead="dot" ]; "163" -> "505E" [ label=" ",color="blue",arrowhead="dot" ]; "164" -> "507E" [ label=" ",color="blue",arrowhead="dot" ]; "165" -> "509E" [ label=" ",color="blue",arrowhead="dot" ]; "166" -> "511E" [ label=" ",color="blue",arrowhead="dot" ]; "167" -> "513E" [ label=" ",color="blue",arrowhead="dot" ]; "168" -> "515E" [ label=" ",color="blue",arrowhead="dot" ]; "169" -> "517E" [ label=" ",color="blue",arrowhead="dot" ]; "170" -> "519E" [ label=" ",color="blue",arrowhead="dot" ]; "171" -> "521E" [ label=" ",color="blue",arrowhead="dot" ]; "172" -> "523E" [ label=" ",color="blue",arrowhead="dot" ]; "173" -> "525E" [ label=" ",color="blue",arrowhead="dot" ]; "174" -> "527E" [ label=" ",color="blue",arrowhead="dot" ]; "175" -> "529E" [ label=" ",color="blue",arrowhead="dot" ]; "176" -> "531E" [ label=" ",color="blue",arrowhead="dot" ]; "177" -> "533E" [ label=" ",color="blue",arrowhead="dot" ]; "178" -> "535E" [ label=" ",color="blue",arrowhead="dot" ]; "179" -> "537E" [ label=" ",color="blue",arrowhead="dot" ]; "180" -> "539E" [ label=" ",color="blue",arrowhead="dot" ]; "181" -> "541E" [ label=" ",color="blue",arrowhead="dot" ]; "182" -> "543E" [ label=" ",color="blue",arrowhead="dot" ]; "183" -> "545E" [ label=" ",color="blue",arrowhead="dot" ]; "184" -> "547E" [ label=" ",color="blue",arrowhead="dot" ]; "185" -> "549E" [ label=" ",color="blue",arrowhead="dot" ]; "186" -> "551E" [ label=" ",color="blue",arrowhead="dot" ]; "187" -> "553E" [ label=" ",color="blue",arrowhead="dot" ]; "188" -> "555E" [ label=" ",color="blue",arrowhead="dot" ]; "189" -> "557E" [ label=" ",color="blue",arrowhead="dot" ]; "190" -> "559E" [ label=" ",color="blue",arrowhead="dot" ]; "191" -> "561E" [ label=" ",color="blue",arrowhead="dot" ]; "192" -> "563E" [ label=" ",color="blue",arrowhead="dot" ]; "193" -> "565E" [ label=" ",color="blue",arrowhead="dot" ]; "194" -> "567E" [ label=" ",color="blue",arrowhead="dot" ]; "195" -> "569E" [ label=" ",color="blue",arrowhead="dot" ]; "196" -> "571E" [ label=" ",color="blue",arrowhead="dot" ]; "197" -> "573E" [ label=" ",color="blue",arrowhead="dot" ]; "198" -> "575E" [ label=" ",color="blue",arrowhead="dot" ]; "199" -> "577E" [ label=" ",color="blue",arrowhead="dot" ]; "200" -> "579E" [ label=" ",color="blue",arrowhead="dot" ]; "201" -> "581E" [ label=" ",color="blue",arrowhead="dot" ]; "202" -> "583E" [ label=" ",color="blue",arrowhead="dot" ]; "203" -> "585E" [ label=" ",color="blue",arrowhead="dot" ]; "204" -> "587E" [ label=" ",color="blue",arrowhead="dot" ]; "205" -> "751E" [ label=" ",color="blue",arrowhead="dot" ]; "206" -> "589E" [ label=" ",color="blue",arrowhead="dot" ]; "207" -> "593E" [ label=" ",color="blue",arrowhead="dot" ]; "208" -> "597E" [ label=" ",color="blue",arrowhead="dot" ]; "209" -> "599E" [ label=" ",color="blue",arrowhead="dot" ]; "210" -> "601E" [ label=" ",color="blue",arrowhead="dot" ]; "211" -> "603E" [ label=" ",color="blue",arrowhead="dot" ]; "212" -> "605E" [ label=" ",color="blue",arrowhead="dot" ]; "213" -> "607E" [ label=" ",color="blue",arrowhead="dot" ]; "214" -> "609E" [ label=" ",color="blue",arrowhead="dot" ]; "215" -> "611E" [ label=" ",color="blue",arrowhead="dot" ]; "216" -> "613E" [ label=" ",color="blue",arrowhead="dot" ]; "217" -> "615E" [ label=" ",color="blue",arrowhead="dot" ]; "218" -> "617E" [ label=" ",color="blue",arrowhead="dot" ]; "219" -> "619E" [ label=" ",color="blue",arrowhead="dot" ]; "220" -> "621E" [ label=" ",color="blue",arrowhead="dot" ]; "221" -> "623E" [ label=" ",color="blue",arrowhead="dot" ]; "222" -> "752E" [ label=" ",color="blue",arrowhead="dot" ]; "223" -> "625E" [ label=" ",color="blue",arrowhead="dot" ]; "224" -> "627E" [ label=" ",color="blue",arrowhead="dot" ]; "225" -> "629E" [ label=" ",color="blue",arrowhead="dot" ]; "226" -> "631E" [ label=" ",color="blue",arrowhead="dot" ]; "227" -> "633E" [ label=" ",color="blue",arrowhead="dot" ]; "228" -> "635E" [ label=" ",color="blue",arrowhead="dot" ]; "229" -> "637E" [ label=" ",color="blue",arrowhead="dot" ]; "230" -> "639E" [ label=" ",color="blue",arrowhead="dot" ]; "231" -> "641E" [ label=" ",color="blue",arrowhead="dot" ]; "232" -> "643E" [ label=" ",color="blue",arrowhead="dot" ]; "233" -> "645E" [ label=" ",color="blue",arrowhead="dot" ]; "234" -> "647E" [ label=" ",color="blue",arrowhead="dot" ]; "235" -> "649E" [ label=" ",color="blue",arrowhead="dot" ]; "236" -> "651E" [ label=" ",color="blue",arrowhead="dot" ]; "237" -> "653E" [ label=" ",color="blue",arrowhead="dot" ]; "238" -> "655E" [ label=" ",color="blue",arrowhead="dot" ]; "239" -> "657E" [ label=" ",color="blue",arrowhead="dot" ]; "240" -> "659E" [ label=" ",color="blue",arrowhead="dot" ]; "241" -> "661E" [ label=" ",color="blue",arrowhead="dot" ]; "242" -> "663E" [ label=" ",color="blue",arrowhead="dot" ]; "243" -> "665E" [ label=" ",color="blue",arrowhead="dot" ]; "244" -> "667E" [ label=" ",color="blue",arrowhead="dot" ]; "245" -> "669E" [ label=" ",color="blue",arrowhead="dot" ]; "246" -> "671E" [ label=" ",color="blue",arrowhead="dot" ]; "247" -> "673E" [ label=" ",color="blue",arrowhead="dot" ]; "248" -> "675E" [ label=" ",color="blue",arrowhead="dot" ]; "249" -> "679E" [ label=" ",color="blue",arrowhead="dot" ]; "250" -> "753E" [ label=" ",color="blue",arrowhead="dot" ]; "251" -> "681E" [ label=" ",color="blue",arrowhead="dot" ]; "252" -> "683E" [ label=" ",color="blue",arrowhead="dot" ]; "253" -> "685E" [ label=" ",color="blue",arrowhead="dot" ]; "254" -> "687E" [ label=" ",color="blue",arrowhead="dot" ]; "255" -> "689E" [ label=" ",color="blue",arrowhead="dot" ]; "256" -> "691E" [ label=" ",color="blue",arrowhead="dot" ]; "257" -> "693E" [ label=" ",color="blue",arrowhead="dot" ]; "258" -> "695E" [ label=" ",color="blue",arrowhead="dot" ]; "259" -> "697E" [ label=" ",color="blue",arrowhead="dot" ]; "260" -> "699E" [ label=" ",color="blue",arrowhead="dot" ]; "261" -> "703E" [ label=" ",color="blue",arrowhead="dot" ]; "262" -> "705E" [ label=" ",color="blue",arrowhead="dot" ]; "264" -> "709E" [ label=" ",color="blue",arrowhead="dot" ]; "265" -> "711E" [ label=" ",color="blue",arrowhead="dot" ]; "266" -> "713E" [ label=" ",color="blue",arrowhead="dot" ]; "267" -> "715E" [ label=" ",color="blue",arrowhead="dot" ]; "268" -> "717E" [ label=" ",color="blue",arrowhead="dot" ]; "269" -> "719E" [ label=" ",color="blue",arrowhead="dot" ]; "270" -> "721E" [ label=" ",color="blue",arrowhead="dot" ]; "272" -> "34E" [ label=" ",color="blue",arrowhead="dot" ]; "272" -> "252E" [ label=" ",color="blue",arrowhead="dot" ]; "272" -> "436E" [ label=" ",color="blue",arrowhead="dot" ]; "274" -> "59E" [ label=" ",color="blue",arrowhead="dot" ]; "274" -> "500E" [ label=" ",color="blue",arrowhead="dot" ]; "274" -> "720E" [ label=" ",color="blue",arrowhead="dot" ]; "275" -> "98E" [ label=" ",color="blue",arrowhead="dot" ]; "278" -> "35E" [ label=" ",color="blue",arrowhead="dot" ]; "278" -> "488E" [ label=" ",color="blue",arrowhead="dot" ]; "278" -> "598E" [ label=" ",color="blue",arrowhead="dot" ]; "278" -> "604E" [ label=" ",color="blue",arrowhead="dot" ]; "278" -> "628E" [ label=" ",color="blue",arrowhead="dot" ]; "279" -> "99E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "242E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "270E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "272E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "284E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "286E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "288E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "586E" [ label=" ",color="blue",arrowhead="dot" ]; "280" -> "763E" [ label=" ",color="blue",arrowhead="dot" ]; "281" -> "45E" [ label=" ",color="blue",arrowhead="dot" ]; "281" -> "470E" [ label=" ",color="blue",arrowhead="dot" ]; "281" -> "670E" [ label=" ",color="blue",arrowhead="dot" ]; "281" -> "722E" [ label=" ",color="blue",arrowhead="dot" ]; "282" -> "103E" [ label=" ",color="blue",arrowhead="dot" ]; "283" -> "165E" [ label=" ",color="blue",arrowhead="dot" ]; "284" -> "39E" [ label=" ",color="blue",arrowhead="dot" ]; "284" -> "224E" [ label=" ",color="blue",arrowhead="dot" ]; "284" -> "268E" [ label=" ",color="blue",arrowhead="dot" ]; "284" -> "632E" [ label=" ",color="blue",arrowhead="dot" ]; "284" -> "710E" [ label=" ",color="blue",arrowhead="dot" ]; "285" -> "53E" [ label=" ",color="blue",arrowhead="dot" ]; "286" -> "38E" [ label=" ",color="blue",arrowhead="dot" ]; "286" -> "166E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "40E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "218E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "244E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "246E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "258E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "290E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "292E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "308E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "318E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "388E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "472E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "478E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "566E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "570E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "574E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "608E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "614E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "658E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "664E" [ label=" ",color="blue",arrowhead="dot" ]; "288" -> "682E" [ label=" ",color="blue",arrowhead="dot" ]; "289" -> "41E" [ label=" ",color="blue",arrowhead="dot" ]; "289" -> "636E" [ label=" ",color="blue",arrowhead="dot" ]; "289" -> "642E" [ label=" ",color="blue",arrowhead="dot" ]; "289" -> "690E" [ label=" ",color="blue",arrowhead="dot" ]; "289" -> "700E" [ label=" ",color="blue",arrowhead="dot" ]; "290" -> "56E" [ label=" ",color="blue",arrowhead="dot" ]; "290" -> "264E" [ label=" ",color="blue",arrowhead="dot" ]; "290" -> "510E" [ label=" ",color="blue",arrowhead="dot" ]; "290" -> "718E" [ label=" ",color="blue",arrowhead="dot" ]; "291" -> "66E" [ label=" ",color="blue",arrowhead="dot" ]; "291" -> "76E" [ label=" ",color="blue",arrowhead="dot" ]; "291" -> "610E" [ label=" ",color="blue",arrowhead="dot" ]; "292" -> "73E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "49E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "214E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "216E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "236E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "278E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "358E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "398E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "400E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "402E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "404E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "406E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "408E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "412E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "438E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "448E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "476E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "504E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "552E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "634E" [ label=" ",color="blue",arrowhead="dot" ]; "293" -> "768E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "44E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "92E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "250E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "316E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "380E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "424E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "442E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "446E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "454E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "460E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "462E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "648E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "656E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "666E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "692E" [ label=" ",color="blue",arrowhead="dot" ]; "295" -> "712E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "47E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "330E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "514E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "516E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "518E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "520E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "522E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "526E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "528E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "530E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "532E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "534E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "536E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "538E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "540E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "542E" [ label=" ",color="blue",arrowhead="dot" ]; "296" -> "544E" [ label=" ",color="blue",arrowhead="dot" ]; "297" -> "46E" [ label=" ",color="blue",arrowhead="dot" ]; "297" -> "93E" [ label=" ",color="blue",arrowhead="dot" ]; "297" -> "206E" [ label=" ",color="blue",arrowhead="dot" ]; "297" -> "426E" [ label=" ",color="blue",arrowhead="dot" ]; "297" -> "550E" [ label=" ",color="blue",arrowhead="dot" ]; "297" -> "706E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "36E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "95E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "364E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "394E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "420E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "456E" [ label=" ",color="blue",arrowhead="dot" ]; "298" -> "624E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "48E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "168E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "260E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "282E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "554E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "590E" [ label=" ",color="blue",arrowhead="dot" ]; "299" -> "767E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "62E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "190E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "226E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "238E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "254E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "256E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "262E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "266E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "274E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "276E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "294E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "296E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "310E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "320E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "322E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "332E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "340E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "344E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "346E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "348E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "374E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "378E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "452E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "508E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "524E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "612E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "626E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "638E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "644E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "654E" [ label=" ",color="blue",arrowhead="dot" ]; "300" -> "672E" [ label=" ",color="blue",arrowhead="dot" ]; "302" -> "797E" [ label=" ",color="blue",arrowhead="dot" ]; "302" -> "798E" [ label=" ",color="blue",arrowhead="dot" ]; "303" -> "52E" [ label=" ",color="blue",arrowhead="dot" ]; "303" -> "650E" [ label=" ",color="blue",arrowhead="dot" ]; "304" -> "50E" [ label=" ",color="blue",arrowhead="dot" ]; "304" -> "640E" [ label=" ",color="blue",arrowhead="dot" ]; "304" -> "646E" [ label=" ",color="blue",arrowhead="dot" ]; "304" -> "652E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "55E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "220E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "338E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "368E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "486E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "490E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "562E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "564E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "600E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "668E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "674E" [ label=" ",color="blue",arrowhead="dot" ]; "306" -> "698E" [ label=" ",color="blue",arrowhead="dot" ]; "307" -> "107E" [ label=" ",color="blue",arrowhead="dot" ]; "308" -> "108E" [ label=" ",color="blue",arrowhead="dot" ]; "309" -> "109E" [ label=" ",color="blue",arrowhead="dot" ]; "310" -> "110E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "58E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "234E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "300E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "306E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "314E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "342E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "354E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "370E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "382E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "422E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "444E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "582E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "620E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "630E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "684E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "696E" [ label=" ",color="blue",arrowhead="dot" ]; "311" -> "801E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "42E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "192E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "194E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "196E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "198E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "200E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "202E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "204E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "312E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "336E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "376E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "384E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "386E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "428E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "474E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "484E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "546E" [ label=" ",color="blue",arrowhead="dot" ]; "312" -> "548E" [ label=" ",color="blue",arrowhead="dot" ]; "314" -> "113E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "43E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "240E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "298E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "334E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "360E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "390E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "418E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "492E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "502E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "584E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "588E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "602E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "606E" [ label=" ",color="blue",arrowhead="dot" ]; "315" -> "662E" [ label=" ",color="blue",arrowhead="dot" ]; "316" -> "51E" [ label=" ",color="blue",arrowhead="dot" ]; "317" -> "116E" [ label=" ",color="blue",arrowhead="dot" ]; "318" -> "74E" [ label=" ",color="blue",arrowhead="dot" ]; "319" -> "57E" [ label=" ",color="blue",arrowhead="dot" ]; "319" -> "94E" [ label=" ",color="blue",arrowhead="dot" ]; "319" -> "350E" [ label=" ",color="blue",arrowhead="dot" ]; "319" -> "440E" [ label=" ",color="blue",arrowhead="dot" ]; "319" -> "466E" [ label=" ",color="blue",arrowhead="dot" ]; "319" -> "676E" [ label=" ",color="blue",arrowhead="dot" ]; "320" -> "60E" [ label=" ",color="blue",arrowhead="dot" ]; "320" -> "366E" [ label=" ",color="blue",arrowhead="dot" ]; "320" -> "434E" [ label=" ",color="blue",arrowhead="dot" ]; "320" -> "458E" [ label=" ",color="blue",arrowhead="dot" ]; "320" -> "618E" [ label=" ",color="blue",arrowhead="dot" ]; "321" -> "72E" [ label=" ",color="blue",arrowhead="dot" ]; "321" -> "362E" [ label=" ",color="blue",arrowhead="dot" ]; "321" -> "372E" [ label=" ",color="blue",arrowhead="dot" ]; "321" -> "572E" [ label=" ",color="blue",arrowhead="dot" ]; "322" -> "54E" [ label=" ",color="blue",arrowhead="dot" ]; "322" -> "222E" [ label=" ",color="blue",arrowhead="dot" ]; "322" -> "302E" [ label=" ",color="blue",arrowhead="dot" ]; "322" -> "556E" [ label=" ",color="blue",arrowhead="dot" ]; "322" -> "558E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "37E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "208E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "210E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "352E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "450E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "568E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "576E" [ label=" ",color="blue",arrowhead="dot" ]; "323" -> "686E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "228E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "248E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "304E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "468E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "578E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "660E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "688E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "694E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "714E" [ label=" ",color="blue",arrowhead="dot" ]; "324" -> "766E" [ label=" ",color="blue",arrowhead="dot" ]; "325" -> "97E" [ label=" ",color="blue",arrowhead="dot" ]; "325" -> "506E" [ label=" ",color="blue",arrowhead="dot" ]; "326" -> "61E" [ label=" ",color="blue",arrowhead="dot" ]; "326" -> "175E" [ label=" ",color="blue",arrowhead="dot" ]; "326" -> "482E" [ label=" ",color="blue",arrowhead="dot" ]; "328" -> "75E" [ label=" ",color="blue",arrowhead="dot" ]; "328" -> "580E" [ label=" ",color="blue",arrowhead="dot" ]; "329" -> "96E" [ label=" ",color="blue",arrowhead="dot" ]; "330" -> "100E" [ label=" ",color="blue",arrowhead="dot" ]; "330" -> "170E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "63E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "67E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "68E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "69E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "70E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "71E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "802E" [ label=" ",color="blue",arrowhead="dot" ]; "333" -> "793E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "64E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "81E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "82E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "83E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "84E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "85E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "86E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "87E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "88E" [ label=" ",color="blue",arrowhead="dot" ]; "334" -> "89E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "1E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "2E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "3E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "4E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "5E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "6E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "7E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "8E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "9E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "10E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "11E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "12E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "13E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "14E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "15E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "16E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "17E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "18E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "19E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "20E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "21E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "22E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "23E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "24E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "25E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "26E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "27E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "28E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "29E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "30E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "31E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "65E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "119E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "150E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "176E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "743E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "744E" [ label=" ",color="blue",arrowhead="dot" ]; "336" -> "764E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "120E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "121E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "122E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "123E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "124E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "125E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "126E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "127E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "128E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "129E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "130E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "131E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "132E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "133E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "134E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "135E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "136E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "137E" [ label=" ",color="blue",arrowhead="dot" ]; "337" -> "138E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "151E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "153E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "154E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "155E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "156E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "157E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "158E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "159E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "160E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "161E" [ label=" ",color="blue",arrowhead="dot" ]; "339" -> "162E" [ label=" ",color="blue",arrowhead="dot" ]; "347" -> "139E" [ label=" ",color="blue",arrowhead="dot" ]; "347" -> "795E" [ label=" ",color="blue",arrowhead="dot" ]; "348" -> "799E" [ label=" ",color="blue",arrowhead="dot" ]; "348" -> "800E" [ label=" ",color="blue",arrowhead="dot" ]; "349" -> "141E" [ label=" ",color="blue",arrowhead="dot" ]; "350" -> "142E" [ label=" ",color="blue",arrowhead="dot" ]; "350" -> "678E" [ label=" ",color="blue",arrowhead="dot" ]; "351" -> "143E" [ label=" ",color="blue",arrowhead="dot" ]; "351" -> "232E" [ label=" ",color="blue",arrowhead="dot" ]; "351" -> "680E" [ label=" ",color="blue",arrowhead="dot" ]; "351" -> "704E" [ label=" ",color="blue",arrowhead="dot" ]; "352" -> "144E" [ label=" ",color="blue",arrowhead="dot" ]; "352" -> "432E" [ label=" ",color="blue",arrowhead="dot" ]; "353" -> "145E" [ label=" ",color="blue",arrowhead="dot" ]; "354" -> "146E" [ label=" ",color="blue",arrowhead="dot" ]; "354" -> "396E" [ label=" ",color="blue",arrowhead="dot" ]; "355" -> "147E" [ label=" ",color="blue",arrowhead="dot" ]; "356" -> "148E" [ label=" ",color="blue",arrowhead="dot" ]; "357" -> "149E" [ label=" ",color="blue",arrowhead="dot" ]; "358" -> "167E" [ label=" ",color="blue",arrowhead="dot" ]; "359" -> "169E" [ label=" ",color="blue",arrowhead="dot" ]; "360" -> "171E" [ label=" ",color="blue",arrowhead="dot" ]; "361" -> "172E" [ label=" ",color="blue",arrowhead="dot" ]; "362" -> "173E" [ label=" ",color="blue",arrowhead="dot" ]; "363" -> "174E" [ label=" ",color="blue",arrowhead="dot" ]; "364" -> "101E" [ label=" ",color="blue",arrowhead="dot" ]; "365" -> "102E" [ label=" ",color="blue",arrowhead="dot" ]; "367" -> "104E" [ label=" ",color="blue",arrowhead="dot" ]; "368" -> "105E" [ label=" ",color="blue",arrowhead="dot" ]; "369" -> "106E" [ label=" ",color="blue",arrowhead="dot" ]; "374" -> "111E" [ label=" ",color="blue",arrowhead="dot" ]; "375" -> "112E" [ label=" ",color="blue",arrowhead="dot" ]; "377" -> "114E" [ label=" ",color="blue",arrowhead="dot" ]; "378" -> "115E" [ label=" ",color="blue",arrowhead="dot" ]; "380" -> "117E" [ label=" ",color="blue",arrowhead="dot" ]; "380" -> "392E" [ label=" ",color="blue",arrowhead="dot" ]; "381" -> "118E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "177E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "178E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "179E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "180E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "181E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "182E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "183E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "184E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "185E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "186E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "187E" [ label=" ",color="blue",arrowhead="dot" ]; "382" -> "188E" [ label=" ",color="blue",arrowhead="dot" ]; "383" -> "730E" [ label=" ",color="blue",arrowhead="dot" ]; "383" -> "732E" [ label=" ",color="blue",arrowhead="dot" ]; "383" -> "741E" [ label=" ",color="blue",arrowhead="dot" ]; "383" -> "765E" [ label=" ",color="blue",arrowhead="dot" ]; "383" -> "796E" [ label=" ",color="blue",arrowhead="dot" ]; "384" -> "726E" [ label=" ",color="blue",arrowhead="dot" ]; "384" -> "728E" [ label=" ",color="blue",arrowhead="dot" ]; "384" -> "742E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "328E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "496E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "594E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "622E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "754E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "755E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "756E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "757E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "758E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "759E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "760E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "761E" [ label=" ",color="blue",arrowhead="dot" ]; "385" -> "762E" [ label=" ",color="blue",arrowhead="dot" ]; "1E" -> "34E" [ color="purple",arrowhead="none" ]; "2E" -> "35E" [ color="purple",arrowhead="none" ]; "3E" -> "36E" [ color="purple",arrowhead="none" ]; "4E" -> "37E" [ color="purple",arrowhead="none" ]; "5E" -> "38E" [ color="purple",arrowhead="none" ]; "6E" -> "39E" [ color="purple",arrowhead="none" ]; "7E" -> "40E" [ color="purple",arrowhead="none" ]; "9E" -> "41E" [ color="purple",arrowhead="none" ]; "10E" -> "42E" [ color="purple",arrowhead="none" ]; "11E" -> "43E" [ color="purple",arrowhead="none" ]; "12E" -> "44E" [ color="purple",arrowhead="none" ]; "13E" -> "45E" [ color="purple",arrowhead="none" ]; "14E" -> "46E" [ color="purple",arrowhead="none" ]; "15E" -> "47E" [ color="purple",arrowhead="none" ]; "16E" -> "48E" [ color="purple",arrowhead="none" ]; "49E" -> "17E" [ color="purple",arrowhead="none" ]; "18E" -> "50E" [ color="purple",arrowhead="none" ]; "19E" -> "51E" [ color="purple",arrowhead="none" ]; "20E" -> "52E" [ color="purple",arrowhead="none" ]; "21E" -> "53E" [ color="purple",arrowhead="none" ]; "22E" -> "54E" [ color="purple",arrowhead="none" ]; "23E" -> "55E" [ color="purple",arrowhead="none" ]; "24E" -> "56E" [ color="purple",arrowhead="none" ]; "25E" -> "57E" [ color="purple",arrowhead="none" ]; "26E" -> "58E" [ color="purple",arrowhead="none" ]; "27E" -> "59E" [ color="purple",arrowhead="none" ]; "28E" -> "60E" [ color="purple",arrowhead="none" ]; "29E" -> "61E" [ color="purple",arrowhead="none" ]; "30E" -> "62E" [ color="purple",arrowhead="none" ]; "31E" -> "63E" [ color="purple",arrowhead="none" ]; "64E" -> "65E" [ color="purple",arrowhead="none" ]; "66E" -> "8E" [ color="purple",arrowhead="none" ]; "71E" -> "76E" [ color="purple",arrowhead="none" ]; "67E" -> "72E" [ color="purple",arrowhead="none" ]; "68E" -> "73E" [ color="purple",arrowhead="none" ]; "69E" -> "74E" [ color="purple",arrowhead="none" ]; "70E" -> "75E" [ color="purple",arrowhead="none" ]; "81E" -> "92E" [ color="purple",arrowhead="none" ]; "82E" -> "93E" [ color="purple",arrowhead="none" ]; "83E" -> "94E" [ color="purple",arrowhead="none" ]; "84E" -> "95E" [ color="purple",arrowhead="none" ]; "85E" -> "96E" [ color="purple",arrowhead="none" ]; "86E" -> "97E" [ color="purple",arrowhead="none" ]; "87E" -> "98E" [ color="purple",arrowhead="none" ]; "88E" -> "99E" [ color="purple",arrowhead="none" ]; "89E" -> "100E" [ color="purple",arrowhead="none" ]; "101E" -> "120E" [ color="purple",arrowhead="none" ]; "102E" -> "121E" [ color="purple",arrowhead="none" ]; "103E" -> "122E" [ color="purple",arrowhead="none" ]; "104E" -> "123E" [ color="purple",arrowhead="none" ]; "105E" -> "124E" [ color="purple",arrowhead="none" ]; "106E" -> "125E" [ color="purple",arrowhead="none" ]; "107E" -> "126E" [ color="purple",arrowhead="none" ]; "108E" -> "127E" [ color="purple",arrowhead="none" ]; "109E" -> "128E" [ color="purple",arrowhead="none" ]; "110E" -> "129E" [ color="purple",arrowhead="none" ]; "111E" -> "130E" [ color="purple",arrowhead="none" ]; "112E" -> "131E" [ color="purple",arrowhead="none" ]; "113E" -> "132E" [ color="purple",arrowhead="none" ]; "114E" -> "133E" [ color="purple",arrowhead="none" ]; "115E" -> "134E" [ color="purple",arrowhead="none" ]; "116E" -> "135E" [ color="purple",arrowhead="none" ]; "117E" -> "136E" [ color="purple",arrowhead="none" ]; "118E" -> "137E" [ color="purple",arrowhead="none" ]; "119E" -> "138E" [ color="purple",arrowhead="none" ]; "139E" -> "151E" [ color="purple",arrowhead="none" ]; "141E" -> "153E" [ color="purple",arrowhead="none" ]; "142E" -> "154E" [ color="purple",arrowhead="none" ]; "143E" -> "155E" [ color="purple",arrowhead="none" ]; "144E" -> "156E" [ color="purple",arrowhead="none" ]; "145E" -> "157E" [ color="purple",arrowhead="none" ]; "146E" -> "158E" [ color="purple",arrowhead="none" ]; "147E" -> "159E" [ color="purple",arrowhead="none" ]; "148E" -> "160E" [ color="purple",arrowhead="none" ]; "149E" -> "161E" [ color="purple",arrowhead="none" ]; "150E" -> "162E" [ color="purple",arrowhead="none" ]; "165E" -> "177E" [ color="purple",arrowhead="none" ]; "166E" -> "178E" [ color="purple",arrowhead="none" ]; "167E" -> "179E" [ color="purple",arrowhead="none" ]; "168E" -> "180E" [ color="purple",arrowhead="none" ]; "169E" -> "181E" [ color="purple",arrowhead="none" ]; "170E" -> "182E" [ color="purple",arrowhead="none" ]; "171E" -> "183E" [ color="purple",arrowhead="none" ]; "172E" -> "184E" [ color="purple",arrowhead="none" ]; "173E" -> "185E" [ color="purple",arrowhead="none" ]; "174E" -> "186E" [ color="purple",arrowhead="none" ]; "175E" -> "187E" [ color="purple",arrowhead="none" ]; "176E" -> "188E" [ color="purple",arrowhead="none" ]; "189E" -> "190E" [ color="purple",arrowhead="none" ]; "191E" -> "192E" [ color="purple",arrowhead="none" ]; "193E" -> "194E" [ color="purple",arrowhead="none" ]; "195E" -> "196E" [ color="purple",arrowhead="none" ]; "197E" -> "198E" [ color="purple",arrowhead="none" ]; "199E" -> "200E" [ color="purple",arrowhead="none" ]; "201E" -> "202E" [ color="purple",arrowhead="none" ]; "203E" -> "204E" [ color="purple",arrowhead="none" ]; "205E" -> "206E" [ color="purple",arrowhead="none" ]; "207E" -> "208E" [ color="purple",arrowhead="none" ]; "209E" -> "210E" [ color="purple",arrowhead="none" ]; "412E" -> "211E" [ color="purple",arrowhead="none" ]; "214E" -> "213E" [ color="purple",arrowhead="none" ]; "216E" -> "215E" [ color="purple",arrowhead="none" ]; "217E" -> "218E" [ color="purple",arrowhead="none" ]; "219E" -> "220E" [ color="purple",arrowhead="none" ]; "221E" -> "222E" [ color="purple",arrowhead="none" ]; "223E" -> "224E" [ color="purple",arrowhead="none" ]; "225E" -> "226E" [ color="purple",arrowhead="none" ]; "227E" -> "228E" [ color="purple",arrowhead="none" ]; "231E" -> "232E" [ color="purple",arrowhead="none" ]; "233E" -> "234E" [ color="purple",arrowhead="none" ]; "236E" -> "235E" [ color="purple",arrowhead="none" ]; "237E" -> "238E" [ color="purple",arrowhead="none" ]; "239E" -> "240E" [ color="purple",arrowhead="none" ]; "241E" -> "242E" [ color="purple",arrowhead="none" ]; "243E" -> "244E" [ color="purple",arrowhead="none" ]; "245E" -> "246E" [ color="purple",arrowhead="none" ]; "247E" -> "248E" [ color="purple",arrowhead="none" ]; "249E" -> "250E" [ color="purple",arrowhead="none" ]; "251E" -> "252E" [ color="purple",arrowhead="none" ]; "253E" -> "254E" [ color="purple",arrowhead="none" ]; "255E" -> "256E" [ color="purple",arrowhead="none" ]; "257E" -> "258E" [ color="purple",arrowhead="none" ]; "259E" -> "260E" [ color="purple",arrowhead="none" ]; "261E" -> "262E" [ color="purple",arrowhead="none" ]; "263E" -> "264E" [ color="purple",arrowhead="none" ]; "265E" -> "266E" [ color="purple",arrowhead="none" ]; "267E" -> "268E" [ color="purple",arrowhead="none" ]; "269E" -> "270E" [ color="purple",arrowhead="none" ]; "271E" -> "272E" [ color="purple",arrowhead="none" ]; "273E" -> "274E" [ color="purple",arrowhead="none" ]; "275E" -> "276E" [ color="purple",arrowhead="none" ]; "278E" -> "277E" [ color="purple",arrowhead="none" ]; "279E" -> "767E" [ color="purple",arrowhead="none" ]; "281E" -> "282E" [ color="purple",arrowhead="none" ]; "283E" -> "284E" [ color="purple",arrowhead="none" ]; "285E" -> "286E" [ color="purple",arrowhead="none" ]; "768E" -> "287E" [ color="purple",arrowhead="none" ]; "289E" -> "290E" [ color="purple",arrowhead="none" ]; "291E" -> "292E" [ color="purple",arrowhead="none" ]; "293E" -> "294E" [ color="purple",arrowhead="none" ]; "295E" -> "296E" [ color="purple",arrowhead="none" ]; "297E" -> "298E" [ color="purple",arrowhead="none" ]; "299E" -> "300E" [ color="purple",arrowhead="none" ]; "301E" -> "302E" [ color="purple",arrowhead="none" ]; "303E" -> "304E" [ color="purple",arrowhead="none" ]; "305E" -> "306E" [ color="purple",arrowhead="none" ]; "307E" -> "308E" [ color="purple",arrowhead="none" ]; "309E" -> "310E" [ color="purple",arrowhead="none" ]; "311E" -> "312E" [ color="purple",arrowhead="none" ]; "313E" -> "314E" [ color="purple",arrowhead="none" ]; "315E" -> "316E" [ color="purple",arrowhead="none" ]; "317E" -> "318E" [ color="purple",arrowhead="none" ]; "319E" -> "320E" [ color="purple",arrowhead="none" ]; "321E" -> "322E" [ color="purple",arrowhead="none" ]; "327E" -> "800E" [ color="purple",arrowhead="none" ]; "329E" -> "330E" [ color="purple",arrowhead="none" ]; "331E" -> "332E" [ color="purple",arrowhead="none" ]; "333E" -> "334E" [ color="purple",arrowhead="none" ]; "335E" -> "336E" [ color="purple",arrowhead="none" ]; "337E" -> "338E" [ color="purple",arrowhead="none" ]; "339E" -> "340E" [ color="purple",arrowhead="none" ]; "341E" -> "342E" [ color="purple",arrowhead="none" ]; "343E" -> "344E" [ color="purple",arrowhead="none" ]; "345E" -> "346E" [ color="purple",arrowhead="none" ]; "347E" -> "348E" [ color="purple",arrowhead="none" ]; "349E" -> "350E" [ color="purple",arrowhead="none" ]; "351E" -> "352E" [ color="purple",arrowhead="none" ]; "353E" -> "354E" [ color="purple",arrowhead="none" ]; "412E" -> "355E" [ color="purple",arrowhead="none" ]; "357E" -> "358E" [ color="purple",arrowhead="none" ]; "359E" -> "360E" [ color="purple",arrowhead="none" ]; "361E" -> "362E" [ color="purple",arrowhead="none" ]; "363E" -> "364E" [ color="purple",arrowhead="none" ]; "365E" -> "366E" [ color="purple",arrowhead="none" ]; "367E" -> "368E" [ color="purple",arrowhead="none" ]; "369E" -> "370E" [ color="purple",arrowhead="none" ]; "371E" -> "372E" [ color="purple",arrowhead="none" ]; "373E" -> "374E" [ color="purple",arrowhead="none" ]; "375E" -> "376E" [ color="purple",arrowhead="none" ]; "377E" -> "378E" [ color="purple",arrowhead="none" ]; "379E" -> "380E" [ color="purple",arrowhead="none" ]; "381E" -> "382E" [ color="purple",arrowhead="none" ]; "383E" -> "384E" [ color="purple",arrowhead="none" ]; "385E" -> "386E" [ color="purple",arrowhead="none" ]; "387E" -> "388E" [ color="purple",arrowhead="none" ]; "389E" -> "390E" [ color="purple",arrowhead="none" ]; "391E" -> "392E" [ color="purple",arrowhead="none" ]; "393E" -> "394E" [ color="purple",arrowhead="none" ]; "395E" -> "396E" [ color="purple",arrowhead="none" ]; "397E" -> "398E" [ color="purple",arrowhead="none" ]; "399E" -> "400E" [ color="purple",arrowhead="none" ]; "402E" -> "401E" [ color="purple",arrowhead="none" ]; "404E" -> "403E" [ color="purple",arrowhead="none" ]; "406E" -> "405E" [ color="purple",arrowhead="none" ]; "408E" -> "407E" [ color="purple",arrowhead="none" ]; "236E" -> "409E" [ color="purple",arrowhead="none" ]; "412E" -> "411E" [ color="purple",arrowhead="none" ]; "412E" -> "413E" [ color="purple",arrowhead="none" ]; "278E" -> "415E" [ color="purple",arrowhead="none" ]; "417E" -> "418E" [ color="purple",arrowhead="none" ]; "419E" -> "420E" [ color="purple",arrowhead="none" ]; "421E" -> "422E" [ color="purple",arrowhead="none" ]; "423E" -> "424E" [ color="purple",arrowhead="none" ]; "425E" -> "426E" [ color="purple",arrowhead="none" ]; "427E" -> "428E" [ color="purple",arrowhead="none" ]; "431E" -> "432E" [ color="purple",arrowhead="none" ]; "433E" -> "434E" [ color="purple",arrowhead="none" ]; "435E" -> "436E" [ color="purple",arrowhead="none" ]; "438E" -> "437E" [ color="purple",arrowhead="none" ]; "439E" -> "440E" [ color="purple",arrowhead="none" ]; "441E" -> "442E" [ color="purple",arrowhead="none" ]; "443E" -> "444E" [ color="purple",arrowhead="none" ]; "445E" -> "446E" [ color="purple",arrowhead="none" ]; "448E" -> "447E" [ color="purple",arrowhead="none" ]; "449E" -> "450E" [ color="purple",arrowhead="none" ]; "451E" -> "452E" [ color="purple",arrowhead="none" ]; "453E" -> "454E" [ color="purple",arrowhead="none" ]; "455E" -> "456E" [ color="purple",arrowhead="none" ]; "457E" -> "458E" [ color="purple",arrowhead="none" ]; "459E" -> "460E" [ color="purple",arrowhead="none" ]; "461E" -> "462E" [ color="purple",arrowhead="none" ]; "236E" -> "463E" [ color="purple",arrowhead="none" ]; "465E" -> "466E" [ color="purple",arrowhead="none" ]; "467E" -> "468E" [ color="purple",arrowhead="none" ]; "469E" -> "470E" [ color="purple",arrowhead="none" ]; "471E" -> "472E" [ color="purple",arrowhead="none" ]; "473E" -> "474E" [ color="purple",arrowhead="none" ]; "476E" -> "475E" [ color="purple",arrowhead="none" ]; "477E" -> "478E" [ color="purple",arrowhead="none" ]; "479E" -> "358E" [ color="purple",arrowhead="none" ]; "481E" -> "482E" [ color="purple",arrowhead="none" ]; "483E" -> "484E" [ color="purple",arrowhead="none" ]; "485E" -> "486E" [ color="purple",arrowhead="none" ]; "487E" -> "488E" [ color="purple",arrowhead="none" ]; "489E" -> "490E" [ color="purple",arrowhead="none" ]; "491E" -> "492E" [ color="purple",arrowhead="none" ]; "495E" -> "795E" [ color="purple",arrowhead="none" ]; "499E" -> "500E" [ color="purple",arrowhead="none" ]; "501E" -> "502E" [ color="purple",arrowhead="none" ]; "504E" -> "503E" [ color="purple",arrowhead="none" ]; "505E" -> "506E" [ color="purple",arrowhead="none" ]; "507E" -> "508E" [ color="purple",arrowhead="none" ]; "509E" -> "510E" [ color="purple",arrowhead="none" ]; "412E" -> "511E" [ color="purple",arrowhead="none" ]; "513E" -> "514E" [ color="purple",arrowhead="none" ]; "515E" -> "516E" [ color="purple",arrowhead="none" ]; "517E" -> "518E" [ color="purple",arrowhead="none" ]; "519E" -> "520E" [ color="purple",arrowhead="none" ]; "521E" -> "522E" [ color="purple",arrowhead="none" ]; "523E" -> "524E" [ color="purple",arrowhead="none" ]; "525E" -> "526E" [ color="purple",arrowhead="none" ]; "527E" -> "528E" [ color="purple",arrowhead="none" ]; "529E" -> "530E" [ color="purple",arrowhead="none" ]; "531E" -> "532E" [ color="purple",arrowhead="none" ]; "533E" -> "534E" [ color="purple",arrowhead="none" ]; "535E" -> "536E" [ color="purple",arrowhead="none" ]; "537E" -> "538E" [ color="purple",arrowhead="none" ]; "539E" -> "540E" [ color="purple",arrowhead="none" ]; "541E" -> "542E" [ color="purple",arrowhead="none" ]; "543E" -> "544E" [ color="purple",arrowhead="none" ]; "545E" -> "546E" [ color="purple",arrowhead="none" ]; "547E" -> "548E" [ color="purple",arrowhead="none" ]; "549E" -> "550E" [ color="purple",arrowhead="none" ]; "551E" -> "552E" [ color="purple",arrowhead="none" ]; "553E" -> "554E" [ color="purple",arrowhead="none" ]; "555E" -> "556E" [ color="purple",arrowhead="none" ]; "557E" -> "558E" [ color="purple",arrowhead="none" ]; "278E" -> "559E" [ color="purple",arrowhead="none" ]; "561E" -> "562E" [ color="purple",arrowhead="none" ]; "563E" -> "564E" [ color="purple",arrowhead="none" ]; "565E" -> "566E" [ color="purple",arrowhead="none" ]; "567E" -> "568E" [ color="purple",arrowhead="none" ]; "569E" -> "570E" [ color="purple",arrowhead="none" ]; "571E" -> "572E" [ color="purple",arrowhead="none" ]; "573E" -> "574E" [ color="purple",arrowhead="none" ]; "575E" -> "576E" [ color="purple",arrowhead="none" ]; "577E" -> "578E" [ color="purple",arrowhead="none" ]; "579E" -> "580E" [ color="purple",arrowhead="none" ]; "581E" -> "582E" [ color="purple",arrowhead="none" ]; "583E" -> "584E" [ color="purple",arrowhead="none" ]; "585E" -> "586E" [ color="purple",arrowhead="none" ]; "587E" -> "588E" [ color="purple",arrowhead="none" ]; "589E" -> "590E" [ color="purple",arrowhead="none" ]; "593E" -> "594E" [ color="purple",arrowhead="none" ]; "597E" -> "598E" [ color="purple",arrowhead="none" ]; "599E" -> "600E" [ color="purple",arrowhead="none" ]; "601E" -> "602E" [ color="purple",arrowhead="none" ]; "603E" -> "604E" [ color="purple",arrowhead="none" ]; "605E" -> "606E" [ color="purple",arrowhead="none" ]; "607E" -> "608E" [ color="purple",arrowhead="none" ]; "609E" -> "610E" [ color="purple",arrowhead="none" ]; "611E" -> "612E" [ color="purple",arrowhead="none" ]; "613E" -> "614E" [ color="purple",arrowhead="none" ]; "615E" -> "358E" [ color="purple",arrowhead="none" ]; "617E" -> "618E" [ color="purple",arrowhead="none" ]; "619E" -> "620E" [ color="purple",arrowhead="none" ]; "621E" -> "622E" [ color="purple",arrowhead="none" ]; "623E" -> "624E" [ color="purple",arrowhead="none" ]; "625E" -> "626E" [ color="purple",arrowhead="none" ]; "627E" -> "628E" [ color="purple",arrowhead="none" ]; "629E" -> "630E" [ color="purple",arrowhead="none" ]; "631E" -> "632E" [ color="purple",arrowhead="none" ]; "634E" -> "633E" [ color="purple",arrowhead="none" ]; "635E" -> "636E" [ color="purple",arrowhead="none" ]; "637E" -> "638E" [ color="purple",arrowhead="none" ]; "639E" -> "640E" [ color="purple",arrowhead="none" ]; "641E" -> "642E" [ color="purple",arrowhead="none" ]; "643E" -> "644E" [ color="purple",arrowhead="none" ]; "645E" -> "646E" [ color="purple",arrowhead="none" ]; "647E" -> "648E" [ color="purple",arrowhead="none" ]; "649E" -> "650E" [ color="purple",arrowhead="none" ]; "651E" -> "652E" [ color="purple",arrowhead="none" ]; "653E" -> "654E" [ color="purple",arrowhead="none" ]; "655E" -> "656E" [ color="purple",arrowhead="none" ]; "657E" -> "658E" [ color="purple",arrowhead="none" ]; "659E" -> "660E" [ color="purple",arrowhead="none" ]; "661E" -> "662E" [ color="purple",arrowhead="none" ]; "663E" -> "664E" [ color="purple",arrowhead="none" ]; "665E" -> "666E" [ color="purple",arrowhead="none" ]; "667E" -> "668E" [ color="purple",arrowhead="none" ]; "669E" -> "670E" [ color="purple",arrowhead="none" ]; "671E" -> "672E" [ color="purple",arrowhead="none" ]; "673E" -> "674E" [ color="purple",arrowhead="none" ]; "675E" -> "676E" [ color="purple",arrowhead="none" ]; "679E" -> "680E" [ color="purple",arrowhead="none" ]; "681E" -> "682E" [ color="purple",arrowhead="none" ]; "683E" -> "684E" [ color="purple",arrowhead="none" ]; "685E" -> "686E" [ color="purple",arrowhead="none" ]; "687E" -> "688E" [ color="purple",arrowhead="none" ]; "689E" -> "690E" [ color="purple",arrowhead="none" ]; "691E" -> "692E" [ color="purple",arrowhead="none" ]; "693E" -> "694E" [ color="purple",arrowhead="none" ]; "695E" -> "696E" [ color="purple",arrowhead="none" ]; "697E" -> "698E" [ color="purple",arrowhead="none" ]; "699E" -> "700E" [ color="purple",arrowhead="none" ]; "703E" -> "704E" [ color="purple",arrowhead="none" ]; "705E" -> "706E" [ color="purple",arrowhead="none" ]; "709E" -> "710E" [ color="purple",arrowhead="none" ]; "711E" -> "712E" [ color="purple",arrowhead="none" ]; "713E" -> "714E" [ color="purple",arrowhead="none" ]; "715E" -> "398E" [ color="purple",arrowhead="none" ]; "717E" -> "718E" [ color="purple",arrowhead="none" ]; "719E" -> "720E" [ color="purple",arrowhead="none" ]; "721E" -> "722E" [ color="purple",arrowhead="none" ]; "725E" -> "726E" [ color="purple",arrowhead="none" ]; "727E" -> "728E" [ color="purple",arrowhead="none" ]; "729E" -> "730E" [ color="purple",arrowhead="none" ]; "731E" -> "732E" [ color="purple",arrowhead="none" ]; "741E" -> "743E" [ color="purple",arrowhead="none" ]; "742E" -> "744E" [ color="purple",arrowhead="none" ]; "745E" -> "754E" [ color="purple",arrowhead="none" ]; "746E" -> "755E" [ color="purple",arrowhead="none" ]; "747E" -> "756E" [ color="purple",arrowhead="none" ]; "748E" -> "757E" [ color="purple",arrowhead="none" ]; "749E" -> "758E" [ color="purple",arrowhead="none" ]; "750E" -> "759E" [ color="purple",arrowhead="none" ]; "751E" -> "760E" [ color="purple",arrowhead="none" ]; "752E" -> "761E" [ color="purple",arrowhead="none" ]; "753E" -> "762E" [ color="purple",arrowhead="none" ]; "763E" -> "764E" [ color="purple",arrowhead="none" ]; "765E" -> "766E" [ color="purple",arrowhead="none" ]; "770E" -> "783E" [ color="purple",arrowhead="none" ]; "770E" -> "784E" [ color="purple",arrowhead="none" ]; "769E" -> "785E" [ color="purple",arrowhead="none" ]; "769E" -> "786E" [ color="purple",arrowhead="none" ]; "769E" -> "787E" [ color="purple",arrowhead="none" ]; "770E" -> "788E" [ color="purple",arrowhead="none" ]; "770E" -> "789E" [ color="purple",arrowhead="none" ]; "769E" -> "790E" [ color="purple",arrowhead="none" ]; "770E" -> "791E" [ color="purple",arrowhead="none" ]; "769E" -> "792E" [ color="purple",arrowhead="none" ]; "793E" -> "769E" [ color="purple",arrowhead="none" ]; "769E" -> "784E" [ color="purple",arrowhead="none" ]; "770E" -> "785E" [ color="purple",arrowhead="none" ]; "788E" -> "787E" [ color="purple",arrowhead="none" ]; "770E" -> "792E" [ color="purple",arrowhead="none" ]; "798E" -> "799E" [ color="purple",arrowhead="none" ]; "796E" -> "797E" [ color="purple",arrowhead="none" ]; "793E" -> "789E" [ color="purple",arrowhead="none" ]; "783E" -> "787E" [ color="purple",arrowhead="none" ]; "784E" -> "792E" [ color="purple",arrowhead="none" ]; "787E" -> "789E" [ color="purple",arrowhead="none" ]; "769E" -> "791E" [ color="purple",arrowhead="none" ]; "802E" -> "801E" [ color="purple",arrowhead="none" ]; } ocamlgraph-1.8.3/editor/tests/ring_100.gml0000644000175000017500000002125512133565071017256 0ustar mehdimehdigraph [ node [ id 1 label 0 ] node [ id 2 label 1 ] node [ id 3 label 2 ] node [ id 4 label 3 ] node [ id 5 label 4 ] node [ id 6 label 5 ] node [ id 7 label 6 ] node [ id 8 label 7 ] node [ id 9 label 8 ] node [ id 10 label 9 ] node [ id 11 label 10 ] node [ id 12 label 11 ] node [ id 13 label 12 ] node [ id 14 label 13 ] node [ id 15 label 14 ] node [ id 16 label 15 ] node [ id 17 label 16 ] node [ id 18 label 17 ] node [ id 19 label 18 ] node [ id 20 label 19 ] node [ id 21 label 20 ] node [ id 22 label 21 ] node [ id 23 label 22 ] node [ id 24 label 23 ] node [ id 25 label 24 ] node [ id 26 label 25 ] node [ id 27 label 26 ] node [ id 28 label 27 ] node [ id 29 label 28 ] node [ id 30 label 29 ] node [ id 31 label 30 ] node [ id 32 label 31 ] node [ id 33 label 32 ] node [ id 34 label 33 ] node [ id 35 label 34 ] node [ id 36 label 35 ] node [ id 37 label 36 ] node [ id 38 label 37 ] node [ id 39 label 38 ] node [ id 40 label 39 ] node [ id 41 label 40 ] node [ id 42 label 41 ] node [ id 43 label 42 ] node [ id 44 label 43 ] node [ id 45 label 44 ] node [ id 46 label 45 ] node [ id 47 label 46 ] node [ id 48 label 47 ] node [ id 49 label 48 ] node [ id 50 label 49 ] node [ id 51 label 50 ] node [ id 52 label 51 ] node [ id 53 label 52 ] node [ id 54 label 53 ] node [ id 55 label 54 ] node [ id 56 label 55 ] node [ id 57 label 56 ] node [ id 58 label 57 ] node [ id 59 label 58 ] node [ id 60 label 59 ] node [ id 61 label 60 ] node [ id 62 label 61 ] node [ id 63 label 62 ] node [ id 64 label 63 ] node [ id 65 label 64 ] node [ id 66 label 65 ] node [ id 67 label 66 ] node [ id 68 label 67 ] node [ id 69 label 68 ] node [ id 70 label 69 ] node [ id 71 label 70 ] node [ id 72 label 71 ] node [ id 73 label 72 ] node [ id 74 label 73 ] node [ id 75 label 74 ] node [ id 76 label 75 ] node [ id 77 label 76 ] node [ id 78 label 77 ] node [ id 79 label 78 ] node [ id 80 label 79 ] node [ id 81 label 80 ] node [ id 82 label 81 ] node [ id 83 label 82 ] node [ id 84 label 83 ] node [ id 85 label 84 ] node [ id 86 label 85 ] node [ id 87 label 86 ] node [ id 88 label 87 ] node [ id 89 label 88 ] node [ id 90 label 89 ] node [ id 91 label 90 ] node [ id 92 label 91 ] node [ id 93 label 92 ] node [ id 94 label 93 ] node [ id 95 label 94 ] node [ id 96 label 95 ] node [ id 97 label 96 ] node [ id 98 label 97 ] node [ id 99 label 98 ] node [ id 100 label 99 ] edge [ source 2 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 4 target 3 label 0 ] edge [ source 5 target 4 label 0 ] edge [ source 6 target 5 label 0 ] edge [ source 7 target 6 label 0 ] edge [ source 8 target 7 label 0 ] edge [ source 9 target 8 label 0 ] edge [ source 10 target 9 label 0 ] edge [ source 11 target 10 label 0 ] edge [ source 12 target 11 label 0 ] edge [ source 13 target 12 label 0 ] edge [ source 14 target 13 label 0 ] edge [ source 15 target 14 label 0 ] edge [ source 16 target 15 label 0 ] edge [ source 17 target 16 label 0 ] edge [ source 18 target 17 label 0 ] edge [ source 19 target 18 label 0 ] edge [ source 20 target 19 label 0 ] edge [ source 21 target 20 label 0 ] edge [ source 22 target 21 label 0 ] edge [ source 23 target 22 label 0 ] edge [ source 24 target 23 label 0 ] edge [ source 25 target 24 label 0 ] edge [ source 26 target 25 label 0 ] edge [ source 27 target 26 label 0 ] edge [ source 28 target 27 label 0 ] edge [ source 29 target 28 label 0 ] edge [ source 30 target 29 label 0 ] edge [ source 31 target 30 label 0 ] edge [ source 32 target 31 label 0 ] edge [ source 33 target 32 label 0 ] edge [ source 34 target 33 label 0 ] edge [ source 35 target 34 label 0 ] edge [ source 36 target 35 label 0 ] edge [ source 37 target 36 label 0 ] edge [ source 38 target 37 label 0 ] edge [ source 39 target 38 label 0 ] edge [ source 40 target 39 label 0 ] edge [ source 41 target 40 label 0 ] edge [ source 42 target 41 label 0 ] edge [ source 43 target 42 label 0 ] edge [ source 44 target 43 label 0 ] edge [ source 45 target 44 label 0 ] edge [ source 46 target 45 label 0 ] edge [ source 47 target 46 label 0 ] edge [ source 48 target 47 label 0 ] edge [ source 49 target 48 label 0 ] edge [ source 50 target 49 label 0 ] edge [ source 51 target 50 label 0 ] edge [ source 52 target 51 label 0 ] edge [ source 53 target 52 label 0 ] edge [ source 54 target 53 label 0 ] edge [ source 55 target 54 label 0 ] edge [ source 56 target 55 label 0 ] edge [ source 57 target 56 label 0 ] edge [ source 58 target 57 label 0 ] edge [ source 59 target 58 label 0 ] edge [ source 60 target 59 label 0 ] edge [ source 61 target 60 label 0 ] edge [ source 62 target 61 label 0 ] edge [ source 63 target 62 label 0 ] edge [ source 64 target 63 label 0 ] edge [ source 65 target 64 label 0 ] edge [ source 66 target 65 label 0 ] edge [ source 67 target 66 label 0 ] edge [ source 68 target 67 label 0 ] edge [ source 69 target 68 label 0 ] edge [ source 70 target 69 label 0 ] edge [ source 71 target 70 label 0 ] edge [ source 72 target 71 label 0 ] edge [ source 73 target 72 label 0 ] edge [ source 74 target 73 label 0 ] edge [ source 75 target 74 label 0 ] edge [ source 76 target 75 label 0 ] edge [ source 77 target 76 label 0 ] edge [ source 78 target 77 label 0 ] edge [ source 79 target 78 label 0 ] edge [ source 80 target 79 label 0 ] edge [ source 81 target 80 label 0 ] edge [ source 82 target 81 label 0 ] edge [ source 83 target 82 label 0 ] edge [ source 84 target 83 label 0 ] edge [ source 85 target 84 label 0 ] edge [ source 86 target 85 label 0 ] edge [ source 87 target 86 label 0 ] edge [ source 88 target 87 label 0 ] edge [ source 89 target 88 label 0 ] edge [ source 90 target 89 label 0 ] edge [ source 91 target 90 label 0 ] edge [ source 92 target 91 label 0 ] edge [ source 93 target 92 label 0 ] edge [ source 94 target 93 label 0 ] edge [ source 95 target 94 label 0 ] edge [ source 96 target 95 label 0 ] edge [ source 97 target 96 label 0 ] edge [ source 98 target 97 label 0 ] edge [ source 99 target 98 label 0 ] edge [ source 100 target 1 label 0 ] edge [ source 100 target 99 label 0 ] ] ocamlgraph-1.8.3/editor/tests/dep_ed.dot0000644000175000017500000000030212133565071017154 0ustar mehdimehdidigraph G { size="7.5,10" ; rankdir = TB ; "Ed_main" -> "Ed_display" ; "Ed_main" -> "Ed_draw" ; "Ed_graph" -> "Ed_hyper" ; "Ed_draw" -> "Ed_graph" ; "Ed_display" -> "Ed_graph" ; } ocamlgraph-1.8.3/editor/tests/full30.gml0000644000175000017500000006153712133565071017053 0ustar mehdimehdigraph [ node [ id 1 label 1 ] node [ id 2 label 2 ] node [ id 3 label 3 ] node [ id 4 label 4 ] node [ id 5 label 5 ] node [ id 6 label 6 ] node [ id 7 label 7 ] node [ id 8 label 8 ] node [ id 9 label 9 ] node [ id 10 label 10 ] node [ id 11 label 11 ] node [ id 12 label 12 ] node [ id 13 label 13 ] node [ id 14 label 14 ] node [ id 15 label 15 ] node [ id 16 label 16 ] node [ id 17 label 17 ] node [ id 18 label 18 ] node [ id 19 label 19 ] node [ id 20 label 20 ] node [ id 21 label 21 ] node [ id 22 label 22 ] node [ id 23 label 23 ] node [ id 24 label 24 ] node [ id 25 label 25 ] node [ id 26 label 26 ] node [ id 27 label 27 ] node [ id 28 label 28 ] node [ id 29 label 29 ] node [ id 30 label 30 ] edge [ source 1 target 1 label 0 ] edge [ source 2 target 1 label 0 ] edge [ source 2 target 2 label 0 ] edge [ source 3 target 1 label 0 ] edge [ source 3 target 2 label 0 ] edge [ source 3 target 3 label 0 ] edge [ source 4 target 1 label 0 ] edge [ source 4 target 2 label 0 ] edge [ source 4 target 3 label 0 ] edge [ source 4 target 4 label 0 ] edge [ source 5 target 1 label 0 ] edge [ source 5 target 2 label 0 ] edge [ source 5 target 3 label 0 ] edge [ source 5 target 4 label 0 ] edge [ source 5 target 5 label 0 ] edge [ source 6 target 1 label 0 ] edge [ source 6 target 2 label 0 ] edge [ source 6 target 3 label 0 ] edge [ source 6 target 4 label 0 ] edge [ source 6 target 5 label 0 ] edge [ source 6 target 6 label 0 ] edge [ source 7 target 1 label 0 ] edge [ source 7 target 2 label 0 ] edge [ source 7 target 3 label 0 ] edge [ source 7 target 4 label 0 ] edge [ source 7 target 5 label 0 ] edge [ source 7 target 6 label 0 ] edge [ source 7 target 7 label 0 ] edge [ source 8 target 1 label 0 ] edge [ source 8 target 2 label 0 ] edge [ source 8 target 3 label 0 ] edge [ source 8 target 4 label 0 ] edge [ source 8 target 5 label 0 ] edge [ source 8 target 6 label 0 ] edge [ source 8 target 7 label 0 ] edge [ source 8 target 8 label 0 ] edge [ source 9 target 1 label 0 ] edge [ source 9 target 2 label 0 ] edge [ source 9 target 3 label 0 ] edge [ source 9 target 4 label 0 ] edge [ source 9 target 5 label 0 ] edge [ source 9 target 6 label 0 ] edge [ source 9 target 7 label 0 ] edge [ source 9 target 8 label 0 ] edge [ source 9 target 9 label 0 ] edge [ source 10 target 1 label 0 ] edge [ source 10 target 2 label 0 ] edge [ source 10 target 3 label 0 ] edge [ source 10 target 4 label 0 ] edge [ source 10 target 5 label 0 ] edge [ source 10 target 6 label 0 ] edge [ source 10 target 7 label 0 ] edge [ source 10 target 8 label 0 ] edge [ source 10 target 9 label 0 ] edge [ source 10 target 10 label 0 ] edge [ source 11 target 1 label 0 ] edge [ source 11 target 2 label 0 ] edge [ source 11 target 3 label 0 ] edge [ source 11 target 4 label 0 ] edge [ source 11 target 5 label 0 ] edge [ source 11 target 6 label 0 ] edge [ source 11 target 7 label 0 ] edge [ source 11 target 8 label 0 ] edge [ source 11 target 9 label 0 ] edge [ source 11 target 10 label 0 ] edge [ source 11 target 11 label 0 ] edge [ source 12 target 1 label 0 ] edge [ source 12 target 2 label 0 ] edge [ source 12 target 3 label 0 ] edge [ source 12 target 4 label 0 ] edge [ source 12 target 5 label 0 ] edge [ source 12 target 6 label 0 ] edge [ source 12 target 7 label 0 ] edge [ source 12 target 8 label 0 ] edge [ source 12 target 9 label 0 ] edge [ source 12 target 10 label 0 ] edge [ source 12 target 11 label 0 ] edge [ source 12 target 12 label 0 ] edge [ source 13 target 1 label 0 ] edge [ source 13 target 2 label 0 ] edge [ source 13 target 3 label 0 ] edge [ source 13 target 4 label 0 ] edge [ source 13 target 5 label 0 ] edge [ source 13 target 6 label 0 ] edge [ source 13 target 7 label 0 ] edge [ source 13 target 8 label 0 ] edge [ source 13 target 9 label 0 ] edge [ source 13 target 10 label 0 ] edge [ source 13 target 11 label 0 ] edge [ source 13 target 12 label 0 ] edge [ source 13 target 13 label 0 ] edge [ source 14 target 1 label 0 ] edge [ source 14 target 2 label 0 ] edge [ source 14 target 3 label 0 ] edge [ source 14 target 4 label 0 ] edge [ source 14 target 5 label 0 ] edge [ source 14 target 6 label 0 ] edge [ source 14 target 7 label 0 ] edge [ source 14 target 8 label 0 ] edge [ source 14 target 9 label 0 ] edge [ source 14 target 10 label 0 ] edge [ source 14 target 11 label 0 ] edge [ source 14 target 12 label 0 ] edge [ source 14 target 13 label 0 ] edge [ source 14 target 14 label 0 ] edge [ source 15 target 1 label 0 ] edge [ source 15 target 2 label 0 ] edge [ source 15 target 3 label 0 ] edge [ source 15 target 4 label 0 ] edge [ source 15 target 5 label 0 ] edge [ source 15 target 6 label 0 ] edge [ source 15 target 7 label 0 ] edge [ source 15 target 8 label 0 ] edge [ source 15 target 9 label 0 ] edge [ source 15 target 10 label 0 ] edge [ source 15 target 11 label 0 ] edge [ source 15 target 12 label 0 ] edge [ source 15 target 13 label 0 ] edge [ source 15 target 14 label 0 ] edge [ source 15 target 15 label 0 ] edge [ source 16 target 1 label 0 ] edge [ source 16 target 2 label 0 ] edge [ source 16 target 3 label 0 ] edge [ source 16 target 4 label 0 ] edge [ source 16 target 5 label 0 ] edge [ source 16 target 6 label 0 ] edge [ source 16 target 7 label 0 ] edge [ source 16 target 8 label 0 ] edge [ source 16 target 9 label 0 ] edge [ source 16 target 10 label 0 ] edge [ source 16 target 11 label 0 ] edge [ source 16 target 12 label 0 ] edge [ source 16 target 13 label 0 ] edge [ source 16 target 14 label 0 ] edge [ source 16 target 15 label 0 ] edge [ source 16 target 16 label 0 ] edge [ source 17 target 1 label 0 ] edge [ source 17 target 2 label 0 ] edge [ source 17 target 3 label 0 ] edge [ source 17 target 4 label 0 ] edge [ source 17 target 5 label 0 ] edge [ source 17 target 6 label 0 ] edge [ source 17 target 7 label 0 ] edge [ source 17 target 8 label 0 ] edge [ source 17 target 9 label 0 ] edge [ source 17 target 10 label 0 ] edge [ source 17 target 11 label 0 ] edge [ source 17 target 12 label 0 ] edge [ source 17 target 13 label 0 ] edge [ source 17 target 14 label 0 ] edge [ source 17 target 15 label 0 ] edge [ source 17 target 16 label 0 ] edge [ source 17 target 17 label 0 ] edge [ source 18 target 1 label 0 ] edge [ source 18 target 2 label 0 ] edge [ source 18 target 3 label 0 ] edge [ source 18 target 4 label 0 ] edge [ source 18 target 5 label 0 ] edge [ source 18 target 6 label 0 ] edge [ source 18 target 7 label 0 ] edge [ source 18 target 8 label 0 ] edge [ source 18 target 9 label 0 ] edge [ source 18 target 10 label 0 ] edge [ source 18 target 11 label 0 ] edge [ source 18 target 12 label 0 ] edge [ source 18 target 13 label 0 ] edge [ source 18 target 14 label 0 ] edge [ source 18 target 15 label 0 ] edge [ source 18 target 16 label 0 ] edge [ source 18 target 17 label 0 ] edge [ source 18 target 18 label 0 ] edge [ source 19 target 1 label 0 ] edge [ source 19 target 2 label 0 ] edge [ source 19 target 3 label 0 ] edge [ source 19 target 4 label 0 ] edge [ source 19 target 5 label 0 ] edge [ source 19 target 6 label 0 ] edge [ source 19 target 7 label 0 ] edge [ source 19 target 8 label 0 ] edge [ source 19 target 9 label 0 ] edge [ source 19 target 10 label 0 ] edge [ source 19 target 11 label 0 ] edge [ source 19 target 12 label 0 ] edge [ source 19 target 13 label 0 ] edge [ source 19 target 14 label 0 ] edge [ source 19 target 15 label 0 ] edge [ source 19 target 16 label 0 ] edge [ source 19 target 17 label 0 ] edge [ source 19 target 18 label 0 ] edge [ source 19 target 19 label 0 ] edge [ source 20 target 1 label 0 ] edge [ source 20 target 2 label 0 ] edge [ source 20 target 3 label 0 ] edge [ source 20 target 4 label 0 ] edge [ source 20 target 5 label 0 ] edge [ source 20 target 6 label 0 ] edge [ source 20 target 7 label 0 ] edge [ source 20 target 8 label 0 ] edge [ source 20 target 9 label 0 ] edge [ source 20 target 10 label 0 ] edge [ source 20 target 11 label 0 ] edge [ source 20 target 12 label 0 ] edge [ source 20 target 13 label 0 ] edge [ source 20 target 14 label 0 ] edge [ source 20 target 15 label 0 ] edge [ source 20 target 16 label 0 ] edge [ source 20 target 17 label 0 ] edge [ source 20 target 18 label 0 ] edge [ source 20 target 19 label 0 ] edge [ source 20 target 20 label 0 ] edge [ source 21 target 1 label 0 ] edge [ source 21 target 2 label 0 ] edge [ source 21 target 3 label 0 ] edge [ source 21 target 4 label 0 ] edge [ source 21 target 5 label 0 ] edge [ source 21 target 6 label 0 ] edge [ source 21 target 7 label 0 ] edge [ source 21 target 8 label 0 ] edge [ source 21 target 9 label 0 ] edge [ source 21 target 10 label 0 ] edge [ source 21 target 11 label 0 ] edge [ source 21 target 12 label 0 ] edge [ source 21 target 13 label 0 ] edge [ source 21 target 14 label 0 ] edge [ source 21 target 15 label 0 ] edge [ source 21 target 16 label 0 ] edge [ source 21 target 17 label 0 ] edge [ source 21 target 18 label 0 ] edge [ source 21 target 19 label 0 ] edge [ source 21 target 20 label 0 ] edge [ source 21 target 21 label 0 ] edge [ source 22 target 1 label 0 ] edge [ source 22 target 2 label 0 ] edge [ source 22 target 3 label 0 ] edge [ source 22 target 4 label 0 ] edge [ source 22 target 5 label 0 ] edge [ source 22 target 6 label 0 ] edge [ source 22 target 7 label 0 ] edge [ source 22 target 8 label 0 ] edge [ source 22 target 9 label 0 ] edge [ source 22 target 10 label 0 ] edge [ source 22 target 11 label 0 ] edge [ source 22 target 12 label 0 ] edge [ source 22 target 13 label 0 ] edge [ source 22 target 14 label 0 ] edge [ source 22 target 15 label 0 ] edge [ source 22 target 16 label 0 ] edge [ source 22 target 17 label 0 ] edge [ source 22 target 18 label 0 ] edge [ source 22 target 19 label 0 ] edge [ source 22 target 20 label 0 ] edge [ source 22 target 21 label 0 ] edge [ source 22 target 22 label 0 ] edge [ source 23 target 1 label 0 ] edge [ source 23 target 2 label 0 ] edge [ source 23 target 3 label 0 ] edge [ source 23 target 4 label 0 ] edge [ source 23 target 5 label 0 ] edge [ source 23 target 6 label 0 ] edge [ source 23 target 7 label 0 ] edge [ source 23 target 8 label 0 ] edge [ source 23 target 9 label 0 ] edge [ source 23 target 10 label 0 ] edge [ source 23 target 11 label 0 ] edge [ source 23 target 12 label 0 ] edge [ source 23 target 13 label 0 ] edge [ source 23 target 14 label 0 ] edge [ source 23 target 15 label 0 ] edge [ source 23 target 16 label 0 ] edge [ source 23 target 17 label 0 ] edge [ source 23 target 18 label 0 ] edge [ source 23 target 19 label 0 ] edge [ source 23 target 20 label 0 ] edge [ source 23 target 21 label 0 ] edge [ source 23 target 22 label 0 ] edge [ source 23 target 23 label 0 ] edge [ source 24 target 1 label 0 ] edge [ source 24 target 2 label 0 ] edge [ source 24 target 3 label 0 ] edge [ source 24 target 4 label 0 ] edge [ source 24 target 5 label 0 ] edge [ source 24 target 6 label 0 ] edge [ source 24 target 7 label 0 ] edge [ source 24 target 8 label 0 ] edge [ source 24 target 9 label 0 ] edge [ source 24 target 10 label 0 ] edge [ source 24 target 11 label 0 ] edge [ source 24 target 12 label 0 ] edge [ source 24 target 13 label 0 ] edge [ source 24 target 14 label 0 ] edge [ source 24 target 15 label 0 ] edge [ source 24 target 16 label 0 ] edge [ source 24 target 17 label 0 ] edge [ source 24 target 18 label 0 ] edge [ source 24 target 19 label 0 ] edge [ source 24 target 20 label 0 ] edge [ source 24 target 21 label 0 ] edge [ source 24 target 22 label 0 ] edge [ source 24 target 23 label 0 ] edge [ source 24 target 24 label 0 ] edge [ source 25 target 1 label 0 ] edge [ source 25 target 2 label 0 ] edge [ source 25 target 3 label 0 ] edge [ source 25 target 4 label 0 ] edge [ source 25 target 5 label 0 ] edge [ source 25 target 6 label 0 ] edge [ source 25 target 7 label 0 ] edge [ source 25 target 8 label 0 ] edge [ source 25 target 9 label 0 ] edge [ source 25 target 10 label 0 ] edge [ source 25 target 11 label 0 ] edge [ source 25 target 12 label 0 ] edge [ source 25 target 13 label 0 ] edge [ source 25 target 14 label 0 ] edge [ source 25 target 15 label 0 ] edge [ source 25 target 16 label 0 ] edge [ source 25 target 17 label 0 ] edge [ source 25 target 18 label 0 ] edge [ source 25 target 19 label 0 ] edge [ source 25 target 20 label 0 ] edge [ source 25 target 21 label 0 ] edge [ source 25 target 22 label 0 ] edge [ source 25 target 23 label 0 ] edge [ source 25 target 24 label 0 ] edge [ source 25 target 25 label 0 ] edge [ source 26 target 1 label 0 ] edge [ source 26 target 2 label 0 ] edge [ source 26 target 3 label 0 ] edge [ source 26 target 4 label 0 ] edge [ source 26 target 5 label 0 ] edge [ source 26 target 6 label 0 ] edge [ source 26 target 7 label 0 ] edge [ source 26 target 8 label 0 ] edge [ source 26 target 9 label 0 ] edge [ source 26 target 10 label 0 ] edge [ source 26 target 11 label 0 ] edge [ source 26 target 12 label 0 ] edge [ source 26 target 13 label 0 ] edge [ source 26 target 14 label 0 ] edge [ source 26 target 15 label 0 ] edge [ source 26 target 16 label 0 ] edge [ source 26 target 17 label 0 ] edge [ source 26 target 18 label 0 ] edge [ source 26 target 19 label 0 ] edge [ source 26 target 20 label 0 ] edge [ source 26 target 21 label 0 ] edge [ source 26 target 22 label 0 ] edge [ source 26 target 23 label 0 ] edge [ source 26 target 24 label 0 ] edge [ source 26 target 25 label 0 ] edge [ source 26 target 26 label 0 ] edge [ source 27 target 1 label 0 ] edge [ source 27 target 2 label 0 ] edge [ source 27 target 3 label 0 ] edge [ source 27 target 4 label 0 ] edge [ source 27 target 5 label 0 ] edge [ source 27 target 6 label 0 ] edge [ source 27 target 7 label 0 ] edge [ source 27 target 8 label 0 ] edge [ source 27 target 9 label 0 ] edge [ source 27 target 10 label 0 ] edge [ source 27 target 11 label 0 ] edge [ source 27 target 12 label 0 ] edge [ source 27 target 13 label 0 ] edge [ source 27 target 14 label 0 ] edge [ source 27 target 15 label 0 ] edge [ source 27 target 16 label 0 ] edge [ source 27 target 17 label 0 ] edge [ source 27 target 18 label 0 ] edge [ source 27 target 19 label 0 ] edge [ source 27 target 20 label 0 ] edge [ source 27 target 21 label 0 ] edge [ source 27 target 22 label 0 ] edge [ source 27 target 23 label 0 ] edge [ source 27 target 24 label 0 ] edge [ source 27 target 25 label 0 ] edge [ source 27 target 26 label 0 ] edge [ source 27 target 27 label 0 ] edge [ source 28 target 1 label 0 ] edge [ source 28 target 2 label 0 ] edge [ source 28 target 3 label 0 ] edge [ source 28 target 4 label 0 ] edge [ source 28 target 5 label 0 ] edge [ source 28 target 6 label 0 ] edge [ source 28 target 7 label 0 ] edge [ source 28 target 8 label 0 ] edge [ source 28 target 9 label 0 ] edge [ source 28 target 10 label 0 ] edge [ source 28 target 11 label 0 ] edge [ source 28 target 12 label 0 ] edge [ source 28 target 13 label 0 ] edge [ source 28 target 14 label 0 ] edge [ source 28 target 15 label 0 ] edge [ source 28 target 16 label 0 ] edge [ source 28 target 17 label 0 ] edge [ source 28 target 18 label 0 ] edge [ source 28 target 19 label 0 ] edge [ source 28 target 20 label 0 ] edge [ source 28 target 21 label 0 ] edge [ source 28 target 22 label 0 ] edge [ source 28 target 23 label 0 ] edge [ source 28 target 24 label 0 ] edge [ source 28 target 25 label 0 ] edge [ source 28 target 26 label 0 ] edge [ source 28 target 27 label 0 ] edge [ source 28 target 28 label 0 ] edge [ source 29 target 1 label 0 ] edge [ source 29 target 2 label 0 ] edge [ source 29 target 3 label 0 ] edge [ source 29 target 4 label 0 ] edge [ source 29 target 5 label 0 ] edge [ source 29 target 6 label 0 ] edge [ source 29 target 7 label 0 ] edge [ source 29 target 8 label 0 ] edge [ source 29 target 9 label 0 ] edge [ source 29 target 10 label 0 ] edge [ source 29 target 11 label 0 ] edge [ source 29 target 12 label 0 ] edge [ source 29 target 13 label 0 ] edge [ source 29 target 14 label 0 ] edge [ source 29 target 15 label 0 ] edge [ source 29 target 16 label 0 ] edge [ source 29 target 17 label 0 ] edge [ source 29 target 18 label 0 ] edge [ source 29 target 19 label 0 ] edge [ source 29 target 20 label 0 ] edge [ source 29 target 21 label 0 ] edge [ source 29 target 22 label 0 ] edge [ source 29 target 23 label 0 ] edge [ source 29 target 24 label 0 ] edge [ source 29 target 25 label 0 ] edge [ source 29 target 26 label 0 ] edge [ source 29 target 27 label 0 ] edge [ source 29 target 28 label 0 ] edge [ source 29 target 29 label 0 ] edge [ source 30 target 1 label 0 ] edge [ source 30 target 2 label 0 ] edge [ source 30 target 3 label 0 ] edge [ source 30 target 4 label 0 ] edge [ source 30 target 5 label 0 ] edge [ source 30 target 6 label 0 ] edge [ source 30 target 7 label 0 ] edge [ source 30 target 8 label 0 ] edge [ source 30 target 9 label 0 ] edge [ source 30 target 10 label 0 ] edge [ source 30 target 11 label 0 ] edge [ source 30 target 12 label 0 ] edge [ source 30 target 13 label 0 ] edge [ source 30 target 14 label 0 ] edge [ source 30 target 15 label 0 ] edge [ source 30 target 16 label 0 ] edge [ source 30 target 17 label 0 ] edge [ source 30 target 18 label 0 ] edge [ source 30 target 19 label 0 ] edge [ source 30 target 20 label 0 ] edge [ source 30 target 21 label 0 ] edge [ source 30 target 22 label 0 ] edge [ source 30 target 23 label 0 ] edge [ source 30 target 24 label 0 ] edge [ source 30 target 25 label 0 ] edge [ source 30 target 26 label 0 ] edge [ source 30 target 27 label 0 ] edge [ source 30 target 28 label 0 ] edge [ source 30 target 29 label 0 ] edge [ source 30 target 30 label 0 ] ] ocamlgraph-1.8.3/INSTALL0000644000175000017500000000067512133565071013642 0ustar mehdimehdi =========================== How to create the library ? =========================== You need Objective Caml >= 3.10.2 to compile this library. Configure with ./configure Compile with make Install (as root if needed) with make install findlib users may also do make install-findlib ================================= How to create the documentation ? ================================= create a local documentation with make doc ocamlgraph-1.8.3/FAQ0000644000175000017500000000672212133565071013142 0ustar mehdimehdi========================== FREQUENTLY ASKED QUESTIONS ========================== ========== Q: I need to store some information into vertices and/or edges I need several kind of labels on the edges ----- A: Use one of the functor implementation provided in Persistent or Imperative. If for instance you want mutable directed graphs with colored vertices, you may do type color = Red | Green | Blue | Yellow module G = Imperative.Digraph.Abstract(struct type t = color end) (to be able to change the color you would use `type t = color ref' instead) ========== ========== Q: How to choose between concrete and abstract vertices for my graph implementation? ----- A: If you fall into one of the following cases, use abstract vertices: - you cannot provide efficient comparison/hash functions for vertices; or - you wish to get two different vertices with the same label. In other cases, it is certainly easier to use concrete vertices. ========== ========== Q: Is it possible to serialize graphs? ----- A: Graphs are serializable data structures: just call [Pervasives.output_value] on your graph (for example). But abstract graphs use integer tags to identify vertices; this tag is made from the global reference [Blocks.cpt_vertex]. There are two related issues. 1) If there are abstract vertices in RAM while unmarshalling some others, you have to be sure that RAM vertices do not share tags with unmarshalled ones (except if you really want that). 2) If you need to create new vertices after unserialising an abstract graph, you have to: - serialize [!Blocks.cpt_vertex]; - call function [Blocks.after_unserialization] after your unserialisation process. There is no issue with concrete graph: it may be easier to use them if unmarshalling is required. ========== ========== Q: I need Foobar-Tarjan algorithm and it is not provided ----- A: Please contribute by sending us the code :-) See next question. ========== ========== Q: How can I contribute to this library? ----- A: You can contribute either with a graph data structure or with an algorithm over graphs. For the former, please follow the signatures given in module Sig. For the latter, write your algorithm as a functor, following examples in modules Path, Flow, Components, etc. ========== ========== Q: Your implementation of algorithm AAA could be greatly improved provided you add this and this into the graph data structure ----- A: Of course yes. But the idea behind ocamlgraph is to be as generic as possible (any algorithm should be useable on any implementation). When the graph data structure provides additional capabilities (such as marking, etc.) it is possible to provide a more efficient implementation into some specialized functor. See module Traverse for instance (where DFS and cycle detection are optimized for imperative graphs equipped with marks) ========== ========== Q: I have a graph implementation with polymorphic types for vertices or edges and thus I can't apply the algorithms functors ----- A: Here we bump into Ocaml's type system limitations: the number of type parameters must be know when the functor is written and the simplest choice for us was to assume no type parameter at all. (This is exactly the same for functors Set.Make or Map.Make from Ocaml standard library.) As a (bad) workaround, you can copy the functor body and substitute your own functions for the functor arguments. ========== ocamlgraph-1.8.3/META.in0000644000175000017500000000016512133565071013661 0ustar mehdimehdiversion = "VERSION" description = "Generic Graph Library" requires="" archive(byte) = "CMA" archive(native) = "CMXA" ocamlgraph-1.8.3/src/0000755000175000017500000000000012133565071013370 5ustar mehdimehdiocamlgraph-1.8.3/src/fixpoint.mli0000644000175000017500000001173412133565070015740 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright (c) 2010 - 2012 Technische Universitaet Muenchen * Markus W. Weissmann * All rights reserved. *) (** Fixpoint computation implemented using the work list algorithm. This module makes writing data-flow analysis easy. One of the simplest fixpoint analysis is that of reachability. Given a directed graph module [G], its analysis can be implemented as follows: {[ module Reachability = Graph.Fixpoint.Make(G) (struct type vertex = G.E.vertex type edge = G.E.t type g = G.t type data = bool let direction = Graph.Fixpoint.Forward let equal = (=) let join = (||) let analyze _ = (fun x -> x) end) ]} The types for [vertex], [edge] and [g] are those of the graph to be analyzed. The [data] type is [bool]: It will tell if the vertex is reachable from the start vertex. The [equal] operation for [bool] is simply structural equality; the [join] operation is logical or. The [analyze] function is very simple, too: If the predecessor vertex is reachable, so is the successor vertex of the edge. To use the analysis, an instance of a graph [g] is required. For this analysis a predicate [is_root_vertex : G.E.vertex -> bool] is required to initialize the reachability of the root vertex to [true] and of all other vertices to [false]. {[ let g = ... let result = Reachability.analyze is_root_vertex g ]} The [result] is a map of type [G.E.vertex -> bool] that can be queried for every vertex to tell if the vertex is reachable from the root vertex. @author Markus W. Weissmann @see "Introduction to Lattices and Order" B. A. Davey and H. A. Priestley, Cambridge University Press, 2002 @see "Fixed Point Theory" Andrzej Granas and James Dugundji, Springer, 2003 @see "Principles of Program Analysis" Flemming Nielson, Hanne Riis Nielson and Chris Hankin, Springer, 2005 @see "Ubersetzerbau 3: Analyse und Transformation" Reinhard Wilhelm and Helmut Seidl, Springer, 2010 *) (** Minimal graph signature for work list algorithm *) module type G = sig type t module V : Sig.COMPARABLE module E : sig type t val dst : t -> V.t val src : t -> V.t end val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val succ_e : t -> V.t -> E.t list val pred_e : t -> V.t -> E.t list val succ : t -> V.t -> V.t list val pred : t -> V.t -> V.t list end type direction = Forward | Backward (** Type of an analysis *) module type Analysis = sig type data (** information stored at each vertex *) type edge (** type of edges of the underlying graph *) type vertex (** type of vertices of the underlying graph *) type g (** type of the underlying graph *) val direction : direction (** the direction of the analysis *) val join : data -> data -> data (** operation how to join data when paths meet *) val equal : data -> data -> bool (** predicate to determine the fixpoint *) val analyze : edge -> data -> data (** the actual analysis of one edge; provided the edge and the incoming data, it needs to compute the outgoing data *) end module Make (G : G) (A : Analysis with type g = G.t with type edge = G.E.t with type vertex = G.V.t) : sig val analyze : (G.V.t -> A.data) -> A.g -> (G.V.t -> A.data) (** [analyze f g] computes the fixpoint on the given graph using the work list algorithm. Beware that a misconstructed Analysis will not terminate! [f] is used to create the initial analysis data. The function returned is a map to see what data was computed for which node. Beware of applying function [analyze] partially, to arguments [f] and [g] only. The result is a function that is to be used to query the result of the analysis. *) end ocamlgraph-1.8.3/src/graphml.mli0000644000175000017500000000461412133565071015532 0ustar mehdimehdi(******************************************************************************) (* *) (* Copyright (C) 2012 Pietro Abate *) (* *) (* This library is free software: 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, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (* *) (******************************************************************************) (** Generic GraphMl Printer *) (** Graph information required by Graphml *) module type G = sig type t type vertex module E : sig type t val src: t -> vertex val dst : t -> vertex end val is_directed : bool val iter_vertex : (vertex -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit end (** Graphml Printer given a graph and required info *) module Print (G: G) (L : sig val vertex_properties : (string * string * string option) list (** List of the type of the vertex proprierties. The format is (id,type,default). *) val edge_properties : (string * string * string option) list (** List of the type of the edge proprierties. *) val map_vertex : G.vertex -> (string * string) list (** Associates to each vertex a key/value list where the key is the id of a vertex attribute and the value is the value associated to this vertex *) val map_edge : G.E.t -> (string * string) list (** Associates to each edge a key/value list *) val vertex_uid : G.vertex -> int (** @return a unique integer identifier for the vertex *) val edge_uid : G.E.t -> int (** @return a unique integer identifier for the edge *) end) : sig val print : Format.formatter -> G.t -> unit (** [print fmt graph] print the GraphMl representation of the given graph on the given formatter *) end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/flow.ml0000644000175000017500000002201512133565070014670 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module type FLOW = sig type t type label val max_capacity : label -> t val min_capacity : label -> t val flow : label -> t val add : t -> t -> t val sub : t -> t -> t val zero : t val compare : t -> t -> int end module type G_GOLDBERG = sig type t module V : Sig.COMPARABLE module E : Sig.EDGE with type vertex = V.t val nb_vertex : t -> int val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit val fold_succ_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val fold_pred_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end module Goldberg(G: G_GOLDBERG)(F: FLOW with type label = G.E.label) = struct module V = Hashtbl.Make(G.V) module E = Hashtbl.Make(Util.HTProduct(G.V)(G.V)) module Se = Set.Make(G.E) module Sv = Set.Make(G.V) let excedents = V.create 997 let hauteur = V.create 997 let flot = E.create 997 let fold_booleen f = List.fold_left (fun r x->(f x) or r) false let capacite_restante g e = F.sub (F.max_capacity (G.E.label e)) (E.find flot (G.E.src e, G.E.dst e)) let reste_excedent x = F.compare (V.find excedents x) F.zero > 0 let flux_et_reflux g x = let s = G.fold_succ_e (fun e s-> if F.compare (capacite_restante g e) (F.min_capacity (G.E.label e)) > 0 then e::s else s) g x [] in G.fold_pred_e (fun e s -> if F.compare (E.find flot (G.E.src e, G.E.dst e)) (F.min_capacity (G.E.label e)) > 0 then (G.E.create (G.E.dst e) (G.E.label e) (G.E.src e))::s else s) g x s let pousser g e l = let x, y = G.E.src e, G.E.dst e in let ex = V.find excedents x in let cxy = capacite_restante g e in if F.compare ex F.zero > 0 && F.compare cxy (F.min_capacity (G.E.label e)) > 0 && V.find hauteur x = (V.find hauteur y + 1) then let d = if F.compare ex cxy < 0 then ex else cxy in let fxy = E.find flot (x,y) in let ex = V.find excedents x in let ey = V.find excedents y in E.replace flot (x,y) (F.add fxy d); E.replace flot (y,x) (F.sub F.zero (F.add fxy d)); V.replace excedents x (F.sub ex d); V.replace excedents y (F.add ey d); if reste_excedent x then l:=Sv.add x !l; if reste_excedent y then l:=Sv.add y !l; true else (if F.compare ex F.zero > 0 then l:=Sv.add x !l; false) let elever g p x = let u = flux_et_reflux g x in reste_excedent x && not (G.V.equal x p) && List.for_all (fun e -> (V.find hauteur (G.E.src e)) <= (V.find hauteur (G.E.dst e))) u && (let min = List.fold_left (fun m e -> min (V.find hauteur (G.E.dst e)) m) max_int u in V.replace hauteur x (1+min); true) let init_preflot g s p = G.iter_vertex (fun x -> V.add excedents x F.zero; V.add hauteur x 0) g; G.iter_edges_e (fun e -> let x,y = G.E.src e, G.E.dst e in E.add flot (x,y) (F.flow (G.E.label e)); E.add flot (y,x) (F.sub F.zero (F.flow (G.E.label e)))) g; V.add hauteur s (G.nb_vertex g); G.fold_succ_e (fun e l -> let y = G.E.dst e in let c = F.max_capacity (G.E.label e) in E.add flot (s,y) c; E.add flot (y,s) (F.sub F.zero c); V.add excedents y c; y::l) g s [] let maxflow g s p = let push_and_pull l x = G.fold_succ_e (fun e r->pousser g e l or r) g x false or G.fold_pred_e (fun e r->pousser g e l or r) g x false in let todo = ref (init_preflot g s p) in while (fold_booleen (elever g p) !todo) or (let l = ref Sv.empty in let r = fold_booleen (push_and_pull l) !todo in todo:=Sv.elements !l; r) do () done; let flot_max = G.fold_pred_e (fun e f -> F.add (E.find flot (G.E.src e,p)) f) g p F.zero in let flot_init = G.fold_pred_e (fun e f -> F.add (F.flow (G.E.label e)) f) g p F.zero in let f e = let x,y = G.E.src e, G.E.dst e in try E.find flot (x,y) with Not_found -> F.flow (G.E.label e) in f, F.sub flot_max flot_init end (*****************************************************************************) module type G_FORD_FULKERSON = sig type t module V : Sig.HASHABLE module E : sig type t type label val src : t -> V.t val dst : t -> V.t val label : t -> label end val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit val iter_pred_e : (E.t -> unit) -> t -> V.t -> unit end module Ford_Fulkerson (G: G_FORD_FULKERSON) (F: FLOW with type label = G.E.label) = struct (* redefinition of F *) module F = struct include F type u = | Flow of F.t | Infinity let min x y = match x, y with | Flow _, Infinity -> x | Flow fx, Flow fy when F.compare fx fy < 0 -> x | (Infinity, _) | (Flow _, Flow _) -> y end module Mark = struct module H = Hashtbl.Make(G.V) type mark = Plus | Minus let marked = H.create 997 let unvisited = Queue.create () let clear () = H.clear marked let mem = H.mem marked let set s e tag = assert (not (mem s)); H.add marked s (e, tag); Queue.add s unvisited let get s : G.E.t * mark = let e, tag = H.find marked s in (match e with None -> assert false | Some e -> e), tag exception Empty = Queue.Empty let next () = Queue.pop unvisited end module Result = struct module H = Hashtbl.Make (struct open G type t = E.t module U = Util.HTProduct(V)(V) let equal e1 e2 = U.equal (E.src e1, E.dst e1) (E.src e2, E.dst e2) let hash e = U.hash (E.src e, E.dst e) end) let create () = H.create 997 let find = H.find let flow r e = try find r e with Not_found -> let f = F.flow (G.E.label e) in H.add r e f; f let change op r e f = try H.replace r e (op (find r e) f); with Not_found -> assert false let grow = change F.add let reduce = change F.sub end let is_full r e = F.compare (F.max_capacity (G.E.label e)) (Result.flow r e) = 0 let is_empty r e = F.compare (F.min_capacity (G.E.label e)) (Result.flow r e) = 0 let set_flow r s t a = let rec loop t = if not (G.V.equal s t) then let e, tag = Mark.get t in match tag with | Mark.Plus -> Result.grow r e a; loop (G.E.src e) | Mark.Minus -> Result.reduce r e a; loop (G.E.dst e) in loop t let grow_flow r s t a = let rec loop u b = if G.V.equal s u then begin match b with | F.Infinity -> (* source = destination *) assert (G.V.equal s t); a | F.Flow f -> set_flow r s t f; F.add a f end else let e, tag = Mark.get u in let l = G.E.label e in match tag with | Mark.Plus -> loop (G.E.src e) (F.min b (F.Flow (F.sub (F.max_capacity l) (Result.flow r e)))) | Mark.Minus -> loop (G.E.dst e) (F.min b (F.Flow (F.sub (Result.flow r e) (F.min_capacity l)))) in loop t F.Infinity let maxflow g s t = let r = Result.create () in let succ s = G.iter_succ_e (fun e -> assert (G.V.equal s (G.E.src e)); let t = G.E.dst e in if not (Mark.mem t || is_full r e) then Mark.set t (Some e) Mark.Plus) g s in let pred s = G.iter_pred_e (fun e -> assert (G.V.equal s (G.E.dst e)); let t = G.E.src e in if not (Mark.mem t || is_empty r e) then Mark.set t (Some e) Mark.Minus) g s in let internal_loop a = try while true do let s = Mark.next () in succ s; pred s done; assert false with Mark.Empty -> if Mark.mem t then grow_flow r s t a else a in let rec external_loop a = Mark.clear (); Mark.set s None Mark.Plus; let a' = internal_loop a in if a = a' then a else external_loop a' in let a = external_loop F.zero in (fun e -> try Result.find r e with Not_found -> F.flow (G.E.label e)), a end ocamlgraph-1.8.3/src/persistent.ml0000644000175000017500000002263312133565071016130 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Sig open Util open Blocks module type S = sig (** Persistent Unlabeled Graphs *) module Concrete (V: COMPARABLE) : Sig.P with type V.t = V.t and type V.label = V.t and type E.t = V.t * V.t and type E.label = unit (** Abstract Persistent Unlabeled Graphs *) module Abstract(V: sig type t end) : Sig.P with type V.label = V.t and type E.label = unit (** Persistent Labeled Graphs *) module ConcreteLabeled (V: COMPARABLE)(E: ORDERED_TYPE_DFT) : Sig.P with type V.t = V.t and type V.label = V.t and type E.t = V.t * E.t * V.t and type E.label = E.t (** Abstract Persistent Labeled Graphs *) module AbstractLabeled (V: sig type t end)(E: ORDERED_TYPE_DFT) : Sig.P with type V.label = V.t and type E.label = E.t end module P = Make(Make_Map) type 'a abstract_vertex = { tag : int; label : 'a } (* Vertex for the abstract persistent graphs. *) module AbstractVertex(V: sig type t end) = struct type label = V.t type t = label abstract_vertex let compare x y = Pervasives.compare x.tag y.tag let hash x = x.tag let equal x y = x.tag = y.tag let label x = x.label let create l = if !cpt_vertex = first_value_for_cpt_vertex - 1 then invalid_arg "Too much vertices"; incr cpt_vertex; { tag = !cpt_vertex; label = l } end module Digraph = struct module Concrete(V:COMPARABLE) = struct include P.Digraph.Concrete(V) let remove_vertex g v = if HM.mem v g then let g = HM.remove v g in HM.fold (fun k s -> HM.add k (S.remove v s)) g empty else g end module ConcreteLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT) = struct include P.Digraph.ConcreteLabeled(V)(E) let remove_vertex g v = if HM.mem v g then let g = HM.remove v g in let remove v = S.filter (fun (v2, _) -> not (V.equal v v2)) in HM.fold (fun k s -> HM.add k (remove v s)) g empty else g end module ConcreteBidirectional(V: COMPARABLE) = struct include P.Digraph.ConcreteBidirectional(V) let remove_vertex g v = if HM.mem v g then let remove v = S.filter (fun v' -> not (V.equal v v')) in let g = fold_pred (fun v' acc -> let in_set, out_set = HM.find v' acc in HM.add v' (in_set, remove v out_set) acc) g v g in let g = fold_succ (fun v' acc -> let in_set, out_set = HM.find v' acc in HM.add v' (remove v in_set, out_set) acc) g v g in HM.remove v g else g end module ConcreteBidirectionalLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT) = struct include P.Digraph.ConcreteBidirectionalLabeled(V)(E) let remove_vertex (g:t) (v:vertex) = if HM.mem v g then let remove v = S.filter (fun (v', _) -> not (V.equal v v')) in let g = fold_pred (fun v' acc -> let in_set, out_set = HM.find v' acc in HM.add v' (in_set, remove v out_set) acc) g v g in let g = fold_succ (fun v' acc -> let in_set, out_set = HM.find v' acc in HM.add v' (remove v in_set, out_set) acc) g v g in HM.remove v g else g end module Abstract(V: sig type t end) = struct include P.Digraph.Abstract(AbstractVertex(V)) let empty = { edges = G.empty; size = 0 } let add_vertex g v = if mem_vertex g v then g else { edges = G.unsafe_add_vertex g.edges v; size = Pervasives.succ g.size } let add_edge g v1 v2 = let g = add_vertex g v1 in let g = add_vertex g v2 in { g with edges = G.unsafe_add_edge g.edges v1 v2 } let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_vertex g v = if HM.mem v g.edges then let e = HM.remove v g.edges in let e = HM.fold (fun k s g -> HM.add k (S.remove v s) g) e HM.empty in { edges = e; size = Pervasives.pred g.size } else g let remove_edge g v1 v2 = { g with edges = remove_edge g v1 v2 } let remove_edge_e g e = { g with edges = remove_edge_e g e } end module AbstractLabeled(V: sig type t end)(Edge: ORDERED_TYPE_DFT) = struct include P.Digraph.AbstractLabeled(AbstractVertex(V))(Edge) let empty = { edges = G.empty; size = 0 } let add_vertex g v = if mem_vertex g v then g else { edges = G.unsafe_add_vertex g.edges v; size = Pervasives.succ g.size } let add_edge_e g (v1, l, v2) = let g = add_vertex g v1 in let g = add_vertex g v2 in { g with edges = G.unsafe_add_edge g.edges v1 (v2, l) } let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) let remove_vertex g v = if HM.mem v g.edges then let remove v s = S.fold (fun (v2, _ as e) s -> if not (V.equal v v2) then S.add e s else s) s S.empty in let edges = HM.remove v g.edges in { edges = HM.fold (fun k s g -> HM.add k (remove v s) g) edges HM.empty; size = Pervasives.pred g.size } else g let remove_edge g v1 v2 = { g with edges = remove_edge g v1 v2 } let remove_edge_e g e = { g with edges = remove_edge_e g e } end end module Graph = struct module Concrete(V: COMPARABLE) = struct module G = struct include Digraph.Concrete(V) type return = t end include Graph(G) (* Export some definitions of [G] *) let empty = G.empty (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge g v1 v2 = let g = G.add_edge g v1 v2 in assert (G.HM.mem v1 g && G.HM.mem v2 g); G.unsafe_add_edge g v2 v1 let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_edge g v1 v2 = let g = G.remove_edge g v1 v2 in assert (G.HM.mem v1 g && G.HM.mem v2 g); G.unsafe_remove_edge g v2 v1 let remove_edge_e g (v1, v2) = remove_edge g v1 v2 end module ConcreteLabeled(V: COMPARABLE)(Edge: ORDERED_TYPE_DFT) = struct module G = struct include Digraph.ConcreteLabeled(V)(Edge) type return = t end include Graph(G) (* Export some definitions of [G] *) let empty = G.empty (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge_e g (v1, l, v2 as e) = let g = G.add_edge_e g e in assert (G.HM.mem v1 g && G.HM.mem v2 g); G.unsafe_add_edge g v2 (v1, l) let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) let remove_edge g v1 v2 = let g = G.remove_edge g v1 v2 in assert (G.HM.mem v1 g && G.HM.mem v2 g); G.unsafe_remove_edge g v2 v1 let remove_edge_e g (v1, l, v2 as e) = let g = G.remove_edge_e g e in assert (G.HM.mem v1 g && G.HM.mem v2 g); G.unsafe_remove_edge_e g (v2, l, v1) end module Abstract(V: sig type t end) = struct module G = struct include Digraph.Abstract(V) type return = t end include Graph(G) (* Export some definitions of [G] *) let empty = G.empty (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge g v1 v2 = let g = G.add_edge g v1 v2 in assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); { g with G.edges = G.unsafe_add_edge g.G.edges v2 v1 } let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_edge g v1 v2 = let g = G.remove_edge g v1 v2 in assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); { g with G.edges = G.unsafe_remove_edge g.G.edges v2 v1 } let remove_edge_e g (v1, v2) = remove_edge g v1 v2 end module AbstractLabeled (V: sig type t end)(Edge: ORDERED_TYPE_DFT) = struct module G = struct include Digraph.AbstractLabeled(V)(Edge) type return = t end include Graph(G) (* Export some definitions of [G] *) let empty = G.empty (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge_e g (v1, l, v2 as e) = let g = G.add_edge_e g e in assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); { g with G.edges = G.unsafe_add_edge g.G.edges v2 (v1, l) } let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) let remove_edge g v1 v2 = let g = G.remove_edge g v1 v2 in assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); { g with G.edges = G.unsafe_remove_edge g.G.edges v2 v1 } let remove_edge_e g (v1, l, v2 as e) = let g = G.remove_edge_e g e in assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); { g with G.edges = G.unsafe_remove_edge_e g.G.edges (v2, l, v1) } end end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/nonnegative.ml0000644000175000017500000005732612133565071016254 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This module is a contribution of Yuto Takei *) open Sig open Blocks open Printf module type WEIGHT = sig type label type t val weight : label -> t val compare : t -> t -> int val add : t -> t -> t val zero : t end module Imperative (G: Sig.IM) (W: WEIGHT with type label = G.E.label) = struct module S = Set.Make(G.V) module M = Map.Make(G.V) module V = G.V module E = G.E (* [G.t] represents graph itself. [unit M.t] maintains a list of source vertices to keep track of distances for all vertices. [(G.E.t option * W.t) M.t M.t] holds mappings for all vertices, each of which contains its shortest-path tree ancestor (parent) and a distances from source vertices. *) type t = G.t * S.t ref * (G.E.t option * W.t) M.t M.t ref type edge = G.edge type vertex = G.vertex let sov v = string_of_int (Obj.magic (V.label v)) let dump_cycle cycle = let v0 = G.E.src (List.hd cycle) in print_string ("(" ^ (sov v0) ^ ")"); let v1 = List.fold_left (fun v e -> assert ((G.V.compare v (G.E.src e)) = 0); let v = G.E.dst e in print_string ("-(" ^ (sov v) ^ ")"); v) v0 cycle in assert (v0 = v1); print_string "\n" let dump_set = S.iter (fun x -> print_string ((sov x) ^ ", ")) let dump (src, dist) = print_string "====================\nS: "; dump_set !src; print_string "\nMap:"; M.iter (fun k v -> print_string ("\n " ^ (sov k) ^ ": "); M.iter (fun k (origin, dist) -> print_string ( "(" ^ (sov k) ^ ">>" ^ (match origin with | None -> "---" | Some e -> (sov (G.E.src e)) ^ ">" ^ (sov (G.E.dst e))) ^ ":" ^ (string_of_int (Obj.magic dist)) ^ ") ")) v) !dist; print_string "\n" (* If an edge is going to be added to the graph, which will cause a negative cycle, raises [Negative_cycle] with edges that can form such the cycle. *) exception Negative_cycle of G.E.t list let create ?size () = let g = match size with | Some size -> G.create ~size () | None -> G.create () in (g, ref S.empty, ref M.empty) let copy (g, src, dist) = (G.copy g, ref (!src), ref (!dist)) let clear (g, src, dist) = G.clear g; src := S.empty; dist := M.empty let add_vertex (g, src, dist) v = (* Before adding vertex to the graph, make sure that the vertex is not in the graph. If already in the graph, just do nothing and return as is. *) if not (G.mem_vertex g v) then begin (* Add a vertex to the original one *) G.add_vertex g v; (* The new vertex will immediately be added to the source list *) src := S.add v !src; (* The new edge should contain a distance mapping with only from myself with distance zero. *) dist := M.add v (M.add v (None, W.zero) M.empty) !dist; dump (src, dist) end let rec propagate (g, src, dist) q start = if Queue.is_empty q then (g, src, dist) else begin let (v1, v1src) = Queue.pop q in let v1dist = M.find v1 dist in let dist = G.fold_succ_e (fun e dist -> let v2 = G.E.dst e in let v2dist = if M.mem v2 dist then M.find v2 dist else M.empty in (* Compare distances from given source vertices. If relax happens, record it to the new list. *) let (v2dist, nextSrc) = S.fold (fun x (v2dist, nextSrc) -> let _, dev1 = M.find x v1dist in let ndev2 = W.add dev1 (W.weight (G.E.label e)) in let improvement = try let _, dev2 = M.find x v2dist in W.compare ndev2 dev2 < 0 with Not_found -> true in if improvement then let v2dist = M.add x (Some e, ndev2) v2dist in let nextSrc = S.add x nextSrc in (v2dist, nextSrc) else (v2dist, nextSrc) ) v1src (v2dist, S.empty) in if S.is_empty nextSrc then dist else if G.V.equal start v2 then (* Propagation reaches back to the starting node, which immediately means presence of a negative cycle. *) (* We should use one of 'src' to traverse to the start node *) let dist = M.add v2 v2dist dist in let cycle = S.fold (fun s x -> let rec build_cycle x ret = match M.find s (M.find x dist) with | Some e, _ -> let y = G.E.src e in let cycle = e :: ret in if G.V.equal start y then Some cycle else build_cycle y cycle | _ -> None in match x with | None -> build_cycle v2 [] | Some _ -> x) nextSrc None in let cycle = match cycle with | Some x -> x | None -> assert false in dump_cycle cycle; raise (Negative_cycle cycle) else begin (* TODO: Some room for improvement. If queue has (v2, s) already, technically we can merge nextSrc into s, so that the number of propagation can be reduced. *) Queue.push (v2, nextSrc) q; M.add v2 v2dist dist end ) g v1 dist in propagate (g, src, dist) q start end let m_cardinal m = M.fold (fun _ _ acc -> acc+1) m 0 let set_of_map m = M.fold (fun k _ acc -> S.add k acc) m S.empty let add_edge_internal (g, src, dist) v1 v2 = (* Distance mappings at v1 *) let dv1 = M.find v1 dist in (* To reduce the amount of codes, we just start propagation from v1. Of course, this can be optimized by starting from v2. But it may duplicate the same code in multiple places in the file. In addition, such an optimization only cost for small amount, which precisely is the operations to relax edges from v1, other than which have been existed before this [add_edge_e] call. *) let q = Queue.create () in (* We need to check whether v2 should be kept in the source list or not. That is, if there maybe a cycle with v1, the distance from v1 should be still maintained. Otherwise, simply ignore the distance from v2 *) if m_cardinal dv1 = 1 && M.mem v2 dv1 then ( (* Now we definitely introduced a loop (and possibly non-negative)! Let me see if this would be negative or not... *) Queue.add (v1, (S.add v2 S.empty)) q; propagate (g, src, dist) q v1 ) else ( (* Or even if we fall back to else-clause here, the edge addition may have introduced a cycle. Anyway, we need to check if one is newly created or not at [propagate] *) let (src, dist, dv1) = if not (S.mem v2 src) then (* If v2 isn't one of the source vertices, just simply do propagation. *) (src, dist, dv1) else (* We can exclude v2 from the list of source because one can reach v2 from some other vertex. *) let src = S.remove v2 src in (* Note that following line can be skipped only if the user don't remove vertex. Otherwise, such operation like [add_edge g v1 v2] > [remove_vertex g v2] > [add_vertex g v2] can result in unexpected behavior. *) let dist = M.map (M.remove v2) dist in (* We need to re-obtain the distance mappings at v1, since it can be changed by the line above. *) let dv1 = M.find v1 dist in (src, dist, dv1) in (* Now let's start propagation. *) Queue.add (v1, set_of_map dv1) q; propagate (g, src, dist) q v1) let add_edge_e (g, src, dist) e = (* Before adding edge to the graph, make sure that the edge is not in the graph. If already in the graph, just do nothing and return as is. *) if not (G.mem_edge_e g e) then begin (* Vertices involved *) let v1 = G.E.src e in let v2 = G.E.dst e in List.iter (add_vertex (g, src, dist)) [v1 ; v2]; begin try (* Because we can restore the graph by calling [G.remove_edge_e] even in case of failure, we first add it by [G.add_edge_e]. *) G.add_edge_e g e; let (_, src', dist') = add_edge_internal (g, !src, !dist) v1 v2 in src := src'; dist := dist' with exp -> (* In case of excecption, restore the graph by removing the edge, and rethrow the exception. *) G.remove_edge_e g e; raise exp end; dump (src, dist) end let add_edge (g, src, dist) v1 v2 = (* Same as [add_edge_e] *) if not (G.mem_edge g v1 v2) then begin List.iter (add_vertex (g, src, dist)) [v1 ; v2]; begin try (* Because we cannot know the default value for edge length, we first try to add one by [G.add_edge]. If there occurs an exception, restore the graph by [G.remove_edge] since there were no other connections between [v1] and [v2]. *) G.add_edge g v1 v2; let (_, src', dist') = add_edge_internal (g, !src, !dist) v1 v2 in src := src'; dist := dist' with exp -> (* In case of excecption, restore the graph by removing the edge, and rethrow the exception. *) G.remove_edge g v1 v2; raise exp end; dump (src, dist) end let remove_edge_internal (g, src) v2 = (* Actually, we need to rebuild the distance table, rather than traverse precedants to remove the edge. *) let q = Queue.create () in print_string ("dump: "); dump_set src; let dist = S.fold (fun x dist -> print_string ("source: " ^ (sov x) ^ "\n"); Queue.add (x, (S.add x S.empty)) q; M.add x (M.add x (None, W.zero) M.empty) dist) src M.empty in let g, src, dist = propagate (g, src, dist) q (S.choose src) in if M.mem v2 dist then (g, src, dist) else ( Queue.add (v2, (S.add v2 S.empty)) q; let src = S.add v2 src in let dist = M.add v2 (M.add v2 (None, W.zero) M.empty) dist in propagate (g, src, dist) q v2) let remove_edge_e (g, src, dist) e = (* Same as [add_edge_e] *) if G.mem_edge_e g e then begin G.remove_edge_e g e; (* Vertices involved *) let v2 = G.E.dst e in let (_, src', dist') = remove_edge_internal (g, !src) v2 in src := src'; dist := dist'; dump (src, dist) end let remove_edge (g, src, dist) v1 v2 = (* Same as [add_edge] *) if G.mem_edge g v1 v2 then begin G.remove_edge g v1 v2; let (_, src', dist') = remove_edge_internal (g, !src) v2 in src := src'; dist := dist'; dump (src, dist) end let remove_vertex (g, src, dist) v = (* Same as [add_edge] *) if G.mem_vertex g v then begin (* [remove_vertex] first deletes all outgoing edges from [v] *) G.iter_succ_e (fun e -> remove_edge_e (g, src, dist) e) g v; (* Then after, deletes all incoming edges to [v] *) G.iter_pred_e (fun e -> remove_edge_e (g, src, dist) e) g v; (* Note that we are iterating on [g] that is being modified during iteration. We can do such an above iteration since G is here permanent. Do not try this for imperative graph. *) (* Now we can feel free to delete [v]. *) G.remove_vertex g v; src := S.remove v !src; dist := M.remove v (M.map (M.remove v) !dist); dump (src, dist) end let map_vertex f (g, src, dist) = let map_map update m = M.fold (fun v m acc -> M.add (f v) (update m) acc) m M.empty in let (g, src, dist) = (G.map_vertex f g, S.fold (fun v acc -> S.add (f v) acc) !src S.empty, let update = function | None, _ as v -> v | Some e, w -> Some (E.create (f (E.src e)) (E.label e) (f (E.dst e))), w in map_map (map_map update) !dist) in (g, ref src, ref dist) let fold_pred_e f (g, _, _) = G.fold_pred_e f g let iter_pred_e f (g, _, _) = G.iter_pred_e f g let fold_succ_e f (g, _, _) = G.fold_succ_e f g let iter_succ_e f (g, _, _) = G.iter_succ_e f g let fold_pred f (g, _, _) = G.fold_pred f g let fold_succ f (g, _, _) = G.fold_succ f g let iter_pred f (g, _, _) = G.iter_pred f g let iter_succ f (g, _, _) = G.iter_succ f g let fold_edges_e f (g, _, _) = G.fold_edges_e f g let iter_edges_e f (g, _, _) = G.iter_edges_e f g let fold_edges f (g, _, _) = G.fold_edges f g let iter_edges f (g, _, _) = G.iter_edges f g let fold_vertex f (g, _, _) = G.fold_vertex f g let iter_vertex f (g, _, _) = G.iter_vertex f g let pred_e (g, _, _) = G.pred_e g let succ_e (g, _, _) = G.succ_e g let pred (g, _, _) = G.pred g let succ (g, _, _) = G.succ g let find_all_edges (g, _, _) = G.find_all_edges g let find_edge (g, _, _) = G.find_edge g let mem_edge_e (g, _, _) = G.mem_edge_e g let mem_edge (g, _, _) = G.mem_edge g let mem_vertex (g, _, _) = G.mem_vertex g let in_degree (g, _, _) = G.in_degree g let out_degree (g, _, _) = G.out_degree g let nb_edges (g, _, _) = G.nb_edges g let nb_vertex (g, _, _) = G.nb_vertex g let is_empty (g, _, _) = G.is_empty g let is_directed = G.is_directed module Mark = struct type graph = t type vertex = G.vertex let clear g = let (g, _, _) = g in G.Mark.clear g let get = G.Mark.get let set = G.Mark.set end end module Persistent (G: Sig.P) (W: WEIGHT with type label = G.E.label) = struct module S = Set.Make(G.V) module M = Map.Make(G.V) module E = G.E module V = G.V (* [G.t] represents graph itself. [unit M.t] maintains a list of source vertices to keep track of distances for all vertices. [(G.E.t option * W.t) M.t M.t] holds mappings for all vertices, each of which contains its shortest-path tree ancestor (parent) and a distances from source vertices. *) type t = G.t * S.t * (G.E.t option * W.t) M.t M.t type edge = G.edge type vertex = G.vertex (* If an edge is going to be added to the graph, which will cause a negative cycle, raises [Negative_cycle] with edges that can form such the cycle. *) exception Negative_cycle of G.E.t list let empty : t = let g = G.empty in let src = S.empty in let dist = M.empty in (g, src, dist) let add_vertex (g, src, dist) v = (* Before adding vertex to the graph, make sure that the vertex is not in the graph. If already in the graph, just do nothing and return as is. *) if G.mem_vertex g v then (g, src, dist) else (* Add a vertex to the original one *) (G.add_vertex g v), (* The new vertex will immediately be added to the source list *) (S.add v src), (* The new edge should contain a distance mapping with only from myself with distance zero. *) (M.add v (M.add v (None, W.zero) M.empty) dist) let rec propagate (g, src, dist) q start = if Queue.is_empty q then (g, src, dist) else begin let (v1, v1src) = Queue.pop q in let v1dist = M.find v1 dist in let dist = G.fold_succ_e (fun e dist -> let v2 = G.E.dst e in let v2dist = M.find v2 dist in (* Compare distances from given source vertices. If relax happens, record it to the new list. *) let (v2dist, nextSrc) = S.fold (fun x (v2dist, nextSrc) -> let _, dev1 = M.find x v1dist in let ndev2 = W.add dev1 (W.weight (G.E.label e)) in let improvement = try let _, dev2 = M.find x v2dist in W.compare ndev2 dev2 < 0 with Not_found -> true in if improvement then let v2dist = M.add x (Some e, ndev2) v2dist in let nextSrc = S.add x nextSrc in (v2dist, nextSrc) else (v2dist, nextSrc) ) v1src (v2dist, S.empty) in if S.is_empty nextSrc then dist else if G.V.equal start v2 then (* Propagation reaches back to the starting node, which immediately means presence of a negative cycle. *) (* We should use one of 'src' to traverse to the start node *) let s = S.choose nextSrc in let rec build_cycle x ret = match M.find s (M.find x dist) with | Some e, _ -> let y = G.E.src e in let cycle = e :: ret in if G.V.equal start y then cycle else build_cycle y cycle | _ -> assert false in raise (Negative_cycle (build_cycle v2 [])) else begin (* TODO: Some room for improvement. If queue has (v2, s) already, technically we can merge nextSrc into s, so that the number of propagation can be reduced. *) Queue.push (v2, nextSrc) q; M.add v2 v2dist dist end ) g v1 dist in propagate (g, src, dist) q start end let m_cardinal m = M.fold (fun _ _ acc -> acc+1) m 0 let set_of_map m = M.fold (fun k _ acc -> S.add k acc) m S.empty let add_edge_internal (g, src, dist) v1 v2 = (* Distance mappings at v1 *) let dv1 = M.find v1 dist in (* To reduce the amount of codes, we just start propagation from v1. Of course, this can be optimized by starting from v2. But it may duplicate the same code in multiple places in the file. In addition, such an optimization only cost for small amount, which precisely is the operations to relax edges from v1, other than which have been existed before this [add_edge_e] call. *) let q = Queue.create () in (* We need to check whether v2 should be kept in the source list or not. That is, if there maybe a cycle with v1, the distance from v1 should be still maintained. Otherwise, simply ignore the distance from v2 *) if m_cardinal dv1 = 1 && M.mem v2 dv1 then ( (* Now we definitely introduced a loop (but possibly non-negative)! Let me see if this would be negative or not... *) Queue.add (v1, (S.add v2 S.empty)) q; propagate (g, src, dist) q v1 ) else ( (* Or even if we fall back to else-clause here, the edge addition may have introduced a cycle. Anyway, we need to check if one is newly created or not at [propagate] *) let (src, dist, dv1) = if not (S.mem v2 src) then (* If v2 isn't one of the source vertices, just simply do propagation. *) (src, dist, dv1) else (* We can exclude v2 from the list of source because one can reach v2 from some other vertex. *) ((S.remove v2 src), (* Note that following line can be skipped only if the user don't remove vertex. Otherwise, such operation like [add_edge g v1 v2] > [remove_vertex g v2] > [add_vertex g v2] can result in unexpected behaviour. *) (M.map (M.remove v2) dist), (* We need to re-obtain the distance mappings at v1, since it can be changed by the line above. *) (M.find v1 dist)) in (* Now let's start propagation. *) Queue.add (v1, set_of_map dv1) q; propagate (g, src, dist) q v1) let add_edge_e (g, src, dist) e = (* Before adding edge to the graph, make sure that the edge is not in the graph. If already in the graph, just do nothing and return as is. *) if G.mem_edge_e g e then (g, src, dist) else begin (* Vertices involved *) let v1 = G.E.src e in let v2 = G.E.dst e in let (g, src, dist) = List.fold_left add_vertex (g, src, dist) [v1 ; v2] in let g = G.add_edge_e g e in add_edge_internal (g, src, dist) v1 v2 end let add_edge (g, src, dist) v1 v2 = (* Same as [add_edge_e] *) if G.mem_edge g v1 v2 then (g, src, dist) else begin let (g, src, dist) = List.fold_left add_vertex (g, src, dist) [v1 ; v2] in let g = G.add_edge g v1 v2 in add_edge_internal (g, src, dist) v1 v2 end let remove_edge_internal (g, src) v2 = (* Actually, we need to rebuild the distance table, rather than traverse precedants to remove the edge. *) let q = Queue.create () in let dist = S.fold (fun x dist -> Queue.add (x, (S.add x S.empty)) q; M.add x (M.add x (None, W.zero) M.empty) dist) src M.empty in let g, src, dist = propagate (g, src, dist) q (S.choose src) in if M.mem v2 dist then (g, src, dist) else ( Queue.add (v2, (S.add v2 S.empty)) q; let src = S.add v2 src in let dist = M.add v2 (M.add v2 (None, W.zero) M.empty) dist in propagate (g, src, dist) q v2) let remove_edge_e (g, src, dist) e = (* Same as [add_edge_e] *) if not (G.mem_edge_e g e) then (g, src, dist) else begin let g = G.remove_edge_e g e in (* Vertices involved *) let v2 = G.E.dst e in remove_edge_internal (g, src) v2 end let remove_edge (g, src, dist) v1 v2 = (* Same as [add_edge] *) if not (G.mem_edge g v1 v2) then (g, src, dist) else begin let g = G.remove_edge g v1 v2 in remove_edge_internal (g, src) v2 end let remove_vertex t v = (* [remove_vertex] first deletes all outgoing edges from [v] *) let (g, _, _) = t in let t = G.fold_succ_e (fun e t -> remove_edge_e t e) g v t in (* Then after, deletes all incoming edges to [v] *) let (g, _, _) = t in let t = G.fold_pred_e (fun e t -> remove_edge_e t e) g v t in (* Note that we are iterating on [g] that is being modified during iteration. We can do such an above iteration since G is here permanent. Do not try this for imperative graph. *) let (g, src, dist) = t in (* Now we can feel free to delete [v]. *) (G.remove_vertex g v, (S.remove v src), (M.map (M.remove v) dist)) let map_vertex f (g, src, dist) = let map_map update m = M.fold (fun v m acc -> M.add (f v) (update m) acc) m M.empty in (G.map_vertex f g, S.fold (fun v acc -> S.add (f v) acc) src S.empty, let update = function | None, _ as v -> v | Some e, w -> Some (E.create (f (E.src e)) (E.label e) (f (E.dst e))), w in map_map (map_map update) dist) (* All below are wrappers *) let fold_pred_e f (g, _, _) = G.fold_pred_e f g let iter_pred_e f (g, _, _) = G.iter_pred_e f g let fold_succ_e f (g, _, _) = G.fold_succ_e f g let iter_succ_e f (g, _, _) = G.iter_succ_e f g let fold_pred f (g, _, _) = G.fold_pred f g let fold_succ f (g, _, _) = G.fold_succ f g let iter_pred f (g, _, _) = G.iter_pred f g let iter_succ f (g, _, _) = G.iter_succ f g let fold_edges_e f (g, _, _) = G.fold_edges_e f g let iter_edges_e f (g, _, _) = G.iter_edges_e f g let fold_edges f (g, _, _) = G.fold_edges f g let iter_edges f (g, _, _) = G.iter_edges f g let fold_vertex f (g, _, _) = G.fold_vertex f g let iter_vertex f (g, _, _) = G.iter_vertex f g let pred_e (g, _, _) = G.pred_e g let succ_e (g, _, _) = G.succ_e g let pred (g, _, _) = G.pred g let succ (g, _, _) = G.succ g let find_all_edges (g, _, _) = G.find_all_edges g let find_edge (g, _, _) = G.find_edge g let mem_edge_e (g, _, _) = G.mem_edge_e g let mem_edge (g, _, _) = G.mem_edge g let mem_vertex (g, _, _) = G.mem_vertex g let in_degree (g, _, _) = G.in_degree g let out_degree (g, _, _) = G.out_degree g let nb_edges (g, _, _) = G.nb_edges g let nb_vertex (g, _, _) = G.nb_vertex g let is_empty (g, _, _) = G.is_empty g let is_directed = G.is_directed end ocamlgraph-1.8.3/src/dot.ml0000644000175000017500000001570212133565070014514 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Parser for DOT file format *) open Dot_ast let parse_dot_ast_from_chan c = let lb = Lexing.from_channel c in let dot = try Dot_parser.file Dot_lexer.token lb with Parsing.Parse_error -> let n = Lexing.lexeme_start lb in failwith (Printf.sprintf "Dot.parse: parse error character %d" n) in close_in c; dot let parse_dot_ast f = let c = open_in f in parse_dot_ast_from_chan c type clusters_hash = (string, attr list) Hashtbl.t let get_string = function | String s -> s | Ident s -> s | Number s -> s | Html s -> s module Parse (B : Builder.S) (L : sig val node : node_id -> attr list -> B.G.V.label (** how to build the node label out of the set of attributes *) val edge : attr list -> B.G.E.label (** how to build the edge label out of the set of attributes *) end) = struct module Attr = struct module M = Map.Make (struct type t = id let compare : t -> t -> int = Pervasives.compare end) type t = id option M.t let empty = M.empty let add = List.fold_left (fun a (x,v) -> M.add x v a) let addl = List.fold_left add let list a = M.fold (fun x v l -> (x,v) :: l) a [] end let create_graph_and_clusters dot = (* pass 1*) (* collect node attributes *) let def_node_attr = ref Attr.empty in let node_attr = Hashtbl.create 97 in (* collect cluster attributes *) let def_clust_attr = ref Attr.empty in let clust_attr = Hashtbl.create 97 in (* collect clusters nodes *) let clust_nodes = Hashtbl.create 97 in let add_node_attr id al = let l = try Hashtbl.find node_attr id with Not_found -> !def_node_attr in Hashtbl.replace node_attr id (Attr.addl l al) in let add_clust_attr id_opt al = match id_opt with | Some id -> let s = get_string id in let l = try Hashtbl.find clust_attr s with Not_found -> !def_clust_attr in Hashtbl.replace clust_attr s (Attr.addl l al) | _ -> () in let add_clust_node id_cluster id_node = let id_nodes = try Hashtbl.find clust_nodes id_cluster with Not_found -> [] in Hashtbl.add clust_nodes id_cluster (id_node :: id_nodes) in let rec collect_node_attr cluster_op stmts = List.iter ( function | Node_stmt (id, al) -> add_node_attr id al; begin match cluster_op with | Some id_cluster -> add_clust_node id_cluster id | _ -> () end | Attr_node al -> def_node_attr := Attr.addl !def_node_attr al | Edge_stmt (NodeId id, nl, _) -> add_node_attr id []; List.iter (function | NodeId id -> add_node_attr id [] | _ -> ()) nl | Subgraph (SubgraphDef (id, stmts)) -> collect_node_attr (Some id) stmts | Attr_graph al -> begin match cluster_op with | Some id -> add_clust_attr id al | None -> () end | _ -> () ) stmts in collect_node_attr None dot.stmts; (* pass 2: build the graph and the clusters *) let def_edge_attr = ref Attr.empty in let nodes = Hashtbl.create 97 in let node g id l = try g, Hashtbl.find nodes id with Not_found -> let l = try Hashtbl.find node_attr id with Not_found -> Attr.empty in let n = B.G.V.create (L.node id [Attr.list l]) in Hashtbl.add nodes id n; B.add_vertex g n, n in let rec add_stmts g stmts = List.fold_left (fun g s -> match s with | Node_stmt (id, al) -> let g,_ = node g id al in g | Edge_stmt (NodeId id, nl, al) -> let al = Attr.addl !def_edge_attr al in let el = L.edge [Attr.list al] in let g,vn = node g id [] in fst (List.fold_left (fun (g,pvn) m -> match m with | NodeId idm -> let g,vm = node g idm [] in let e = B.G.E.create pvn el vm in ((B.add_edge_e g e),vm) | NodeSub _ -> (g,pvn)) (g,vn) nl) | Attr_edge al -> def_edge_attr := Attr.addl !def_edge_attr al; g | Subgraph (SubgraphDef (_, stmts)) -> add_stmts g stmts | _ -> g ) g stmts in let graph = add_stmts (B.empty ()) dot.stmts in let clusters_hash = let h = Hashtbl.create 30 in Hashtbl.iter (fun k a -> Hashtbl.add h k [Attr.list a]) clust_attr; h in graph, clusters_hash let get_graph_bb stmts = let graph_bb = ref None in let read_attr = function | (Ident "bb" , Some (String bb)) -> graph_bb := Some bb | _ -> () in let read_stmt = function | Attr_graph attrs -> List.iter (List.iter read_attr) attrs | _ -> () in List.iter read_stmt stmts; !graph_bb let parse_dot_from_chan c = let lb = Lexing.from_channel c in let dot = try Dot_parser.file Dot_lexer.token lb with Parsing.Parse_error -> let n = Lexing.lexeme_start lb in failwith (Printf.sprintf "Dot.parse: parse error character %d" n) in close_in c; dot let parse_dot f = let c = open_in f in parse_dot_from_chan c let parse f = fst (create_graph_and_clusters (parse_dot f)) let parse_with_bb_from_chan c = let dot = parse_dot_from_chan c in create_graph_and_clusters dot, get_graph_bb dot.stmts let parse_bounding_box_and_clusters f = let dot = parse_dot f in let graph, clusters = create_graph_and_clusters dot in match get_graph_bb dot.stmts with | Some bounding_box -> graph, bounding_box, clusters | None -> failwith "Cannot read bounding box in xdot file" end ocamlgraph-1.8.3/src/kruskal.mli0000644000175000017500000000505512133565071015554 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: kruskal.mli,v 1.5 2005-06-30 10:48:55 filliatr Exp $ *) (** Kruskal's minimum-spanning-tree algorithm. *) (** Minimal graph signature for Kruskal. Sub-signature of {!Sig.G}. *) module type G = sig type t module V : Sig.COMPARABLE module E : sig type t type label val label : t -> label val dst : t -> V.t val src : t -> V.t end val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_edges_e : (E.t -> unit) -> t -> unit end (** Functor providing an implementation of Kruskal's minimum-spanning-tree algorithm. Parameter [W] ensures that label on edges are comparable. *) module Make(G: G)(W: Sig.ORDERED_TYPE with type t = G.E.label) : sig val spanningtree : G.t -> G.E.t list end (** {2 Generic version where union-find implementation is provided} *) (** Signature of union-find. *) module type UNIONFIND = sig type elt type t val init : elt list -> t val find : elt -> t -> elt val union : elt -> elt -> t -> unit end (** Functor providing an implementation of Kruskal's minimum-spanning-tree algorithm using a user-defined union-find algorithm. Parameter [W] ensures that label on edges are comparable. *) module Generic (G: G) (W: Sig.ORDERED_TYPE with type t = G.E.label) (UF: UNIONFIND with type elt = G.V.t) : sig val spanningtree : G.t -> G.E.t list end ocamlgraph-1.8.3/src/topological.ml0000644000175000017500000001254112133565071016241 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module type G = sig type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit end module Make(G: G) = struct module Scc = Components.Make(G) let fold f g acc = (* build the graph of strongly-connected components *) let n, scc = Scc.scc g in let vertices = Array.make n [] in let edges = Array.make n [] in let degree = Array.make n 0 in (* in-degree *) let add_vertex x = let ix = scc x in vertices.(ix) <- x :: vertices.(ix); let add_edge y = let iy = scc y in if ix <> iy then begin edges.(ix) <- iy :: edges.(ix); degree.(iy) <- degree.(iy) + 1 end in G.iter_succ add_edge g x in G.iter_vertex add_vertex g; (* standard topological sort on a DAG *) let todo = Queue.create () in let rec walk acc = if Queue.is_empty todo then acc else let i = Queue.pop todo in let acc = List.fold_right f vertices.(i) acc in List.iter (fun j -> let d = degree.(j) in assert (d > 0); (* no back edge *) if d = 1 then Queue.push j todo else degree.(j) <- d-1) edges.(i); walk acc in for i = 0 to n-1 do if degree.(i) = 0 then Queue.push i todo done; walk acc let iter f g = fold (fun v () -> f v) g () end module Make_stable(G: sig include G val in_degree : t -> V.t -> int end) = struct module H = Hashtbl.Make(G.V) module C = Path.Check(G) let choose ~old (v, n) = let l, min = old in if n = min then v :: l, n else if n < min then [ v ], n else old module Q = struct module S = Set.Make(G.V) type elt = G.V.t type q = S.t ref let create () = ref S.empty let push v s = s := S.add v !s let pop s = let r = S.min_elt !s in s := S.remove r !s; r let is_empty s = S.is_empty !s let choose ~old new_ = let l, n = choose ~old new_ in List.sort G.V.compare l, n end let rec choose_independent_vertex checker = function | [] -> assert false | [ v ] -> v | v :: l -> (* choose [v] if each other vertex [v'] is in the same cycle (a path from v to v') or is in a separate component (no path from v' to v). So, if there is a path from v' to without any path from v to v', discard v. *) if List.for_all (fun v' -> C.check_path checker v v' || not (C.check_path checker v' v)) l then v else choose_independent_vertex checker l (* in case of multiple cycles, choose one vertex in a cycle which does not depend of any other. *) let find_top_cycle checker vl = (* choose [v] if each other vertex [v'] is in the same cycle (a path from v to v') or is in a separate component (no path from v' to v). So, if there is a path from v' to without any path from v to v', discard v. *) let on_top_cycle v = List.for_all (fun v' -> G.V.equal v v' || C.check_path checker v v' || not (C.check_path checker v' v)) vl in List.filter on_top_cycle vl let fold f g acc = let checker = C.create g in let degree = H.create 997 in let todo = Q.create () in let push x = H.remove degree x; Q.push x todo in let rec walk acc = if Q.is_empty todo then (* let's find any node of minimal degree *) let min, _ = H.fold (fun v d old -> Q.choose ~old (v, d)) degree ([], max_int) in match min with | [] -> acc | _ -> let vl = find_top_cycle checker min in List.iter push vl; (* let v = choose_independent_vertex checker min in push v; *) walk acc else let v = Q.pop todo in let acc = f v acc in G.iter_succ (fun x-> try let d = H.find degree x in if d = 1 then push x else H.replace degree x (d-1) with Not_found -> (* [x] already visited *) ()) g v; walk acc in G.iter_vertex (fun v -> let d = G.in_degree g v in if d = 0 then Q.push v todo else H.add degree v d) g; walk acc let iter f g = fold (fun v () -> f v) g () end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/topological.mli0000644000175000017500000000703212133565071016411 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Topological order. This functor provides functions which allow iterating over a graph in topological order. Cycles in graphs are allowed. Specification is the following: if vertex [x] is visited before vertex [y] then either there is a path from [x] to [y], or there is no path from [y] to [x]. In the particular case of a DAG, this simplifies to: if there is an edge from [x] to [y], then [x] is visited before [y]. *) (** Minimal graph signature to provide. Sub-signature of {!Sig.G}. *) module type G = sig type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit end (** Functor providing topological iterators over a graph. *) module Make(G: G) : sig val fold : (G.V.t -> 'a -> 'a) -> G.t -> 'a -> 'a (** [fold action g seed] allows iterating over the graph [g] in topological order. [action node accu] is called repeatedly, where [node] is the node being visited, and [accu] is the result of the [action]'s previous invocation, if any, and [seed] otherwise. If [g] contains cycles, the order is unspecified inside the cycles and every node in the cycles will be presented exactly once. Not tail-recursive. Complexity: O(V+E) *) val iter : (G.V.t -> unit) -> G.t -> unit (** [iter action] calls [action node] repeatedly. Nodes are (again) presented to [action] in topological order. The order is the same as for [fold]. *) end (** Provide the same features than {!Make}, except that the resulting topological ordering is stable according to vertices comparison: if two vertices [v1] and [v2] are topologically equal, [v1] is presented first to the iterator if and only if [G.V.compare v1 v2 <= 0]. In particular, the resulting order is not dependent on the provided hash function. This property is not guaranteed by the functor {!Make}. The counterpart is a less efficient implementation: worst time complexity is O(E*V*ln(V)) instead of O(E*V) (with E = number of edges and V = number of vertices. *) module Make_stable(G: sig include G val in_degree : t -> V.t -> int end): sig val fold : (G.V.t -> 'a -> 'a) -> G.t -> 'a -> 'a val iter : (G.V.t -> unit) -> G.t -> unit end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/builder.ml0000644000175000017500000000452012133565070015350 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Sig module type S = sig module G : Sig.G val empty : unit -> G.t val copy : G.t -> G.t val add_vertex : G.t -> G.V.t -> G.t val add_edge : G.t -> G.V.t -> G.V.t -> G.t val add_edge_e : G.t -> G.E.t -> G.t val remove_vertex : G.t -> G.V.t -> G.t val remove_edge : G.t -> G.V.t -> G.V.t -> G.t val remove_edge_e : G.t -> G.E.t -> G.t end module type INT = S with type G.V.label = int module P(G : Sig.P) = struct module G = G let empty () = G.empty let copy g = g let add_vertex = G.add_vertex let add_edge = G.add_edge let add_edge_e = G.add_edge_e let remove_vertex = G.remove_vertex let remove_edge = G.remove_edge let remove_edge_e = G.remove_edge_e end module I(G : Sig.I) = struct module G = G let empty () = G.create ~size:997 () let copy = G.copy let add_vertex g v = G.add_vertex g v; g let add_edge g v1 v2 = G.add_edge g v1 v2; g let add_edge_e g e = G.add_edge_e g e; g let remove_vertex g v = G.remove_vertex g v; g let remove_edge g v1 v2 = G.remove_edge g v1 v2; g let remove_edge_e g e = G.remove_edge_e g e; g end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/dominator.mli0000644000175000017500000001333712133565070016075 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright © 2009 Carnegie-Mellon University, David Brumley, and Ivan Jager. From the BAP library; see http://bap.ece.cmu.edu *) (** Dominators All of the functions in this module assume that the graph is not modified between calling one of these functions and using the returned functions. Such mutation results in undefined behavior. @author Ivan Jager *) exception Unreachable module type G = sig type t module V : Sig.COMPARABLE val pred : t -> V.t -> V.t list val succ : t -> V.t -> V.t list val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_vertex : (V.t -> unit) -> t -> unit val nb_vertex : t -> int val create: ?size:int -> unit -> t val add_edge : t -> V.t -> V.t -> unit end module Make(G : G) : sig module S : Set.S with type elt = G.V.t (** function from [n] to [n]'s immediate dominator *) type idom = G.V.t -> G.V.t (** [idoms x y] is true when [x] is [y]'s immediate dominator *) type idoms = G.V.t -> G.V.t -> bool (** function from [x] to a list of nodes immediately dominated by [x] *) type dom_tree = G.V.t -> G.V.t list (** function from node to a list of nodes that dominate it. *) type dominators = G.V.t -> G.V.t list (** [dom x y] returns true iff [x] dominates [y] *) type dom = G.V.t -> G.V.t -> bool (** [sdom x y] returns true iff [x] strictly dominates [y]. *) type sdom = G.V.t -> G.V.t -> bool (** function from [x] to a list of nodes not dominated by [x], but with predecessors which are dominated by [x] *) type dom_frontier = G.V.t -> G.V.t list type dom_graph = unit -> G.t type dom_functions = { idom : idom; idoms : idoms; dom_tree : dom_tree; dominators : dominators; dom : dom; sdom : sdom; dom_frontier : dom_frontier; dom_graph : dom_graph } (** Computes the dominator tree, using the Lengauer-Tarjan algorithm. [compute_idom cfg s0] returns a function [idom : V.t -> V.t] s.t. [idom x] returns the immediate dominator of [x] *) val compute_idom : G.t -> G.V.t -> G.V.t -> G.V.t (** Given a function from a node to it's dominators, returns a function [dom : V.t -> V.t -> bool] s.t. [dom x y] returns true when [x] dominates [y] *) val dominators_to_dom : ('a -> S.t) -> S.elt -> 'a -> bool (** Given a function from a node to it's dominators, returns a function [sdom : V.t -> V.t -> bool] s.t. [sdom x y] returns true when [x] strictly dominates [y] *) val dominators_to_sdom : (G.V.t -> S.t) -> S.elt -> G.V.t -> bool val dom_to_sdom : (G.V.t -> G.V.t -> bool) -> G.V.t -> G.V.t -> bool (** Given a a function from a node to it's dominators, returns a function from a node to it's strict dominators. *) val dominators_to_sdominators : (S.elt -> S.t) -> S.elt -> S.t (** Given a function from a node to it's dominators, returns a function [idoms : G.V.t -> G.V.t -> bool] s.t. [idoms x y] returns true when [x] is the immediate dominator of [y]. *) val dominators_to_idoms : (S.elt -> S.t) -> S.elt -> S.elt -> bool (** Computes a dominator tree (function from x to a list of nodes immediately dominated by x) for the given CFG and dominator function. Note: The dominator tree is also called [IDom] by Muchnick. Note: If you are computing a post-dominator tree, then the optional argument pred should be G.succ. *) val dominators_to_dom_tree : G.t -> ?pred:(G.t -> S.elt -> S.elt list) -> (S.elt -> S.t) -> S.elt -> S.t (** Computes a dominator tree (function from x to a list of nodes immediately dominated by x) for the given CFG and idom function. *) val idom_to_dom_tree : G.t -> (G.V.t -> G.V.t) -> G.V.t -> G.V.t list val idom_to_idoms : idom -> G.V.t -> G.V.t -> bool (** Computes the dominance frontier. As specified in section 19.1 of Modern Compiler Implementation in ML by Andrew Appel. *) val compute_dom_frontier : G.t -> dom_tree -> idom -> G.V.t -> G.V.t list val idom_to_dominators : ('a -> 'a) -> 'a -> 'a list val idom_to_dom : (G.V.t -> G.V.t) -> G.V.t -> G.V.t -> bool val compute_dom_graph : G.t -> dom_tree -> G.t (** Computes all dominance functions. This function computes some things eagerly and some lazily, so don't worry about it doing extra work to compute functions you don't need, but also don't call it if you aren't going to use anything it returns. @return a record containing all dominance functions for the given graph and entry node. *) val compute_all : G.t -> G.V.t -> dom_functions end ocamlgraph-1.8.3/src/leaderlist.mli0000644000175000017500000000406612133565071016231 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright (c) 2010 - 2011 Technische Universitaet Muenchen * Markus W. Weissmann * Florian Pichlmeier * All rights reserved. *) (** The leader list algorithm; it generates a list of basic blocks from a directed graph. A basic block is a forward path of nodes that requires neither branching from nor into. *) (** Minimal graph signature for leader list algorithm *) module type G = sig type t module V : Sig.COMPARABLE val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val succ : t -> V.t -> V.t list val pred : t -> V.t -> V.t list end module Make (G : G) : sig val leader_lists : G.t -> G.V.t -> G.V.t list list (** [leader_lists graph root] computes the leader lists or basic blocks of the given graph. The node [root] is always a leader of a basic block. *) end ocamlgraph-1.8.3/src/dot_ast.mli0000644000175000017500000000375112133565070015535 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id:$ *) (** AST for DOT file format. *) type id = | Ident of string | Number of string | String of string | Html of string type attr = (id * id option) list type compass_pt = N | Ne | E | Se | S | Sw | W | Nw type port = | PortId of id * compass_pt option | PortC of compass_pt type node_id = id * port option type subgraph = | SubgraphId of id | SubgraphDef of id option * stmt list and node = | NodeId of node_id | NodeSub of subgraph and stmt = | Node_stmt of node_id * attr list | Edge_stmt of node * node list * attr list | Attr_graph of attr list | Attr_node of attr list | Attr_edge of attr list | Equal of id * id | Subgraph of subgraph type file = { strict : bool; digraph : bool; id : id option; stmts : stmt list } ocamlgraph-1.8.3/src/traverse.ml0000644000175000017500000002335712133565071015567 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Graph traversal *) module type G = sig val is_directed : bool type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_succ : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end (* depth-first search *) module Dfs(G : G) = struct module H = Hashtbl.Make(G.V) let iter ?(pre=fun _ -> ()) ?(post=fun _ -> ()) g = let h = H.create 65537 in let rec visit v = if not (H.mem h v) then begin H.add h v (); pre v; G.iter_succ visit g v; post v end in G.iter_vertex visit g let postfix post g = iter ~post g let iter_component ?(pre=fun _ -> ()) ?(post=fun _ -> ()) g v = let h = H.create 65537 in let rec visit v = H.add h v (); pre v; G.iter_succ (fun w -> if not (H.mem h w) then visit w) g v; post v in visit v let prefix_component pre g = iter_component ~pre g let postfix_component post g = iter_component ~post g (* invariant: not in [h] means not visited at all; [h v = true] means already visited in the current component; [h v = false] means already visited in another tree *) let has_cycle g = let h = H.create 65537 in let rec visit v = H.add h v true; G.iter_succ (fun w -> try if H.find h w then raise Exit with Not_found -> visit w) g v; H.replace h v false in try G.iter_vertex (fun v -> if not (H.mem h v) then visit v) g; false with Exit -> true let has_cycle_undirected g = let h = H.create 65537 in let father = H.create 65537 in let is_father u v = (* u is the father of v in the DFS descent *) try G.V.equal (H.find father v) u with Not_found -> false in let rec visit v = H.add h v true; G.iter_succ (fun w -> try if H.find h w && not (is_father w v) then raise Exit with Not_found -> H.add father w v; visit w) g v; H.remove father v; H.replace h v false in try G.iter_vertex (fun v -> if not (H.mem h v) then visit v) g; false with Exit -> true let has_cycle g = if G.is_directed then has_cycle g else has_cycle_undirected g module Tail = struct let has_cycle g = let h = H.create 65537 in let stack = Stack.create () in let loop () = while not (Stack.is_empty stack) do let v = Stack.top stack in if H.mem h v then begin (* we are now done with node v *) (* assert (H.find h v = true); *) H.replace h v false; ignore (Stack.pop stack) end else begin (* we start DFS from node v *) H.add h v true; G.iter_succ (fun w -> try if H.find h w then raise Exit with Not_found -> Stack.push w stack) g v; end done in try G.iter_vertex (fun v -> if not (H.mem h v) then begin Stack.push v stack; loop () end) g; false with Exit -> true let has_cycle_undirected g = let h = H.create 65537 in let father = H.create 65537 in let is_father u v = (* u is the father of v in the DFS descent *) try G.V.equal (H.find father v) u with Not_found -> false in let stack = Stack.create () in let loop () = while not (Stack.is_empty stack) do let v = Stack.top stack in if H.mem h v then begin (* we are now done with node v *) (* assert (H.find h v = true); *) H.remove father v; H.replace h v false; ignore (Stack.pop stack) end else begin (* we start DFS from node v *) H.add h v true; G.iter_succ (fun w -> try if H.find h w && not (is_father w v) then raise Exit with Not_found -> H.add father w v; Stack.push w stack) g v; end done in try G.iter_vertex (fun v -> if not (H.mem h v) then begin Stack.push v stack; loop () end) g; false with Exit -> true let has_cycle g = if G.is_directed then has_cycle g else has_cycle_undirected g let iter f g = let h = H.create 65537 in let stack = Stack.create () in let loop () = while not (Stack.is_empty stack) do let v = Stack.pop stack in if not (H.mem h v) then begin H.add h v (); f v; G.iter_succ (fun w -> if not (H.mem h w) then Stack.push w stack) g v end done in G.iter_vertex (fun v -> if not (H.mem h v) then begin Stack.push v stack; loop () end) g let iter_component f g v0 = let h = H.create 65537 in let stack = Stack.create () in Stack.push v0 stack; while not (Stack.is_empty stack) do let v = Stack.pop stack in if not (H.mem h v) then begin H.add h v (); f v; G.iter_succ (fun w -> if not (H.mem h w) then Stack.push w stack) g v end done end let prefix = Tail.iter let has_cycle = Tail.has_cycle let prefix_component = Tail.iter_component (* step-by-step iterator *) module S = Set.Make(G.V) type iterator = S.t * G.V.t list * G.t (** (h, st, g) where h is the set of marked vertices and st the stack invariant: the first element of st is not in h i.e. to be visited *) let start g = let st = G.fold_vertex (fun v st -> v :: st) g [] in S.empty, st, g let get (s,st,_) = match st with | [] -> raise Exit | v :: _ -> v let step (s,st,g) = match st with | [] -> raise Exit | v :: st -> let s' = S.add v s in let st' = G.fold_succ (fun w st -> w :: st) g v st in let rec clean = function | w :: st when S.mem w s' -> clean st | st -> st in (s', clean st', g) end (* breadth-first search *) module Bfs(G : G) = struct module H = Hashtbl.Make(G.V) let iter f g = let h = H.create 65537 in let q = Queue.create () in (* invariant: [h] contains exactly the vertices which have been pushed *) let push v = if not (H.mem h v) then begin H.add h v (); Queue.add v q end in let loop () = while not (Queue.is_empty q) do let v = Queue.pop q in f v; G.iter_succ push g v done in G.iter_vertex (fun v -> push v; loop ()) g let iter_component f g v0 = let h = H.create 65537 in let q = Queue.create () in (* invariant: [h] contains exactly the vertices which have been pushed *) let push v = if not (H.mem h v) then begin H.add h v (); Queue.add v q end in push v0; while not (Queue.is_empty q) do let v = Queue.pop q in f v; G.iter_succ push g v done (* step-by-step iterator *) (* simple, yet O(1)-amortized, persistent queues *) module Q = struct type 'a t = 'a list * 'a list exception Empty let empty = [], [] let is_empty = function [], [] -> true | _ -> false let push x (i,o) = (x :: i, o) let pop = function | i, y :: o -> y, (i,o) | [], [] -> raise Empty | i, [] -> match List.rev i with | x :: o -> x, ([], o) | [] -> assert false let peek q = fst (pop q) end module S = Set.Make(G.V) (* state is [(s,q,g)] : [s] contains elements never been pushed in [q] *) type iterator = S.t * G.V.t Q.t * G.t let start g = let s = G.fold_vertex S.add g S.empty in s, Q.empty, g let get (s,q,g) = if Q.is_empty q then if S.is_empty s then raise Exit else S.choose s else Q.peek q let step (s,q,g) = let push v (s,q as acc) = if S.mem v s then S.remove v s, Q.push v q else acc in let v,s',q' = if Q.is_empty q then begin if S.is_empty s then raise Exit; let v = S.choose s in v, S.remove v s, q end else let v,q' = Q.pop q in v, s, q' in let s'',q'' = G.fold_succ push g v (s',q') in (s'',q'',g) end (* Graph traversal with marking. *) module type GM = sig type t module V : sig type t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit module Mark : sig val clear : t -> unit val get : V.t -> int val set : V.t -> int -> unit end end module Mark(G : GM) = struct let dfs g = G.Mark.clear g; let n = ref 0 in let rec visit v = if G.Mark.get v = 0 then begin incr n; G.Mark.set v !n; G.iter_succ visit g v end in G.iter_vertex visit g (* invariant: [h v = 0] means not visited at all; [h v = 1] means already visited in the current component; [h v = 2] means already visited in another tree *) let has_cycle g = G.Mark.clear g; let rec visit v = G.Mark.set v 1; G.iter_succ (fun w -> let m = G.Mark.get w in if m = 1 then raise Exit; if m = 0 then visit w) g v; G.Mark.set v 2 in try G.iter_vertex (fun v -> if G.Mark.get v = 0 then visit v) g; false with Exit -> true end ocamlgraph-1.8.3/src/merge.mli0000644000175000017500000001624712133565071015204 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2012 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Provides functions to extend any module satisfying one of the signatures Sig.P, Sig.I and Builder.S .*) module type S = sig type graph type vertex type edge type edge_label val merge_vertex: graph -> vertex list -> graph (** If no element of [vl] belongs to [g] then [merge_vertex g (v::vl)] is the graph [g]. Otherwise the collection of vertices of [merge_vertex g (v::vl)] is the collection of vertices of [g] from which all the elements of [vl] were removed and to which [v] was added. Any edge of [merge_vertex g (v::vl)] is an edge of [g] whose source (destination) was changed to [v] if it belongs to [vl]. The function [merge_vertex] always returns a graph with a smaller collection of vertices and a smaller collection of edges (in the weak sense). However the labels appearing in [merge_vertex g v::vl] are exactly the ones appearing in [g].*) val merge_edges_e: ?src:vertex -> ?dst:vertex -> graph -> edge list -> graph (** If no element of [el] belongs to [g] then [merge_edges_e g (e::el)] is the graph [g]. Otherwise the collection of vertices of [merge_edges_e g (e::el)] is precisely the collection of vertices of [g] from which the sources and the destinations of all the elements of [el] were removed and to which the vertices [v] and [w] were added. If [dst] was provided then [v] is [src] otherwise it is the source of [e]. If [dst] was provided then [w] is [y] otherwise it is the destination of [e]. The collection of edges of [merge_edges_e g e::el] is precisely the collection of edges of [g] from which all the elements of [el] were removed and to which an edge from [v] to [w] sharing the label of [e] was added; the edges of [g] being understood up to the fact their source and destination were updated. Note [v=w] if and only if the source of some element of [el] matches the destination of some element of [el] (possibly the same).*) val merge_edges_with_label: ?src:vertex -> ?dst:vertex -> ?label:edge_label -> graph -> edge_label -> graph (** The graph [merge_edges_with_label ?src ?tgt ?label g l] is the graph [merge_edges_e ?src ?dst g el] with [el] being the list of all edges of [g] carrying the label [l]. If the optional value [label] is provided then the edge to which all the elements of [el] are identified carries the label [label]. Otherwise it carries the label [l]. In particular [merge_edges_with_label ?src ?tgt ?label g l] is the graph [g] if and only if there is at most one edge of [g] carrying the label [l].*) val merge_isolabelled_edges: graph -> graph (** The graph [merge_isolabelled_edges g] is obtained from [g] by identifying two vertices when they are the sources (destinations) of two edges sharing the same label. Therefore two distinct edges of the returned graph cannot carry the same label. In particular if all the edges share the same label then the returned graph is either empty (if [g] is so) or a single vertex (if [g] has no edge and at least one vertex) or a single vertex and a single edge (if [g] has both a vertex and an edge). A label is carried by some edge of [merge_isolabelled_edges g] if and only if it is carried by some edge of [g].*) val merge_ends: ?strict:bool -> ?specified_vertex:vertex -> graph -> graph (** A vertex [v] of [g] is called an end if every edge of [g] arriving to [v] also starts from [v]. It is called a strict end if no edge of [g] arrives to it. The graph [merge_ends g] is the graph [merge_vertex vl] where [vl] is the list of (strict) ends of [g]. The vertex substituted to the ends can be specified.*) val merge_starts: ?strict:bool -> ?specified_vertex:vertex -> graph -> graph (** A vertex [v] of [g] is called a start if every edge of [g] starting from [v] also arrives to [v]. It is called a strict start if no edge of [g] starts from it. The graph [merge_starts g] is the graph [merge_vertex vl] where [vl] is the list of (strict) starts of [g]. The vertex substituted to the starts can be specified.*) val merge_scc: ?loop_killer:bool -> ?specified_vertex:(vertex list -> vertex) -> graph -> graph (** The vertex of every strongly connected component are identified. If the option [loop_killer] is set to [true] then all the edges between identified vertices are removed. The option [specified_vertex] allows to choose the vertex that replaces the elements of a strongly connected component.*) end (** Extension for the module [X].*) module B(X: Builder.S) : S with type graph = X.G.t and type vertex := X.G.vertex and type edge := X.G.edge and type edge_label = X.G.E.label (**Extension for the module [G].*) module P(G: Sig.P): S with type graph = G.t and type vertex := G.vertex and type edge := G.edge and type edge_label = G.E.label (**Extension for the module [G].*) module I(G: Sig.I): sig (** Same specification than module type {!S} but modify the graph inplace instead of returning a new graph. *) type graph = G.t type vertex = G.vertex type edge = G.edge type edge_label = G.E.label val merge_vertex: graph -> vertex list -> unit val merge_edges_e: ?src:vertex -> ?dst:vertex -> graph -> edge list -> unit val merge_edges_with_label: ?src:vertex -> ?dst:vertex -> ?label:edge_label -> graph -> edge_label -> unit val merge_isolabelled_edges: graph -> unit val merge_ends: ?strict:bool -> ?specified_vertex:vertex -> graph -> unit val merge_starts: ?strict:bool -> ?specified_vertex:vertex -> graph -> unit val merge_scc: ?loop_killer:bool -> ?specified_vertex:(vertex list -> vertex) -> graph -> unit end with type graph = G.t and type vertex := G.vertex and type edge := G.edge and type edge_label = G.E.label (* Local Variables: compile-command: "make -C .." End: *) (*OCaml >= 3.12*) ocamlgraph-1.8.3/src/cliquetree.ml0000644000175000017500000002205712133565070016071 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module CliqueTree(Gr : Sig.G) = struct (* Original vertex set (of Gr) *) module OVSet = Set.Make(Gr.V) (* Vertex signature *) module rec CliqueV : sig type t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool val label : t -> t val create : Gr.V.t -> t val vertex : t -> Gr.V.t val number : t -> int val set_number : t -> int -> unit val clique : t -> int val set_clique : t -> int -> unit val mark : t -> int val incr_mark : t -> unit val m : t -> CVS.t val set_m : t -> CVS.t -> unit val last : t -> t val set_last : t -> t -> unit end = struct type t = { mutable mark: int; orig: Gr.V.t; mutable m: CVS.t; mutable last: t option; mutable number: int; mutable clique: int; } let compare x y = Gr.V.compare x.orig y.orig let hash x = Gr.V.hash x.orig let equal x y = Gr.V.equal x.orig y.orig type label = t let label x = x let create o = { mark = 0; orig = o; m = CVS.empty; last = None; number = 0; clique = -1; } let vertex x = x.orig let clique x = x.clique let set_clique x v = x.clique <- v let number x = x.number let set_number x v = x.number <- v let mark x = x.mark let incr_mark x = (*Printf.printf "Increasing mark of %s to %i\n%!" (Gr.v_to_string x.orig) (succ x.mark);*) x.mark <- succ x.mark let m x = x.m let set_m x v = x.m <- v let last x = match x.last with Some v -> v | None -> failwith "last not set" let set_last x v = x.last <- Some v end (* Clique tree vertex set *) and CVS : Set.S with type elt = CliqueV.t = Set.Make(CliqueV) (* The final clique tree vertex type: - set of original vertexes ordered by mark. - clique number. *) module CliqueTreeV = Util.DataV (struct type t = CliqueV.t list * CVS.t end) (struct type t = int type label = int let compare : t -> t -> int = Pervasives.compare let hash = Hashtbl.hash let equal x y = x = y let label x = x let create lbl = lbl end) module CliqueTreeE = struct type t = int * CVS.t let compare (x, _ : t) (y, _ : t) = Pervasives.compare x y let default = (0, CVS.empty) let create n s = (n, s) let vertices = snd let width g tri (_, x) = let vertices = List.map CliqueV.vertex (CVS.elements x) in let w = List.fold_left (fun w v -> List.fold_left (fun w v' -> if v <> v' then if not (Gr.mem_edge g v v') && Gr.mem_edge tri v v' then succ w else w else w) w vertices) 0 vertices in assert(w mod 2 = 0); w / 2 end (* The returned tree *) module CliqueTree = Persistent.Digraph.ConcreteLabeled(CliqueTreeV)(CliqueTreeE) (* Intermediate graph *) module G = Persistent.Graph.Concrete(CliqueV) (* Convenient types *) module EdgeSet = Set.Make(G.E) module H = Hashtbl.Make(CliqueV) (* Used to choose some vertex in the intermediate graph *) module Choose = Oper.Choose(G) (* Creates the intermediate graph from the original *) module Copy = Gmap.Vertex(Gr)(struct include G include Builder.P(G) end) open CliqueV let vertices_list x = let l = CVS.elements x in List.sort (fun x y -> (*let markx = mark x and marky = mark y in*) (Pervasives.compare : int -> int -> int) (number y) (number x)) l let mcs_clique g = (* initializations *) let n = Gr.nb_vertex g in let g' = Copy.map CliqueV.create g in let unnumbered = ref (G.fold_vertex CVS.add g' CVS.empty) in let pmark = ref (-1) in let order = ref [] in let cliques = Array.make n ([], CVS.empty) in let ties = ref [] in let j = ref 0 in (* loop, taking each unnumbered vertex in turn *) for i = n downto 1 do (* Find greatest unnumbered vertex if CVS.is_empty !unnumbered then Printf.printf "No more unnumbered vertices\n%!" else Printf.printf "%i unnumbered vertices remaining\n%!" (CVS.cardinal !unnumbered); *) let x, mark = let choosed = CVS.choose !unnumbered in CVS.fold (fun x ((maxx, maxv) as max) -> let v = mark x in if v > maxv then (x, v) else max) !unnumbered (choosed, mark choosed) in (* peo construction *) order := x :: !order; (* now numbered *) unnumbered := CVS.remove x !unnumbered; if mark <= !pmark then begin (* Create a new clique (lemma 8) *) incr j; (* m x is the neighborhoud of x in the previous clique *) cliques.(!j) <- ([x], CVS.add x (m x)); (* Use reverse map of cliques to find what clique we're connected to. m x is the width of the ties *) let clast = clique (last x) in ties := (clast, m x, !j) :: !ties; end else begin let l, c = cliques.(!j) in cliques.(!j) <- (x::l, CVS.add x c); end; G.iter_succ (fun y -> if number y == 0 then begin incr_mark y; set_m y (CVS.add x (m y)); end; set_last y x) g' x; pmark := mark; set_number x i; set_clique x !j; done; let cliques = Array.mapi (fun i (l, c) -> CliqueTreeV.create (List.rev l, c) i) (Array.sub cliques 0 (succ !j)) in let tree = Array.fold_left CliqueTree.add_vertex CliqueTree.empty cliques in let tree, _ = List.fold_left (fun (g, n) (i, verts, j) -> let label = CliqueTreeE.create n verts in let edge = CliqueTree.E.create cliques.(i) label cliques.(j) in (CliqueTree.add_edge_e g edge, succ n)) (tree, 1) !ties in List.map CliqueV.vertex !order, tree, cliques.(0) let sons g x = CliqueTree.fold_succ (fun x y -> x :: y) g x [] exception NotClique let rec drop_while p l = match l with | x :: tl -> if p x then drop_while p tl else l | [] -> [] let test_simpliciality_first l sons = let takeOne l = match !l with | x :: xs -> l := xs; Some x | [] -> None in let vertices = ref l in let sons = ref sons in try while !vertices <> [] && not (List.for_all (fun c -> !c = []) !sons) do (match takeOne vertices with Some v -> let mark = CliqueV.mark v in List.iter (fun s -> match !s with | y :: tl -> let ymark = CliqueV.mark y in if ymark > mark then () else if ymark = mark then s := drop_while (fun y -> CliqueV.mark y = mark) tl else raise NotClique | [] -> ()) !sons | None -> assert false); done; !vertices <> [] with NotClique -> false let test_simpliciality_first' l sons = List.for_all (fun son -> match !son with | [] -> false | xi :: tl -> let other = m xi in CVS.subset other l) sons let test_simpliciality_next vertices sons = match vertices with | x :: tl -> begin try ignore( List.fold_left (fun vm v' -> let vm' = CliqueV.m v' in if CVS.equal vm' vm then CVS.add v' vm' else raise NotClique) (CVS.add x (m x)) tl); true with NotClique -> false end | _ -> true let is_chordal g = let order, tree, root = mcs_clique g in let rec aux c = let csons = sons tree c in let s = List.map CliqueTreeV.data csons in let l = CliqueTreeV.data c in let sons () = List.map (fun (x,y) -> ref x) s in let first = test_simpliciality_first' (snd l) (sons ()) in let next = test_simpliciality_next (fst l) (sons ()) in first && next && (List.for_all aux csons) in aux root let maxwidth g tri tree = CliqueTree.fold_edges_e (fun e res -> let w = CliqueTreeE.width g tri (CliqueTree.E.label e) in max res w) tree 0 end ocamlgraph-1.8.3/src/minsep.mli0000644000175000017500000000561512133565071015375 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Minimal separators of a graph Based on the article: Generating all the minimal separators of a graph. by A. Berry, J.-P. Bordat and O.Cogis http://www.isima.fr/berry/generating.html A set [S] of vertices is a minimal separator if it exists 2 distinct connected components [C] and [D] in [G \ S] such that each vertex of [S] has a successor in [C] and [D]. *) (** Minimal signature for computing the minimal separators *) module type G = sig type t module V : Sig.COMPARABLE val succ: t -> V.t -> V.t list val iter_succ: (V.t -> unit) -> t -> V.t -> unit val fold_succ: (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val iter_vertex: (V.t -> unit) -> t -> unit val fold_vertex: (V.t -> 'a -> 'a) -> t -> 'a -> 'a end module type MINSEP = sig module G : G (** Implementation of a graph *) module Vertex_Set : Set.S with type elt = G.V.t (** Implementation of a set of vertex *) module VSetset : Set.S with type elt = Vertex_Set.t (** Implementation of a set of [Vertex_Set] *) val allminsep : G.t -> Vertex_Set.t list (** [allminsep g] computes the list of all minimal separators of g. *) val list_of_allminsep : G.t -> G.V.t list list (** Less efficient that [allminsep] *) val set_of_allminsep : G.t -> VSetset.t (** Less efficient that [allminsep] *) end (** Implementation for a persistent graph *) module P(G : sig include G val remove_vertex : t -> V.t -> t end) : MINSEP with module G = G (** Implementation for an imperative graph. Less efficient that the implementation for a persistent graph *) module I(G : sig include G module Mark : Sig.MARK with type graph = t and type vertex = V.t end) : MINSEP with module G = G ocamlgraph-1.8.3/src/builder.mli0000644000175000017500000000432112133565070015520 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Graph builders in order to persistent/imperative graphs sharing a same signature. *) open Sig (** {2 Common interface for graph builders}. Note: the following functions always return graphs but this is meaningless for imperative implementations (the graph is modified in-place). This is just to provide a common interface. *) module type S = sig module G : Sig.G val empty : unit -> G.t val copy : G.t -> G.t val add_vertex : G.t -> G.V.t -> G.t val add_edge : G.t -> G.V.t -> G.V.t -> G.t val add_edge_e : G.t -> G.E.t -> G.t val remove_vertex : G.t -> G.V.t -> G.t val remove_edge : G.t -> G.V.t -> G.V.t -> G.t val remove_edge_e : G.t -> G.E.t -> G.t end module type INT = S with type G.V.label = int (** {1 Builders for the various graph implementations} *) module P(G : Sig.P) : S with module G = G (** Persistent Graphs Builders. *) module I(G : Sig.I) : S with module G = G (** Imperative Graphs Builders. *) (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/components.ml0000644000175000017500000000533612133565070016115 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: components.ml,v 1.9 2004-10-22 14:42:06 signoles Exp $ *) open Util module type G = sig type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit end module Make(G: G) = struct module H = Hashtbl.Make(G.V) let scc g = let root = H.create 997 in let hashcomp = H.create 997 in let stack = ref [] in let numdfs = ref 0 in let numcomp = ref 0 in let rec pop x = function | (y, w) :: l when y > x -> H.add hashcomp w !numcomp; pop x l | l -> l in let rec visit v = if not (H.mem root v) then begin let n = incr numdfs; !numdfs in H.add root v n; G.iter_succ (fun w -> visit w; if not (H.mem hashcomp w) then H.replace root v (min (H.find root v) (H.find root w))) g v; if H.find root v = n then begin H.add hashcomp v !numcomp; let s = pop n !stack in stack:= s; incr numcomp end else stack := (n,v) :: !stack; end in G.iter_vertex visit g; !numcomp, (fun v -> H.find hashcomp v) let scc_array g = let n,f = scc g in let t = Array.make n [] in G.iter_vertex (fun v -> let i = f v in t.(i) <- v :: t.(i)) g; t let scc_list g = let _,scc = scc g in let tbl = Hashtbl.create 97 in G.iter_vertex (fun v -> let n = scc v in try let l = Hashtbl.find tbl n in l := v :: !l with Not_found -> Hashtbl.add tbl n (ref [ v ])) g; Hashtbl.fold (fun _ v l -> !v :: l) tbl [] end ocamlgraph-1.8.3/src/path.mli0000644000175000017500000001206612133565071015034 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: path.mli,v 1.9 2005-07-18 07:10:35 filliatr Exp $ *) (** Paths *) (** Minimal graph signature for Dijkstra's algorithm. Sub-signature of {!Sig.G}. *) module type G = sig type t module V : Sig.COMPARABLE module E : sig type t type label val label : t -> label val src : t -> V.t val dst : t -> V.t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a val nb_vertex : t -> int end (** Signature for edges' weights. *) module type WEIGHT = sig type label (** Type for labels of graph edges. *) type t (** Type of edges' weights. *) val weight : label -> t (** Get the weight of an edge. *) val compare : t -> t -> int (** Weights must be ordered. *) val add : t -> t -> t (** Addition of weights. *) val zero : t (** Neutral element for {!add}. *) end module Dijkstra (G: G) (W: WEIGHT with type label = G.E.label) : sig val shortest_path : G.t -> G.V.t -> G.V.t -> G.E.t list * W.t (** [shortest_path g v1 v2] computes the shortest path from vertex [v1] to vertex [v2] in graph [g]. The path is returned as the list of followed edges, together with the total length of the path. raise [Not_found] if the path from [v1] to [v2] does not exist. Complexity: at most O((V+E)log(V)) *) end (* The following module is a contribution of Yuto Takei (University of Tokyo) *) module BellmanFord (G: G) (W: WEIGHT with type label = G.E.label) : sig module H : Hashtbl.S with type key = G.V.t exception NegativeCycle of G.E.t list val all_shortest_paths : G.t -> G.V.t -> W.t H.t (** [shortest_path g vs] computes the distances of shortest paths from vertex [vs] to all other vertices in graph [g]. They are returned as a hash table mapping each vertex reachable from [vs] to its distance from [vs]. If [g] contains a negative-length cycle reachable from [vs], raises [NegativeCycle l] where [l] is such a cycle. Complexity: at most O(VE) *) val find_negative_cycle_from: G.t -> G.V.t -> G.E.t list (** [find_negative_cycle_from g vs] looks for a negative-length cycle in graph [g] that is reachable from vertex [vs] and returns it as a list of edges. If no such a cycle exists, raises [Not_found]. Complexity: at most O(VE). *) val find_negative_cycle: G.t -> G.E.t list (** [find_negative_cycle g] looks for a negative-length cycle in graph [g] and returns it. If the graph [g] is free from such a cycle, raises [Not_found]. Complexity: O(V^2E) *) end (** Check for a path. *) module Check (G : sig type t module V : Sig.COMPARABLE val iter_succ : (V.t -> unit) -> t -> V.t -> unit end) : sig type path_checker (** the abstract data type of a path checker; this is a mutable data structure *) val create : G.t -> path_checker (** [create g] builds a new path checker for the graph [g]; if the graph is mutable, it must not be mutated while this path checker is in use (through the function [check_path] below). *) val check_path : path_checker -> G.V.t -> G.V.t -> bool (** [check_path pc v1 v2] checks whether there is a path from [v1] to [v2] in the graph associated to the path checker [pc]. Complexity: The path checker contains a cache of all results computed so far. This cache is implemented with a hash table so access in this cache is usually O(1). When the result is not in the cache, Dijkstra's algorithm is run to check for the path, and all intermediate results are cached. Note: if checks are to be done for almost all pairs of vertices, it may be more efficient to compute the transitive closure of the graph (see module [Oper]). *) end ocamlgraph-1.8.3/src/gmap.mli0000644000175000017500000000573412133565071015030 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Graph mapping. Map a graph to another one. *) (** {2 Mapping of vertices} *) (** Signature for the source graph. *) module type V_SRC = sig type t module V : Sig.HASHABLE val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a end (** Signature for the destination graph. *) module type V_DST = sig type t type vertex val empty : unit -> t val add_vertex : t -> vertex -> t end (** Provide a mapping function from a mapping of vertices. *) module Vertex(G_Src : V_SRC)(G_Dst : V_DST) : sig val map : (G_Src.V.t -> G_Dst.vertex) -> G_Src.t -> G_Dst.t (** [map f g] applies [f] to each vertex of [g] and so builds a new graph based on [g] *) val filter_map : (G_Src.V.t -> G_Dst.vertex option) -> G_Src.t -> G_Dst.t (** [filter_map f g] applies [f] to each vertex of [g] and so builds a new graph based on [g]; if [None] is returned by [f] the vertex is omitted in the new graph. *) end (** {2 Mapping of edges} *) (** Signature for the source graph. *) module type E_SRC = sig type t module E : Sig.ORDERED_TYPE val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a end (** Signature for the destination graph. *) module type E_DST = sig type t type edge val empty : unit -> t val add_edge_e : t -> edge -> t end (** Provide a mapping function from a mapping of edges. *) module Edge(G_Src: E_SRC)(G_Dst: E_DST) : sig val map : (G_Src.E.t -> G_Dst.edge) -> G_Src.t -> G_Dst.t (** [map f g] applies [f] to each edge of [g] and so builds a new graph based on [g] *) val filter_map : (G_Src.E.t -> G_Dst.edge option) -> G_Src.t -> G_Dst.t (** [filter_map f g] applies [f] to each edge of [g] and so builds a new graph based on [g]; if [None] is returned by [f] the edge is omitted in the new graph. *) end ocamlgraph-1.8.3/src/graphviz.mli0000644000175000017500000004612312133565071015733 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Interface with {i GraphViz} This module provides a basic interface with dot and neato, two programs of the GraphViz toolbox. These tools are available at the following URLs: - {v http://www.graphviz.org v} - {v http://www.research.att.com/sw/tools/graphviz v} *) open Format (***************************************************************************) (** {2 Common stuff} *) (** Because the neato and dot engines present a lot of common points - in particular in the graph description language, large parts of the code is shared. The [CommonAttributes] module defines attributes of graphs, vertices and edges that are understood by the two engines. Then module [DotAttributes] and [NeatoAttributes] define attributes specific to dot and neato respectively. *) (*-------------------------------------------------------------------------*) (** {3 Common types and signatures} *) type color = int type color_with_transparency = int32 (** The two least significant bytes encode the transparency information; the six most signification are the standard RGB color *) val color_to_color_with_transparency: color -> color_with_transparency type arrow_style = [ `None | `Normal | `Inv | `Dot | `Odot | `Invdot | `Invodot ] (** The [ATTRIBUTES] module type defines the interface for the engines. *) module type ATTRIBUTES = sig type graph (** Attributes of graphs. *) type vertex (** Attributes of vertices. *) type edge (** Attributes of edges. *) (** Attributes of (optional) boxes around vertices. *) type subgraph = { sg_name : string; (** Box name. *) sg_attributes : vertex list; (** Box attributes. *) } end (*-------------------------------------------------------------------------*) (** {3 Common attributes} *) (** The [CommonAttributes] module defines attributes for graphs, vertices and edges that are available in the two engines, dot and neato. *) module CommonAttributes : sig (** Attributes of graphs. *) type graph = [ `Center of bool (** Centers the drawing on the page. Default value is [false]. *) | `Fontcolor of color (** Sets the font color. Default value is [black]. *) | `Fontname of string (** Sets the font family name. Default value is ["Times-Roman"]. *) | `Fontsize of int (** Sets the type size (in points). Default value is [14]. *) | `Label of string (** Caption for graph drawing. *) | `Orientation of [ `Portrait | `Landscape ] (** Sets the page orientation. Default value is [`Portrait]. *) | `Page of float * float (** Sets the PostScript pagination unit, e.g [8.5, 11.0]. *) | `Pagedir of [ `TopToBottom | `LeftToRight ] (** Traversal order of pages. Default value is [`TopToBottom]. *) | `Size of float * float (** Sets the bounding box of drawing (in inches). *) | `OrderingOut (** Constrains order of out-edges in a subgraph according to their file sequence *) ] (** Attributes of vertices. *) type vertex = [ `Color of color (** Sets the color of the border of the vertex. Default value is [black] *) | `ColorWithTransparency of color_with_transparency (** Sets the color of the border of the vertex with a transparency component. Default value is fully opaque [black] *) | `Fontcolor of color (** Sets the label font color. Default value is [black]. *) | `Fontname of string (** Sets the label font family name. Default value is ["Times-Roman"]. *) | `Fontsize of int (** Sets the label type size (in points). Default value is [14]. *) | `Height of float (** Sets the minimum height. Default value is [0.5]. *) | `Label of string (** Sets the label printed in the vertex. The string may include escaped newlines [\n], [\l], or [\r] for center, left, and right justified lines. Record labels may contain recursive box lists delimited by { | }. *) | `Orientation of float (** Vertex rotation angle, in degrees. Default value is [0.0]. *) | `Peripheries of int (** Sets the number of periphery lines drawn around the polygon. *) | `Regular of bool (** If [true], then the polygon is made regular, i.e. symmetric about the x and y axis, otherwise the polygon takes on the aspect ratio of the label. Default value is [false]. *) | `Shape of [`Ellipse | `Box | `Circle | `Doublecircle | `Diamond | `Plaintext | `Record | `Polygon of int * float] (** Sets the shape of the vertex. Default value is [`Ellipse]. [`Polygon (i, f)] draws a polygon with [n] sides and a skewing of [f]. *) | `Style of [ `Filled | `Solid | `Dashed | `Dotted | `Bold | `Invis ] (** Sets the layout style of the vertex. Several styles may be combined simultaneously. *) | `Width of float (** Sets the minimum width. Default value is [0.75]. *) ] (** Attributes of edges. *) type edge = [ `Color of color (** Sets the edge stroke color. Default value is [black]. *) | `ColorWithTransparency of color_with_transparency (** Sets the edge stroke color with a transparency component. Default value is fully opaque [black] *) | `Decorate of bool (** If [true], draws a line connecting labels with their edges. *) | `Dir of [ `Forward | `Back | `Both | `None ] (** Sets arrow direction. Default value is [`Forward]. *) | `Fontcolor of color (** Sets the label font color. Default value is [black]. *) | `Fontname of string (** Sets the label font family name. Default value is ["Times-Roman"]. *) | `Fontsize of int (** Sets the label type size (in points). Default value is [14]. *) | `Label of string (** Sets the label to be attached to the edge. The string may include escaped newlines [\n], [\l], or [\r] for centered, left, or right justified lines. *) | `Labelfontcolor of color (** Sets the font color for head and tail labels. Default value is [black]. *) | `Labelfontname of string (** Sets the font family name for head and tail labels. Default value is ["Times-Roman"]. *) | `Labelfontsize of int (** Sets the font size for head and tail labels (in points). Default value is [14]. *) | `Style of [ `Solid | `Dashed | `Dotted | `Bold | `Invis ] (** Sets the layout style of the edge. Several styles may be combined simultaneously. *) ] end (***************************************************************************) (** {2 Interface with the dot engine} *) (** [DotAttributes] extends [CommonAttributes] and implements [ATTRIBUTES]. *) module DotAttributes : sig (** Attributes of graphs. They include all common graph attributes and several specific ones. All attributes described in the "dot User's Manual, February 4, 2002" are handled, excepted: clusterank, color, compound, labeljust, labelloc, ordering, rank, remincross, rotate, searchsize and style. *) type graph = [ CommonAttributes.graph | `Bgcolor of color (** Sets the background color and the inital fill color. *) | `BgcolorWithTransparency of color_with_transparency (** Sets the background color and the inital fill color with a transparency component. *) | `Comment of string (** Comment string. *) | `Concentrate of bool (** If [true], enables edge concentrators. Default value is [false]. *) | `Fontpath of string (** List of directories for fonts. *) | `Layers of string list (** List of layers. *) | `Margin of float (** Sets the page margin (included in the page size). Default value is [0.5]. *) | `Mclimit of float (** Scale factor for mincross iterations. Default value is [1.0]. *) | `Nodesep of float (** Sets the minimum separation between nodes, in inches. Default value is [0.25]. *) | `Nslimit of int (** If set of [f], bounds network simplex iterations by [f * ] when ranking nodes. *) | `Nslimit1 of int (** If set of [f], bounds network simplex iterations by [f * ] when setting x-coordinates. *) | `Ranksep of float (** Sets the minimum separation between ranks. *) | `Quantum of float (** If not [0.0], node label dimensions will be rounded to integral multiples of it. Default value is [0.0]. *) | `Rankdir of [ `TopToBottom | `LeftToRight ] (** Direction of rank ordering. Default value is [`TopToBottom]. *) | `Ratio of [ `Float of float | `Fill | `Compress| `Auto ] (** Sets the aspect ratio. *) | `Samplepoints of int (** Number of points used to represent ellipses and circles on output. Default value is [8]. *) | `Url of string (** URL associated with graph (format-dependent). *) ] (** Attributes of nodes. They include all common node attributes and several specific ones. All attributes described in the "dot User's Manual, February 4, 2002" are handled, excepted: bottomlabel, group, shapefile and toplabel. *) type vertex = [ CommonAttributes.vertex | `Comment of string (** Comment string. *) | `Distortion of float (* TEMPORARY *) | `Fillcolor of color (** Sets the fill color (used when `Style filled). Default value is [lightgrey]. *) | `FillcolorWithTransparency of color_with_transparency (** Sets the fill color (used when `Style filled) with a transparency component. Default value is fully opaque [lightgrey]. *) | `Fixedsize of bool (** If [true], forces the given dimensions to be the actual ones. Default value is [false]. *) | `Layer of string (** Overlay. *) | `Url of string (** The default url for image map files; in PostScript files, the base URL for all relative URLs, as recognized by Acrobat Distiller 3.0 and up. *) | `Z of float (** z coordinate for VRML output. *) ] (** Attributes of edges. They include all common edge attributes and several specific ones. All attributes described in the "dot User's Manual, February 4, 2002" are handled, excepted: lhead and ltail. *) type edge = [ CommonAttributes.edge | `Arrowhead of arrow_style (** Sets the style of the head arrow. Default value is [`Normal]. *) | `Arrowsize of float (** Sets the scaling factor of arrowheads. Default value is [1.0]. *) | `Arrowtail of arrow_style (** Sets the style of the tail arrow. Default value is [`Normal]. *) | `Comment of string (** Comment string. *) | `Constraint of bool (** If [false], causes an edge to be ignored for rank assignment. Default value is [true]. *) | `Headlabel of string (** Sets the label attached to the head arrow. *) | `Headport of [ `N | `NE | `E | `SE | `S | `SW | `W | `NW ] (* TEMPORARY *) | `Headurl of string (** Url attached to head label if output format is ismap. *) | `Labelangle of float (** Angle in degrees which head or tail label is rotated off edge. Default value is [-25.0]. *) | `Labeldistance of float (** Scaling factor for distance of head or tail label from node. Default value is [1.0]. *) | `Labelfloat of bool (** If [true], lessen constraints on edge label placement. Default value is [false]. *) | `Layer of string (** Overlay. *) | `Minlen of int (** Minimum rank distance between head an tail. Default value is [1]. *) | `Samehead of string (** Tag for head node; edge heads with the same tag are merged onto the same port. *) | `Sametail of string (** Tag for tail node; edge tails with the same tag are merged onto the same port. *) | `Taillabel of string (** Sets the label attached to the tail arrow. *) | `Tailport of [ `N | `NE | `E | `SE | `S | `SW | `W | `NW ] (* TEMPORARY *) | `Tailurl of string (** Url attached to tail label if output format is ismap. *) | `Weight of int (** Sets the integer cost of stretching the edge. Default value is [1]. *) ] (** Subgraphs have a name and some vertices. *) type subgraph = { sg_name : string; sg_attributes : vertex list; } end (** Graph module with dot attributes *) module type GraphWithDotAttrs = sig include Sig.G val graph_attributes: t -> DotAttributes.graph list (** Vertex attributes *) val default_vertex_attributes: t -> DotAttributes.vertex list val vertex_name : V.t -> string val vertex_attributes: V.t -> DotAttributes.vertex list (** Edge attributes *) val default_edge_attributes: t -> DotAttributes.edge list val edge_attributes: E.t -> DotAttributes.edge list val get_subgraph : V.t -> DotAttributes.subgraph option (** The box (if exists) which the vertex belongs to. Boxes with same names are not distinguished and so they should have the same attributes. *) end module Dot (X : sig (** Graph implementation. Sub-signature of {!Sig.G} *) type t module V : sig type t end module E : sig type t val src : t -> V.t val dst : t -> V.t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit (** Graph, vertex and edge attributes. *) val graph_attributes: t -> DotAttributes.graph list val default_vertex_attributes: t -> DotAttributes.vertex list val vertex_name : V.t -> string val vertex_attributes: V.t -> DotAttributes.vertex list val get_subgraph : V.t -> DotAttributes.subgraph option (** The box (if exists) which the vertex belongs to. Boxes with same names are not distinguished and so they should have the same attributes. *) val default_edge_attributes: t -> DotAttributes.edge list val edge_attributes: E.t -> DotAttributes.edge list end) : sig val fprint_graph: formatter -> X.t -> unit (** [fprint_graph ppf graph] pretty prints the graph [graph] in the CGL language on the formatter [ppf]. *) val output_graph: out_channel -> X.t -> unit (** [output_graph oc graph] pretty prints the graph [graph] in the dot language on the channel [oc]. *) end (***************************************************************************) (** {2 The neato engine} *) module NeatoAttributes : sig (** Attributes of graphs. They include all common graph attributes and several specific ones. All attributes described in the "Neato User's manual, April 10, 2002" are handled. *) type graph = [ CommonAttributes.graph | `Margin of float * float (** Sets the page margin (included in the page size). Default value is [0.5, 0.5]. *) | `Start of int (** Seed for random number generator. *) | `Overlap of bool (** Default value is [true]. *) | `Spline of bool (** [true] makes edge splines if nodes don't overlap. Default value is [false]. *) | `Sep of float (** Edge spline separation factor from nodes. Default value is [0.0]. *) ] (** Attributes of nodes. They include all common node attributes and several specific ones. All attributes described in the "Neato User's manual, April 10, 2002" are handled. *) type vertex = [ CommonAttributes.vertex | `Pos of float * float (** Initial coordinates of the vertex. *) ] (** Attributes of edges. They include all common edge attributes and several specific ones. All attributes described in the "Neato User's manual, April 10, 2002" are handled. *) type edge = [ CommonAttributes.edge | `Id of string (** Optional value to distinguish multiple edges. *) | `Len of float (** Preferred length of edge. Default value is [1.0]. *) | `Weight of float (** Strength of edge spring. Default value is [1.0]. *) ] (** Subgraphs have a name and some vertices. *) type subgraph = { sg_name : string; sg_attributes : vertex list; } end module Neato (X : sig (** Graph implementation. Sub-signature of {!Sig.G}. *) type t module V : sig type t end module E : sig type t val src : t -> V.t val dst : t -> V.t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit (** Graph, vertex and edge attributes. *) val graph_attributes: t -> NeatoAttributes.graph list val default_vertex_attributes: t -> NeatoAttributes.vertex list val vertex_name : V.t -> string val vertex_attributes: V.t -> NeatoAttributes.vertex list val get_subgraph : V.t -> NeatoAttributes.subgraph option (** The box (if exists) which the vertex belongs to. Boxes with same names are not distinguished and so they should have the same attributes. *) val default_edge_attributes: t -> NeatoAttributes.edge list val edge_attributes: E.t -> NeatoAttributes.edge list end) : sig val set_command: string -> unit (** Several functions provided by this module run the external program {i neato}. By default, this command is supposed to be in the default path and is invoked by {i neato}. The function [set_command] allows to set an alternative path at run time. *) exception Error of string val handle_error: ('a -> 'b) -> 'a -> 'b val fprint_graph: formatter -> X.t -> unit (** [fprint_graph ppf graph] pretty prints the graph [graph] in the CGL language on the formatter [ppf]. *) val output_graph: out_channel -> X.t -> unit (** [output_graph oc graph] pretty prints the graph [graph] in the dot language on the channel [oc]. *) end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/traverse.mli0000644000175000017500000001117512133565071015733 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Graph traversal. *) (** {2 Dfs and Bfs} *) (** Minimal graph signature for {!Dfs} and {!Bfs}. Sub-signature of {!Sig.G}. *) module type G = sig val is_directed : bool type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_succ : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end (** Depth-first search *) module Dfs(G : G) : sig (** {2 Classical big-step iterators} *) val iter : ?pre:(G.V.t -> unit) -> ?post:(G.V.t -> unit) -> G.t -> unit (** [iter pre post g] visits all nodes of [g] in depth-first search, applying [pre] to each visited node before its successors, and [post] after them. Each node is visited exactly once. Not tail-recursive. *) val prefix : (G.V.t -> unit) -> G.t -> unit (** applies only a prefix function; note that this function is more efficient than [iter] and is tail-recursive. *) val postfix : (G.V.t -> unit) -> G.t -> unit (** applies only a postfix function. Not tail-recursive. *) (** Same thing, but for a single connected component (only [prefix_component] is tail-recursive) *) val iter_component : ?pre:(G.V.t -> unit) -> ?post:(G.V.t -> unit) -> G.t -> G.V.t -> unit val prefix_component : (G.V.t -> unit) -> G.t -> G.V.t -> unit val postfix_component : (G.V.t -> unit) -> G.t -> G.V.t -> unit (** {2 Step-by-step iterator} This is a variant of the iterators above where you can move on step by step. The abstract type [iterator] represents the current state of the iteration. The [step] function returns the next state. In each state, function [get] returns the currently visited vertex. On the final state both [get] and [step] raises exception [Exit]. Note: the iterator type is persistent (i.e. is not modified by the [step] function) and thus can be used in backtracking algorithms. *) type iterator val start : G.t -> iterator val step : iterator -> iterator val get : iterator -> G.V.t (** {2 Cycle detection} *) val has_cycle : G.t -> bool (** [has_cycle g] checks for a cycle in [g]. Linear in time and space. *) end (** Breadth-first search *) module Bfs(G : G) : sig (** {2 Classical big-step iterators} *) val iter : (G.V.t -> unit) -> G.t -> unit val iter_component : (G.V.t -> unit) -> G.t -> G.V.t -> unit (** {2 Step-by-step iterator} See module [Dfs] *) type iterator val start : G.t -> iterator val step : iterator -> iterator val get : iterator -> G.V.t end (** {2 Traversal with marking} Provide a more efficient version of depth-first algorithm when graph vertices are marked. *) (** Minimal graph signature for graph traversal with marking. Sub-signature of {!Sig.IM}. *) module type GM = sig type t module V : sig type t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit module Mark : sig val clear : t -> unit val get : V.t -> int val set : V.t -> int -> unit end end (** Graph traversal with marking. Only applies to imperative graphs with marks. *) module Mark(G : GM) : sig val dfs : G.t -> unit (** [dfs g] traverses [g] in depth-first search, marking all nodes. *) val has_cycle : G.t -> bool (** [has_cycle g] checks for a cycle in [g]. Modifies the marks. Linear time, constant space. *) end ocamlgraph-1.8.3/src/gml.mll0000644000175000017500000001236512133565071014664 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: gml.mll,v 1.3 2005-07-06 13:20:31 conchon Exp $ *) { open Lexing type value = | Int of int | Float of float | String of string | List of value_list and value_list = (string * value) list } let space = [' ' '\t' '\r' '\n']+ let ident = ['a'-'z' 'A'-'Z'] ['a'-'z' 'A'-'Z' '0'-'9']* let digit = ['0'-'9'] let sign = '-' | '+' let integer = sign? digit+ let mantissa = 'E' sign? digit+ let real = sign? digit* '.' digit* mantissa? let in_string = [^ '"']* rule file = parse | space { file lexbuf } | (ident as key) space { let v = value lexbuf in (key, v) :: file lexbuf } | eof { [] } | _ as c { failwith ("Gml: invalid character " ^ String.make 1 c) } and value_list = parse | space { value_list lexbuf } | (ident as key) space { let v = value lexbuf in (key, v) :: value_list lexbuf } | ']' { [] } | _ as c { failwith ("Gml: invalid character " ^ String.make 1 c) } and value = parse | integer as i { Int (int_of_string i) } | real as r { Float (float_of_string r) } | '"' (in_string as s) '"' { String s } | '[' { let l = value_list lexbuf in List l } | _ as c { failwith ("Gml: invalid character " ^ String.make 1 c) } { let parse f = let c = open_in f in let lb = from_channel c in let v = file lb in close_in c; v module Parse (B : Builder.S) (L : sig val node : value_list -> B.G.V.label val edge : value_list -> B.G.E.label end) = struct let create_graph l = let nodes = Hashtbl.create 97 in let g = B.empty () in (* 1st pass: create the nodes *) let g = List.fold_left (fun g v -> match v with | "node", List l -> let n = B.G.V.create (L.node l) in begin try let id = List.assoc "id" l in Hashtbl.add nodes id n with Not_found -> () end; B.add_vertex g n | _ -> g) g l in (* 2nd pass: add the edges *) List.fold_left (fun g v -> match v with | "edge", List l -> begin try let source = List.assoc "source" l in let target = List.assoc "target" l in let nsource = Hashtbl.find nodes source in let ntarget = Hashtbl.find nodes target in let e = B.G.E.create nsource (L.edge l) ntarget in B.add_edge_e g e with Not_found -> g end | _ -> g) g l let parse f = match parse f with | ["graph", List l] -> create_graph l | _ -> invalid_arg "Gml.Parse.parse: not a graph file" end module type G = sig module V : sig type t val hash : t -> int val equal : t -> t -> bool type label val label : t -> label end module E : sig type t type label val src : t -> V.t val dst : t -> V.t val label : t -> label end type t val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit end module Print (G : G) (L : sig val node : G.V.label -> value_list val edge : G.E.label -> value_list end) = struct open Format module H = Hashtbl.Make(G.V) let print fmt g = let nodes = H.create 97 in let cpt = ref 0 in let id n = try H.find nodes n with Not_found -> incr cpt; let id = !cpt in H.add nodes n id; id in fprintf fmt "@[graph [@\n"; let rec value fmt = function | Int n -> fprintf fmt "%d" n | Float f -> fprintf fmt "%f" f | String s -> fprintf fmt "\"%s\"" s | List l -> fprintf fmt "[@\n @[%a@]@\n]" value_list l and value_list fmt = function | [] -> () | [s,v] -> fprintf fmt "%s %a" s value v | (s,v) :: l -> fprintf fmt "%s %a@\n" s value v; value_list fmt l in G.iter_vertex (fun v -> fprintf fmt " @[node [@\n id %d@\n @[%a@]@\n]@]@\n" (id v) value_list (L.node (G.V.label v))) g; G.iter_edges_e (fun e -> fprintf fmt " @[edge [@\n source %d@\n target %d@\n @[%a@]@\n]@]@\n" (id (G.E.src e)) (id (G.E.dst e)) value_list (L.edge (G.E.label e))) g; fprintf fmt "]@\n" end } ocamlgraph-1.8.3/src/gml.mli0000644000175000017500000000523112133565071014653 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: gml.mli,v 1.3 2005-07-06 13:20:31 conchon Exp $ *) (** Parser and pretty-printer for GML file format. *) type value = | Int of int | Float of float | String of string | List of value_list and value_list = (string * value) list (** {2 Parser} *) (** Provide a parser for GML file format. *) module Parse (B : Builder.S) (L : sig val node : value_list -> B.G.V.label (** How to build the node label out of the set of GML attributes. For example {v node [ id 12 label "foo" ] v} will call this function with [["id", Int 12; "label", String "foo"]] *) val edge : value_list -> B.G.E.label (** How to build the edge label out of the set of GML attributes *) end) : sig val parse : string -> B.G.t end (** {2 Pretty-printer} *) (** Signature for graph required by {!Print}. Sub-signature of {!Sig.G}. *) module type G = sig module V : sig type t val hash : t -> int val equal : t -> t -> bool type label val label : t -> label end module E : sig type t type label val src : t -> V.t val dst : t -> V.t val label : t -> label end type t val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit end (** Provide a pretty-printer for GML file format. *) module Print (G: G) (L: sig val node : G.V.label -> value_list val edge : G.E.label -> value_list end) : sig val print : Format.formatter -> G.t -> unit end ocamlgraph-1.8.3/src/leaderlist.ml0000644000175000017500000000705312133565071016057 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright (c) 2010 - 2011 Technische Universitaet Muenchen * Markus W. Weissmann * Florian Pichlmeier * All rights reserved. *) (* Minimal graph signature for leader list algorithm *) module type G = sig type t module V : Sig.COMPARABLE val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val succ : t -> V.t -> V.t list val pred : t -> V.t -> V.t list end module Make (G : G) = struct module S = Set.Make(G.V) let leader_lists g root = (* partition all vertices into two Sets *) let partition_vertices f g = G.fold_vertex (fun n (s1, s2) -> if f n then (S.add n s1, s2) else (s1, S.add n s2)) g (S.empty, S.empty) in (* predicate to determine if a node is a leader *) let is_leader n = if n = root then true (* the root node is always a leader *) else match G.pred g n with | [] -> true (* this would be dead code -- it has no predecessor so make it a leader anyway *) | x::[] -> begin match G.succ g x with | [] -> assert false (* -> inconsistency in the graph implementation *) | y::[] -> false (* this is a straight, continuous control flow *) | _ -> true (* predecessor has multiple successors *) end | _ -> true (* more than one predecessor *) in let (leader, entourage) = partition_vertices is_leader g in (* build a basic block *) let basic_block x = let rec basic_block x bb = match G.succ g x with | [] -> x::bb (* no successors -- end of basic block *) | y::ys -> begin match S.mem y entourage with | true -> (* successor is not a leader, continue collecting *) basic_block y (x::bb) | false -> x :: bb (* successor is a leader -- end of basic block *) end in (* blocks a are built in reverse order for performance reasons -- correct that *) List.rev (basic_block x []) in let basic_block_list = S.fold (fun x ss -> (basic_block x)::ss) leader [] in List.rev basic_block_list (* this will bring the head of the lists in ascending order -- as given by Set.S *) end ocamlgraph-1.8.3/src/fixpoint.ml0000644000175000017500000001436012133565070015565 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright (c) 2010 - 2012 Technische Universitaet Muenchen * Markus W. Weissmann * All rights reserved. *) (* maximum fixpoint point calculation with the work list algorithm; to implement a concrete analysis, implement a module that satisfies the Rules signature. Such a module in the Analysis functor gives a complete analysis/optimization module that works on a CFG. *) type direction = Forward | Backward module type Analysis = sig type data type edge type vertex type g val direction : direction val join : data -> data -> data val equal : data -> data -> bool val analyze : edge -> data -> data end (** Minimal graph signature for work list algorithm *) module type G = sig type t module V : Sig.COMPARABLE module E : sig type t val dst : t -> V.t val src : t -> V.t end val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val succ_e : t -> V.t -> E.t list val pred_e : t -> V.t -> E.t list val succ : t -> V.t -> V.t list val pred : t -> V.t -> V.t list end module Make (G : G) (A : Analysis with type g = G.t with type edge = G.E.t with type vertex = G.V.t) = struct module M = Map.Make(G.V) module N = Set.Make(G.V) let analyze initial g = let (nodes, data) = G.fold_vertex (fun vertex (n, m) -> (N.add vertex n, M.add vertex (initial vertex) m)) g (N.empty, M.empty) in (* generate an associative map to quickly find the incoming * (outgoing) edges of a node during the anaysis store a pair of * a partially applied analysis function and the corresponding * 'partner' node *) let nodemap : ((A.data -> A.data) * G.V.t) list M.t = let add = match A.direction with | Forward -> (fun n -> let preds = G.pred_e g n in List.map (fun edge -> (A.analyze edge, G.E.src edge)) preds) | Backward -> (fun n -> let succs = G.succ_e g n in List.map (fun edge -> (A.analyze edge, G.E.dst edge)) succs) in G.fold_vertex (fun vertex m -> M.add vertex (add vertex) m) g M.empty in let rec worklist (data : A.data M.t) (wl : N.t) = (* 'meet' an arbitrary number of data-sets *) let meet ~default = function | [] -> default | [x] -> x | x::xs -> List.fold_left (fun a b -> A.join a b) x xs in (* analyze one node, creating a new data-set and node-worklist as necessary *) let analyze_node analysis n d wl = match analysis d n with | None -> (d, wl) | Some d' -> (d', N.add n wl) in try (* get some node from the node-set -- this will eventually trigger an exception *) let n = N.choose wl in (* remove the chosen node from the set *) let wl = N.remove n wl in let (f, ns) = match A.direction with (* analyze all INCOMING edges of all SUCCESSOR nodes of the node to be processed *) | Forward -> (* process one node: analyze all it's incoming edges and merge the resulting data; if the result is different to the previously stored data for this node, return a new tuple, else None *) let new_node_data (data : A.data M.t) node = let edges = M.find node nodemap in let analysis = List.map (fun (f, src) -> f (M.find src data)) edges in let node_data = M.find node data in let node_data' = meet ~default:node_data analysis in if A.equal node_data node_data' then None else Some (M.add node node_data' data) in (new_node_data, G.succ g n) (* analyze all OUTGOING edges of all PREDECESSOR nodes of the node to be processed *) | Backward -> let new_node_data (data : A.data M.t) node = let edges = M.find node nodemap in let analysis = List.map (fun (f, dst) -> f (M.find dst data)) edges in let node_data = M.find node data in let node_data' = meet ~default:node_data analysis in if A.equal node_data node_data' then None else Some (M.add node node_data' data) in (new_node_data, G.pred g n) in (* analyze all successor nodes by analyzing all of their predecessor edges *) let (data, wl) = List.fold_left (fun (d, wl) n -> analyze_node f n d wl) (data, wl) ns in (* do a recursive call: the recursion will eventually end with a * Not_found exception when no nodes are left in the work list *) worklist data wl with Not_found -> data in let data = worklist data nodes in (fun n -> M.find n data) end ocamlgraph-1.8.3/src/imperative.ml0000644000175000017500000004377112133565071016103 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Sig open Blocks module type S = sig (** Imperative Unlabeled Graphs *) module Concrete (V: COMPARABLE) : Sig.I with type V.t = V.t and type V.label = V.t and type E.t = V.t * V.t and type E.label = unit (** Abstract Imperative Unlabeled Graphs *) module Abstract(V: sig type t end) : Sig.IM with type V.label = V.t and type E.label = unit and type E.label = unit (** Imperative Labeled Graphs *) module ConcreteLabeled (V: COMPARABLE)(E: ORDERED_TYPE_DFT) : Sig.I with type V.t = V.t and type V.label = V.t and type E.t = V.t * E.t * V.t and type E.label = E.t (** Abstract Imperative Labeled Graphs *) module AbstractLabeled (V: sig type t end)(E: ORDERED_TYPE_DFT) : Sig.IM with type V.label = V.t and type E.label = E.t end module I = Make(Make_Hashtbl) type 'a abstract_vertex = { tag : int; label : 'a; mutable mark : int } (* Implement module type [MARK]. *) module Make_Mark (X: sig type graph type label val iter_vertex : (label abstract_vertex -> unit) -> graph -> unit end) = struct type vertex = X.label abstract_vertex type graph = X.graph let get v = v.mark let set v m = v.mark <- m let clear g = X.iter_vertex (fun v -> set v 0) g end (* Vertex for abstract imperative graphs: comparing to vertex for abstract **persistent** graphs, marks are added. *) module AbstractVertex(V: sig type t end) = struct type label = V.t type t = label abstract_vertex let compare x y = Pervasives.compare x.tag y.tag let hash x = x.tag let equal x y = x.tag = y.tag let label x = x.label let create l = if !cpt_vertex = first_value_for_cpt_vertex - 1 then invalid_arg "Too much vertices"; incr cpt_vertex; { tag = !cpt_vertex; label = l; mark = 0 } end module Digraph = struct module Concrete(V: COMPARABLE) = struct include I.Digraph.Concrete(V) let add_vertex g v = ignore (add_vertex g v) let add_edge g v1 v2 = ignore (add_edge g v1 v2) let remove_edge g v1 v2 = ignore (remove_edge g v1 v2) let remove_edge_e g e = ignore (remove_edge_e g e) let add_edge_e g e = ignore (add_edge_e g e) let remove_vertex g v = if HM.mem v g then begin ignore (HM.remove v g); HM.iter (fun k s -> ignore (HM.add k (S.remove v s) g)) g end end module ConcreteLabeled(V: COMPARABLE)(E: ORDERED_TYPE_DFT) = struct include I.Digraph.ConcreteLabeled(V)(E) let add_vertex g v = ignore (add_vertex g v) let remove_edge g v1 v2 = ignore (remove_edge g v1 v2) let remove_edge_e g e = ignore (remove_edge_e g e) let add_edge_e g e = ignore (add_edge_e g e) let add_edge g v1 v2 = ignore (add_edge g v1 v2) let remove_vertex g v = if HM.mem v g then begin ignore (HM.remove v g); let remove v = S.filter (fun (v2, _) -> not (V.equal v v2)) in HM.iter (fun k s -> ignore (HM.add k (remove v s) g)) g end end module ConcreteBidirectional(V: COMPARABLE) = struct include I.Digraph.ConcreteBidirectional(V) let add_vertex g v = ignore (add_vertex g v) let add_edge g v1 v2 = add_vertex g v1; add_vertex g v2; ignore (unsafe_add_edge g v1 v2) let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_edge g v1 v2 = ignore (remove_edge g v1 v2) let remove_edge_e g e = ignore (remove_edge_e g e) let remove_vertex g v = if HM.mem v g then begin iter_pred_e (fun e -> remove_edge_e g e) g v; iter_succ_e (fun e -> remove_edge_e g e) g v; ignore (HM.remove v g) end end module ConcreteBidirectionalLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT) = struct include I.Digraph.ConcreteBidirectionalLabeled(V)(E) let add_vertex g v = ignore (add_vertex g v) let add_edge g v1 v2 = add_vertex g v1; add_vertex g v2; ignore (unsafe_add_edge g v1 v2) let add_edge_e g (v1, l, v2) = add_vertex g v1; add_vertex g v2; ignore (unsafe_add_edge_e g (v1, l, v2)) let remove_edge g v1 v2 = ignore (remove_edge g v1 v2) let remove_edge_e g e = ignore (remove_edge_e g e) let remove_vertex g v = if HM.mem v g then begin iter_pred_e (fun e -> remove_edge_e g e) g v; iter_succ_e (fun e -> remove_edge_e g e) g v; ignore (HM.remove v g) end end module Abstract(V: sig type t end) = struct include I.Digraph.Abstract(AbstractVertex(V)) let add_vertex g v = if not (HM.mem v g.edges) then begin g.size <- Pervasives.succ g.size; ignore (G.unsafe_add_vertex g.edges v) end let add_edge g v1 v2 = add_vertex g v1; add_vertex g v2; ignore (unsafe_add_edge g.edges v1 v2) let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_vertex g v = if HM.mem v g.edges then let e = g.edges in ignore (HM.remove v e); HM.iter (fun k s -> ignore (HM.add k (S.remove v s) e)) e; g.size <- Pervasives.pred g.size module Mark = Make_Mark (struct type graph = t type label = V.label let iter_vertex = iter_vertex end) let remove_edge g v1 v2 = ignore (remove_edge g v1 v2) let remove_edge_e g e = ignore (remove_edge_e g e) end module AbstractLabeled(V: sig type t end)(Edge: ORDERED_TYPE_DFT) = struct include I.Digraph.AbstractLabeled(AbstractVertex(V))(Edge) let add_vertex g v = if not (HM.mem v g.edges) then begin g.size <- Pervasives.succ g.size; ignore (G.unsafe_add_vertex g.edges v) end let add_edge_e g (v1, l, v2) = add_vertex g v1; add_vertex g v2; ignore (unsafe_add_edge g.edges v1 (v2, l)) let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) let remove_vertex g v = if HM.mem v g.edges then let remove s = S.fold (fun (v2, _ as e) s -> if not (V.equal v v2) then S.add e s else s) s S.empty in let e = g.edges in ignore (HM.remove v e); HM.iter (fun k s -> ignore (HM.add k (remove s) e)) e; g.size <- Pervasives.pred g.size module Mark = Make_Mark (struct type graph = t type label = V.label let iter_vertex = iter_vertex end) let remove_edge g v1 v2 = ignore (remove_edge g v1 v2) let remove_edge_e g e = ignore (remove_edge_e g e) end end module Graph = struct module Concrete(V: COMPARABLE) = struct module G = struct include Digraph.Concrete(V) type return = unit end include Graph(G) (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge g v1 v2 = G.add_edge g v1 v2; assert (G.HM.mem v1 g && G.HM.mem v2 g); ignore (G.unsafe_add_edge g v2 v1) let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_edge g v1 v2 = G.remove_edge g v1 v2; assert (G.HM.mem v1 g && G.HM.mem v2 g); ignore (G.unsafe_remove_edge g v2 v1) let remove_edge_e g (v1, v2) = remove_edge g v1 v2 end module ConcreteLabeled (V: COMPARABLE)(Edge: ORDERED_TYPE_DFT) = struct module G = struct include Digraph.ConcreteLabeled(V)(Edge) type return = unit end include Graph(G) (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge_e g (v1, l, v2 as e) = G.add_edge_e g e; assert (G.HM.mem v1 g && G.HM.mem v2 g); ignore (G.unsafe_add_edge g v2 (v1, l)) let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) let remove_edge g v1 v2 = G.remove_edge g v1 v2; assert (G.HM.mem v1 g && G.HM.mem v2 g); ignore (G.unsafe_remove_edge g v2 v1) let remove_edge_e g (v1, l, v2 as e) = G.remove_edge_e g e; assert (G.HM.mem v1 g && G.HM.mem v2 g); ignore (G.unsafe_remove_edge_e g (v2, l, v1)) end module Abstract(V: sig type t end) = struct module G = struct include Digraph.Abstract(V) type return = unit end include Graph(G) (* Export some definitions of [G] *) module Mark = G.Mark (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge g v1 v2 = G.add_edge g v1 v2; assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); ignore (G.unsafe_add_edge g.G.edges v2 v1) let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_edge g v1 v2 = G.remove_edge g v1 v2; assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); ignore (G.unsafe_remove_edge g.G.edges v2 v1) let remove_edge_e g (v1, v2) = remove_edge g v1 v2 end module AbstractLabeled (V: sig type t end)(Edge: ORDERED_TYPE_DFT) = struct module G = struct include Digraph.AbstractLabeled(V)(Edge) type return = unit end include Graph(G) (* Export some definitions of [G] *) module Mark = G.Mark (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge_e g (v1, l, v2 as e) = G.add_edge_e g e; assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); ignore (G.unsafe_add_edge g.G.edges v2 (v1, l)) let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) let remove_edge g v1 v2 = G.remove_edge g v1 v2; assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); ignore (G.unsafe_remove_edge g.G.edges v2 v1) let remove_edge_e g (v1, l, v2 as e) = ignore (G.remove_edge_e g e); assert (G.HM.mem v1 g.G.edges && G.HM.mem v2 g.G.edges); ignore (G.unsafe_remove_edge_e g.G.edges (v2, l, v1)) end end module Matrix = struct module type S = sig include Sig.I with type V.t = int and type V.label = int and type E.t = int * int val make : int -> t end module Digraph = struct module V = struct type t = int type label = int let compare : t -> t -> int = Pervasives.compare let hash = Hashtbl.hash let equal = (==) let create i = i let label i = i end module E = struct type t = V.t * V.t type vertex = V.t let compare : t -> t -> int = Pervasives.compare type label = unit let create v1 _ v2 = (v1, v2) let src = fst let dst = snd let label _ = () end type t = Bitv.t array type vertex = V.t type edge = E.t let create ?size () = failwith "[ocamlgraph] do not use Matrix.create; please use Matrix.make instead" let make n = if n < 0 then invalid_arg "[ocamlgraph] Matrix.make"; Array.init n (fun _ -> Bitv.create n false) let is_directed = true let nb_vertex = Array.length let is_empty g = nb_vertex g = 0 let nb_edges = Array.fold_left (Bitv.fold_left (fun n b -> if b then n+1 else n)) 0 let mem_vertex g v = 0 <= v && v < nb_vertex g let mem_edge g i j = Bitv.get g.(i) j let mem_edge_e g (i,j) = Bitv.get g.(i) j let find_edge g i j = if mem_edge g i j then i, j else raise Not_found let find_all_edges g i j = try [ find_edge g i j ] with Not_found -> [] (* constructors *) let add_edge g i j = Bitv.set g.(i) j true let add_edge_e g (i,j) = Bitv.set g.(i) j true let remove_edge g i j = Bitv.set g.(i) j false let remove_edge_e g (i,j) = Bitv.set g.(i) j false let unsafe_add_edge g i j = Bitv.unsafe_set (Array.unsafe_get g i) j true let unsafe_remove_edge g i j = Bitv.unsafe_set (Array.unsafe_get g i) j false let remove_vertex g _ = () let add_vertex g _ = () let clear g = Array.iter (fun b -> Bitv.iteri (fun j _ -> Bitv.set b j false) b) g let copy g = Array.init (nb_vertex g) (fun i -> Bitv.copy g.(i)) (* iter/fold on all vertices/edges of a graph *) let iter_vertex f g = for i = 0 to nb_vertex g - 1 do f i done let iter_edges f g = for i = 0 to nb_vertex g - 1 do Bitv.iteri (fun j b -> if b then f i j) g.(i) done let fold_vertex f g a = let n = nb_vertex g in let rec fold i a = if i = n then a else fold (i+1) (f i a) in fold 0 a let fold_edges f g a = fold_vertex (fun i a -> Bitv.foldi_right (fun j b a -> if b then f i j a else a) g.(i) a) g a (* successors and predecessors of a vertex *) let succ g i = Bitv.foldi_left (fun l j b -> if b then j::l else l) [] g.(i) let pred g i = fold_vertex (fun j a -> if Bitv.unsafe_get g.(j) i then j :: a else a) g [] (* iter/fold on all successor/predecessor of a vertex. *) let iter_succ f g i = let si = g.(i) in for j = 0 to nb_vertex g - 1 do if Bitv.unsafe_get si j then f j done (* optimization w.r.t. [Bitv.iteri (fun j b -> if b then f j) g.(i)] *) let iter_pred f g i = for j = 0 to nb_vertex g - 1 do if Bitv.unsafe_get g.(j) i then f j done let fold_succ f g i a = Bitv.foldi_right (fun j b a -> if b then f j a else a) g.(i) a let fold_pred f g i a = fold_vertex (fun j a -> if Bitv.unsafe_get g.(j) i then f j a else a) g a (* degree *) let out_degree g i = fold_succ (fun _ n -> n + 1) g i 0 let in_degree g i = fold_pred (fun _ n -> n + 1) g i 0 (* map iterator on vertex *) let map_vertex f g = let n = nb_vertex g in let g' = make n in iter_edges (fun i j -> let fi = f i in let fj = f j in if fi < 0 || fi >= n || fj < 0 || fj >= n then invalid_arg "[ocamlgraph] map_vertex"; Bitv.unsafe_set g'.(fi) fj true) g; g' (* labeled edges going from/to a vertex *) (* successors and predecessors of a vertex *) let succ_e g i = Bitv.foldi_left (fun l j b -> if b then (i,j)::l else l) [] g.(i) let pred_e g i = fold_vertex (fun j a -> if Bitv.unsafe_get g.(j) i then (j,i) :: a else a) g [] (* iter/fold on all labeled edges of a graph *) let iter_edges_e f g = for i = 0 to nb_vertex g - 1 do Bitv.iteri (fun j b -> if b then f (i,j)) g.(i) done let fold_edges_e f g a = fold_vertex (fun i a -> Bitv.foldi_right (fun j b a -> if b then f (i,j) a else a) g.(i) a) g a (* iter/fold on all edges going from/to a vertex *) let iter_succ_e f g i = let si = g.(i) in for j = 0 to nb_vertex g - 1 do if Bitv.unsafe_get si j then f (i,j) done let iter_pred_e f g i = for j = 0 to nb_vertex g - 1 do if Bitv.unsafe_get g.(j) i then f (j,i) done let fold_succ_e f g i a = Bitv.foldi_right (fun j b a -> if b then f (i,j) a else a) g.(i) a let fold_pred_e f g i a = fold_vertex (fun j a -> if Bitv.unsafe_get g.(j) i then f (j,i) a else a) g a end module Graph = struct module G = struct include Digraph type return = unit end include Blocks.Graph(G) (* Export some definitions of [G] *) let make = G.make (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge g v1 v2 = G.add_edge g v1 v2; ignore (G.unsafe_add_edge g v2 v1) let add_edge_e g (v1, v2) = add_edge g v1 v2 let remove_edge g v1 v2 = G.remove_edge g v1 v2; ignore (G.unsafe_remove_edge g v2 v1) let remove_edge_e g (v1, v2) = remove_edge g v1 v2 end end (* Faster implementations when vertices are not shared between graphs. *) (**** module UV = struct let cpt_vertex = ref min_int type ('label, 'succ) vertex = { tag : int; label : 'label; mutable mark : int; mutable succ : 'succ; } module Digraph = struct module Abstract(L: ANY_TYPE) : Sig.IM with type V.label = L.t and type E.label = unit = struct module rec V : VERTEX with type label = L.t and type t = (L.t, S.t) vertex = struct type label = L.t type t = (L.t, S.t) vertex let compare x y = compare x.tag y.tag let hash x = Hashtbl.hash x.tag let equal x y = x.tag = y.tag let label x = x.label let create l = assert (!cpt_vertex < max_int); incr cpt_vertex; { tag = !cpt_vertex; label = l; mark = 0; succ = S.empty } end and S : Set.S with type elt = V.t = Set.Make(V) type vertex = V.t module E = struct type t = V.t * V.t type vertex = V.t let compare = Pervasives.compare type label = unit let create v1 _ v2 = (v1, v2) let src = fst let dst = snd let label _ = () end type edge = E.t type t = { mutable vertices : S.t; } let create ?size () = { vertices = S.empty } let is_directed = true let is_empty g = S.is_empty g.vertices let nb_vertex g = S.cardinal g.vertices let out_degree _ v = S.cardinal v.succ let add_vertex g v = g.vertices <- S.add v g.vertices let mem_vertex g v = S.mem v g.vertices let iter_vertex f g = S.iter f g.vertices let fold_vertex f g = S.fold f g.vertices let succ _ v = S.elements v.succ end module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) : Sig.IM with type V.label = V.t and type E.label = E.t = AbstractLabeled (V)(struct type t = unit let compare _ _ = 0 let default = () end) end module Graph = struct module Abstract(V: ANY_TYPE) : Sig.IM with type V.label = V.t and type E.label = unit module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) : Sig.IM with type V.label = V.t and type E.label = E.t end end *****) (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/classic.mli0000644000175000017500000000477312133565070015526 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: classic.mli,v 1.12 2005-02-25 13:54:33 signoles Exp $ *) (** Some classic graphs *) module type S = sig type graph val divisors : int -> graph (** [divisors n] builds the graph of divisors. Vertices are integers from [2] to [n]. [i] is connected to [j] if and only if [i] divides [j]. @raise Invalid_argument is [n < 2]. *) val de_bruijn : int -> graph (** [de_bruijn n] builds the de Bruijn graph of order [n]. Vertices are bit sequences of length [n] (encoded as their interpretation as binary integers). The sequence [xw] is connected to the sequence [wy] for any bits [x] and [y] and any bit sequence [w] of length [n-1]. @raise Invalid_argument is [n < 1] or [n > Sys.word_size-1]. *) val vertex_only : int -> graph (** [vertex_only n] builds a graph with [n] vertices and no edge. *) val full : ?self:bool -> int -> graph (** [full n] builds a graph with [n] vertices and all possible edges. The optional argument [self] indicates if loop edges should be added (default value is [true]). *) end module P (G : Sig.P with type V.label = int) : S with type graph = G.t (** Classic Persistent Graphs *) module I (G : Sig.I with type V.label = int) : S with type graph = G.t (** Classic Imperative Graphs *) ocamlgraph-1.8.3/src/sig.mli0000644000175000017500000002763312133565071014670 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** {b Signatures for graph implementations.} *) (** {2 Signatures for graph implementations} *) (** Signature for vertices. *) module type VERTEX = sig (** Vertices are {!COMPARABLE}. *) type t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool (** Vertices are labeled. *) type label val create : label -> t val label : t -> label end (** Signature for edges. *) module type EDGE = sig (** Edges are {!ORDERED_TYPE}. *) type t val compare : t -> t -> int (** Edges are directed. *) type vertex val src : t -> vertex (** Edge origin. *) val dst : t -> vertex (** Edge destination. *) (** Edges are labeled. *) type label val create : vertex -> label -> vertex -> t (** [create v1 l v2] creates an edge from [v1] to [v2] with label [l] *) val label : t -> label (** Get the label of an edge. *) end (** Common signature for all graphs. *) module type G = sig (** {2 Graph structure} *) (** Abstract type of graphs *) type t (** Vertices have type [V.t] and are labeled with type [V.label] (note that an implementation may identify the vertex with its label) *) module V : VERTEX type vertex = V.t (** Edges have type [E.t] and are labeled with type [E.label]. [src] (resp. [dst]) returns the origin (resp. the destination) of a given edge. *) module E : EDGE with type vertex = vertex type edge = E.t (** Is this an implementation of directed graphs? *) val is_directed : bool (** {2 Size functions} *) val is_empty : t -> bool val nb_vertex : t -> int val nb_edges : t -> int (** Degree of a vertex *) val out_degree : t -> vertex -> int (** [out_degree g v] returns the out-degree of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) val in_degree : t -> vertex -> int (** [in_degree g v] returns the in-degree of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) (** {2 Membership functions} *) val mem_vertex : t -> vertex -> bool val mem_edge : t -> vertex -> vertex -> bool val mem_edge_e : t -> edge -> bool val find_edge : t -> vertex -> vertex -> edge (** [find_edge g v1 v2] returns the edge from [v1] to [v2] if it exists. Unspecified behaviour if [g] has several edges from [v1] to [v2]. @raise Not_found if no such edge exists. *) val find_all_edges : t -> vertex -> vertex -> edge list (** [find_all_edges g v1 v2] returns all the edges from [v1] to [v2]. @since ocamlgraph 1.8 *) (** {2 Successors and predecessors} You should better use iterators on successors/predecessors (see Section "Vertex iterators"). *) val succ : t -> vertex -> vertex list (** [succ g v] returns the successors of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) val pred : t -> vertex -> vertex list (** [pred g v] returns the predecessors of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) (** Labeled edges going from/to a vertex *) val succ_e : t -> vertex -> edge list (** [succ_e g v] returns the edges going from [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) val pred_e : t -> vertex -> edge list (** [pred_e g v] returns the edges going to [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) (** {2 Graph iterators} *) val iter_vertex : (vertex -> unit) -> t -> unit (** Iter on all vertices of a graph. *) val fold_vertex : (vertex -> 'a -> 'a) -> t -> 'a -> 'a (** Fold on all vertices of a graph. *) val iter_edges : (vertex -> vertex -> unit) -> t -> unit (** Iter on all edges of a graph. Edge label is ignored. *) val fold_edges : (vertex -> vertex -> 'a -> 'a) -> t -> 'a -> 'a (** Fold on all edges of a graph. Edge label is ignored. *) val iter_edges_e : (edge -> unit) -> t -> unit (** Iter on all edges of a graph. *) val fold_edges_e : (edge -> 'a -> 'a) -> t -> 'a -> 'a (** Fold on all edges of a graph. *) val map_vertex : (vertex -> vertex) -> t -> t (** Map on all vertices of a graph. *) (** {2 Vertex iterators} Each iterator [iterator f v g] iters [f] to the successors/predecessors of [v] in the graph [g] and raises [Invalid_argument] if [v] is not in [g]. It is the same for functions [fold_*] which use an additional accumulator. Time complexity for ocamlgraph implementations: operations on successors are in O(1) amortized for imperative graphs and in O(ln(|V|)) for persistent graphs while operations on predecessors are in O(max(|V|,|E|)) for imperative graphs and in O(max(|V|,|E|)*ln|V|) for persistent graphs. *) (** iter/fold on all successors/predecessors of a vertex. *) val iter_succ : (vertex -> unit) -> t -> vertex -> unit val iter_pred : (vertex -> unit) -> t -> vertex -> unit val fold_succ : (vertex -> 'a -> 'a) -> t -> vertex -> 'a -> 'a val fold_pred : (vertex -> 'a -> 'a) -> t -> vertex -> 'a -> 'a (** iter/fold on all edges going from/to a vertex. *) val iter_succ_e : (edge -> unit) -> t -> vertex -> unit val fold_succ_e : (edge -> 'a -> 'a) -> t -> vertex -> 'a -> 'a val iter_pred_e : (edge -> unit) -> t -> vertex -> unit val fold_pred_e : (edge -> 'a -> 'a) -> t -> vertex -> 'a -> 'a end (** Signature for persistent (i.e. immutable) graph. *) module type P = sig include G (** A persistent graph is a graph. *) val empty : t (** The empty graph. *) val add_vertex : t -> vertex -> t (** [add_vertex g v] adds the vertex [v] to the graph [g]. Just return [g] if [v] is already in [g]. *) val remove_vertex : t -> vertex -> t (** [remove g v] removes the vertex [v] from the graph [g] (and all the edges going from [v] in [g]). Just return [g] if [v] is not in [g]. Time complexity for ocamlgraph implementations: O(|V|*ln(|V|)) for unlabeled graphs and O(|V|*max(ln(|V|),D)) for labeled graphs. D is the maximal degree of the graph. *) val add_edge : t -> vertex -> vertex -> t (** [add_edge g v1 v2] adds an edge from the vertex [v1] to the vertex [v2] in the graph [g]. Add also [v1] (resp. [v2]) in [g] if [v1] (resp. [v2]) is not in [g]. Just return [g] if this edge is already in [g]. *) val add_edge_e : t -> edge -> t (** [add_edge_e g e] adds the edge [e] in the graph [g]. Add also [E.src e] (resp. [E.dst e]) in [g] if [E.src e] (resp. [E.dst e]) is not in [g]. Just return [g] if [e] is already in [g]. *) val remove_edge : t -> vertex -> vertex -> t (** [remove_edge g v1 v2] removes the edge going from [v1] to [v2] from the graph [g]. If the graph is labelled, all the edges going from [v1] to [v2] are removed from [g]. Just return [g] if this edge is not in [g]. @raise Invalid_argument if [v1] or [v2] are not in [g]. *) val remove_edge_e : t -> edge -> t (** [remove_edge_e g e] removes the edge [e] from the graph [g]. Just return [g] if [e] is not in [g]. @raise Invalid_argument if [E.src e] or [E.dst e] are not in [g]. *) end (** Signature for imperative (i.e. mutable) graphs. *) module type I = sig include G (** An imperative graph is a graph. *) val create : ?size:int -> unit -> t (** [create ()] returns an empty graph. Optionally, a size can be given, which should be on the order of the expected number of vertices that will be in the graph (for hash tables-based implementations). The graph grows as needed, so [size] is just an initial guess. *) val clear: t -> unit (** Remove all vertices and edges from the given graph. @since ocamlgraph 1.4 *) val copy : t -> t (** [copy g] returns a copy of [g]. Vertices and edges (and eventually marks, see module [Mark]) are duplicated. *) val add_vertex : t -> vertex -> unit (** [add_vertex g v] adds the vertex [v] to the graph [g]. Do nothing if [v] is already in [g]. *) val remove_vertex : t -> vertex -> unit (** [remove g v] removes the vertex [v] from the graph [g] (and all the edges going from [v] in [g]). Do nothing if [v] is not in [g]. Time complexity for ocamlgraph implementations: O(|V|*ln(D)) for unlabeled graphs and O(|V|*D) for labeled graphs. D is the maximal degree of the graph. *) val add_edge : t -> vertex -> vertex -> unit (** [add_edge g v1 v2] adds an edge from the vertex [v1] to the vertex [v2] in the graph [g]. Add also [v1] (resp. [v2]) in [g] if [v1] (resp. [v2]) is not in [g]. Do nothing if this edge is already in [g]. *) val add_edge_e : t -> edge -> unit (** [add_edge_e g e] adds the edge [e] in the graph [g]. Add also [E.src e] (resp. [E.dst e]) in [g] if [E.src e] (resp. [E.dst e]) is not in [g]. Do nothing if [e] is already in [g]. *) val remove_edge : t -> vertex -> vertex -> unit (** [remove_edge g v1 v2] removes the edge going from [v1] to [v2] from the graph [g]. If the graph is labelled, all the edges going from [v1] to [v2] are removed from [g]. Do nothing if this edge is not in [g]. @raise Invalid_argument if [v1] or [v2] are not in [g]. *) val remove_edge_e : t -> edge -> unit (** [remove_edge_e g e] removes the edge [e] from the graph [g]. Do nothing if [e] is not in [g]. @raise Invalid_argument if [E.src e] or [E.dst e] are not in [g]. *) end (** Signature for marks on vertices. *) module type MARK = sig type graph (** Type of graphs. *) type vertex (** Type of graph vertices. *) val clear : graph -> unit (** [clear g] sets all the marks to 0 for all the vertices of [g]. *) val get : vertex -> int (** Mark value (in O(1)). *) val set : vertex -> int -> unit (** Set the mark of the given vertex. *) end (** Signature for imperative graphs with marks on vertices. *) module type IM = sig include I (** An imperative graph with marks is an imperative graph. *) (** Mark on vertices. Marks can be used if you want to store some information on vertices: it is more efficient to use marks than an external table. *) module Mark : MARK with type graph = t and type vertex = vertex end (** {2 Signature for ordered and hashable types} *) (** Signature with only an abstract type. *) module type ANY_TYPE = sig type t end (** Signature equivalent to [Set.OrderedType]. *) module type ORDERED_TYPE = sig type t val compare : t -> t -> int end (** Signature equivalent to [Set.OrderedType] with a default value. *) module type ORDERED_TYPE_DFT = sig include ORDERED_TYPE val default : t end (** Signature equivalent to [Hashtbl.HashedType]. *) module type HASHABLE = sig type t val hash : t -> int val equal : t -> t -> bool end (** Signature merging {!ORDERED_TYPE} and {!HASHABLE}. *) module type COMPARABLE = sig type t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/mcs_m.mli0000644000175000017500000000462512133565071015200 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: mcs_m.mli,v 1.2 2004-10-19 15:21:44 signoles Exp $ *) (** Maximal Cardinality Search (MCS-M) algorithm Based on the article: Maximal Cardinality Search for Computing Minimal Triangulations of Graphs. by A. Berry, Jean R. S. Blair, Pinar Heggernes & Barry W. Peyton. @author Matthieu Sozeau @author Pierre-Loic Garoche *) module MaximalCardinalitySearch : sig module P(G : Sig.P) : sig type edgelist = (G.V.t * G.V.t) list (** [mcsm g] returns a tuple [(o, e)] where [o] is a perfect elimination order of [g'] where [g'] is the triangulation [e] applied to [g]. *) val mcsm : G.t -> (int * G.V.t) list * edgelist (** [triangulate g] computes a triangulation of [g] using the MCS-M algorithm *) val triangulate : G.t -> G.t end module I(Gr : Sig.I) : sig type edgelist = (Gr.V.t * Gr.V.t) list (** [mcsm g] return a tuple [(o, e)] where o is a perfect elimination order of [g'] where [g'] is the triangulation [e] applied to [g]. *) val mcsm : Gr.t -> (int * Gr.V.t) list * edgelist (** [triangulate g] triangulates [g] using the MCS-M algorithm *) val triangulate : Gr.t -> unit end end ocamlgraph-1.8.3/src/blocks.ml0000644000175000017500000006470712133565070015214 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Common implementation to persistent and imperative graphs. *) open Sig open Util let first_value_for_cpt_vertex = 0 let cpt_vertex = ref first_value_for_cpt_vertex (* global counter for abstract vertex *) (* [max_cpt t1 t2] returns the maximum of [t1] and [t2] wrt the total ordering induced by tags creation. This ordering is defined as follow: forall tags t1 t2, t1 <= t2 iff t1 is before t2 in the finite sequence [0; 1; ..; max_int; min_int; min_int-1; -1] *) let max_cpt c1 c2 = max (c1 + min_int) (c2 + min_int) - min_int (* This function must be called after the unserialisation of any abstract vertex if you want to create new vertices. *) let after_unserialization serialized_cpt_vertex = cpt_vertex := max_cpt serialized_cpt_vertex !cpt_vertex (* ************************************************************************* *) (** {2 Association table builder} *) (* ************************************************************************* *) (** Common signature to an imperative/persistent association table *) module type HM = sig type 'a return type 'a t type key val create : ?size:int -> unit -> 'a t val create_from : 'a t -> 'a t val empty : 'a return val clear: 'a t -> unit val is_empty : 'a t -> bool val add : key -> 'a -> 'a t -> 'a t val remove : key -> 'a t -> 'a t val mem : key -> 'a t -> bool val find : key -> 'a t -> 'a val find_and_raise : key -> 'a t -> string -> 'a (** [find_and_raise k t s] is equivalent to [find k t] but raises [Invalid_argument s] when [find k t] raises [Not_found] *) val iter : (key -> 'a -> unit) -> 'a t -> unit val map : (key -> 'a -> key * 'a) -> 'a t -> 'a t val fold : (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b val copy : 'a t -> 'a t end module type TBL_BUILDER = functor(X: COMPARABLE) -> HM with type key = X.t (** [HM] implementation using hashtbl. *) module Make_Hashtbl(X: COMPARABLE) = struct include Hashtbl.Make(X) type 'a return = unit let empty = () (* never call and not visible for the user thank's to signature constraints *) let create_from h = create (length h) let create ?(size=97) () = create size let is_empty h = (length h = 0) let find_and_raise k h s = try find h k with Not_found -> invalid_arg s let map f h = let h' = create_from h in iter (fun k v -> let k, v = f k v in add h' k v) h; h' let add k v h = replace h k v; h let remove k h = remove h k; h let mem k h = mem h k let find k h = find h k end (** [HM] implementation using map *) module Make_Map(X: COMPARABLE) = struct include Map.Make(X) type 'a return = 'a t let is_empty m = (m = empty) let create ?size () = assert false (* never call and not visible for the user thank's to signature constraints *) let create_from _ = empty let copy m = m let map f m = fold (fun k v m -> let k, v = f k v in add k v m) m empty let find_and_raise k h s = try find k h with Not_found -> invalid_arg s let clear _ = assert false (* never call and not visible for the user thank's to signature constraints *) end (* ************************************************************************* *) (** {2 Blocks builder} *) (* ************************************************************************* *) (** Common implementation to all (directed) graph implementations. *) module Minimal(S: Set.S)(HM: HM) = struct type vertex = HM.key let is_directed = true let empty = HM.empty let create = HM.create let is_empty = HM.is_empty let copy = HM.copy let clear = HM.clear let nb_vertex g = HM.fold (fun _ _ -> succ) g 0 let nb_edges g = HM.fold (fun _ s n -> n + S.cardinal s) g 0 let out_degree g v = S.cardinal (try HM.find v g with Not_found -> invalid_arg "[ocamlgraph] out_degree") let mem_vertex g v = HM.mem v g let unsafe_add_vertex g v = HM.add v S.empty g let unsafe_add_edge g v1 v2 = HM.add v1 (S.add v2 (HM.find v1 g)) g let add_vertex g v = if HM.mem v g then g else unsafe_add_vertex g v let iter_vertex f = HM.iter (fun v _ -> f v) let fold_vertex f = HM.fold (fun v _ -> f v) end (** All the predecessor operations from the iterators on the edges *) module Pred (S: sig module PV: COMPARABLE module PE: EDGE with type vertex = PV.t type t val mem_vertex : PV.t -> t -> bool val iter_edges : (PV.t -> PV.t -> unit) -> t -> unit val fold_edges : (PV.t -> PV.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_edges_e : (PE.t -> unit) -> t -> unit val fold_edges_e : (PE.t -> 'a -> 'a) -> t -> 'a -> 'a end) = struct open S let iter_pred f g v = if not (mem_vertex v g) then invalid_arg "[ocamlgraph] iter_pred"; iter_edges (fun v1 v2 -> if PV.equal v v2 then f v1) g let fold_pred f g v = if not (mem_vertex v g) then invalid_arg "[ocamlgraph] fold_pred"; fold_edges (fun v1 v2 a -> if PV.equal v v2 then f v1 a else a) g let pred g v = fold_pred (fun v l -> v :: l) g v [] let in_degree g v = if not (mem_vertex v g) then invalid_arg "[ocamlgraph] in_degree"; fold_pred (fun v n -> n + 1) g v 0 let iter_pred_e f g v = if not (mem_vertex v g) then invalid_arg "[ocamlgraph] iter_pred_e"; iter_edges_e (fun e -> if PV.equal v (PE.dst e) then f e) g let fold_pred_e f g v = if not (mem_vertex v g) then invalid_arg "[ocamlgraph] fold_pred_e"; fold_edges_e (fun e a -> if PV.equal v (PE.dst e) then f e a else a) g let pred_e g v = fold_pred_e (fun v l -> v :: l) g v [] end (** Common implementation to all the unlabeled (directed) graphs. *) module Unlabeled(V: COMPARABLE)(HM: HM with type key = V.t) = struct module S = Set.Make(V) module E = struct type vertex = V.t include OTProduct(V)(V) let src = fst let dst = snd type label = unit let label _ = () let create v1 () v2 = v1, v2 end type edge = E.t let mem_edge g v1 v2 = try S.mem v2 (HM.find v1 g) with Not_found -> false let mem_edge_e g (v1, v2) = mem_edge g v1 v2 let find_edge g v1 v2 = if mem_edge g v1 v2 then v1, v2 else raise Not_found let find_all_edges g v1 v2 = try [ find_edge g v1 v2 ] with Not_found -> [] let unsafe_remove_edge g v1 v2 = HM.add v1 (S.remove v2 (HM.find v1 g)) g let unsafe_remove_edge_e g (v1, v2) = unsafe_remove_edge g v1 v2 let remove_edge g v1 v2 = if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge"; HM.add v1 (S.remove v2 (HM.find_and_raise v1 g "[ocamlgraph] remove_edge")) g let remove_edge_e g (v1, v2) = remove_edge g v1 v2 let iter_succ f g v = S.iter f (HM.find_and_raise v g "[ocamlgraph] iter_succ") let fold_succ f g v = S.fold f (HM.find_and_raise v g "[ocamlgraph] fold_succ") let iter_succ_e f g v = iter_succ (fun v2 -> f (v, v2)) g v let fold_succ_e f g v = fold_succ (fun v2 -> f (v, v2)) g v let succ g v = S.elements (HM.find_and_raise v g "[ocamlgraph] succ") let succ_e g v = fold_succ_e (fun e l -> e :: l) g v [] let map_vertex f = HM.map (fun v s -> f v, S.fold (fun v s -> S.add (f v) s) s S.empty) module I = struct type t = S.t HM.t module PV = V module PE = E let iter_edges f = HM.iter (fun v -> S.iter (f v)) let fold_edges f = HM.fold (fun v -> S.fold (f v)) let iter_edges_e f = iter_edges (fun v1 v2 -> f (v1, v2)) let fold_edges_e f = fold_edges (fun v1 v2 a -> f (v1, v2) a) end include I include Pred(struct include I let mem_vertex = HM.mem end) end (** Common implementation to all the labeled (directed) graphs. *) module Labeled(V: COMPARABLE)(E: ORDERED_TYPE)(HM: HM with type key = V.t) = struct module VE = OTProduct(V)(E) module S = Set.Make(VE) module E = struct type vertex = V.t type label = E.t type t = vertex * label * vertex let src (v, _, _) = v let dst (_, _, v) = v let label (_, l, _) = l let create v1 l v2 = v1, l, v2 module C = OTProduct(V)(VE) let compare (x1, x2, x3) (y1, y2, y3) = C.compare (x1, (x3, x2)) (y1, (y3, y2)) end type edge = E.t let mem_edge g v1 v2 = try S.exists (fun (v2', _) -> V.equal v2 v2') (HM.find v1 g) with Not_found -> false let mem_edge_e g (v1, l, v2) = try let ve = v2, l in S.exists (fun ve' -> VE.compare ve ve' = 0) (HM.find v1 g) with Not_found -> false exception Found of edge let find_edge g v1 v2 = try S.iter (fun (v2', l) -> if V.equal v2 v2' then raise (Found (v1, l, v2'))) (HM.find v1 g); raise Not_found with Found e -> e let find_all_edges g v1 v2 = try S.fold (fun (v2', l) acc -> if V.equal v2 v2' then (v1, l, v2') :: acc else acc) (HM.find v1 g) [] with Not_found -> [] let unsafe_remove_edge g v1 v2 = HM.add v1 (S.filter (fun (v2', _) -> not (V.equal v2 v2')) (HM.find v1 g)) g let unsafe_remove_edge_e g (v1, l, v2) = HM.add v1 (S.remove (v2, l) (HM.find v1 g)) g let remove_edge g v1 v2 = if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge"; HM.add v1 (S.filter (fun (v2', _) -> not (V.equal v2 v2')) (HM.find_and_raise v1 g "[ocamlgraph] remove_edge")) g let remove_edge_e g (v1, l, v2) = if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge_e"; HM.add v1 (S.remove (v2, l) (HM.find_and_raise v1 g "[ocamlgraph] remove_edge_e")) g let iter_succ f g v = S.iter (fun (w, _) -> f w) (HM.find_and_raise v g "[ocamlgraph] iter_succ") let fold_succ f g v = S.fold (fun (w, _) -> f w) (HM.find_and_raise v g "[ocamlgraph] fold_succ") let iter_succ_e f g v = S.iter (fun (w, l) -> f (v, l, w)) (HM.find_and_raise v g "[ocamlgraph] iter_succ_e") let fold_succ_e f g v = S.fold (fun (w, l) -> f (v, l, w)) (HM.find_and_raise v g "[ocamlgraph] fold_succ_e") let succ g v = fold_succ (fun w l -> w :: l) g v [] let succ_e g v = fold_succ_e (fun e l -> e :: l) g v [] let map_vertex f = HM.map (fun v s -> f v, S.fold (fun (v, l) s -> S.add (f v, l) s) s S.empty) module I = struct type t = S.t HM.t module PV = V module PE = E let iter_edges f = HM.iter (fun v -> S.iter (fun (w, _) -> f v w)) let fold_edges f = HM.fold (fun v -> S.fold (fun (w, _) -> f v w)) let iter_edges_e f = HM.iter (fun v -> S.iter (fun (w, l) -> f (v, l, w))) let fold_edges_e f = HM.fold (fun v -> S.fold (fun (w, l) -> f (v, l, w))) end include I include Pred(struct include I let mem_vertex = HM.mem end) end (** The vertex module and the vertex table for the concrete graphs. *) module ConcreteVertex(F : TBL_BUILDER)(V: COMPARABLE) = struct module V = struct include V type label = t let label v = v let create v = v end module HM = F(V) end module Make_Abstract (G: sig module HM: HM module S: Set.S include G with type t = S.t HM.t and type V.t = HM.key val remove_edge: t -> vertex -> vertex -> t val remove_edge_e: t -> edge -> t val unsafe_add_vertex: t -> vertex -> t val unsafe_add_edge: t -> vertex -> S.elt -> t val unsafe_remove_edge: t -> vertex -> vertex -> t val unsafe_remove_edge_e: t -> edge -> t val create: ?size:int -> unit -> t val clear: t -> unit end) = struct module I = struct type t = { edges : G.t; mutable size : int } (* BE CAREFUL: [size] is only mutable in the imperative version. As there is no extensible records in current ocaml version, and for genericity purpose, [size] is mutable in both imperative and persistent implementations. Do not modify size in the persistent implementation! *) type vertex = G.vertex type edge = G.edge module PV = G.V module PE = G.E let iter_edges f g = G.iter_edges f g.edges let fold_edges f g = G.fold_edges f g.edges let iter_edges_e f g = G.iter_edges_e f g.edges let fold_edges_e f g = G.fold_edges_e f g.edges let mem_vertex v g = G.mem_vertex g.edges v let create ?size () = { edges = G.create ?size (); size = 0 } let clear g = G.clear g.edges; g.size <- 0 end include I include Pred(I) (* optimisations *) let is_empty g = g.size = 0 let nb_vertex g = g.size (* redefinitions *) module V = G.V module E = G.E module HM = G.HM module S = G.S let unsafe_add_edge = G.unsafe_add_edge let unsafe_remove_edge = G.unsafe_remove_edge let unsafe_remove_edge_e = G.unsafe_remove_edge_e let is_directed = G.is_directed let remove_edge g = G.remove_edge g.edges let remove_edge_e g = G.remove_edge_e g.edges let out_degree g = G.out_degree g.edges let in_degree g = G.in_degree g.edges let nb_edges g = G.nb_edges g.edges let succ g = G.succ g.edges let mem_vertex g = G.mem_vertex g.edges let mem_edge g = G.mem_edge g.edges let mem_edge_e g = G.mem_edge_e g.edges let find_edge g = G.find_edge g.edges let find_all_edges g = G.find_all_edges g.edges let iter_vertex f g = G.iter_vertex f g.edges let fold_vertex f g = G.fold_vertex f g.edges let iter_succ f g = G.iter_succ f g.edges let fold_succ f g = G.fold_succ f g.edges let succ_e g = G.succ_e g.edges let iter_succ_e f g = G.iter_succ_e f g.edges let fold_succ_e f g = G.fold_succ_e f g.edges let map_vertex f g = { g with edges = G.map_vertex f g.edges } (* reimplementation *) let copy g = let h = HM.create () in let vertex v = try HM.find v h with Not_found -> let v' = V.create (V.label v) in let h' = HM.add v v' h in assert (h == h'); v' in map_vertex vertex g end (** Support for explicitly maintaining edge set of predecessors. Crucial for algorithms that do a lot of backwards traversal. *) module BidirectionalMinimal(S:Set.S)(HM:HM) = struct type vertex = HM.key let is_directed = true let empty = HM.empty let create = HM.create let clear = HM.clear let is_empty = HM.is_empty let copy = HM.copy let nb_vertex g = HM.fold (fun _ _ -> succ) g 0 let nb_edges g = HM.fold (fun _ (_,s) n -> n + S.cardinal s) g 0 let out_degree g v = S.cardinal (snd (try HM.find v g with Not_found -> invalid_arg "[ocamlgraph] out_degree")) let mem_vertex g v = HM.mem v g let unsafe_add_vertex g v = HM.add v (S.empty, S.empty) g let add_vertex g v = if HM.mem v g then g else unsafe_add_vertex g v let iter_vertex f = HM.iter (fun v _ -> f v) let fold_vertex f = HM.fold (fun v _ -> f v) end module BidirectionalUnlabeled(V:COMPARABLE)(HM:HM with type key = V.t) = struct module S = Set.Make(V) module E = struct type vertex = V.t include OTProduct(V)(V) let src = fst let dst = snd type label = unit let label _ = () let create v1 () v2 = v1, v2 end type edge = E.t let mem_edge g v1 v2 = try S.mem v2 (snd (HM.find v1 g)) with Not_found -> false let mem_edge_e g (v1,v2) = mem_edge g v1 v2 let find_edge g v1 v2 = if mem_edge g v1 v2 then v1, v2 else raise Not_found let find_all_edges g v1 v2 = try [ find_edge g v1 v2 ] with Not_found -> [] let unsafe_remove_edge g v1 v2 = let in_set, out_set = HM.find v1 g in let g = HM.add v1 (in_set, S.remove v2 out_set) g in let in_set, out_set = HM.find v2 g in HM.add v2 (S.remove v1 in_set, out_set) g let unsafe_remove_edge_e g (v1,v2) = unsafe_remove_edge g v1 v2 let remove_edge g v1 v2 = if not (HM.mem v2 g && HM.mem v1 g) then invalid_arg "[ocamlgraph] remove_edge"; unsafe_remove_edge g v1 v2 let remove_edge_e g (v1, v2) = remove_edge g v1 v2 let iter_succ f g v = S.iter f (snd (HM.find_and_raise v g "[ocamlgraph] iter_succ")) let fold_succ f g v = S.fold f (snd (HM.find_and_raise v g "[ocamlgraph] fold_succ")) let iter_succ_e f g v = iter_succ (fun v2 -> f (v, v2)) g v let fold_succ_e f g v = fold_succ (fun v2 -> f (v, v2)) g v let succ g v = S.elements (snd (HM.find_and_raise v g "[ocamlgraph] succ")) let succ_e g v = fold_succ_e (fun e l -> e :: l) g v [] let map_vertex f = HM.map (fun v (s1,s2) -> f v, (S.fold (fun v s -> S.add (f v) s) s1 S.empty, S.fold (fun v s -> S.add (f v) s) s2 S.empty)) module I = struct (* we keep sets for both incoming and outgoing edges *) type t = (S.t (* incoming *) * S.t (* outgoing *)) HM.t module PV = V module PE = E let iter_edges f = HM.iter (fun v (_, outset) -> S.iter (f v) outset) let fold_edges f = HM.fold (fun v (_, outset) -> S.fold (f v) outset) let iter_edges_e f = iter_edges (fun v1 v2 -> f (v1, v2)) let fold_edges_e f = fold_edges (fun v1 v2 a -> f (v1, v2) a) end include I let iter_pred f g v = S.iter f (fst (HM.find_and_raise v g "[ocamlgraph] iter_pred")) let fold_pred f g v = S.fold f (fst (HM.find_and_raise v g "[ocamlgraph] fold_pred")) let pred g v = S.elements (fst (HM.find_and_raise v g "[ocamlgraph] pred")) let in_degree g v = S.cardinal (fst (try HM.find v g with Not_found -> invalid_arg "[ocamlgraph] in_degree")) let iter_pred_e f g v = iter_pred (fun v2 -> f (v2, v)) g v let fold_pred_e f g v = fold_pred (fun v2 -> f (v2, v)) g v let pred_e g v = fold_pred_e (fun e l -> e :: l) g v [] end module BidirectionalLabeled (V:COMPARABLE)(E:ORDERED_TYPE)(HM:HM with type key = V.t) = struct module VE = OTProduct(V)(E) module S = Set.Make(VE) module E = struct type vertex = V.t type label = E.t type t = vertex * label * vertex let src (v, _, _) = v let dst (_, _, v) = v let label (_, l, _) = l let create v1 l v2 = v1, l, v2 module C = OTProduct(V)(VE) let compare (x1, x2, x3) (y1, y2, y3) = C.compare (x1, (x3, x2)) (y1, (y3, y2)) end type edge = E.t let mem_edge g v1 v2 = try S.exists (fun (v2', _) -> V.equal v2 v2') (snd (HM.find v1 g)) with Not_found -> false let mem_edge_e g (v1, l, v2) = try let ve = v2, l in S.exists (fun ve' -> VE.compare ve ve' = 0) (snd (HM.find v1 g)) with Not_found -> false exception Found of edge let find_edge g v1 v2 = try S.iter (fun (v2', l) -> if V.equal v2 v2' then raise (Found (v1, l, v2'))) (snd (HM.find v1 g)); raise Not_found with Found e -> e let find_all_edges g v1 v2 = try S.fold (fun (v2', l) acc -> if V.equal v2 v2' then (v1, l, v2') :: acc else acc) (snd (HM.find v1 g)) [] with Not_found -> [] let unsafe_remove_edge g v1 v2 = let in_set, out_set = HM.find v1 g in let del v set = S.filter (fun (v', _) -> not (V.equal v v')) set in let g = HM.add v1 (in_set, del v2 out_set) g in let in_set, out_set = HM.find v2 g in HM.add v2 (del v1 in_set, out_set) g let unsafe_remove_edge_e g (v1, l, v2) = let in_set, out_set = HM.find v1 g in let g = HM.add v1 (in_set, S.remove (v2, l) out_set) g in let in_set, out_set = HM.find v2 g in HM.add v2 (S.remove (v1, l) in_set, out_set) g let remove_edge g v1 v2 = (* if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge";*) let in_set, out_set = HM.find_and_raise v1 g "[ocamlgraph] remove_edge" in let del v set = S.filter (fun (v', _) -> not (V.equal v v')) set in let g = HM.add v1 (in_set, del v2 out_set) g in let in_set, out_set = HM.find_and_raise v2 g "[ocamlgraph] remove_edge" in HM.add v2 (del v1 in_set, out_set) g let remove_edge_e g (v1, l, v2) = (* if not (HM.mem v2 g) then invalid_arg "[ocamlgraph] remove_edge_e";*) let in_set, out_set = HM.find_and_raise v1 g "[ocamlgraph] remove_edge_e" in let g = HM.add v1 (in_set, S.remove (v2, l) out_set) g in let in_set, out_set = HM.find_and_raise v2 g "[ocamlgraph] remove_edge_e" in HM.add v2 (S.remove (v1, l) in_set, out_set) g let iter_succ f g v = S.iter (fun (w, _) -> f w) (snd (HM.find_and_raise v g "[ocamlgraph] iter_succ")) let fold_succ f g v = S.fold (fun (w, _) -> f w) (snd (HM.find_and_raise v g "[ocamlgraph] fold_succ")) let iter_succ_e f g v = S.iter (fun (w, l) -> f (v, l, w)) (snd (HM.find_and_raise v g "[ocamlgraph] iter_succ_e")) let fold_succ_e f g v = S.fold (fun (w, l) -> f (v, l, w)) (snd (HM.find_and_raise v g "[ocamlgraph] fold_succ_e")) let succ g v = fold_succ (fun w l -> w :: l) g v [] let succ_e g v = fold_succ_e (fun e l -> e :: l) g v [] let map_vertex f = HM.map (fun v (s1,s2) -> f v, (S.fold (fun (v, l) s -> S.add (f v, l) s) s1 S.empty, S.fold (fun (v, l) s -> S.add (f v, l) s) s2 S.empty)) module I = struct type t = (S.t * S.t) HM.t module PV = V module PE = E let iter_edges f = HM.iter (fun v (_,outset) -> S.iter (fun (w, _) -> f v w) outset) let fold_edges f = HM.fold (fun v (_,outset) -> S.fold (fun (w, _) -> f v w) outset) let iter_edges_e f = HM.iter (fun v (_,outset) -> S.iter (fun (w, l) -> f (v, l, w)) outset) let fold_edges_e f = HM.fold (fun v (_,outset) -> S.fold (fun (w, l) -> f (v, l, w)) outset) end include I let iter_pred f g v = S.iter (fun (w, _) -> f w) (fst (HM.find_and_raise v g "[ocamlgraph] iter_pred")) let fold_pred f g v = S.fold (fun (w, _) -> f w) (fst (HM.find_and_raise v g "[ocamlgraph] fold_pred")) let in_degree g v = S.cardinal (fst (try HM.find v g with Not_found -> invalid_arg "[ocamlgraph] in_degree")) let iter_pred_e f g v = S.iter (fun (w, l) -> f (w, l, v)) (fst (HM.find_and_raise v g "[ocamlgraph] iter_pred_e")) let fold_pred_e f g v = S.fold (fun (w, l) -> f (w, l, v)) (fst (HM.find_and_raise v g "[ocamlgraph] fold_pred_e")) let pred g v = fold_pred (fun w l -> w :: l) g v [] let pred_e g v = fold_pred_e (fun e l -> e :: l) g v [] end (** Build persistent (resp. imperative) graphs from a persistent (resp. imperative) association table *) module Make(F : TBL_BUILDER) = struct module Digraph = struct module Concrete(V: COMPARABLE) = struct include ConcreteVertex(F)(V) include Unlabeled(V)(HM) include Minimal(S)(HM) let add_edge g v1 v2 = let g = add_vertex g v1 in let g = add_vertex g v2 in unsafe_add_edge g v1 v2 let add_edge_e g (v1, v2) = add_edge g v1 v2 end module ConcreteBidirectional(V: COMPARABLE) = struct include ConcreteVertex(F)(V) include BidirectionalUnlabeled(V)(HM) include BidirectionalMinimal(S)(HM) let unsafe_add_edge g v1 v2 = let in_set, out_set = HM.find v1 g in let g = HM.add v1 (in_set,S.add v2 out_set) g in let in_set, out_set = HM.find v2 g in HM.add v2 (S.add v1 in_set,out_set) g let add_edge g v1 v2 = let g = add_vertex g v1 in let g = add_vertex g v2 in unsafe_add_edge g v1 v2 let add_edge_e g (v1, v2) = add_edge g v1 v2 end module ConcreteLabeled(V: COMPARABLE)(Edge: ORDERED_TYPE_DFT) = struct include ConcreteVertex(F)(V) include Labeled(V)(Edge)(HM) include Minimal(S)(HM) let add_edge_e g (v1, l, v2) = let g = add_vertex g v1 in let g = add_vertex g v2 in unsafe_add_edge g v1 (v2, l) let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) end module ConcreteBidirectionalLabeled (V: COMPARABLE)(Edge: ORDERED_TYPE_DFT) = struct include ConcreteVertex(F)(V) include BidirectionalLabeled(V)(Edge)(HM) include BidirectionalMinimal(S)(HM) let unsafe_add_edge_e g (v1, l, v2) = let in_set, out_set = HM.find v1 g in let g = HM.add v1 (in_set,S.add (v2,l) out_set) g in let in_set, out_set = HM.find v2 g in HM.add v2 (S.add (v1,l) in_set,out_set) g let unsafe_add_edge g v1 v2 = unsafe_add_edge_e g (v1, Edge.default, v2) let add_edge_e g (v1, l, v2) = let g = add_vertex g v1 in let g = add_vertex g v2 in unsafe_add_edge_e g (v1, l, v2) let add_edge g v1 v2 = add_edge_e g (v1, Edge.default, v2) end module Abstract(V: VERTEX) = struct module G = struct module V = V module HM = F(V) include Unlabeled(V)(HM) include Minimal(S)(HM) end include Make_Abstract(G) end module AbstractLabeled(V: VERTEX)(E: ORDERED_TYPE_DFT) = struct module G = struct module V = V module HM = F(V) include Labeled(V)(E)(HM) include Minimal(S)(HM) end include Make_Abstract(G) end end end (** Implementation of undirected graphs from implementation of directed graphs. *) module Graph (G: sig include Sig.G val create: ?size:int -> unit -> t val clear: t -> unit val copy: t -> t type return val add_vertex: t -> vertex -> return val remove_vertex: t -> vertex -> return end) = struct include G let is_directed = false (* Redefine iterators and [nb_edges]. *) let iter_edges f = iter_edges (fun v1 v2 -> if V.compare v1 v2 >= 0 then f v1 v2) let fold_edges f = fold_edges (fun v1 v2 acc -> if V.compare v1 v2 >= 0 then f v1 v2 acc else acc) let iter_edges_e f = iter_edges_e (fun e -> if V.compare (E.src e) (E.dst e) >= 0 then f e) let fold_edges_e f = fold_edges_e (fun e acc -> if V.compare (E.src e) (E.dst e) >= 0 then f e acc else acc) let nb_edges g = fold_edges_e (fun _ -> (+) 1) g 0 (* Redefine operations on predecessors: predecessors are successors in an undirected graph. *) let pred = succ let in_degree = out_degree let iter_pred = iter_succ let fold_pred = fold_succ let pred_e = succ_e let iter_pred_e = iter_succ_e let fold_pred_e = fold_succ_e end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/dot_parser.mly0000644000175000017500000000734512133565070016265 0ustar mehdimehdi/**************************************************************************/ /* */ /* Ocamlgraph: a generic graph library for OCaml */ /* Copyright (C) 2004-2010 */ /* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles */ /* */ /* This software is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License version 2.1, with the special exception on linking */ /* described in file LICENSE. */ /* */ /* This software 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. */ /* */ /**************************************************************************/ /* $Id:$ */ /* DOT parser, following http://www.graphviz.org/doc/info/lang.html */ %{ open Dot_ast open Parsing let compass_pt = function | Ident "n" -> N | Ident "ne" -> Ne | Ident "e" -> E | Ident "se" -> Se | Ident "s" -> S | Ident "sw" -> Sw | Ident "w" -> W | Ident "nw" -> Nw | _ -> invalid_arg "compass_pt" %} %token ID %token COLON COMMA EQUAL SEMICOLON EDGEOP %token STRICT GRAPH DIGRAPH LBRA RBRA LSQ RSQ NODE EDGE SUBGRAPH EOF %nonassoc ID %nonassoc LBRA %type file %start file %% file: | strict_opt graph_or_digraph id_opt LBRA stmt_list RBRA EOF { { strict = $1; digraph = $2; id = $3; stmts = $5 } } ; strict_opt: | /* epsilon */ { false } | STRICT { true } ; graph_or_digraph: | GRAPH { false } | DIGRAPH { true } ; stmt_list: | /* epsilon */ { [] } | list1_stmt { $1 } ; list1_stmt: | stmt semicolon_opt { [$1] } | stmt semicolon_opt list1_stmt { $1 :: $3 } ; semicolon_opt: | /* epsilon */ { () } | SEMICOLON { () } ; stmt: | node_stmt { $1 } | edge_stmt { $1 } | attr_stmt { $1 } | ID EQUAL ID { Equal ($1, $3) } | subgraph { Subgraph $1 } ; node_stmt: | node_id attr_list_opt { Node_stmt ($1, $2) } ; edge_stmt: | node edge_rhs attr_list_opt { Edge_stmt ($1, $2, $3) } ; attr_stmt: | GRAPH attr_list { Attr_graph $2 } | NODE attr_list { Attr_node $2 } | EDGE attr_list { Attr_edge $2 } ; edge_rhs: | EDGEOP node edge_rhs_opt { $2 :: $3 } ; edge_rhs_opt: | /* epsilon */ { [] } | EDGEOP node edge_rhs_opt { $2 :: $3 } ; node: | node_id { NodeId $1 } | subgraph { NodeSub $1 } ; node_id: | ID port_opt { $1, $2 } ; port_opt: | /* epsilon */ { None } | port { Some $1 } ; port: | COLON ID { try PortC (compass_pt $2) with Invalid_argument _ -> PortId ($2, None) } | COLON ID COLON ID { let cp = try compass_pt $4 with Invalid_argument _ -> raise Parse_error in PortId ($2, Some cp) } ; attr_list_opt: | /* epsilon */ { [] } | attr_list { $1 } ; attr_list: | LSQ a_list RSQ { [$2] } | LSQ a_list RSQ attr_list { $2 :: $4 } ; id_opt: | /* epsilon */ { None } | ID { Some $1 } ; a_list: | equality comma_opt { [$1] } | equality comma_opt a_list { $1 :: $3 } ; equality: | ID { $1, None } | ID EQUAL ID { $1, Some $3 } ; comma_opt: | /* epsilon */ { () } | COMMA { () } ; subgraph: | SUBGRAPH ID { SubgraphId $2 } | SUBGRAPH ID LBRA stmt_list RBRA { SubgraphDef (Some $2, $4) } | SUBGRAPH LBRA stmt_list RBRA { SubgraphDef (None, $3) } | LBRA stmt_list RBRA { SubgraphDef (None, $2) } ; ocamlgraph-1.8.3/src/delaunay.ml0000644000175000017500000002653212133565070015533 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: delaunay.ml,v 1.12 2005-11-02 13:43:35 filliatr Exp $ *) (** Code follows Don Knuth's algorithm from ``Axioms and hulls'' (LNCS 606, Springer-Verlag, 1992), pp. 73-77. Some code and comments are taken from the Stanford Graph Base, file [gb_plane]. *) open Printf module type CCC = sig type point val ccw : point -> point -> point -> bool val in_circle : point -> point -> point -> point -> bool end module type Triangulation = sig module S : CCC type triangulation val triangulate : S.point array -> triangulation val iter : (S.point -> S.point -> unit) -> triangulation -> unit val fold : (S.point -> S.point -> 'a -> 'a) -> triangulation -> 'a -> 'a val iter_triangles : (S.point -> S.point -> S.point -> unit) -> triangulation -> unit end module Make (S : CCC) = struct module S = S type point = Point of int | Infinity (* Each edge of the current triangulation is represented by two arcs pointing in opposite directions; the two arcs are called mates. Each arc conceptually has a triangle on its left and a mate on its right. *) type arc = { mutable vert : point; (* v, if this arc goes from u to v *) mutable next : arc; (* the arc from v that shares a triangle with this one *) mutable inst : node ref; (* instruction to change when the triangle is modified *) mate : int } and node = | Branch of int * int * node ref * node ref | Terminal of arc type triangulation = { points : S.point array; arcs : arc array; last_used_arc : int } let rec dummy_arc = { vert = Infinity; next = dummy_arc; inst = ref (Terminal dummy_arc); mate = -1 } let make_arc n i = { vert = Infinity; next = dummy_arc; inst = ref (Terminal dummy_arc); mate = 6 * n - 7 - i } let finite = function Point p -> p | Infinity -> assert false (* [flip] will be used in both steps T4 and T5 *) let flip c d e t'' p n n' = let e' = e.next in let c' = c.next in let c'' = c'.next in e.next <- c; c.next <- c''; c''.next <- e; c''.inst <- n; c.inst <- n; e.inst <- n; c.vert <- Point p; d.next <- e'; e'.next <- c'; c'.next <- d; c'.inst <- n'; e'.inst <- n'; d.inst <- n'; d.vert <- Point t'' let triangulate points = let ccw p q r = S.ccw points.(p) points.(q) points.(r) in let in_circle p q r s = S.in_circle points.(p) points.(q) points.(r) points.(s) in let n = Array.length points in if n < 2 then invalid_arg "triangulate"; let arcs = Array.init (6 * n - 6) (make_arc n) in let mate i = 6 * n - 7 - i in (*i DEBUG let rec dump d l = eprintf "%s" (String.make (2*d) ' '); match !l with | Terminal a -> eprintf "T %d\n" (mate a.mate) | Branch (u, v, l, r) -> eprintf "N %d %d\n" u v; dump (d+1) l; dump (d+1) r in i*) (* initialization: create a trivial triangulation for the first 2 vertices *) let u = 0 in let v = 1 in let a1 = arcs.(0) in let a2 = arcs.(1) in let a3 = arcs.(2) in let b1 = arcs.(mate 0) in let b2 = arcs.(mate 1) in let b3 = arcs.(mate 2) in let l1 = ref (Terminal a2) in let l2 = ref (Terminal b3) in a1.vert <- Point v; a1.next <- a2; a1.inst <- l1; a2.vert <- Infinity; a2.next <- a3; a2.inst <- l1; a3.vert <- Point u; a3.next <- a1; a3.inst <- l1; b1.vert <- Point u; b1.next <- b3; b1.inst <- l2; b2.vert <- Point v; b2.next <- b1; b2.inst <- l2; b3.vert <- Infinity; b3.next <- b2; b3.inst <- l2; let l0 = ref (Branch (u, v, l1, l2)) in let j = ref 2 in (* last used arc *) (* then for each new vertex [p] *) for p = 2 to n - 1 do (* Step T1 *) let rec step_T1 l p = match !l with | Terminal al -> l, al | Branch (pl, ql, al, bl) -> step_T1 (if ccw pl ql p then al else bl) p in let l, al = step_T1 l0 p in (* Step T2 *) let a = al in let b = a.next in let c = b.next in let q = a.vert in let r = b.vert in let s = c.vert in j := !j + 3; let aj = arcs.(!j) in let aj_1 = arcs.(!j - 1) in let aj_2 = arcs.(!j - 2) in let bj = arcs.(aj.mate) in let bj_1 = arcs.(aj_1.mate) in let bj_2 = arcs.(aj_2.mate) in let l' = ref (Terminal a) in let l'' = ref (Terminal aj) in let l''' = ref (Terminal c) in aj.vert <- q; aj.next <- b; aj.inst <- l''; aj_1.vert <- r; aj_1.next <- c; aj_1.inst <- l'''; aj_2.vert <- s; aj_2.next <- a; aj_2.inst <- l'; bj.vert <- Point p; bj.next <- aj_2; bj.inst <- l'; bj_1.vert <- Point p; bj_1.next <- aj; bj_1.inst <- l''; bj_2.vert <- Point p; bj_2.next <- aj_1; bj_2.inst <- l'''; a.next <- bj; a.inst <- l'; b.next <- bj_1; b.inst <- l''; c.next <- bj_2; c.inst <- l'''; let r = finite r in let s = finite s in (* steps T3 or T4 depending on [q] *) let r = match q with | Point q -> (* Step T3 *) let n = ref (Branch (q, p, l', l'')) in let n' = ref (Branch (s, p, l''', l')) in l := Branch (r, p, n, n'); r | Infinity -> (* Step T4 *) let n = ref (Branch (s, p, l''', l')) in l := Branch (r, p, l'', n); let rec loop m a d s t = if t <> r && ccw p s t then begin let n = ref (Terminal d) in match !m with | Branch (mu, mv, ml, is_l') -> assert (is_l' == l'); m := Branch (mu, mv, ml, d.inst); d.inst := Branch (t, p, n, l'); let m = d.inst in flip a arcs.(a.mate) d t p n l'; let a = arcs.(a.mate).next in let d = arcs.(a.mate).next in let s = t in let t = finite d.vert in l' := Terminal a; loop m a d s t | Terminal _ -> assert false end else begin (* at exit of while loop *) let n = ref (Terminal d.next) in d.inst := Branch (s, p, n, l'); d.inst <- n; d.next.inst <- n; d.next.next.inst <- n; s end in let d = arcs.(a.mate).next in loop n a d s (finite d.vert) in (* Step T5 *) let rec loop c = let d = arcs.(c.mate) in let e = d.next in let t = finite d.vert in let t' = finite c.vert in let t'' = e.vert in if t'' <> Infinity && in_circle (finite t'') t' t p then begin let t'' = finite t'' in let n = ref (Terminal e) in let n' = ref (Terminal d) in c.inst := Branch (t'', p, n, n'); d.inst := Branch (t'', p, n, n'); flip c d e t'' p n n'; loop e end else if t' <> r then loop arcs.(c.next.mate).next else () (* break *) in loop c done; { points = points; arcs = arcs; last_used_arc = !j } let iter f t = let points = t.points in let n = Array.length t.arcs in for i = 0 to t.last_used_arc do match t.arcs.(i).vert, t.arcs.(n - 1 - i).vert with | Point u, Point v -> f points.(u) points.(v) | _ -> () done let iter_triangles f t = let n = Array.length t.arcs in let seen_arc = Array.create n false in let mate i = n - 1 - i in let index a = mate a.mate in for i = 0 to n-1 do if not seen_arc.(i) then begin let a1 = t.arcs.(i) in let a2 = a1.next in let a3 = a2.next in seen_arc.(i) <- true; seen_arc.(index a2) <- true; seen_arc.(index a3) <- true; match a1.vert, a2.vert, a3.vert with | Point i1, Point i2, Point i3 -> f t.points.(i1) t.points.(i2) t.points.(i3) | _ -> () end done let fold f t a = let points = t.points in let n = Array.length t.arcs in let rec loop i a = if i <= t.last_used_arc then match t.arcs.(i).vert, t.arcs.(n - 1 - i).vert with | Point u, Point v -> loop (succ i) (f points.(u) points.(v) a) | _ -> loop (succ i) a else a in loop 0 a end (** Points with floating point coordinates *) module FloatPoints = struct type point = float * float let ( + ) = ( +. ) let ( - ) = ( -. ) let ( * ) = ( *. ) let det = function | [| [| a00; a01 |]; [| a10; a11 |] |] -> a00 * a11 - a01 * a10 | [| [| a00; a01; a02 |]; [| a10; a11; a12 |]; [| a20; a21; a22 |] |] -> a00*a11*a22 - a00*a12*a21 - a10*a01*a22 + a10*a02*a21 + a20*a01*a12 - a20*a02*a11 | [| [| a00; a01; a02; a03 |]; [| a10; a11; a12; a13 |]; [| a20; a21; a22; a23 |]; [| a30; a31; a32; a33 |] |] -> a00*a11*a22*a33 - a00*a11*a23*a32 - a00*a21*a12*a33 + a00*a21*a13*a32 + a00*a31*a12*a23 - a00*a31*a13*a22 - a10*a01*a22*a33 + a10*a01*a23*a32 + a10*a21*a02*a33 - a10*a21*a03*a32 - a10*a31*a02*a23 + a10*a31*a03*a22 + a20*a01*a12*a33 - a20*a01*a13*a32 - a20*a11*a02*a33 + a20*a11*a03*a32 + a20*a31*a02*a13 - a20*a31*a03*a12 - a30*a01*a12*a23 + a30*a01*a13*a22 + a30*a11*a02*a23 - a30*a11*a03*a22 - a30*a21*a02*a13 + a30*a21*a03*a12 | _ -> assert false let ccw (xu,yu) (xv,yv) (xw,yw) = det [| [| xu; yu; 1.0 |]; [| xv; yv; 1.0 |]; [| xw; yw; 1.0 |] |] > 0.0 (*i DEBUG let ccw (xu,yu) (xv,yv) (xw,yw) = eprintf "ccw((%.0f,%.0f),(%.0f,%.0f),(%.0f,%.0f)) -> " xu yu xv yv xw yw; let r = ccw (xu,yu) (xv,yv) (xw,yw) in eprintf "%b\n" r; flush stderr; r i*) let in_circle (xt,yt) (xu,yu) (xv,yv) (xw,yw) = det [| [| xt; yt; (xt * xt + yt * yt); 1.0 |]; [| xu; yu; (xu * xu + yu * yu); 1.0 |]; [| xv; yv; (xv * xv + yv * yv); 1.0 |]; [| xw; yw; (xw * xw + yw * yw); 1.0 |]; |] > 0.0 (*i DEBUG let in_circle (xt,yt) (xu,yu) (xv,yv) (xw,yw) = eprintf "in_circle((%.0f,%.0f),(%.0f,%.0f),(%.0f,%.0f),(%.0f,%.0f)) -> " xt yt xu yu xv yv xw yw; let r = in_circle (xt,yt) (xu,yu) (xv,yv) (xw,yw) in eprintf "%b\n" r; flush stderr; r i*) end module Float = Make(FloatPoints) (** Points with integer coordinates. We approximate using module [FloatPoints] but this could be made exact following Knuth's code in Axioms and Hulls *) module IntPoints = struct type point = int * int let ccw (xu,yu) (xv,yv) (xw,yw) = FloatPoints.ccw (float xu, float yu) (float xv, float yv) (float xw, float yw) let in_circle (xt,yt) (xu,yu) (xv,yv) (xw,yw) = FloatPoints.in_circle (float xt, float yt) (float xu, float yu) (float xv, float yv) (float xw, float yw) end module Int = Make(IntPoints) ocamlgraph-1.8.3/src/dot_lexer.mll0000644000175000017500000000633612133565070016072 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id:$ *) { open Lexing open Dot_ast open Dot_parser let string_buf = Buffer.create 1024 let keyword = let h = Hashtbl.create 17 in List.iter (fun (s,k) -> Hashtbl.add h s k) [ "strict", STRICT; "graph", GRAPH; "digraph", DIGRAPH; "subgraph", SUBGRAPH; "node", NODE; "edge", EDGE; ]; fun s -> let s = String.lowercase s in Hashtbl.find h s } let alpha = ['a'-'z' 'A'-'Z' '_'] let digit = ['0'-'9'] let ident = alpha (alpha | digit)* let number = '-'? ('.'['0'-'9']+ | ['0'-'9']+('.'['0'-'9']*)? ) let space = [' ' '\t' '\r' '\n']+ rule token = parse | space { token lexbuf } | ('#' | "//") [^ '\n']* '\n' { token lexbuf } | "/*" { comment lexbuf; token lexbuf } | ":" { COLON } | "," { COMMA } | ";" { SEMICOLON } | "=" { EQUAL } | "{" { LBRA } | "}" { RBRA } | "[" { LSQ } | "]" { RSQ } | "--" | "->" { EDGEOP } | ident as s { try keyword s with Not_found -> ID (Ident s) } | number as s { ID (Number s) } | "\"" { Buffer.clear string_buf; let s = string lexbuf in ID (String s) } | "<" { Buffer.clear string_buf; html lexbuf; ID (Html (Buffer.contents string_buf)) } | eof { EOF } | _ as c { failwith ("Dot_lexer: invalid character " ^ String.make 1 c) } and string = parse | "\"" { Buffer.contents string_buf } | "\\" "\"" { Buffer.add_char string_buf '"'; string lexbuf } | _ as c { Buffer.add_char string_buf c; string lexbuf } | eof { failwith ("Dot_lexer: unterminated string literal") } and html = parse | ">" { () } | "<" { Buffer.add_char string_buf '<'; html lexbuf; Buffer.add_char string_buf '>'; html lexbuf } | _ as c { Buffer.add_char string_buf c; html lexbuf } | eof { failwith ("Dot_lexer: unterminated html literal") } and comment = parse | "*/" { () } | _ { comment lexbuf } | eof { failwith "Dot_lexer: unterminated comment" } ocamlgraph-1.8.3/src/md.mli0000644000175000017500000000443312133565071014477 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Minimum Degree algorithm Based on the article: The Minimum Degree Heuristic and the Minimal Triangulation Process by A. Berry, Pinar Heggernes & Geneviève Simonet. @author Matthieu Sozeau @author Pierre-Loic Garoche *) module P(G : Sig.P) : sig type edgeset = (G.V.t * G.V.t) list val md : G.t -> G.t * edgeset * G.V.t list (** [md g] return a tuple [(g', e, o)] where [g'] is a triangulated graph, [e] is the triangulation of [g] and [o] is a perfect elimination order of [g'] *) val triangulate : G.t -> G.t (** [triangulate g] return the graph [g'] produced by applying miminum degree to [g]. *) end module I(G : Sig.I) : sig type edgeset = (G.V.t * G.V.t) list val md : G.t -> G.t * edgeset * G.V.t list (** [md g] return a tuple [(g', e, o)] where [g'] is a triangulated graph, [e] is the triangulation of [g] and [o] is a perfect elimination order of [g'] *) val triangulate : G.t -> G.t (** [triangulate g] return the graph [g'] produced by applying miminum degree to [g]. *) end ocamlgraph-1.8.3/src/sig_pack.mli0000644000175000017500000003256012133565071015661 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: sig_pack.mli,v 1.23 2005-07-18 07:10:35 filliatr Exp $ *) (** Immediate access to the library: contain a signature gathering an imperative graph signature and all algorithms. Vertices and edges are labeled with integers. *) (** Signature gathering an imperative graph signature and all algorithms. Vertices and edges are labeled with integers. *) module type S = sig (** {2 Graph structure} *) (** abstract type of graphs *) type t (** Vertices *) module V : sig (** Vertices are [COMPARABLE] *) type t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool (** vertices are labeled with integers *) type label = int val create : label -> t val label : t -> label end type vertex = V.t (** Edges *) module E : sig (** Edges are [ORDERED]. *) type t val compare : t -> t -> int (** Edges are directed. *) val src : t -> V.t val dst : t -> V.t (** Edges are labeled with integers. *) type label = int val create : V.t -> label -> V.t -> t (** [create v1 l v2] creates an edge from [v1] to [v2] with label [l] *) val label : t -> label type vertex = V.t end type edge = E.t (** is this an implementation of directed graphs? *) val is_directed : bool (** {2 Graph constructors and destructors} *) val create : ?size:int -> unit -> t (** Return an empty graph. Optionally, a size can be given, which should be on the order of the expected number of vertices that will be in the graph (for hash tables-based implementations). The graph grows as needed, so [size] is just an initial guess. *) val clear: t -> unit (** Remove all vertices and edges from the given graph. @since ocamlgraph 1.4 *) val copy : t -> t (** [copy g] returns a copy of [g]. Vertices and edges (and eventually marks, see module [Mark]) are duplicated. *) val add_vertex : t -> V.t -> unit (** [add_vertex g v] adds the vertex [v] from the graph [g]. Do nothing if [v] is already in [g]. *) val remove_vertex : t -> V.t -> unit (** [remove g v] removes the vertex [v] from the graph [g] (and all the edges going from [v] in [g]). Do nothing if [v] is not in [g]. *) val add_edge : t -> V.t -> V.t -> unit (** [add_edge g v1 v2] adds an edge from the vertex [v1] to the vertex [v2] in the graph [g]. Add also [v1] (resp. [v2]) in [g] if [v1] (resp. [v2]) is not in [g]. Do nothing if this edge is already in [g]. *) val add_edge_e : t -> E.t -> unit (** [add_edge_e g e] adds the edge [e] in the graph [g]. Add also [E.src e] (resp. [E.dst e]) in [g] if [E.src e] (resp. [E.dst e]) is not in [g]. Do nothing if [e] is already in [g]. *) val remove_edge : t -> V.t -> V.t -> unit (** [remove_edge g v1 v2] removes the edge going from [v1] to [v2] from the graph [g]. Do nothing if this edge is not in [g]. @raise Invalid_argument if [v1] or [v2] are not in [g]. *) val remove_edge_e : t -> E.t -> unit (** [remove_edge_e g e] removes the edge [e] from the graph [g]. Do nothing if [e] is not in [g]. @raise Invalid_argument if [E.src e] or [E.dst e] are not in [g]. *) (** Vertices contains integers marks, which can be set or used by some algorithms (see for instance module [Marking] below) *) module Mark : sig type graph = t type vertex = V.t val clear : t -> unit (** [clear g] sets all marks to 0 from all the vertives of [g]. *) val get : V.t -> int val set : V.t -> int -> unit end (** {2 Size functions} *) val is_empty : t -> bool val nb_vertex : t -> int val nb_edges : t -> int (** Degree of a vertex *) val out_degree : t -> V.t -> int (** [out_degree g v] returns the out-degree of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) val in_degree : t -> V.t -> int (** [in_degree g v] returns the in-degree of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) (** {2 Membership functions} *) val mem_vertex : t -> V.t -> bool val mem_edge : t -> V.t -> V.t -> bool val mem_edge_e : t -> E.t -> bool val find_edge : t -> V.t -> V.t -> E.t val find_all_edges : t -> V.t -> V.t -> E.t list (** {2 Successors and predecessors of a vertex} *) val succ : t -> V.t -> V.t list (** [succ g v] returns the successors of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) val pred : t -> V.t -> V.t list (** [pred g v] returns the predecessors of [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) (** Labeled edges going from/to a vertex *) val succ_e : t -> V.t -> E.t list (** [succ_e g v] returns the edges going from [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) val pred_e : t -> V.t -> E.t list (** [pred_e g v] returns the edges going to [v] in [g]. @raise Invalid_argument if [v] is not in [g]. *) (** {2 Graph iterators} *) (** iter/fold on all vertices/edges of a graph *) val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges : (V.t -> V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val fold_edges : (V.t -> V.t -> 'a -> 'a) -> t -> 'a -> 'a (** map iterator on vertex *) val map_vertex : (V.t -> V.t) -> t -> t (** iter/fold on all labeled edges of a graph *) val iter_edges_e : (E.t -> unit) -> t -> unit val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a (** {2 Vertex iterators} Each iterator [iterator f v g] iters [f] to the successors/predecessors of [v] in the graph [g] and raises [Invalid_argument] if [v] is not in [g]. *) (** iter/fold on all successors/predecessors of a vertex. *) val iter_succ : (V.t -> unit) -> t -> V.t -> unit val iter_pred : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val fold_pred : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a (** iter/fold on all edges going from/to a vertex. *) val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit val fold_succ_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val iter_pred_e : (E.t -> unit) -> t -> V.t -> unit val fold_pred_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a (** {2 Basic operations} *) val find_vertex : t -> int -> V.t (** [vertex g i] returns a vertex of label [i] in [g]. The behaviour is unspecified if [g] has several vertices with label [i]. Note: this function is inefficient (linear in the number of vertices); you should better keep the vertices as long as you create them. *) val transitive_closure : ?reflexive:bool -> t -> t (** [transitive_closure ?reflexive g] returns the transitive closure of [g] (as a new graph). Loops (i.e. edges from a vertex to itself) are added only if [reflexive] is [true] (default is [false]). *) val add_transitive_closure : ?reflexive:bool -> t -> t (** [add_transitive_closure ?reflexive g] replaces [g] by its transitive closure. Meaningless for persistent implementations (then acts as [transitive_closure]). *) val mirror : t -> t (** [mirror g] returns a new graph which is the mirror image of [g]: each edge from [u] to [v] has been replaced by an edge from [v] to [u]. For undirected graphs, it simply returns a copy of [g]. *) val complement : t -> t (** [complement g] builds a new graph which is the complement of [g]: each edge present in [g] is not present in the resulting graph and vice-versa. Edges of the returned graph are unlabeled. *) val intersect : t -> t -> t (** [intersect g1 g2] returns a new graph which is the intersection of [g1] and [g2]: each vertex and edge present in [g1] *and* [g2] is present in the resulting graph. *) val union : t -> t -> t (** [union g1 g2] returns a new graph which is the union of [g1] and [g2]: each vertex and edge present in [g1] *or* [g2] is present in the resulting graph. *) (** {2 Traversal} *) (** Depth-first search *) module Dfs : sig val iter : ?pre:(V.t -> unit) -> ?post:(V.t -> unit) -> t -> unit (** [iter pre post g] visits all nodes of [g] in depth-first search, applying [pre] to each visited node before its successors, and [post] after them. Each node is visited exactly once. *) val prefix : (V.t -> unit) -> t -> unit (** applies only a prefix function *) val postfix : (V.t -> unit) -> t -> unit (** applies only a postfix function *) (** Same thing, but for a single connected component *) val iter_component : ?pre:(V.t -> unit) -> ?post:(V.t -> unit) -> t -> V.t -> unit val prefix_component : (V.t -> unit) -> t -> V.t -> unit val postfix_component : (V.t -> unit) -> t -> V.t -> unit val has_cycle : t -> bool end (** Breadth-first search *) module Bfs : sig val iter : (V.t -> unit) -> t -> unit val iter_component : (V.t -> unit) -> t -> V.t -> unit end (** Graph traversal with marking *) module Marking : sig val dfs : t -> unit val has_cycle : t -> bool end (** {2 Graph generators} *) (** Classic graphs *) module Classic : sig val divisors : int -> t (** [divisors n] builds the graph of divisors. Vertices are integers from [2] to [n]. [i] is connected to [j] if and only if [i] divides [j]. @raise Invalid_argument is [n < 2]. *) val de_bruijn : int -> t (** [de_bruijn n] builds the de Bruijn graph of order [n]. Vertices are bit sequences of length [n] (encoded as their interpretation as binary integers). The sequence [xw] is connected to the sequence [wy] for any bits [x] and [y] and any bit sequence [w] of length [n-1]. @raise Invalid_argument is [n < 1] or [n > Sys.word_size-1]. *) val vertex_only : int -> t (** [vertex_only n] builds a graph with [n] vertices and no edge. *) val full : ?self:bool -> int -> t (** [full n] builds a graph with [n] vertices and all possible edges. The optional argument [self] indicates if loop edges should be added (default value is [true]). *) end (** Random graphs *) module Rand : sig val graph : ?loops:bool -> v:int -> e:int -> unit -> t (** [random v e] generates a random with [v] vertices and [e] edges. *) val labeled : (V.t -> V.t -> E.label) -> ?loops:bool -> v:int -> e:int -> unit -> t (** [random_labeled f] is similar to [random] except that edges are labeled using function [f] *) end (** Strongly connected components *) module Components : sig val scc : t -> int*(V.t -> int) (** strongly connected components *) val scc_array : t -> V.t list array val scc_list : t -> V.t list list end (** {2 Classical algorithms} *) val shortest_path : t -> V.t -> V.t -> E.t list * int (** Dijkstra's shortest path algorithm. Weights are the labels. *) val ford_fulkerson : t -> V.t -> V.t -> (E.t -> int) * int (** Ford Fulkerson maximum flow algorithm *) val goldberg : t -> V.t -> V.t -> (E.t -> int) * int (** Goldberg maximum flow algorithm *) val bellman_ford : t -> V.t -> E.t list (** [bellman_ford g v] finds a negative cycle from [v], and returns it, or raises [Not_found] if there is no such cycle *) (** Path checking *) module PathCheck : sig type path_checker val create : t -> path_checker val check_path : path_checker -> V.t -> V.t -> bool end (** Topological order *) module Topological : sig val fold : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter : (V.t -> unit) -> t -> unit val fold_stable : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_stable : (V.t -> unit) -> t -> unit end val spanningtree : t -> E.t list (** Kruskal algorithm *) (** {2 Input / Output} *) val dot_output : t -> string -> unit (** DOT output in a file *) val display_with_gv : t -> unit (** Displays the given graph using the external tools "dot" and "gv" and returns when gv's window is closed *) val parse_gml_file : string -> t val parse_dot_file : string -> t val print_gml : Format.formatter -> t -> unit val print_gml_file : t -> string -> unit (* val print_graphml : Format.formatter -> t -> unit *) end ocamlgraph-1.8.3/src/oper.ml0000644000175000017500000001117112133565071014670 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Basic operations over graphs *) module type S = sig type g val transitive_closure : ?reflexive:bool -> g -> g val add_transitive_closure : ?reflexive:bool -> g -> g val mirror : g -> g val complement : g -> g val intersect : g -> g -> g val union : g -> g -> g end module Make(B : Builder.S) = struct open B (* Roy-Warshall's algorithm *) type g = G.t let add_transitive_closure ?(reflexive=false) g0 = let phi v g = let g = if reflexive then B.add_edge g v v else g in G.fold_succ (fun sv g -> G.fold_pred (fun pv g -> B.add_edge g pv sv) g v g) g v g in G.fold_vertex phi g0 g0 let transitive_closure ?(reflexive=false) g0 = add_transitive_closure ~reflexive (B.copy g0) module H = Hashtbl.Make(G.V) let mirror g = if G.is_directed then begin let g' = G.fold_vertex (fun v g' -> B.add_vertex g' v) g (B.empty ()) in G.fold_edges_e (fun e g' -> let v1 = G.E.src e in let v2 = G.E.dst e in B.add_edge_e g' (G.E.create v2 (G.E.label e) v1)) g g' end else g let complement g = G.fold_vertex (fun v g' -> G.fold_vertex (fun w g' -> if G.mem_edge g v w then g' else B.add_edge g' v w) g g') g (B.empty ()) let intersect g1 g2 = G.fold_vertex (fun v g -> try let succ = G.succ_e g2 v in G.fold_succ_e (fun e g -> if List.exists (fun e' -> G.E.compare e e' = 0) succ then B.add_edge_e g e else g) g1 v (B.add_vertex g v) with Invalid_argument _ -> (* [v] not in [g2] *) g) g1 (B.empty ()) let union g1 g2 = let add g1 g2 = (* add the graph [g1] in [g2] *) G.fold_vertex (fun v g -> G.fold_succ_e (fun e g -> B.add_edge_e g e) g1 v (B.add_vertex g v)) g1 g2 in add g1 (B.copy g2) end module P(G : Sig.P) = Make(Builder.P(G)) module I(G : Sig.I) = Make(Builder.I(G)) module Choose(G : sig type t type vertex type edge val iter_vertex : (vertex -> unit) -> t -> unit val iter_edges_e : (edge -> unit) -> t -> unit end) = struct exception Found_Vertex of G.vertex let choose_vertex g = try G.iter_vertex (fun v -> raise (Found_Vertex v)) g; invalid_arg "choose_vertex" with Found_Vertex v -> v exception Found_Edge of G.edge let choose_edge g = try G.iter_edges_e (fun v -> raise (Found_Edge v)) g; invalid_arg "choose_vertex" with Found_Edge v -> v end module Neighbourhood(G : sig type t module V : Sig.COMPARABLE val fold_succ: (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val succ: t -> V.t -> V.t list end) = struct module Vertex_Set = Set.Make(G.V) let set_from_vertex g v = G.fold_succ (fun v' s -> if G.V.equal v v' then s else Vertex_Set.add v' s) g v Vertex_Set.empty let list_from_vertex g v = let rec aux = function | [] -> [] | v' :: l -> if G.V.equal v v' then begin assert (not (List.exists (G.V.equal v) l)); l end else v' :: aux l in aux (G.succ g v) let set_from_vertices g l = let fold_left f = List.fold_left f Vertex_Set.empty l in let env_init = fold_left (fun s v -> Vertex_Set.add v s) in let add x s = if Vertex_Set.mem x env_init then s else Vertex_Set.add x s in fold_left (fun s v -> G.fold_succ add g v s) let list_from_vertices g l = Vertex_Set.elements (set_from_vertices g l) end ocamlgraph-1.8.3/src/delaunay.mli0000644000175000017500000000656512133565070015710 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: delaunay.mli,v 1.8 2004-02-20 14:37:40 signoles Exp $ *) (** Delaunay triangulation. *) (** Delaunay triangulation is available for any CCC system in the sense of Knuth's ``Axioms and Hulls'' *) module type CCC = sig type point val ccw : point -> point -> point -> bool (** The counterclockwise relation [ccw p q r] states that the circle through points [(p,q,r)] is traversed counterclockwise when we encounter the points in cyclic order [p,q,r,p,...] **) val in_circle : point -> point -> point -> point -> bool (** The relation [in_circle p q r s] states that [s] lies inside the circle [(p,q,r)] if [ccw p q r] is true, or outside that circle if [ccw p q r] is false. *) end (** The result of triangulation is an abstract value of type [triangulation]. Then one can iterate over all edges of the triangulation. *) module type Triangulation = sig module S : CCC type triangulation val triangulate : S.point array -> triangulation (** [triangulate a] computes the Delaunay triangulation of a set of points, given as an array [a]. If [N] is the number of points (that is [Array.length a]), then the running time is $O(N \log N)$ on the average and $O(N^2)$ on the worst-case. The space used is always $O(N)$. *) val iter : (S.point -> S.point -> unit) -> triangulation -> unit (** [iter f t] iterates over all edges of the triangulation [t]. [f u v] is called once for each undirected edge [(u,v)]. *) val fold : (S.point -> S.point -> 'a -> 'a) -> triangulation -> 'a -> 'a val iter_triangles : (S.point -> S.point -> S.point -> unit) -> triangulation -> unit end (** Generic Delaunay triangulation *) module Make(S : CCC) : Triangulation with module S = S (** Points with integer coordinates *) module IntPoints : CCC with type point = int * int (** Delaunay triangulation with integer coordinates *) module Int : Triangulation with module S = IntPoints (** Points with floating point coordinates *) module FloatPoints : CCC with type point = float * float (** Delaunay triangulation with floating point coordinates *) module Float : Triangulation with module S = FloatPoints ocamlgraph-1.8.3/src/kruskal.ml0000644000175000017500000000471212133565071015402 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: kruskal.ml,v 1.5 2005-06-30 10:48:55 filliatr Exp $ *) open Util module type UNIONFIND = sig type elt type t val init : elt list -> t val find : elt -> t -> elt val union : elt -> elt -> t -> unit end module type G = sig type t module V : Sig.COMPARABLE module E : sig type t type label val label : t -> label val dst : t -> V.t val src : t -> V.t end val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_edges_e : (E.t -> unit) -> t -> unit end module Generic (G: G) (W : Sig.ORDERED_TYPE with type t = G.E.label) (UF: UNIONFIND with type elt = G.V.t) = struct let spanningtree g = let vertices = G.fold_vertex (fun v a -> v :: a) g [] in let uf = UF.init vertices in let edges = let l = ref [] in G.iter_edges_e (fun e -> l := e :: !l) g; List.sort (fun e e'-> W.compare (G.E.label e) (G.E.label e')) !l in let s = ref [] in let cover e = let u, v = G.E.src e, G.E.dst e in if G.V.compare (UF.find u uf) (UF.find v uf) <> 0 then begin UF.union u v uf; s := e :: !s end in List.iter cover edges; !s end module Make(G: G)(W : Sig.ORDERED_TYPE with type t=G.E.label) = Generic(G)(W)(Unionfind.Make(G.V)) ocamlgraph-1.8.3/src/rand.ml0000644000175000017500000001515712133565071014657 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: rand.ml,v 1.18 2005-03-31 13:32:51 filliatr Exp $ *) module type S = sig type graph type vertex type edge_label val graph : ?loops:bool -> v:int -> e:int -> unit -> graph val labeled : (vertex -> vertex -> edge_label) -> ?loops:bool -> v:int -> e:int -> unit -> graph (* DEBUG *) val random_few_edges : loops:bool -> v:int -> e:int -> graph val random_many_edges : loops:bool -> v:int -> e:int -> graph end module Make(B : Builder.INT) = struct open B type graph = G.t type vertex = G.V.t type edge_label = G.E.label open Int64 let max_edges ~loops ~v ~e = if v <= 0 || e < 0 then invalid_arg "random"; let v64 = of_int v in let max_e = mul v64 (pred v64) in let max_e = if G.is_directed then max_e else div max_e (of_int 2) in let max_e = if loops then add max_e v64 else max_e in if of_int e > max_e then invalid_arg "random: too many edges"; max_e let fold_for i0 i1 f = let rec loop i v = if i > i1 then v else loop (i + 1) (f v i) in loop i0 (* naive implementation: we randomly chose edges up to [e] different edges *) let random_few_edges add_edge ~loops ~v ~e = let _ = max_edges ~loops ~v ~e in let a = Array.init v G.V.create in let g = Array.fold_left add_vertex (empty ()) a in let rec random_edge g = let i = Random.int v in let j = Random.int v in if (i = j && not loops) || G.mem_edge g a.(i) a.(j) then random_edge g else add_edge g a.(i) a.(j) in fold_for 1 e (fun g _ -> random_edge g) g (* other implementation in O(v * v); faster when [e] is large *) let random_many_edges add_edge ~loops ~v ~e = let v64 = of_int v in let max_e = max_edges ~loops ~v ~e in let a = Array.init v G.V.create in let g = Array.fold_left add_vertex (empty ()) a in let rec add_edges i j max nb g = assert (max >= 0L && max_e = add max (add (mul (of_int i) v64) (of_int (j - (match G.is_directed, loops with | true, true -> 0 | true, false -> if j > i then i + 1 else i | false, true -> i * (i - 1) / 2 + if j > i then i else j | false, false -> i*(i+1)/2 + if j > i then i+1 else j))))); if nb = 0 then g else let add_edges = let i, j = if j = v - 1 then i + 1, 0 else i, j + 1 in add_edges i j in if (i = j && not loops) || (not G.is_directed && i > j) then add_edges max nb g else let add_edges = add_edges (pred max) in if Random.int64 max < of_int nb then add_edges (nb - 1) (add_edge g a.(i) a.(j)) else add_edges nb g in add_edges 0 0 max_e e g let random ~loops ~v ~e = let r = float e /. (float v *. float v) in (if r < 0.4 then random_few_edges else random_many_edges) ~loops ~v ~e let graph ?(loops=false) ~v ~e () = random B.add_edge ~loops ~v ~e let labeled f ?(loops=false) ~v ~e () = random (fun g v1 v2 -> B.add_edge_e g (G.E.create v1 (f v1 v2) v2)) ~loops ~v ~e (* DEBUG *) let random_few_edges = random_few_edges B.add_edge let random_many_edges = random_many_edges B.add_edge end module P (G : Sig.P with type V.label = int) = Make(Builder.P(G)) module I (G : Sig.I with type V.label = int) = Make(Builder.I(G)) (** Random planar graphs *) module Planar = struct module type S = sig type graph val graph : ?loops:bool -> xrange:int*int -> yrange:int*int -> prob:float -> int -> graph end module Make (B : Builder.S with type G.V.label = int * int and type G.E.label = int) = struct type graph = B.G.t open B.G module Point = struct type point = V.t let ccw v1 v2 v3 = Delaunay.IntPoints.ccw (V.label v1) (V.label v2) (V.label v3) let in_circle v1 v2 v3 v4 = Delaunay.IntPoints.in_circle (V.label v1) (V.label v2) (V.label v3) (V.label v4) let distance v1 v2 = let x1,y1 = V.label v1 in let x2,y2 = V.label v2 in let sqr x = let x = float x in x *. x in truncate (sqrt (sqr (x1 - x2) +. sqr (y1 - y2))) end module Triangulation = Delaunay.Make(Point) let graph ?(loops=false) ~xrange:(xmin,xmax) ~yrange:(ymin,ymax) ~prob v = if not (0.0 <= prob && prob <= 1.0) then invalid_arg "Planar.graph"; if v < 2 then invalid_arg "Planar.graph"; (* [v] random points and their Delaunay triangulation *) let random_point () = xmin + Random.int (1 + xmax - xmin), ymin + Random.int (1 + ymax - ymin) in let vertices = Array.init v (fun _ -> V.create (random_point ())) in let t = Triangulation.triangulate vertices in (* a graph with [v] vertices and random loops if any *) let g = Array.fold_left B.add_vertex (B.empty ()) vertices in let g = if loops then Array.fold_left (fun g v -> if Random.float 1.0 < prob then g else let e = E.create v 0 v in B.add_edge_e g e) g vertices else g in (* we keep some edges from the triangulation according to [prob] *) let add_edge v1 v2 g = if Random.float 1.0 < prob then g else let e = E.create v1 (Point.distance v1 v2) v2 in B.add_edge_e g e in Triangulation.fold (fun v1 v2 g -> let g = add_edge v1 v2 g in if is_directed then add_edge v2 v1 g else g) t g end module P (G : Sig.P with type V.label = int * int and type E.label = int) = Make(Builder.P(G)) module I (G : Sig.I with type V.label = int * int and type E.label = int) = Make(Builder.I(G)) end ocamlgraph-1.8.3/src/graphml.ml0000644000175000017500000000707312133565071015363 0ustar mehdimehdi(******************************************************************************) (* *) (* Copyright (C) 2012 Pietro Abate *) (* *) (* This library is free software: 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, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (* *) (******************************************************************************) module type G = sig type t type vertex module E : sig type t val src: t -> vertex val dst : t -> vertex end val is_directed : bool val iter_vertex : (vertex -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit end module Print (G: G) (L : sig val vertex_properties : (string * string * string option) list val edge_properties : (string * string * string option) list val map_vertex : G.vertex -> (string * string) list val map_edge : G.E.t -> (string * string) list val vertex_uid : G.vertex -> int val edge_uid : G.E.t -> int end) = struct type t = G.t let header = " " ;; let data_pp fmt (key,value) = Format.fprintf fmt "%s" key value let pp_type fmt t prop typ default = Format.fprintf fmt "" t prop prop typ; match default with |None -> Format.fprintf fmt "\n" |Some s -> begin Format.fprintf fmt "\n %s\n" s; Format.fprintf fmt "\n" end let print fmt graph = Format.fprintf fmt "%s\n" header; (* node attributed declaration *) List.iter (fun (prop,typ,default) -> pp_type fmt "node" prop typ default) L.vertex_properties; (* edge attributed declaration *) List.iter (fun (prop,typ,default) -> pp_type fmt "edge" prop typ default) L.edge_properties ; let directed = if G.is_directed then "edgedefault=\"directed\"" else "" in Format.fprintf fmt "\n" directed; (* vertex printer *) G.iter_vertex (fun vertex -> let id = L.vertex_uid vertex in let l = L.map_vertex vertex in Format.fprintf fmt " \n" id; List.iter (Format.fprintf fmt " %a\n" data_pp) l; Format.fprintf fmt " \n") graph ; (* edge printer *) G.iter_edges_e (fun edge -> let n1 = L.vertex_uid (G.E.src edge) in let n2 = L.vertex_uid (G.E.dst edge) in let eid = L.edge_uid edge in let l = L.map_edge edge in Format.fprintf fmt " \n" eid n1 n2; List.iter (Format.fprintf fmt " %a\n" data_pp) l; Format.fprintf fmt " \n") graph ; Format.fprintf fmt "\n"; Format.fprintf fmt "\n" end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/components.mli0000644000175000017500000000527112133565070016264 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: components.mli,v 1.12 2004-10-22 14:42:06 signoles Exp $ *) (** Strongly connected components. *) (** Minimal graph signature required by {!Make}. Sub-signature of {!Sig.G}. *) module type G = sig type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit end (** Functor providing functions to compute strongly connected components of a graph. *) module Make (G: G) : sig val scc : G.t -> int * (G.V.t -> int) (** [scc g] computes the strongly connected components of [g]. The result is a pair [(n,f)] where [n] is the number of components. Components are numbered from [0] to [n-1], and [f] is a function mapping each vertex to its component number. In particular, [f u = f v] if and only if [u] and [v] are in the same component. Another property of the numbering is that components are numbered in a topological order: if there is an arc from [u] to [v], then [f u >= f u] Not tail-recursive. Complexity: O(V+E) The function returned has complexity O(1) *) val scc_array : G.t -> G.V.t list array (** [scc_array] computes the strongly connected components of [g]. Components are stored in the resulting array, indexed with a numbering with the same properties as for [scc] above. *) val scc_list : G.t -> G.V.t list list (** [scc_list] computes the strongly connected components of [g]. The result is a partition of the set of the vertices of [g]. *) end ocamlgraph-1.8.3/src/dominator.ml0000644000175000017500000002732412133565070015725 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright © 2009 Carnegie-Mellon University, David Brumley, and Ivan Jager. From the BAP library; see http://bap.ece.cmu.edu *) (* stuff to read: http://www.hipersoft.rice.edu/grads/publications/dom14.pdf Modern Compiler Implementation in ML, by Appel Introduction to Algorithms, Cormen et al *) exception Unreachable module type G = sig type t module V : Sig.COMPARABLE val pred : t -> V.t -> V.t list val succ : t -> V.t -> V.t list val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_vertex : (V.t -> unit) -> t -> unit val nb_vertex : t -> int val create: ?size:int -> unit -> t val add_edge : t -> V.t -> V.t -> unit end module Make(G : G) = struct module H = Hashtbl.Make(G.V) module S = Set.Make(G.V) (** function from [n] to [n]'s immediate dominator *) type idom = G.V.t -> G.V.t (** [idoms x y] is true when [x] is [y]'s immediate dominator *) type idoms = G.V.t -> G.V.t -> bool (** function from [x] to a list of nodes immediately dominated by [x] *) type dom_tree = G.V.t -> G.V.t list (** function from node to a list of nodes that dominate it. *) type dominators = G.V.t -> G.V.t list (** [dom x y] returns true iff [x] dominates [y] *) type dom = G.V.t -> G.V.t -> bool (** [sdom x y] returns true iff [x] strictly dominates [y]. *) type sdom = G.V.t -> G.V.t -> bool (** function from [x] to a list of nodes not dominated by [x], but with predecessors which are dominated by [x] *) type dom_frontier = G.V.t -> G.V.t list type dom_graph = unit -> G.t type dom_functions = { idom : idom; idoms: idoms; dom_tree: dom_tree; dominators: dominators; dom: dom; sdom: sdom; dom_frontier: dom_frontier; dom_graph : dom_graph; } let set_of_list x = List.fold_left (fun set v -> S.add v set) S.empty x (** Fold over the nodes. Function [f] is applied in reverse-topologicalish order. *) let pseudo_topological_fold f x nodes succ = let found = H.create 57 in let rec visit x n = if H.mem found n then (* black or gray *) x else (* white *) let () = H.add found n () in let x = List.fold_left visit x (succ n) in f n x in List.fold_left visit x nodes (** Given the entry nodes into a graph, and a successor function, returns the nodes in pseudo topological order. *) let pseudo_topological_sort nodes succ = pseudo_topological_fold (fun x y -> x::y) [] nodes succ (** Computes the dominator tree, using the Lengauer-Tarjan algorithm. [compute_idom cfg s0] returns a function [idom : V.t -> V.t] s.t. [idom x] returns the immediate dominator of [x] *) let compute_idom cfg s0 = (* based on the Tiger book, section 19.2. This uses path compression, but doesn't yet do balanced path compression, so the runtime is O(N log(N)) rather than O(N inverseackerman(N)) *) let size = G.nb_vertex cfg in let bucket = H.create size (* node n -> *) and dfnum_h = H.create size (* node -> DFS number *) and parent = H.create size (* node -> parent in DFS tree*) and semi_h = H.create size (* node -> semidominator *) and ancestor = H.create size (* node -> *) and best = H.create size (* node -> *) and samedom = H.create size (* node -> node with same idom *) and idom = H.create size (* node n -> idom n *) and vertex = Array.make size s0 (* DFS number -> node *) and nn = ref 0 in let dfnum x = try H.find dfnum_h x with Not_found -> raise Unreachable and semi = H.find semi_h in let rec dfs p n = if not(H.mem dfnum_h n) then ( let enn = !nn in H.add dfnum_h n enn; vertex.(enn) <- n; (match p with | Some p -> H.add parent n p | None -> () ); nn := (enn + 1); List.iter (dfs (Some n)) (G.succ cfg n) ) in let rec ancestor_with_lowest_semi v = try let a = H.find ancestor v in let b = ancestor_with_lowest_semi a in let () = H.replace ancestor v (H.find ancestor a) in let best_v = H.find best v in if dfnum(semi b) < dfnum(semi best_v) then (H.replace best v b; b) else best_v with Not_found -> H.find best v in let link p n = H.replace ancestor n p; H.replace best n n; in let semidominator n = let s = H.find parent n in List.fold_left (fun s v -> try (* FIXME: do we want to allow unreachable nodes? *) let s' = if dfnum v <= dfnum n then v else semi(ancestor_with_lowest_semi v) in if dfnum s' < dfnum s then s' else s with Unreachable -> (* maybe switch to Not_found later *) s (* v is unreachable from s0 *) ) s (G.pred cfg n) in let () = dfs None s0 in let lastn = !nn - 1 in while decr nn; !nn > 0 do (* skip over the root node *) let i = !nn in let n = vertex.(i) in let p = H.find parent n in let s = semidominator n in H.add semi_h n s; H.add bucket s n; link p n; (* now that the path from p to v is in the forest, calculate the dominator of v based on the first clause of the Dominator Theorem, otherwise defer until y's dominator is known *) List.iter (fun v -> let y = ancestor_with_lowest_semi v in if semi y = semi v then H.add idom v p else H.add samedom v y; H.remove bucket p (*could use H.remove_all if we used extlib*) ) (H.find_all bucket p) done; (* now all the defered calculations can be done *) for i = 1 to lastn do let n = vertex.(i) in try H.add idom n (H.find idom (H.find samedom n)) with Not_found -> () done; H.find idom (** Given a function from a node to it's dominators, returns a function [dom : V.t -> V.t -> bool] s.t. [dom x y] returns true when [x] dominates [y] *) let dominators_to_dom dominators x y = S.mem x (dominators y) (** Given a function from a node to it's dominators, returns a function [sdom : V.t -> V.t -> bool] s.t. [sdom x y] returns true when [x] strictly dominates [y] *) let dominators_to_sdom dominators x y = not(G.V.equal x y) && dominators_to_dom dominators x y let dom_to_sdom dom x y = not(G.V.equal x y) && dom x y (** Given a a function from a node to it's dominators, returns a function from a node to it's strict dominators. *) let dominators_to_sdominators dominators x = S.remove x (dominators x) (** Given a function from a node to it's dominators, returns a function [idoms : G.V.t -> G.V.t -> bool] s.t. [idoms x y] returns true when [x] is the immediate dominator of [y]. *) let dominators_to_idoms dominators = let sdom = dominators_to_sdom dominators in (fun x y -> sdom x y && let sdoms = dominators_to_sdominators dominators y in S.for_all (fun w -> G.V.equal x w || not(sdom x w)) sdoms ) (** Computes a dominator tree (function from x to a list of nodes immediately dominated by x) for the given CFG and dominator function. Note: The dominator tree is also called [IDom] by Muchnick. Note: If you are computing a post-dominator tree, then the optional argument pred should be G.succ. *) let dominators_to_dom_tree cfg ?(pred=G.pred) dominators = let idoms = dominators_to_idoms dominators in let tree = H.create 9999 in let () = G.iter_vertex (fun y -> match pred cfg y with [x] -> ( (* a node that is not reachable from start has no idom *) if S.is_empty (dominators x) then () else H.add tree x y ) | _ -> ( S.iter (fun x -> if idoms x y then H.add tree x y) (dominators y) ) ) cfg in (* FIXME: maybe faster to convert eagerly *) fun x -> set_of_list(H.find_all tree x) (** Computes a dominator tree (function from x to a list of nodes immediately dominated by x) for the given CFG and idom function. *) let idom_to_dom_tree cfg idom = let tree = H.create (G.nb_vertex cfg) in let () = G.iter_vertex (fun v -> try H.add tree (idom v) v with Not_found -> () (* s0 doesn't have an idom *) ) cfg in H.find_all tree let idom_to_idoms (idom:idom) x y = try G.V.equal x (idom y) with Not_found -> false (* s0 doesn't have an idom *) (** Computes the dominance frontier. As specified in section 19.1 of Modern Compiler Implementation in ML by Andrew Appel. *) let compute_dom_frontier cfg (dom_tree:dom_tree) (idom:idom) = let children = dom_tree in let idoms = idom_to_idoms idom in let df_cache = H.create 57 in let df_local n = (* The successors of n that are not strictly dominated by n *) List.filter (fun y -> not((idoms n y))) (G.succ cfg n) in let rec df n = try H.find df_cache n with Not_found -> let s = df_local n in let res = add_df_ups s n in let () = H.add df_cache n res in res and add_df_ups s n = List.fold_left (fun s c -> List.fold_left (* the appel errata uses sdom, but Muchnick uses idoms, which should be a bit faster and is the same *) (fun s w -> if idoms n w then s else w::s) s (df c) ) s (children n) in df let idom_to_dominators idom x = let rec d y list = try let i = idom y in d i (i::list) with Not_found -> list in d x [] let rec idom_to_dom idom x y = try let d = idom y in G.V.equal x d || idom_to_dom idom x d with Not_found -> false let compute_dom_graph cfg dom_tree = let g = G.create ~size:(G.nb_vertex cfg) () in G.iter_vertex (fun p -> try List.iter (G.add_edge g p) (dom_tree p) with Not_found -> () ) cfg; g (** Computes all dominance functions. This function computes some things eagerly and some lazily, so don't worry about it doing extra work to compute functions you don't need, but also don't call it if you aren't going to use anything it returns. @return a record containing all dominance functions for the given graph and entry node. *) let compute_all cfg s0 = let idom = compute_idom cfg s0 in let idoms = idom_to_idoms idom in let dom_tree = lazy(idom_to_dom_tree cfg idom) in let dominators = idom_to_dominators idom in let dom = idom_to_dom idom in let sdom = dom_to_sdom dom in let dom_frontier = lazy(compute_dom_frontier cfg (Lazy.force dom_tree) idom) in { idom=idom; idoms=idoms; dom_tree=(fun x -> Lazy.force dom_tree x); dominators=dominators; dom=dom; sdom=sdom; dom_frontier=(fun x -> Lazy.force dom_frontier x); dom_graph=(fun () -> compute_dom_graph cfg (Lazy.force dom_tree)); } end ocamlgraph-1.8.3/src/contraction.mli0000644000175000017500000000427012133565070016420 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright (c) 2012 Technische Universitaet Muenchen * Markus W. Weissmann * All rights reserved. *) (** Edge contraction for directed, edge-labeled graphs *) (* This algorithm should be extensible to undirected, unlabeled graphs! *) (** Minimal graph signature for edge contraction algorithm *) module type G = sig type t module V : Sig.COMPARABLE type vertex = V.t module E : Sig.EDGE with type vertex = vertex type edge = E.t val empty : t val add_edge_e : t -> edge -> t val fold_edges_e : (edge -> 'a -> 'a) -> t -> 'a -> 'a val fold_vertex : (vertex -> 'a -> 'a) -> t -> 'a -> 'a end module Make (G : G) : sig val contract : (G.E.t -> bool) -> G.t -> G.t (** [contract p g] will perform edge contraction on the graph [g]. The edges for which the property [p] holds/is true will get contracted: The resulting graph will not have these edges; the start- and end-node of these edges will get united. *) end ocamlgraph-1.8.3/src/flow.mli0000644000175000017500000000711712133565070015047 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Algorithms on flows The following flow algorithms only apply to networks, that are directed graphs together with a source (a 0 in-degree vertex) and a terminal (a 0 out-degree vertex). *) (** {1 Maximum flow algorithms} *) (** Signature for edges' flow. *) module type FLOW = sig type t (** Type of edges. *) type label (** Type of labels on edges. *) (** Maximum and minimum capacities for a label on an edge. *) val max_capacity : label -> t val min_capacity : label -> t (** Current flow for a label on an edge. *) val flow : label -> t (** [+] and [-] on flows. *) val add : t -> t -> t val sub : t -> t -> t (** Neutral element for [add] and [sub]. *) val zero : t (** A total ordering over flows. *) val compare : t -> t -> int end (** {2 Goldberg maximal flow algorithm} *) (** Minimal graph signature for Goldberg. Sub-signature of {!Sig.G}. *) module type G_GOLDBERG = sig type t module V : Sig.COMPARABLE module E : Sig.EDGE with type vertex = V.t val nb_vertex : t -> int val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit val fold_succ_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val fold_pred_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end module Goldberg(G: G_GOLDBERG)(F: FLOW with type label = G.E.label) : sig val maxflow : G.t -> G.V.t -> G.V.t -> (G.E.t -> F.t) * F.t (** [maxflow g v1 v2] searchs the maximal flow from source [v1] to terminal [v2] using the Goldberg algorithm. It returns the new flows on each edges and the growth of the flow. *) end (** {2 Ford-Fulkerson maximal flow algorithm} *) (** Minimal digraph signature for Ford-Fulkerson. Sub-signature of {!Sig.G}. *) module type G_FORD_FULKERSON = sig type t module V : Sig.HASHABLE module E : sig type t type label val src : t -> V.t val dst : t -> V.t val label : t -> label end val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit val iter_pred_e : (E.t -> unit) -> t -> V.t -> unit end module Ford_Fulkerson (G: G_FORD_FULKERSON) (F: FLOW with type label = G.E.label) : sig val maxflow : G.t -> G.V.t -> G.V.t -> (G.E.t -> F.t) * F.t (** [maxflow g v1 v2] searchs the maximal flow from source [v1] to terminal [v2] using the Ford-Fulkerson algorithm. It returns the new flows on each edges and the growth of the flow. *) end ocamlgraph-1.8.3/src/persistent.mli0000644000175000017500000000725512133565071016304 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Persistent Graph Implementations. *) open Sig (** Signature of persistent graphs. *) module type S = sig (** Edges may be labeled or not: - Unlabeled: there is no label on edges - Labeled: you have to provide a label implementation as a functor parameter. Vertices may be concrete or abstract: - Concrete: type of vertex labels and type of vertices are identified. - Abstract: type of vertices is abstract (in particular it is not equal to type of vertex labels How to choose between concrete and abstract vertices for my graph implementation? Usually, if you fall into one of the following cases, use abstract vertices: - you cannot provide efficient comparison/hash functions for vertices; or - you wish to get two different vertices with the same label. In other cases, it is certainly easier to use concrete vertices. *) (** Persistent Unlabeled Graphs. *) module Concrete (V: COMPARABLE) : Sig.P with type V.t = V.t and type V.label = V.t and type E.t = V.t * V.t and type E.label = unit (** Abstract Persistent Unlabeled Graphs. *) module Abstract(V: ANY_TYPE) : Sig.P with type V.label = V.t and type E.label = unit (** Persistent Labeled Graphs. *) module ConcreteLabeled (V: COMPARABLE)(E: ORDERED_TYPE_DFT) : Sig.P with type V.t = V.t and type V.label = V.t and type E.t = V.t * E.t * V.t and type E.label = E.t (** Abstract Persistent Labeled Graphs. *) module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) : Sig.P with type V.label = V.t and type E.label = E.t end (** Persistent Directed Graphs. *) module Digraph : sig include S (** {2 Bidirectional graphs} Bidirectional graphs use more memory space (at worse the double) that standard concrete directional graphs. But accessing predecessors and removing a vertex are faster. *) (** Imperative Unlabeled, bidirectional graph. *) module ConcreteBidirectional (V: COMPARABLE) : Sig.P with type V.t = V.t and type V.label = V.t and type E.t = V.t * V.t and type E.label = unit (** Imperative Labeled and bidirectional graph. *) module ConcreteBidirectionalLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT) : Sig.P with type V.t = V.t and type V.label = V.t and type E.t = V.t * E.t * V.t and type E.label = E.t end (** Persistent Undirected Graphs. *) module Graph : S (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/pack.mli0000644000175000017500000000327712133565071015022 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: pack.mli,v 1.1 2004-02-04 11:52:02 filliatr Exp $ *) (** {b Immediate access to the library}: provides implementation of imperative graphs labeled with integer as well as algorithms on such graphs. So if you bother functors, you can use this module. *) (** Directed imperative graphs with edges and vertices labeled with integer. *) module Digraph : Sig_pack.S (** Undirected imperative graphs with edges and vertices labeled with integer. *) module Graph : Sig_pack.S ocamlgraph-1.8.3/src/contraction.ml0000644000175000017500000000604212133565070016246 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Copyright (c) 2012 Technische Universitaet Muenchen * Markus W. Weissmann * All rights reserved. *) (* Edge contraction for directed, edge-labeled graphs *) module type G = sig type t module V : Sig.COMPARABLE type vertex = V.t module E : Sig.EDGE with type vertex = vertex type edge = E.t val empty : t val add_edge_e : t -> edge -> t val fold_edges_e : (edge -> 'a -> 'a) -> t -> 'a -> 'a val fold_vertex : (vertex -> 'a -> 'a) -> t -> 'a -> 'a end module Make (G : G) = struct module M = Map.Make(G.V) module S = Set.Make(G.V) let contract prop g = (* if the edge is to be removed (property = true): * make a union of the two union-sets of start and end node; * put this set in the map for all nodes in this set *) let f edge m = if prop edge then let s_src, s_dst = M.find (G.E.src edge) m, M.find (G.E.dst edge) m in let s = S.union s_src s_dst in S.fold (fun vertex m -> M.add vertex s m) s m else m in (* if the edge is to be kept, add it to the new graph, exchanging * the start and end node with the minimum element from the set of * to-be-unified nodes; 'minimum is an arbitrary choice: any * deterministic choice will do *) let add m edge g = if prop edge then g else let lookup n = S.min_elt (M.find n m) in G.add_edge_e g (G.E.create (lookup (G.E.src edge)) (G.E.label edge) (lookup (G.E.dst edge))) in (* initialize map with singleton-sets for every node (of itself) *) let m = G.fold_vertex (fun vertex m -> M.add vertex (S.singleton vertex) m) g M.empty in (* find all closures *) let m = G.fold_edges_e f g m in (* rewrite the node numbers to close the gaps *) G.fold_edges_e (add m) g G.empty end ocamlgraph-1.8.3/src/md.ml0000644000175000017500000000773412133565071014335 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module P(G : Sig.P) = struct module VertexSet = Set.Make(G.V) module CT = Cliquetree.CliqueTree(G) module Choose = Oper.Choose(G) type edgeset = (G.V.t * G.V.t) list let md g = let gref = ref g in let gtri = ref g in let n = G.nb_vertex g in let tri = ref [] in let ord = ref [] in let i = ref 0 in while not (CT.is_chordal !gtri) && !i < n do let v = let x = G.fold_vertex (fun v' x -> let deg' = G.out_degree !gref v' in match x with Some (v,deg) when deg' > deg -> x | _ -> Some (v', deg')) !gref None in match x with Some (v,_) -> v | None -> failwith "Expecting some vertex" in let ng = G.succ !gref v in let g', tri' = List.fold_left (fun (g, tri) v -> let tri' = List.fold_left (fun tri v' -> if v <> v' && not (G.mem_edge g v v') then (v, v') :: tri else tri) tri ng in let g' = List.fold_left (fun g v' -> if v <> v' then G.add_edge g v v' else g) g ng in (g', tri')) (!gref, []) ng in ord := v :: !ord; gtri := List.fold_left (fun g (x,y) -> G.add_edge g x y) !gtri tri'; gref := G.remove_vertex g' v; tri := tri' @ !tri; incr i; done; (!gtri, !tri, !ord) let triangulate g = let gtri, _, _ = md g in gtri end module I(G : Sig.I) = struct module VertexSet = Set.Make(G.V) module CT = Cliquetree.CliqueTree(G) module Choose = Oper.Choose(G) type edgeset = (G.V.t * G.V.t) list module Copy = Gmap.Vertex(G)(struct include G include Builder.I(G) end) let md g = let gtri = Copy.map (fun x -> x) g in let gcur = Copy.map (fun x -> x) g in let n = G.nb_vertex g in let tri = ref [] in let ord = ref [] in let i = ref 0 in while not (CT.is_chordal gtri) && !i < n do let v = let x = G.fold_vertex (fun v' x -> let deg' = G.out_degree gcur v' in match x with Some (v,deg) when deg' > deg -> x | _ -> Some (v', deg')) gcur None in match x with Some (v,_) -> v | None -> failwith "Expecting some vertex" in let ng = G.succ gcur v in let tri' = List.fold_left (fun tri v -> List.fold_left (fun tri v' -> let tri' = if v <> v' && not (G.mem_edge g v v') then (v, v') :: tri else tri in List.iter (fun v' -> if v <> v' then G.add_edge gcur v v') ng; tri') tri ng) [] ng in ord := v :: !ord; List.iter (fun (x,y) -> G.add_edge gtri x y) tri'; G.remove_vertex gcur v; tri := tri' @ !tri; incr i; done; (gtri, !tri, !ord) let triangulate g = let gtri, _, _ = md g in gtri end ocamlgraph-1.8.3/src/pack.ml0000644000175000017500000001347012133565071014645 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: pack.ml,v 1.13 2006-05-12 14:07:16 filliatr Exp $ *) module Generic(G : Sig.IM with type V.label = int and type E.label = int) = struct include G exception Found of V.t let find_vertex g i = try iter_vertex (fun v -> if V.label v = i then raise (Found v)) g; raise Not_found with Found v -> v module Builder = Builder.I(G) module Dfs = Traverse.Dfs(G) module Bfs = Traverse.Bfs(G) module Marking = Traverse.Mark(G) module Classic = Classic.I(G) module Rand = Rand.I(G) module Components = Components.Make(G) module W = struct type label = int type t = int let weight x = x let zero = 0 let add = (+) let compare : t -> t -> int = Pervasives.compare end include Path.Dijkstra(G)(W) module BF = Path.BellmanFord(G)(W) let bellman_ford = BF.find_negative_cycle_from module F = struct type label = int type t = int let max_capacity x = x let min_capacity _ = 0 let flow _ = 0 let add = (+) let sub = (-) let compare : t -> t -> int = Pervasives.compare let max = max_int let min = 0 let zero = 0 end module FF = Flow.Ford_Fulkerson(G)(F) let ford_fulkerson g = if not G.is_directed then invalid_arg "ford_fulkerson: not a directed graph"; FF.maxflow g module Goldberg = Flow.Goldberg(G)(F) let goldberg g = if not G.is_directed then invalid_arg "goldberg: not a directed graph"; Goldberg.maxflow g include Oper.Make(Builder) module PathCheck = Path.Check(G) module Topological = struct include Topological.Make(G) module S = Topological.Make_stable(G) let fold_stable = S.fold let iter_stable = S.iter end module Int = struct type t = int let compare : t -> t -> int = Pervasives.compare end include Kruskal.Make(G)(Int) module Display = struct include G let vertex_name v = string_of_int (V.label v) let graph_attributes _ = [] let default_vertex_attributes _ = [] let vertex_attributes _ = [] let default_edge_attributes _ = [] let edge_attributes e = [ `Label (string_of_int (E.label e) ) ] let get_subgraph _ = None end module Dot_ = Graphviz.Dot(Display) module Neato = Graphviz.Neato(Display) let dot_output g f = let oc = open_out f in if is_directed then Dot_.output_graph oc g else Neato.output_graph oc g; close_out oc let display_with_gv g = let tmp = Filename.temp_file "graph" ".dot" in dot_output g tmp; ignore (Sys.command ("dot -Tps " ^ tmp ^ " | gv -")); Sys.remove tmp module GmlParser = Gml.Parse (Builder) (struct let node l = try match List.assoc "id" l with Gml.Int n -> n | _ -> -1 with Not_found -> -1 let edge _ = 0 end) let parse_gml_file = GmlParser.parse module DotParser = Dot.Parse (Builder) (struct let nodes = Hashtbl.create 97 let new_node = ref 0 let node (id,_) _ = try Hashtbl.find nodes id with Not_found -> incr new_node; Hashtbl.add nodes id !new_node; !new_node let edge _ = 0 end) let parse_dot_file = DotParser.parse open Format module GmlPrinter = Gml.Print (G) (struct let node n = ["label", Gml.Int n] let edge n = ["label", Gml.Int n] end) let print_gml = GmlPrinter.print let print_gml_file g f = let c = open_out f in let fmt = formatter_of_out_channel c in fprintf fmt "%a@." GmlPrinter.print g; close_out c let uid h find add = let n = ref 0 in fun x -> try find h x with Not_found -> incr n; add h x !n; !n (* module GraphmlPrinter = Graphml.Print (G) (struct let node n = ["label", Gml.Int n] let edge n = ["label", Gml.Int n] module Vhash = Hashtbl.Make(G.V) let vertex_uid = uid (Vhash.create 17) Vhash.find Vhash.add module Ehash = Hashtbl.Make(G.E) let edge_uid = uid (Ehash.create 17) Ehash.find Ehash.add end) let print_gml = GmlPrinter.print let print_gml_file g f = let c = open_out f in let fmt = formatter_of_out_channel c in fprintf fmt "%a@." GmlPrinter.print g; close_out c *) end module I = struct type t = int let compare : t -> t -> int = Pervasives.compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module IW = struct type label = I.t type t = int module M = Map.Make(I) let map = M.empty let weight lbl = lbl let compare : t -> t -> int = Pervasives.compare let add = (+) let zero = 0 end module Digraph = Generic(Imperative.Digraph.AbstractLabeled(I)(I)) module Graph = Generic(Imperative.Graph.AbstractLabeled(I)(I)) ocamlgraph-1.8.3/src/coloring.ml0000644000175000017500000001004712133565070015537 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module type GM = sig val is_directed : bool type t val nb_vertex : t -> int module V : Sig.COMPARABLE val out_degree : t -> V.t -> int val iter_vertex : (V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_succ : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a module Mark : sig val get : V.t -> int val set : V.t -> int -> unit end end (** Graph coloring with marking. Only applies to imperative graphs with marks. *) module Mark(G : GM) = struct exception NoColoring module Bfs = Traverse.Bfs(G) let coloring g k = (* first step: we eliminate vertices with less than [k] successors *) let stack = Stack.create () in let nb_to_color = ref (G.nb_vertex g) in let count = ref 1 in while !count > 0 do count := 0; let erase v = incr count; G.Mark.set v (k+1); Stack.push v stack in G.iter_vertex (fun v -> if G.Mark.get v = 0 && G.out_degree g v < k then erase v) g; (*Format.printf "eliminating %d nodes@." !count;*) nb_to_color := !nb_to_color - !count done; (* second step: we k-color the remaining of the graph *) (* [try_color v i] tries to assign color [i] to vertex [v] *) let try_color v i = G.Mark.set v i; G.iter_succ (fun w -> if G.Mark.get w = i then raise NoColoring) g v in let uncolor v = G.Mark.set v 0 in if !nb_to_color > 0 then begin let rec iterate iter = let v = Bfs.get iter in let m = G.Mark.get v in if m > 0 then iterate (Bfs.step iter) else begin for i = 1 to k do try try_color v i; iterate (Bfs.step iter) with NoColoring -> () done; uncolor v; raise NoColoring end in try iterate (Bfs.start g) with Exit -> () end; (* third step: we color the eliminated vertices, in reverse order *) Stack.iter (fun v -> try for i = 1 to k do try try_color v i; raise Exit with NoColoring -> () done; raise NoColoring (* it may still fail on a self edge v->v *) with Exit -> ()) stack end (** Graph coloring for graphs without marks: we use an external hashtbl *) module type G = sig val is_directed : bool type t val nb_vertex : t -> int module V : Sig.COMPARABLE val out_degree : t -> V.t -> int val iter_vertex : (V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_succ : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end module Make(G: G) = struct module H = Hashtbl.Make(G.V) let coloring g k = let h = H.create 97 in let module M = Mark(struct include G module Mark = struct let get v = try H.find h v with Not_found -> 0 let set v n = H.replace h v n end end ) in M.coloring g k; h end ocamlgraph-1.8.3/src/nonnegative.mli0000644000175000017500000000524312133565071016414 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* This module is a contribution of Yuto Takei *) open Sig open Blocks open Persistent (** Weighted graphs without negative-cycles. *) (** This graph maintains the invariant that it is free of such cycles that the total length of edges involving is negative. With introduction of those negative-cycles causes an inability to compute the shortest paths from arbitrary vertex. By using the graph modules defined here, introduction of such a cycle is automatically prevented. *) (** Signature for edges' weights. *) module type WEIGHT = sig type label (** Type for labels of graph edges. *) type t (** Type of edges' weights. *) val weight : label -> t (** Get the weight of an edge. *) val compare : t -> t -> int (** Weights must be ordered. *) val add : t -> t -> t (** Addition of weights. *) val zero : t (** Neutral element for {!add}. *) end module Imperative (G: Sig.IM) (W: WEIGHT with type label = G.E.label) : sig include Sig.IM with module V = G.V and module E = G.E exception Negative_cycle of G.E.t list end (** Persistent graphs with negative-cycle prevention *) module Persistent (G: Sig.P) (W: WEIGHT with type label = G.E.label) : sig include Sig.P with module V = G.V and module E = G.E exception Negative_cycle of G.E.t list (** Exception [NegativeCycle] is raised whenever a negative cycle is introduced for the first time (either with [add_edge] or [add_edge_e]) *) end ocamlgraph-1.8.3/src/strat.ml0000644000175000017500000001352512133565071015065 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Signature for graphs *) module type G = sig type t module V : Sig.ORDERED_TYPE type vertex = V.t val mem_vertex : t -> vertex -> bool val succ : t -> vertex -> vertex list val fold_vertex : (vertex -> 'a -> 'a) -> t -> 'a -> 'a val fold_succ : (vertex -> 'a -> 'a) -> t -> vertex -> 'a -> 'a end (* Signature for graph add-ons: an initial vertex, final vertices and membership of vertices to either true or false, i.e. first or second player *) module type PLAYER = sig type t type vertex val get_initial : t -> vertex val is_final : t -> vertex -> bool val turn : t -> vertex -> bool end (* Signature for strategies : for a given state, the strategy tells which state to go to *) module type STRAT = sig type t type vertex val empty : t val add : t -> vertex -> vertex -> t val next : t -> vertex -> vertex (* Raises Invalid_argument if vertex's image is not defined *) end (* Implements strategy algorithms on graphs *) module Algo (G : G) (P : PLAYER with type vertex = G.vertex) (S : STRAT with type vertex = G.vertex) : sig (* coherent_player g p returns true iff the completion p is coherent w.r.t. the graph g *) val coherent_player : G.t -> P.t -> bool (* coherent_strat g s returns true iff the strategy s is coherent w.r.t. the graph g *) val coherent_strat : G.t -> S.t -> bool (* game g p a b returns true iff a wins in g given the completion p (i.e. the game goes through a final state). *) val game : G.t -> P.t -> S.t -> S.t -> bool (* strategy g p s returns true iff s wins in g given the completion p, whatever strategy plays the other player. *) val strategy : G.t -> P.t -> S.t -> bool (* strategyA g p returns true iff there exists a winning stragegy for the true player. In this case, the winning strategy is provided. *) val strategyA : G.t -> P.t -> (bool * S.t) end = struct module SetV = Set.Make (G.V) let rec eq l1 l2 = match l1, l2 with [], [] -> true | e1 :: l1', e2 :: l2' -> (e1 = e2) && (eq l1' l2') | _ -> false let rec eq_mem i l1 l2 = match l1, l2 with [], [] -> (true, false) | e1 :: l1', e2 :: l2' -> if e1 = e2 then if e1 = i then (eq l1' l2', true) else eq_mem i l1' l2' else (false, false) | _ -> (false, false) let puit g v = match G.succ g v with [] -> true | _ -> false let get_finals g p = let f a l = if P.is_final p a then a :: l else l in G.fold_vertex f g [] let coherent_player g p = G.mem_vertex g (P.get_initial p) let coherent_strat g s = let f v b = try let v' = S.next s v in b && (G.mem_vertex g v') with Invalid_argument _ -> true in G.fold_vertex f g true let game g p a b = let rec game_aux l pi = let continue x = try game_aux (SetV.add pi l) (S.next x pi) with Invalid_argument _ -> false in (P.is_final p pi) || (if SetV.mem pi l then false else if P.turn p pi then continue a else continue b) in game_aux SetV.empty (P.get_initial p) let rec attract1 g p s l = let f v l1 = if not (List.mem v l1) then if P.turn p v then try if List.mem (S.next s v) l1 then v :: l1 else l1 with Invalid_argument _ -> l1 else if puit g v then l1 else if G.fold_succ (fun v' b -> b && (List.mem v' l1)) g v true then v :: l1 else l1 else l1 in G.fold_vertex f g l let rec strategy g p s = let rec strategy_aux l1 l2 = let (b1, b2) = eq_mem (P.get_initial p) l1 l2 in if b1 then b2 else strategy_aux (attract1 g p s l1) l1 in let finaux = get_finals g p in strategy_aux (attract1 g p s finaux) finaux let rec attract g p (l, l') = let f v (l1, l1') = if not (List.mem v l1) then if P.turn p v then let f' v' l2 = (match l2 with [] -> if List.mem v' l1 then [v'] else [] | _ -> l2) in (match G.fold_succ f' g v [] with [] -> (l1, l1') | v' :: _ -> (v :: l1, S.add l1' v v' )) else if puit g v then (l1, l1') else if G.fold_succ (fun v' b -> b && (List.mem v' l1)) g v true then (v :: l1, l1') else (l1, l1') else (l1, l1') in G.fold_vertex f g (l, l') let rec strategyA g p = let rec strategyA_aux l1 l2 f = let (b1, b2) = eq_mem (P.get_initial p) l1 l2 in if b1 then (b2, f) else let (new_l1, new_f) = attract g p (l1, f) in strategyA_aux new_l1 l1 new_f in let finaux = get_finals g p in let (l, r) = attract g p (finaux, S.empty) in strategyA_aux l finaux r;; end ocamlgraph-1.8.3/src/classic.ml0000644000175000017500000000610712133565070015346 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: classic.ml,v 1.9 2004-02-02 08:11:14 filliatr Exp $ *) module type S = sig type graph val divisors : int -> graph val de_bruijn : int -> graph val vertex_only : int -> graph val full : ?self:bool -> int -> graph end module Generic(B : Builder.INT) = struct type graph = B.G.t let divisors n = if n < 2 then invalid_arg "divisors"; let v = Array.init (n + 1) (fun i -> B.G.V.create i) in let rec loop g i = let sqrt_i = truncate (sqrt (float i)) in let rec loop_i g d = if d > sqrt_i then g else if i mod d == 0 then loop_i (B.add_edge (B.add_edge g v.(i / d) v.(i)) v.(d) v.(i)) (d+1) else loop_i g (succ d) in if i > n then g else loop (loop_i (B.add_vertex g v.(i)) 2) (i+1) in loop (B.empty ()) 2 let fold_for i0 i1 f = let rec loop i v = if i > i1 then v else loop (i + 1) (f v i) in loop i0 let de_bruijn n = if n < 1 || n > Sys.word_size - 1 then invalid_arg "de_bruijn"; let v = Array.init (1 lsl n) (fun i -> B.G.V.create i) in let all_1 = 1 lsl n - 1 in (* 11...1 *) let g = fold_for 0 all_1 (fun g i -> B.add_vertex g v.(i)) (B.empty ()) in let rec loop g i = if i > all_1 then g else let si = (i lsl 1) land all_1 in let g = B.add_edge g v.(i) v.(si) in let g = B.add_edge g v.(i) v.(si lor 1) in loop g (i + 1) in loop g 0 let vertex_only n = fold_for 1 n (fun g i -> B.add_vertex g (B.G.V.create i)) (B.empty ()) let full ?(self=true) n = let v = Array.init (n + 1) (fun i -> B.G.V.create i) in fold_for 1 n (fun g i -> fold_for 1 n (fun g j -> if self || i <> j then B.add_edge g v.(i) v.(j) else g) g) (fold_for 1 n (fun g i -> B.add_vertex g v.(i)) (B.empty ())) end module P (G : Sig.P with type V.label = int) = Generic(Builder.P(G)) module I (G : Sig.I with type V.label = int) = Generic(Builder.I(G)) ocamlgraph-1.8.3/src/util.mli0000644000175000017500000000401312133565071015046 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Some useful operations. *) open Sig (** Cartesian product of two ordered types. *) module OTProduct(X: ORDERED_TYPE)(Y: ORDERED_TYPE) : ORDERED_TYPE with type t = X.t * Y.t (** Cartesian product of two hashable types. *) module HTProduct(X: HASHABLE)(Y: HASHABLE) : HASHABLE with type t = X.t * Y.t (** Cartesian product of two comparable types. *) module CMPProduct(X: COMPARABLE)(Y: COMPARABLE) : COMPARABLE with type t = X.t * Y.t (** Create a vertex type with some data attached to it *) module DataV(L : sig type t end)(V : Sig.COMPARABLE) : sig type data = L.t and label = V.t and t = data ref * V.t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool val create : data -> V.t -> t val label : t -> V.t val data : t -> data val set_data : t -> data -> unit end ocamlgraph-1.8.3/src/merge.ml0000644000175000017500000001720312133565071015024 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2012 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module type S = sig type graph type vertex type edge type edge_label val merge_vertex: graph -> vertex list -> graph val merge_edges_e: ?src:vertex -> ?dst:vertex -> graph -> edge list -> graph val merge_edges_with_label: ?src:vertex -> ?dst:vertex -> ?label:edge_label -> graph -> edge_label -> graph val merge_isolabelled_edges: graph -> graph val merge_ends: ?strict:bool -> ?specified_vertex:vertex -> graph -> graph val merge_starts: ?strict:bool -> ?specified_vertex:vertex -> graph -> graph val merge_scc: ?loop_killer:bool -> ?specified_vertex:(vertex list -> vertex) -> graph -> graph end module B(B: Builder.S) = struct type graph = B.G.t type vertex = B.G.vertex type edge = B.G.edge type edge_label = B.G.E.label let mem x ec = List.exists (fun y -> B.G.V.equal x y) ec let identify x ec = match ec with | [] -> false , x | y :: ec -> if mem x ec then true, y else false, x let identify_extremities g vl = let f e accu = let sx, x = identify (B.G.E.src e) vl in let sy, y = identify (B.G.E.dst e) vl in if sx || sy then B.G.E.(create x (label e) y) :: accu else accu in B.G.fold_edges_e f g [] let merge_vertex g vl = match vl with | [] -> g | _ :: vl' -> let to_be_added = identify_extremities g vl in let g = List.fold_left B.remove_vertex g vl' in List.fold_left B.add_edge_e g to_be_added let merge_edges_e ?src ?dst g el = match el with | e :: el' -> let el' = List.filter (B.G.mem_edge_e g) el' in if el' <> [] then (let el = e :: el' in let extremities e = B.G.E.(src e, dst e) in let sources , destinations = List.split (List.map extremities el) in let remove accu e = try B.remove_edge_e accu e with Invalid_argument _ -> g in let g = List.fold_left remove g el in if List.exists (fun v -> mem v destinations) sources then let v = match src with | None -> (match dst with | None -> List.hd sources | Some w -> w) | Some v -> v in let g = merge_vertex g (v :: sources @ destinations) in B.add_edge_e g B.G.E.(create v (label e) v) else let v = match src with None -> List.hd sources | Some v -> v in let w = match src with | None -> List.hd destinations | Some w -> w in let g = merge_vertex g sources in let g = merge_vertex g destinations in B.add_edge_e g B.G.E.(create v (label e) w)) else g | [] -> g let merge_edges_with_label ?src ?dst ?label g l = let update_label e = match label with | None -> e | Some l -> B.G.E.(create (src e) l (dst e)) in let collect_edge e accu = if B.G.E.label e = l then (update_label e) :: accu else accu in let edges_to_be_merged = B.G.fold_edges_e collect_edge g [] in merge_edges_e ?src ?dst g edges_to_be_merged let merge_isolabelled_edges g = let module S = Set.Make(B.G.V) in let do_meet s1 s2 = S.exists (fun x -> S.mem x s2) s1 in let module M = (* TODO: using [compare] here is really suspicious *) Map.Make(struct type t = B.G.E.label let compare = compare end) in let accumulating e accu = let l = B.G.E.label e in try let s , d = M.find l accu in let s , d = B.G.E.(S.add (src e) s , S.add (dst e) d) in M.add l (s, d) accu with Not_found -> M.add l B.G.E.(S.singleton (src e), S.singleton (dst e)) accu in let to_be_identified = B.G.fold_edges_e accumulating g M.empty in let gathering _ (s, d) accu = let to_be_gathered, others = List.partition (do_meet s) accu in let accu = List.fold_left (fun accu x -> S.union accu x) s to_be_gathered :: others in let to_be_gathered , others = List.partition (do_meet d) accu in List.fold_left (fun accu x -> S.union accu x) d to_be_gathered :: others in let to_be_identified = M.fold gathering to_be_identified [] in List.fold_left (fun accu s -> merge_vertex accu (S.elements s)) g to_be_identified let merge_ends ?(strict=false) ?specified_vertex g = let accumulator v accu = if let out_d = B.G.out_degree g v in out_d = 0 || ((not strict) && out_d = List.length (B.G.find_all_edges g v v)) then v :: accu else accu in let ends = B.G.(fold_vertex accumulator g []) in let to_be_merged = match specified_vertex with | Some v -> v :: ends | None -> ends in merge_vertex g to_be_merged let merge_starts ?(strict=false) ?specified_vertex g = let accumulator v accu = if let in_d = B.G.in_degree g v in in_d = 0 || ((not strict) && in_d = List.length (B.G.find_all_edges g v v)) then v :: accu else accu in let starts = B.G.(fold_vertex accumulator g []) in let to_be_merged = match specified_vertex with | Some v -> v :: starts | None -> starts in merge_vertex g to_be_merged let merge_scc ?(loop_killer=false) ?specified_vertex g = let module C = Components.Make(B.G) in let components = C.scc_list g in let alter accu to_be_identified = let to_be_identified = match specified_vertex with | None -> to_be_identified | Some f -> (f to_be_identified) :: to_be_identified in let v = List.hd to_be_identified in let accu = merge_vertex accu to_be_identified in if loop_killer then B.remove_edge accu v v else accu in List.fold_left alter g components end module P(G: Sig.P) = B(Builder.P(G)) module I(G: Sig.I) = struct include B(Builder.I(G)) let merge_vertex g vl = ignore (merge_vertex g vl) let merge_edges_e ?src ?dst g el = ignore (merge_edges_e ?src ?dst g el) let merge_edges_with_label ?src ?dst ?label g l = ignore (merge_edges_with_label ?src ?dst ?label g l) let merge_isolabelled_edges g = ignore (merge_isolabelled_edges g) let merge_ends ?strict ?specified_vertex g = ignore (merge_ends ?strict ?specified_vertex g) let merge_starts ?strict ?specified_vertex g = ignore (merge_starts ?strict ?specified_vertex g) let merge_scc ?loop_killer ?specified_vertex g = ignore (merge_scc ?loop_killer ?specified_vertex g) end (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/minsep.ml0000644000175000017500000000777212133565071015232 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module type G = sig type t module V : Sig.COMPARABLE val succ: t -> V.t -> V.t list val iter_succ: (V.t -> unit) -> t -> V.t -> unit val fold_succ: (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val iter_vertex: (V.t -> unit) -> t -> unit val fold_vertex: (V.t -> 'a -> 'a) -> t -> 'a -> 'a end module type MINSEP = sig module G : G module Vertex_Set : Set.S with type elt = G.V.t module VSetset : Set.S with type elt = Vertex_Set.t val allminsep : G.t -> Vertex_Set.t list val list_of_allminsep : G.t -> G.V.t list list val set_of_allminsep : G.t -> VSetset.t end module Make (G : sig include G val cc: t -> V.t list -> V.t list list (** compute the set of connected components of G(V \ l) *) end) = struct module N = Oper.Neighbourhood(G) module Vertex_Set = N.Vertex_Set module VSetset = Set.Make(Vertex_Set) let initialisation g = let cc = G.cc g in let neighbourhood = N.list_from_vertex g in let neighbourhoods = N.set_from_vertices g in G.fold_vertex (fun v s -> List.fold_left (fun s l -> neighbourhoods l :: s) s (cc (v :: neighbourhood v))) g [] let generation g = let neighbourhood = N.list_from_vertex g in let neighbourhoods = N.set_from_vertices g in let cc = G.cc g in let rec gen_aux seen bigs = function | [] -> bigs | s :: tl -> let l = Vertex_Set.elements s in let seen = VSetset.add s seen in let bigs, tl = Vertex_Set.fold (fun v c -> let add_neighbourhoods (bigs, tl) l = let s = neighbourhoods l in s :: bigs, if VSetset.mem s seen then tl else s :: tl in List.fold_left add_neighbourhoods (bigs, tl) (cc (l @ neighbourhood v))) s (bigs, tl) in gen_aux seen bigs tl in fun bigs -> gen_aux VSetset.empty bigs bigs let allminsep g = generation g (initialisation g) let set_of_allminsep g = List.fold_left (fun bigs s -> VSetset.add s bigs) VSetset.empty (allminsep g) let list_of_allminsep g = List.map Vertex_Set.elements (allminsep g) end module P(G : sig include G val remove_vertex : t -> V.t -> t end) = struct module G = G include Make(struct include G let cc = let module CC = Components.Make(G) in fun g l -> let g = List.fold_left remove_vertex g l in CC.scc_list g end) end module I(G : sig include G module Mark : Sig.MARK with type graph = t and type vertex = V.t end) = struct module G = G include Make(struct include G let cc = let module CC = Components.Make (struct include G let iter_vertex f = iter_vertex (fun v -> if Mark.get v=0 then f v) end) in fun g l -> G.Mark.clear g; List.iter (fun v -> G.Mark.set v 1) l; CC.scc_list g end) end ocamlgraph-1.8.3/src/gmap.ml0000644000175000017500000000576712133565071014665 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** {2 Mapping of vertices} *) module type V_SRC = sig type t module V : Sig.HASHABLE val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a end module type V_DST = sig type t type vertex val empty : unit -> t val add_vertex : t -> vertex -> t end module Vertex(G_Src : V_SRC)(G_Dst : V_DST ) = struct module H = Hashtbl.Make(G_Src.V) let vertices = H.create 97 let convert_vertex f x = try H.find vertices x with Not_found -> let x' = f x in H.add vertices x x'; x' let map f g = H.clear vertices; G_Src.fold_vertex (fun x g -> G_Dst.add_vertex g (convert_vertex f x)) g (G_Dst.empty ()) let filter_map f g = G_Src.fold_vertex (fun x g -> match f x with | Some e -> G_Dst.add_vertex g e | None -> g ) g (G_Dst.empty ()) end (** {2 Mapping of edges} *) module type E_SRC = sig type t module E : Sig.ORDERED_TYPE val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a end module type E_DST = sig type t type edge val empty : unit -> t val add_edge_e : t -> edge -> t end module Edge(G_Src: E_SRC)(G_Dst: E_DST) = struct module M = Map.Make(G_Src.E) let edges = ref M.empty let convert_edge f x = try M.find x !edges with Not_found -> let x' = f x in edges := M.add x x' !edges; x' let map f g = edges := M.empty; G_Src.fold_edges_e (fun x g -> G_Dst.add_edge_e g (convert_edge f x)) g (G_Dst.empty ()) let filter_map f g = G_Src.fold_edges_e (fun x g -> match f x with | Some e -> G_Dst.add_edge_e g e | None -> g ) g (G_Dst.empty ()) end (* Vertex (struct include G_Src module V = E let fold_vertex = fold_edges_e end) (struct include G_Dst type vertex = edge let add_vertex = add_edge_e end) *) ocamlgraph-1.8.3/src/imperative.mli0000644000175000017500000001266512133565071016252 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Imperative Graph Implementations. *) open Sig (** Signature of imperative graphs. *) module type S = sig (** Edges may be labeled or not: - Unlabeled: there is no label on edges - Labeled: you have to provide a label implementation as a functor parameter. Vertices may be concrete or abstract: - Concrete: type of vertex labels and type of vertices are identified. - Abstract: type of vertices is abstract (in particular it is not equal to type of vertex labels How to choose between concrete and abstract vertices for my graph implementation? Usually, if you fall into one of the following cases, use abstract vertices: - you cannot provide efficient comparison/hash functions for vertices; or - you wish to get two different vertices with the same label. In other cases, it is certainly easier to use concrete vertices. *) (** Imperative Unlabeled Graphs. *) module Concrete (V: COMPARABLE) : Sig.I with type V.t = V.t and type V.label = V.t and type E.t = V.t * V.t and type E.label = unit (** Abstract Imperative Unlabeled Graphs. *) module Abstract(V: ANY_TYPE) : Sig.IM with type V.label = V.t and type E.label = unit (** Imperative Labeled Graphs. *) module ConcreteLabeled (V: COMPARABLE)(E: ORDERED_TYPE_DFT) : Sig.I with type V.t = V.t and type V.label = V.t and type E.t = V.t * E.t * V.t and type E.label = E.t (** Abstract Imperative Labeled Graphs. *) module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) : Sig.IM with type V.label = V.t and type E.label = E.t end (** Imperative Directed Graphs. *) module Digraph : sig include S (** {2 Bidirectional graphs} Bidirectional graphs use more memory space (at worse the double) that standard concrete directional graphs. But accessing predecessors is in O(1) amortized instead of O(max(|V|,|E|)) and removing a vertex is in O(D*ln(D)) instead of O(|V|*ln(D)). D is the maximal degree of the graph. *) (** Imperative Unlabeled, bidirectional graph. *) module ConcreteBidirectional (V: COMPARABLE) : Sig.I with type V.t = V.t and type V.label = V.t and type E.t = V.t * V.t and type E.label = unit (** Imperative Labeled and bidirectional graph. *) module ConcreteBidirectionalLabeled(V:COMPARABLE)(E:ORDERED_TYPE_DFT) : Sig.I with type V.t = V.t and type V.label = V.t and type E.t = V.t * E.t * V.t and type E.label = E.t end (** Imperative Undirected Graphs. *) module Graph : S (** Imperative graphs implemented as adjacency matrices. *) module Matrix : sig module type S = sig (** Vertices are integers in [0..n-1]. A vertex label is the vertex itself. Edges are unlabeled. *) include Sig.I with type V.t = int and type V.label = int and type E.t = int * int (** Creation. graphs are not resizeable: size is given at creation time. Thus [make] must be used instead of [create]. *) val make : int -> t (** Note: [add_vertex] and [remove_vertex] have no effect. [clear] only removes edges, not vertices. *) end module Digraph : S (** Imperative Directed Graphs implemented with adjacency matrices. *) module Graph : S (** Imperative Undirected Graphs implemented with adjacency matrices. *) end (**** (** Faster implementations for abstract (un)labeled (di)graphs when vertices are _not shared_ between different graphs. This means that, when using the following implementations, two different graphs (created with two calls to [create]) must have disjoint sets of vertices. *) module UV : sig (** directed graphs *) module Digraph : sig module Abstract(V: ANY_TYPE) : Sig.IM with type V.label = V.t and type E.label = unit module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) : Sig.IM with type V.label = V.t and type E.label = E.t end (** undirected graphs *) module Graph : sig module Abstract(V: ANY_TYPE) : Sig.IM with type V.label = V.t and type E.label = unit module AbstractLabeled (V: ANY_TYPE)(E: ORDERED_TYPE_DFT) : Sig.IM with type V.label = V.t and type E.label = E.t end end ****) (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/cliquetree.mli0000644000175000017500000000615312133565070016241 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Construction of the clique tree of a graph and recognition of chordal graphs. Based on the article: Chordal graphs and their clique graph by P. Galinier, M. Habib and C. Paul. @author Matthieu Sozeau *) module CliqueTree(G : Sig.G) : sig (** Original graph vertex *) module CliqueV : sig type t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool val label : t -> t val create : G.V.t -> t val vertex : t -> G.V.t end (** Set of original vertices *) module CVS : Set.S with type elt = CliqueV.t (** Clique tree vertex type *) module CliqueTreeV : sig (** Trace of the algorithm as a list of markers Clique vertices *) type data = CliqueV.t list * CVS.t type label type t val compare : t -> t -> int val hash : t -> int val equal : t -> t -> bool val create : data -> label -> t val label : t -> label val data : t -> data end module CliqueTreeE : sig type t = int * CVS.t val compare : t -> t -> int val default : t val create : int -> CVS.t -> t (** Vertices in the clique tree edge (intersection of the two clique extremities). *) val vertices : t -> CVS.t end (** The clique tree graph type *) module CliqueTree : Sig.G with type V.t = CliqueTreeV.t and type E.label = CliqueTreeE.t (** [mcs_clique g] return an perfect elimination order of [g] (if it is chordal), the clique tree of [g] and its root. *) val mcs_clique : G.t -> G.V.t list * CliqueTree.t * CliqueTree.V.t (** [is_chordal g] uses the clique tree construction to test if a graph is chordal or not. *) val is_chordal : G.t -> bool (** [maxwidth g tri tree] returns the maxwidth characteristic of the triangulation [tri] of graph [g] given the clique tree [tree] of [tri]. *) val maxwidth : G.t -> G.t -> CliqueTree.t -> int end ocamlgraph-1.8.3/src/dot.mli0000644000175000017500000000370612133565070014666 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Parser for DOT file format. *) open Dot_ast val parse_dot_ast : string -> Dot_ast.file type clusters_hash = (string, attr list) Hashtbl.t (** Provide a parser for DOT file format. *) module Parse (B : Builder.S) (L : sig val node : node_id -> attr list -> B.G.V.label (** How to build the node label out of the set of attributes *) val edge : attr list -> B.G.E.label (** How to build the edge label out of the set of attributes *) end) : sig (** Parses a dot file *) val parse : string -> B.G.t (** Parses a dot file and returns the graph, its bounding box and a hash table from clusters to dot attributes *) val parse_bounding_box_and_clusters : string -> B.G.t * string * clusters_hash end ocamlgraph-1.8.3/src/coloring.mli0000644000175000017500000000701112133565070015705 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** [k]-coloring of undirected graphs. A [k]-coloring of a graph [g] is a mapping [c] from nodes to [\{1,...,k\}] such that [c(u) <> c(v)] for any edge [u-v] in [g]. *) (** {2 Graph coloring for graphs without marks} *) (** Minimal graph signature for {!Make}. Sub-signature of {!Sig.G}. *) module type G = sig val is_directed : bool type t val nb_vertex : t -> int module V : Sig.COMPARABLE val out_degree : t -> V.t -> int val iter_vertex : (V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_succ : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end (** Provide a function for [k]-coloring a graph. *) module Make(G: G) : sig module H : Hashtbl.S with type key = G.V.t (** Hash tables used to store the coloring *) val coloring : G.t -> int -> int H.t (** [coloring g k] colors the graph [g] with [k] colors and returns the coloring as a hash table mapping nodes to their colors. *) end (** {2 Graph coloring for graph with integer marks} *) (** Minimal graph signature for {!Mark}. Sub-signature of {!Sig.IM}. *) module type GM = sig val is_directed : bool type t val nb_vertex : t -> int module V : Sig.COMPARABLE val out_degree : t -> V.t -> int val iter_vertex : (V.t -> unit) -> t -> unit val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_succ : (V.t -> unit) -> t -> V.t -> unit val fold_succ : (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a module Mark : sig val get : V.t -> int val set : V.t -> int -> unit end end (** Provide a function for [k]-coloring a graph with integer marks. The provided function is more efficient that the one provided by functor {!Make} above. *) module Mark(G : GM) : sig exception NoColoring val coloring : G.t -> int -> unit (** [coloring g k] colors the nodes of graph [g] using k colors, assigning the marks integer values between 1 and k. raises [NoColoring] when there is no possible coloring. The graph marks may be partially set before starting; the meaning of initial values is as follows: - 0: a node to be colored - any value between 1 and k: a color already assigned - any value greater than k: a node to be ignored @raise NoColoring if [g] cannot be [k]-colored. *) end ocamlgraph-1.8.3/src/graphviz.ml0000644000175000017500000007523512133565071015570 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Interface with {i GraphViz} This module provides a basic interface with dot and neato, two programs of the GraphViz toolbox. These tools are available at the following URLs: http://www.graphviz.org/ http://www.research.att.com/sw/tools/graphviz/ *) open Format open Pervasives (* for compatibility with ocaml 3.12.0+dev17 (incoming ocaml3.12) *) (***************************************************************************) (** {2 Common stuff} *) (** Because the neato and dot engines present a lot of common points - in particular in the graph description language, large parts of the code is shared. First, the [!CommonAttributes] module defines attributes of graphs, nodes and edges that are understood by the two engines. Second, given a module (of type [!ENGINE]) describing an engine the [!MakeEngine] functor provides suitable interface function for it. *) (*-------------------------------------------------------------------------*) (** {3 Common attributes} *) type color = int type color_with_transparency = int32 let color_to_color_with_transparency color = Int32.add (Int32.shift_left (Int32.of_int color) 8) 0xFFl let fprint_color ppf color = fprintf ppf "\"#%06X\"" color let fprint_color_with_transparency ppf color = fprintf ppf "\"#%08lX\"" color let fprint_string ppf s = fprintf ppf "\"%s\"" s (* let s' = String.escaped s in if s' = s && s <> "" then fprintf ppf "%s" s else fprintf ppf "\"%s\"" s'*) let fprint_string_user ppf s = (* let s = String.escaped s in*) fprintf ppf "\"%s\"" s type arrow_style = [ `None | `Normal | `Inv | `Dot | `Odot | `Invdot | `Invodot ] let fprint_arrow_style ppf = function `None -> fprintf ppf "none" | `Normal -> fprintf ppf "normal" | `Inv -> fprintf ppf "inv" | `Dot -> fprintf ppf "dot" | `Odot -> fprintf ppf "odot" | `Invdot -> fprintf ppf "invdot" | `Invodot -> fprintf ppf "invodot" let fprint_dir ppf = function `TopToBottom -> fprintf ppf "TB" | `LeftToRight -> fprintf ppf "LR" (** The [ATTRIBUTES] module type defines the interface for the engines. *) module type ATTRIBUTES = sig type graph (** Attributes of graphs. *) type vertex (** Attributes of vertices. *) type edge (** Attributes of edges. *) (** Attributes of (optional) boxes around vertices. *) type subgraph = { sg_name : string; (** Box name. *) sg_attributes : vertex list; (** Box attributes. *) } end (** The [CommonAttributes] module defines attributes for graphs, nodes and edges that are available in the two engines, dot and neato. *) module CommonAttributes = struct (** Attributes of graphs. *) type graph = [ `Center of bool (** Centers the drawing on the page. Default value is [false]. *) | `Fontcolor of color (** Sets the font color. Default value is [black]. *) | `Fontname of string (** Sets the font family name. Default value is ["Times-Roman"]. *) | `Fontsize of int (** Sets the type size (in points). Default value is [14]. *) | `Label of string (** Caption for graph drawing. *) | `Orientation of [ `Portrait | `Landscape ] (** Sets the page orientation. Default value is [`Portrait]. *) | `Page of float * float (** Sets the PostScript pagination unit, e.g [8.5, 11.0]. *) | `Pagedir of [ `TopToBottom | `LeftToRight ] (** Traversal order of pages. Default value is [`TopToBottom]. *) | `Size of float * float (** Sets the bounding box of drawing (in inches). *) | `OrderingOut (** Constrains order of out-edges in a subgraph according to their file sequence *) ] (** Attributes of nodes. *) type vertex = [ `Color of color (** Sets the color of the border of the node. Default value is [black] *) | `ColorWithTransparency of color_with_transparency (** Sets the color of the border of the vertex with a transparency component. Default value is fully opaque [black] *) | `Fontcolor of color (** Sets the label font color. Default value is [black]. *) | `Fontname of string (** Sets the label font family name. Default value is ["Times-Roman"]. *) | `Fontsize of int (** Sets the label type size (in points). Default value is [14]. *) | `Height of float (** Sets the minimum height. Default value is [0.5]. *) | `Label of string (** Sets the label printed in the node. The string may include escaped newlines [\n], [\l], or [\r] for center, left, and right justified lines. Record labels may contain recursive box lists delimited by { | }. *) | `Orientation of float (** Node rotation angle, in degrees. Default value is [0.0]. *) | `Peripheries of int (** Sets the number of periphery lines drawn around the polygon. *) | `Regular of bool (** If [true], then the polygon is made regular, i.e. symmetric about the x and y axis, otherwise the polygon takes on the aspect ratio of the label. Default value is [false]. *) | `Shape of [`Ellipse | `Box | `Circle | `Doublecircle | `Diamond | `Plaintext | `Record | `Polygon of int * float] (** Sets the shape of the node. Default value is [`Ellipse]. [`Polygon (i, f)] draws a polygon with [n] sides and a skewing of [f]. *) | `Style of [ `Filled | `Solid | `Dashed | `Dotted | `Bold | `Invis ] (** Sets the layout style of the node. Several styles may be combined simultaneously. *) | `Width of float (** Sets the minimum width. Default value is [0.75]. *) ] (** Attributes of edges. *) type edge = [ `Color of color (** Sets the edge stroke color. Default value is [black]. *) | `ColorWithTransparency of color_with_transparency (** Sets the color of the border of the vertex with a transparency component. Default value is fully opaque [black] *) | `Decorate of bool (** If [true], draws a line connecting labels with their edges. *) | `Dir of [ `Forward | `Back | `Both | `None ] (** Sets arrow direction. Default value is [`Forward]. *) | `Fontcolor of color (** Sets the label font color. Default value is [black]. *) | `Fontname of string (** Sets the label font family name. Default value is ["Times-Roman"]. *) | `Fontsize of int (** Sets the label type size (in points). Default value is [14]. *) | `Label of string (** Sets the label to be attached to the edge. The string may include escaped newlines [\n], [\l], or [\r] for centered, left, or right justified lines. *) | `Labelfontcolor of color (** Sets the font color for head and tail labels. Default value is [black]. *) | `Labelfontname of string (** Sets the font family name for head and tail labels. Default value is ["Times-Roman"]. *) | `Labelfontsize of int (** Sets the font size for head and tail labels (in points). Default value is [14]. *) | `Style of [ `Solid | `Dashed | `Dotted | `Bold | `Invis ] (** Sets the layout style of the edge. Several styles may be combined simultaneously. *) ] (** Pretty-print. *) let fprint_orientation ppf = function `Portrait -> fprintf ppf "portrait" | `Landscape -> fprintf ppf "landscape" let fprint_graph ppf = function `Center b -> fprintf ppf "center=%i" (if b then 1 else 0) | `Fontcolor a -> fprintf ppf "fontcolor=%a" fprint_color a | `Fontname s -> fprintf ppf "fontname=%a" fprint_string s | `Fontsize i -> fprintf ppf "fontsize=%i" i | `Label s -> fprintf ppf "label=%a" fprint_string_user s | `Orientation a -> fprintf ppf "orientation=%a" fprint_orientation a | `Page (x, y) -> fprintf ppf "page=\"%f,%f\"" x y | `Pagedir a -> fprintf ppf "pagedir=%a" fprint_dir a | `Size (x, y) -> fprintf ppf "size=\"%f,%f\"" x y | `OrderingOut -> fprintf ppf "ordering=out" let fprint_shape ppf = function | `Ellipse -> fprintf ppf "ellipse" | `Box -> fprintf ppf "box" | `Circle -> fprintf ppf "circle" | `Doublecircle -> fprintf ppf "doublecircle" | `Diamond -> fprintf ppf "diamond" | `Plaintext -> fprintf ppf "plaintext" | `Record -> fprintf ppf "record" | `Polygon (i, f) -> fprintf ppf "polygon, sides=%i, skew=%f" i f let fprint_node_style ppf = function `Filled -> fprintf ppf "filled" | `Solid -> fprintf ppf "solid" | `Dashed -> fprintf ppf "dashed" | `Dotted -> fprintf ppf "dotted" | `Bold -> fprintf ppf "bold" | `Invis -> fprintf ppf "invis" let fprint_vertex ppf = function | `Color a -> fprintf ppf "color=%a" fprint_color a | `ColorWithTransparency a -> fprintf ppf "color=%a" fprint_color_with_transparency a | `Fontcolor a -> fprintf ppf "fontcolor=%a" fprint_color a | `Fontname s -> fprintf ppf "fontname=%a" fprint_string s | `Fontsize i -> fprintf ppf "fontsize=%i" i | `Height f -> fprintf ppf "height=%f" f | `Label s -> fprintf ppf "label=%a" fprint_string_user s | `Orientation f -> fprintf ppf "orientation=%f" f | `Peripheries i -> fprintf ppf "peripheries=%i" i | `Regular b -> fprintf ppf "regular=%b" b | `Shape a -> fprintf ppf "shape=%a" fprint_shape a | `Style a -> fprintf ppf "style=%a" fprint_node_style a | `Width f -> fprintf ppf "width=%f" f let fprint_edge_style = fprint_node_style let fprint_arrow_direction ppf = function `Forward -> fprintf ppf "forward" | `Back -> fprintf ppf "back" | `Both -> fprintf ppf "both" | `None -> fprintf ppf "none" let fprint_edge ppf = function | `Color a -> fprintf ppf "color=%a" fprint_color a | `ColorWithTransparency a -> fprintf ppf "color=%a" fprint_color_with_transparency a | `Decorate b -> fprintf ppf "decorate=%b" b | `Dir a -> fprintf ppf "dir=%a" fprint_arrow_direction a | `Fontcolor a -> fprintf ppf "fontcolor=%a" fprint_color a | `Fontname s -> fprintf ppf "fontname=%a" fprint_string s | `Fontsize i -> fprintf ppf "fontsize=%i" i | `Label s -> fprintf ppf "label=%a" fprint_string_user s | `Labelfontcolor a -> fprintf ppf "labelfontcolor=%a" fprint_color a | `Labelfontname s -> fprintf ppf "labelfontname=\"%s\"" s (* (String.escaped s) *) | `Labelfontsize i -> fprintf ppf "labelfontsize=%i" i | `Style a -> fprintf ppf "style=%a" fprint_edge_style a end (*-------------------------------------------------------------------------*) (** {3 The [MakeEngine] functor} *) (** An engine is described by a module of the following signature. *) module type ENGINE = sig module Attributes : sig include ATTRIBUTES val fprint_graph:formatter -> graph -> unit val fprint_vertex: formatter -> vertex -> unit val fprint_edge: formatter -> edge -> unit end (** The litteral name of the engine. *) val name: string (** The keyword for graphs ("digraph" for dot, "graph" for neato) *) val opening: string (** The litteral for edge arrows ("->" for dot, "--" for neato) *) val edge_arrow: string end module type GRAPH = sig end module MakeEngine (EN: ENGINE) (X : sig type t module V : sig type t end module E : sig type t val src : t -> V.t val dst : t -> V.t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit val graph_attributes: t -> EN.Attributes.graph list val default_vertex_attributes: t -> EN.Attributes.vertex list val vertex_name : V.t -> string val vertex_attributes: V.t -> EN.Attributes.vertex list val default_edge_attributes: t -> EN.Attributes.edge list val edge_attributes: E.t -> EN.Attributes.edge list val get_subgraph : V.t -> EN.Attributes.subgraph option end) = struct let command = ref EN.name let set_command cmd = command := cmd exception Error of string let handle_error f arg = try f arg with Error msg -> Printf.eprintf "%s: %s failure\n %s\n" Sys.argv.(0) EN.name msg; flush stderr; exit 2 (** [fprint_graph_attributes ppf list] pretty prints a list of graph attributes on the formatter [ppf]. Attributes are separated by a ";". *) let fprint_graph_attributes ppf list = List.iter (function att -> fprintf ppf "%a;@ " EN.Attributes.fprint_graph att ) list (** [fprint_graph_attribute printer ppf list] pretty prints a list of attributes on the formatter [ppf], using the printer [printer] for each attribute. The list appears between brackets and attributes are speparated by ",". If the list is empty, nothing is printed. *) let fprint_attributes fprint_attribute ppf = function [] -> () | hd :: tl -> let rec fprint_attributes_rec ppf = function [] -> () | hd' :: tl' -> fprintf ppf ",@ %a%a" fprint_attribute hd' fprint_attributes_rec tl' in fprintf ppf " [@[%a%a@]]" fprint_attribute hd fprint_attributes_rec tl (** [fprint_graph_attributes ppf list] pretty prints a list of node attributes using the format of [fprint_attributes]. *) let fprint_node_attributes ppf list = fprint_attributes EN.Attributes.fprint_vertex ppf list (** [fprint_graph_attributes ppf list] pretty prints a list of edge attributes using the format of [fprint_attributes]. *) let fprint_edge_attributes ppf list = fprint_attributes EN.Attributes.fprint_edge ppf list (** [fprint_graph ppf graph] pretty prints the graph [graph] in the CGL language on the formatter [ppf]. *) let fprint_graph ppf graph = let subgraphs = Hashtbl.create 7 in (* Printing nodes. *) let print_nodes ppf = let default_node_attributes = X.default_vertex_attributes graph in if default_node_attributes <> [] then fprintf ppf "node%a;@ " fprint_node_attributes default_node_attributes; X.iter_vertex (function node -> begin match X.get_subgraph node with | None -> () | Some sg -> try let (sg,nodes) = Hashtbl.find subgraphs sg.EN.Attributes.sg_name in Hashtbl.replace subgraphs sg.EN.Attributes.sg_name (sg,node::nodes) with Not_found -> Hashtbl.add subgraphs sg.EN.Attributes.sg_name (sg,[node]) end; fprintf ppf "%s%a;@ " (X.vertex_name node) fprint_node_attributes (X.vertex_attributes node)) graph in (* Printing subgraphs *) let print_subgraphs ppf = Hashtbl.iter (fun name (sg,nodes) -> fprintf ppf "@[subgraph cluster_%s { %t%t };@]@\n" name (fun ppf -> (List.iter (fun n -> fprintf ppf "%a;@\n" EN.Attributes.fprint_vertex n) sg.EN.Attributes.sg_attributes)) (fun ppf -> (List.iter (fun n -> fprintf ppf "%s;" (X.vertex_name n)) nodes)) ) subgraphs in (* Printing edges *) let print_edges ppf = let default_edge_attributes = X.default_edge_attributes graph in if default_edge_attributes <> [] then fprintf ppf "edge%a;@ " fprint_edge_attributes default_edge_attributes; X.iter_edges_e (function edge -> fprintf ppf "%s %s %s%a;@ " (X.vertex_name (X.E.src edge)) EN.edge_arrow (X.vertex_name (X.E.dst edge)) fprint_edge_attributes (X.edge_attributes edge) ) graph in fprintf ppf "@[%s G {@ @[ %a" EN.opening fprint_graph_attributes (X.graph_attributes graph); fprintf ppf "%t@ " print_nodes; fprintf ppf "%t@ " print_subgraphs; fprintf ppf "%t@ " print_edges; fprintf ppf "@]}@]" (** [output_graph oc graph] pretty prints the graph [graph] in the dot language on the channel [oc]. *) let output_graph oc graph = let ppf = formatter_of_out_channel oc in fprint_graph ppf graph; pp_print_flush ppf () end (***************************************************************************) (** {2 Interface with the dot engine} *) (** The [DotAttributes] module defines attributes for graphs, nodes and edges that are available in the dot engine. *) module DotAttributes = struct (** Attributes of graphs. They include all common graph attributes and several specific ones. All attributes described in the "dot User's Manual, February 4, 2002" are handled, excepted: clusterank, color, compound, labeljust, labelloc, ordering, rank, remincross, rotate, searchsize and style. *) type graph = [ CommonAttributes.graph | `Bgcolor of color (** Sets the background color and the inital fill color. *) | `BgcolorWithTransparency of color_with_transparency (** Sets the background color and the inital fill color with a transparency component. *) | `Comment of string (** Comment string. *) | `Concentrate of bool (** If [true], enables edge concentrators. Default value is [false]. *) | `Fontpath of string (** List of directories for fonts. *) | `Layers of string list (** List of layers. *) | `Margin of float (** Sets the page margin (included in the page size). Default value is [0.5]. *) | `Mclimit of float (** Scale factor for mincross iterations. Default value is [1.0]. *) | `Nodesep of float (** Sets the minimum separation between nodes, in inches. Default value is [0.25]. *) | `Nslimit of int (** If set of [f], bounds network simplex iterations by [f * ] when ranking nodes. *) | `Nslimit1 of int (** If set of [f], bounds network simplex iterations by [f * ] when setting x-coordinates. *) | `Ranksep of float (** Sets the minimum separation between ranks. *) | `Quantum of float (** If not [0.0], node label dimensions will be rounded to integral multiples of it. Default value is [0.0]. *) | `Rankdir of [ `TopToBottom | `LeftToRight ] (** Direction of rank ordering. Default value is [`TopToBottom]. *) | `Ratio of [ `Float of float | `Fill | `Compress| `Auto ] (** Sets the aspect ratio. *) | `Samplepoints of int (** Number of points used to represent ellipses and circles on output. Default value is [8]. *) | `Url of string (** URL associated with graph (format-dependent). *) ] (** Attributes of nodes. They include all common node attributes and several specific ones. All attributes described in the "dot User's Manual, February 4, 2002" are handled, excepted: bottomlabel, group, shapefile and toplabel. *) type vertex = [ CommonAttributes.vertex | `Comment of string (** Comment string. *) | `Distortion of float (* TEMPORARY *) | `Fillcolor of color (** Sets the fill color (used when `Style filled). Default value is [lightgrey]. *) | `FillcolorWithTransparency of color_with_transparency (** Sets the fill color (used when `Style filled) with a transparency component. Default value is fully opaque [lightgrey]. *) | `Fixedsize of bool (** If [true], forces the given dimensions to be the actual ones. Default value is [false]. *) | `Layer of string (** Overlay. *) | `Url of string (** The default url for image map files; in PostScript files, the base URL for all relative URLs, as recognized by Acrobat Distiller 3.0 and up. *) | `Z of float (** z coordinate for VRML output. *) ] (** Attributes of edges. They include all common edge attributes and several specific ones. All attributes described in the "dot User's Manual, February 4, 2002" are handled, excepted: lhead and ltail. *) type edge = [ CommonAttributes.edge | `Arrowhead of arrow_style (** Sets the style of the head arrow. Default value is [`Normal]. *) | `Arrowsize of float (** Sets the scaling factor of arrowheads. Default value is [1.0]. *) | `Arrowtail of arrow_style (** Sets the style of the tail arrow. Default value is [`Normal]. *) | `Comment of string (** Comment string. *) | `Constraint of bool (** If [false], causes an edge to be ignored for rank assignment. Default value is [true]. *) | `Headlabel of string (** Sets the label attached to the head arrow. *) | `Headport of [ `N | `NE | `E | `SE | `S | `SW | `W | `NW ] (* TEMPORARY *) | `Headurl of string (** Url attached to head label if output format is ismap. *) | `Labelangle of float (** Angle in degrees which head or tail label is rotated off edge. Default value is [-25.0]. *) | `Labeldistance of float (** Scaling factor for distance of head or tail label from node. Default value is [1.0]. *) | `Labelfloat of bool (** If [true], lessen constraints on edge label placement. Default value is [false]. *) | `Layer of string (** Overlay. *) | `Minlen of int (** Minimum rank distance between head an tail. Default value is [1]. *) | `Samehead of string (** Tag for head node; edge heads with the same tag are merged onto the same port. *) | `Sametail of string (** Tag for tail node; edge tails with the same tag are merged onto the same port. *) | `Taillabel of string (** Sets the label attached to the tail arrow. *) | `Tailport of [ `N | `NE | `E | `SE | `S | `SW | `W | `NW ] (* TEMPORARY *) | `Tailurl of string (** Url attached to tail label if output format is ismap. *) | `Weight of int (** Sets the integer cost of stretching the edge. Default value is [1]. *) ] type subgraph = { sg_name : string; sg_attributes : vertex list; } (** {4 Pretty-print of attributes} *) let rec fprint_string_list ppf = function [] -> () | [hd] -> fprintf ppf "%s" hd | hd :: tl -> fprintf ppf "%s,%a" hd fprint_string_list tl let fprint_ratio ppf = function `Float f -> fprintf ppf "%f" f | `Fill -> fprintf ppf "fill" | `Compress -> fprintf ppf "compress" | `Auto -> fprintf ppf "auto" let fprint_graph ppf = function #CommonAttributes.graph as att -> CommonAttributes.fprint_graph ppf att | `Bgcolor a -> fprintf ppf "bgcolor=%a" fprint_color a | `BgcolorWithTransparency a -> fprintf ppf "bcolor=%a" fprint_color_with_transparency a | `Comment s -> fprintf ppf "comment=%a" fprint_string s | `Concentrate b -> fprintf ppf "concentrate=%b" b | `Fontpath s -> fprintf ppf "fontpath=%a" fprint_string s | `Layers s -> fprintf ppf "layers=%a" fprint_string_list s | `Margin f -> fprintf ppf "margin=%f" f | `Mclimit f -> fprintf ppf "mclimit=%f" f | `Nodesep f -> fprintf ppf "nodesep=%f" f | `Nslimit i -> fprintf ppf "nslimit=%i" i | `Nslimit1 i -> fprintf ppf "nslimit1=%i" i | `Ranksep f -> fprintf ppf "ranksep=%f" f | `Quantum f -> fprintf ppf "quantum=%f" f | `Rankdir a -> fprintf ppf "rankdir=%a" fprint_dir a | `Ratio a -> fprintf ppf "ratio=%a" fprint_ratio a | `Samplepoints i -> fprintf ppf "samplepoints=%i" i | `Url s -> fprintf ppf "URL=\"%s\"" s (*(String.escaped s)*) let fprint_vertex ppf = function #CommonAttributes.vertex as att -> CommonAttributes.fprint_vertex ppf att | `Comment s -> fprintf ppf "comment=%a" fprint_string s | `Distortion f -> fprintf ppf "distortion=%f" f | `Fillcolor a -> fprintf ppf "fillcolor=%a" fprint_color a | `FillcolorWithTransparency a -> fprintf ppf "fillcolor=%a" fprint_color_with_transparency a | `Fixedsize b -> fprintf ppf "fixedsize=%b" b | `Layer s -> fprintf ppf "layer=%a" fprint_string s | `Url s -> fprintf ppf "URL=\"%s\"" s (*(String.escaped s)*) | `Z f -> fprintf ppf "z=%f" f let fprint_port ppf = function `N -> fprintf ppf "n" | `NE -> fprintf ppf "ne" | `E -> fprintf ppf "e" | `SE -> fprintf ppf "se" | `S -> fprintf ppf "s" | `SW -> fprintf ppf "sw" | `W -> fprintf ppf "w" | `NW -> fprintf ppf "nw" let fprint_edge ppf = function #CommonAttributes.edge as att -> CommonAttributes.fprint_edge ppf att | `Arrowhead a -> fprintf ppf "arrowhead=%a" fprint_arrow_style a | `Arrowsize f -> fprintf ppf "arrowsize=%f" f | `Arrowtail a -> fprintf ppf "arrowtail=%a" fprint_arrow_style a | `Comment s -> fprintf ppf "comment=%a" fprint_string s | `Constraint b -> fprintf ppf "constraint=%b" b | `Headlabel s -> fprintf ppf "headlabel=%a" fprint_string s | `Headport a -> fprintf ppf "headport=%a" fprint_port a | `Headurl s -> fprintf ppf "headURL=%a" fprint_string s | `Labelangle f -> fprintf ppf "labelangle=%f" f | `Labeldistance f -> fprintf ppf "labeldistance=%f" f | `Labelfloat b -> fprintf ppf "labelfloat=%b" b | `Layer s -> fprintf ppf "layer=%a" fprint_string s | `Minlen i -> fprintf ppf "minlen=%i" i | `Samehead s -> fprintf ppf "samehead=%a" fprint_string s | `Sametail s -> fprintf ppf "sametail=%a" fprint_string s | `Taillabel s -> fprintf ppf "taillabel=%a" fprint_string s | `Tailport a -> fprintf ppf "tailport=%a" fprint_port a | `Tailurl s -> fprintf ppf "tailURL=%a" fprint_string s | `Weight i -> fprintf ppf "weight=%i" i end (** Graph modules with dot attributes *) module type GraphWithDotAttrs = sig include Sig.G (** Graph, vertex and edge attributes. *) val graph_attributes: t -> DotAttributes.graph list (** Vertex attributes *) val default_vertex_attributes: t -> DotAttributes.vertex list val vertex_name : V.t -> string val vertex_attributes: V.t -> DotAttributes.vertex list (** Edge attributes *) val default_edge_attributes: t -> DotAttributes.edge list val edge_attributes: E.t -> DotAttributes.edge list val get_subgraph : V.t -> DotAttributes.subgraph option (** The box (if exists) which the vertex belongs to. Boxes with same names are not distinguished and so they should have the same attributes. *) end module Dot = MakeEngine (struct module Attributes = DotAttributes let name = "dot" let opening = "digraph" let edge_arrow = "->" end) (***************************************************************************) (** {2 Interface with the neato engine} *) (** The [NeatoAttributes] module defines attributes for graphs, nodes and edges that are available in the neato engine. *) module NeatoAttributes = struct (** Attributes of graphs. They include all common graph attributes and several specific ones. All attributes described in the "Neato User's manual, April 10, 2002" are handled. *) type graph = [ CommonAttributes.graph | `Margin of float * float (** Sets the page margin (included in the page size). Default value is [0.5, 0.5]. *) | `Start of int (** Seed for random number generator. *) | `Overlap of bool (** Default value is [true]. *) | `Spline of bool (** [true] makes edge splines if nodes don't overlap. Default value is [false]. *) | `Sep of float (** Edge spline separation factor from nodes. Default value is [0.0]. *) ] (** Attributes of nodes. They include all common node attributes and several specific ones. All attributes described in the "Neato User's manual, April 10, 2002" are handled. *) type vertex = [ CommonAttributes.vertex | `Pos of float * float (** Initial coordinates of the node. *) ] (** Attributes of edges. They include all common edge attributes and several specific ones. All attributes described in the "Neato User's manual, April 10, 2002" are handled. *) type edge = [ CommonAttributes.edge | `Id of string (** Optional value to distinguish multiple edges. *) | `Len of float (** Preferred length of edge. Default value is [1.0]. *) | `Weight of float (** Strength of edge spring. Default value is [1.0]. *) ] type subgraph = { sg_name : string; sg_attributes : vertex list; } (** {4 Pretty-print of attributes} *) let fprint_graph ppf = function #CommonAttributes.graph as att -> CommonAttributes.fprint_graph ppf att | `Margin (f1, f2) -> fprintf ppf "margin=\"%f,%f\"" f1 f2 | `Start i -> fprintf ppf "start=%i" i | `Overlap b -> fprintf ppf "overlap=%b" b | `Spline b -> fprintf ppf "spline=%b" b | `Sep f -> fprintf ppf "sep=%f" f let fprint_vertex ppf = function #CommonAttributes.vertex as att -> CommonAttributes.fprint_vertex ppf att | `Pos (f1, f2) -> fprintf ppf "pos=\"%f,%f\"" f1 f2 let fprint_edge ppf = function #CommonAttributes.edge as att -> CommonAttributes.fprint_edge ppf att | `Id s -> fprintf ppf "id=%a" fprint_string s | `Len f -> fprintf ppf "len=%f" f | `Weight f -> fprintf ppf "weight=%f" f end module Neato = MakeEngine (struct module Attributes = NeatoAttributes let name = "neato" let opening = "graph" let edge_arrow = "--" end) (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-1.8.3/src/path.ml0000644000175000017500000001536312133565071014666 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: path.ml,v 1.6 2005-07-18 07:10:35 filliatr Exp $ *) module type WEIGHT = sig type label type t val weight : label -> t val compare : t -> t -> int val add : t -> t -> t val zero : t end module type G = sig type t module V : Sig.COMPARABLE module E : sig type t type label val label : t -> label val src : t -> V.t val dst : t -> V.t end val iter_vertex : (V.t -> unit) -> t -> unit val iter_succ : (V.t -> unit) -> t -> V.t -> unit val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a val nb_vertex : t -> int end module Dijkstra (G: G) (W: WEIGHT with type label = G.E.label) = struct open G.E module H = Hashtbl.Make(G.V) module Elt = struct type t = W.t * G.V.t * G.E.t list (* weights are compared first, and minimal weights come first in the queue *) let compare (w1,v1,_) (w2,v2,_) = let cw = W.compare w2 w1 in if cw != 0 then cw else G.V.compare v1 v2 end module PQ = Heap.Imperative(Elt) let shortest_path g v1 v2 = let visited = H.create 97 in let dist = H.create 97 in let q = PQ.create 17 in let rec loop () = if PQ.is_empty q then raise Not_found; let (w,v,p) = PQ.pop_maximum q in if G.V.compare v v2 = 0 then List.rev p, w else begin if not (H.mem visited v) then begin H.add visited v (); G.iter_succ_e (fun e -> let ev = dst e in if not (H.mem visited ev) then begin let dev = W.add w (W.weight (label e)) in let improvement = try W.compare dev (H.find dist ev) < 0 with Not_found -> true in if improvement then begin H.replace dist ev dev; PQ.add q (dev, ev, e :: p) end end) g v end; loop () end in PQ.add q (W.zero, v1, []); H.add dist v1 W.zero; loop () end (* The following module is a contribution of Yuto Takei (University of Tokyo) *) module BellmanFord (G: G) (W: WEIGHT with type label = G.E.label) = struct open G.E module H = Hashtbl.Make(G.V) exception NegativeCycle of G.E.t list let all_shortest_paths g vs = let dist = H.create 97 in H.add dist vs W.zero; let admissible = H.create 97 in let build_cycle_from x0 = let rec traverse_parent x ret = let e = H.find admissible x in let s = src e in if G.V.equal s x0 then e :: ret else traverse_parent s (e :: ret) in traverse_parent x0 [] in let find_cycle x0 = let visited = H.create 97 in let rec visit x = if H.mem visited x then build_cycle_from x else begin H.add visited x (); let e = H.find admissible x in visit (src e) end in visit x0 in let rec relax i = let update = G.fold_edges_e (fun e x -> let ev1 = src e in let ev2 = dst e in try begin let dev1 = H.find dist ev1 in let dev2 = W.add dev1 (W.weight (label e)) in let improvement = try W.compare dev2 (H.find dist ev2) < 0 with Not_found -> true in if improvement then begin H.replace dist ev2 dev2; H.replace admissible ev2 e; Some ev2 end else x end with Not_found -> x) g None in match update with | Some x -> if i == G.nb_vertex g then raise (NegativeCycle (find_cycle x)) else relax (i + 1) | None -> dist in relax 0 let find_negative_cycle_from g vs = try let _ = all_shortest_paths g vs in raise Not_found with NegativeCycle l -> l module Comp = Components.Make(G) (* This is rather inefficient implementation. Indeed, for each strongly connected component, we run a full Bellman-Ford algorithm using one of its vertex as source, taking all edges into consideration. Instead, we could limit ourselves to the edges of the component. *) let find_negative_cycle g = let rec iter = function | [] -> raise Not_found | (x :: _) :: cl -> begin try find_negative_cycle_from g x with Not_found -> iter cl end | [] :: _ -> assert false (* a component is not empty *) in iter (Comp.scc_list g) end module Check (G : sig type t module V : Sig.COMPARABLE val iter_succ : (V.t -> unit) -> t -> V.t -> unit end) = struct module HV = Hashtbl.Make(G.V) module HVV = Hashtbl.Make(Util.HTProduct(G.V)(G.V)) (* the cache contains the path tests already computed *) type path_checker = { cache : bool HVV.t; graph : G.t } let create g = { cache = HVV.create 97; graph = g } let check_path pc v1 v2 = try HVV.find pc.cache (v1, v2) with Not_found -> (* the path is not in cache; we check it with Dijkstra *) let visited = HV.create 97 in let q = Queue.create () in let rec loop () = if Queue.is_empty q then begin HVV.add pc.cache (v1, v2) false; false end else begin let v = Queue.pop q in HVV.add pc.cache (v1, v) true; if G.V.compare v v2 = 0 then true else begin if not (HV.mem visited v) then begin HV.add visited v (); G.iter_succ (fun v' -> Queue.add v' q) pc.graph v end; loop () end end in Queue.add v1 q; loop () end ocamlgraph-1.8.3/src/mcs_m.ml0000644000175000017500000001246512133565071015030 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: mcs_m.mli,v 1.2 2004-10-19 15:21:44 signoles Exp $ *) module MaximalCardinalitySearch = struct module WeightedV(V : Sig.COMPARABLE) = struct include Util.DataV(struct type t = int end)(V) let weight = data let set_weight = set_data end module P(Gr : Sig.P) = struct type edgelist = (Gr.V.t * Gr.V.t) list module NewV = WeightedV(Gr.V) module G = Persistent.Graph.Concrete(NewV) module EdgeSet = Set.Make(G.E) module VerticesSet = Set.Make(NewV) module Choose = Oper.Choose(G) module H = Hashtbl.Make(NewV) exception Found let check_path g u v = let h = H.create 97 in let maxw = NewV.weight u in let rec aux x : bool = if H.mem h x then false else if x = v then true else if NewV.weight x < maxw || x = u then begin H.add h x (); G.fold_succ (fun x found -> if not found then aux x else found) g x false end else (H.add h x (); false) in aux u module Copy = Gmap.Vertex(Gr)(struct include G include Builder.P(G) end) let fold f d = let rec aux = function (true, a) -> aux (f a) | (false, a) -> a in aux d let mcsm g = let g' = Copy.map (NewV.create 0) g in let (_, _, ord, triang) = fold (fun ((i, g', a, f) as x)-> if i = 0 then (false, x) else let v = G.fold_vertex (fun x max -> if NewV.weight x > NewV.weight max then x else max) g' (ref 0, snd (Choose.choose_vertex g')) in let s = G.fold_vertex (fun x s -> if x = v then s else if check_path g' x v then VerticesSet.add x s else s) g' VerticesSet.empty in let f' = VerticesSet.fold (fun x f -> NewV.set_weight x (succ (NewV.weight x)); if not (G.mem_edge g' x v) then EdgeSet.add (x,v) f else f) s f in let g' = G.remove_vertex g' v in let a' = (i, NewV.label v) :: a in (true, (i - 1, g', a', f'))) (true, (Gr.nb_vertex g, g', [], EdgeSet.empty)) in (List.rev ord, EdgeSet.fold (fun (x, y) e -> (NewV.label x, NewV.label y) :: e) triang []) let triangulate g = let (_, triang) = mcsm g in List.fold_left (fun g (x, y) -> Gr.add_edge g x y) g triang end module I(Gr : Sig.I) = struct type edgelist = (Gr.V.t * Gr.V.t) list module NewV = WeightedV(Gr.V) module G = Imperative.Graph.Concrete(NewV) module EdgeSet = Set.Make(G.E) module VerticesSet = Set.Make(NewV) module Choose = Oper.Choose(G) module H = Hashtbl.Make(NewV) exception Found let check_path g u v = let h = H.create 97 in let maxw = NewV.weight u in let rec aux x : bool = if H.mem h x then false else if x = v then true else if NewV.weight x < maxw || x = u then begin H.add h x (); G.fold_succ (fun x found -> if not found then aux x else found) g x false end else (H.add h x (); false) in aux u module Copy = Gmap.Vertex(Gr)(struct include G include Builder.I(G) end) let mcsm g = let f = ref EdgeSet.empty and a = ref [] and g' = Copy.map (NewV.create 0) g in for i = Gr.nb_vertex g downto 1 do let v = G.fold_vertex (fun x max -> if NewV.weight x > NewV.weight max then x else max) g' (ref 0, snd (Choose.choose_vertex g')) in let s = G.fold_vertex (fun x s -> if x = v then s else if check_path g' x v then VerticesSet.add x s else s) g' VerticesSet.empty in let f' = VerticesSet.fold (fun x f -> NewV.set_weight x (succ (NewV.weight x)); if not (G.mem_edge g' x v) then EdgeSet.add (x,v) f else f) s !f in f := f'; G.remove_vertex g' v; a := (i, NewV.label v) :: !a; done; (List.rev !a, EdgeSet.fold (fun (x, y) e -> (NewV.label x, NewV.label y) :: e) !f []) let triangulate g = let (_, triang) = mcsm g in List.iter (fun (x, y) -> Gr.add_edge g x y) triang end end ocamlgraph-1.8.3/src/util.ml0000644000175000017500000000414112133565071014677 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Sig module OTProduct(X: ORDERED_TYPE)(Y: ORDERED_TYPE) = struct type t = X.t * Y.t let compare (x1, y1) (x2, y2) = let cv = X.compare x1 x2 in if cv != 0 then cv else Y.compare y1 y2 end module HTProduct(X: HASHABLE)(Y: HASHABLE) = struct type t = X.t * Y.t let equal (x1, y1) (x2, y2) = X.equal x1 x2 && Y.equal y1 y2 let hash (x, y) = Hashtbl.hash (X.hash x, Y.hash y) end module CMPProduct(X: COMPARABLE)(Y: COMPARABLE) = struct include HTProduct(X)(Y) include (OTProduct(X)(Y): sig val compare : t -> t -> int end) end module DataV(L : sig type t end)(V : Sig.COMPARABLE) = struct type data = L.t type label = V.t type t = data ref * V.t let compare (_, x) (_, x') = V.compare x x' let hash (_, x) = V.hash x let equal (_, x) (_, x') = V.equal x x' let create y lbl = (ref y, lbl) let label (_, z) = z let data (y, _) = !y let set_data (y, _) = (:=) y end ocamlgraph-1.8.3/src/strat.mli0000644000175000017500000000716712133565071015243 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Strategies Implementation of a winning strategy of a graph: the graph represents a two players game, each vertex belongs to either player (whose turn it is to play) and describes a configuration of the game. The algorithm computes the winning strategy of a player, if any; i.e. the moves to play (which vertex to go to) so that for all possible moves of the other player, the game goes through a final state. @author Nicolas Ayache *) (** Signature for graphs *) module type G = sig type t module V : Sig.ORDERED_TYPE type vertex = V.t val mem_vertex : t -> vertex -> bool val succ : t -> vertex -> vertex list val fold_vertex : (vertex -> 'a -> 'a) -> t -> 'a -> 'a val fold_succ : (vertex -> 'a -> 'a) -> t -> vertex -> 'a -> 'a end (** Signature for graph add-ons: an initial vertex, final vertices and membership of vertices to either true or false, i.e. first or second player *) module type PLAYER = sig type t type vertex val get_initial : t -> vertex val is_final : t -> vertex -> bool val turn : t -> vertex -> bool end (** Signature for strategies: for a given state, the strategy tells which state to go to *) module type STRAT = sig type t type vertex val empty : t val add : t -> vertex -> vertex -> t val next : t -> vertex -> vertex (** @raise Invalid_argument if vertex's image is not defined *) end (** Implements strategy algorithms on graphs *) module Algo (G : G) (P : PLAYER with type vertex = G.vertex) (S : STRAT with type vertex = G.vertex) : sig (** [coherent_player g p] returns [true] iff the completion [p] is coherent w.r.t. the graph g *) val coherent_player : G.t -> P.t -> bool (** [coherent_strat g s] returns [true] iff the strategy [s] is coherent w.r.t. the graph [g] *) val coherent_strat : G.t -> S.t -> bool (** [game g p a b] returns [true] iff [a] wins in [g] given the completion [p] (i.e. the game goes through a final state). *) val game : G.t -> P.t -> S.t -> S.t -> bool (** [strategy g p s] returns [true] iff [s] wins in [g] given the completion [p], whatever strategy plays the other player. *) val strategy : G.t -> P.t -> S.t -> bool (** [strategyA g p] returns [true] iff there exists [a] winning stragegy for the true player. In this case, the winning strategy is provided. *) val strategyA : G.t -> P.t -> (bool * S.t) end ocamlgraph-1.8.3/src/rand.mli0000644000175000017500000001034512133565071015022 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id: rand.mli,v 1.12 2005-03-31 13:32:51 filliatr Exp $ *) (** Random graph generation. *) (** {2 Random graphs} *) module type S = sig type graph type vertex type edge_label val graph : ?loops:bool -> v:int -> e:int -> unit -> graph (** [graph v e] generates a random graph with exactly [v] vertices and [e] edges. Vertices are labeled with [0] ... [v-1]. The boolean [loops] indicates whether loops are allowed; default value is no loop ([false]). @raise Invalid_argument if [e] exceeds the maximal number of edges. *) val labeled : (vertex -> vertex -> edge_label) -> ?loops:bool -> v:int -> e:int -> unit -> graph (** [labeled f] is similar to [graph] except that edges are labeled using function [f]. @raise Invalid_argument if there are too many edges. *) (** The two functions above actually make a choice between two different implementations according to the ratio e/(v*v). When this ratio is small, [random_few_edges] is selected; otherwise [random_many_edges] is selected. *) val random_few_edges : loops:bool -> v:int -> e:int -> graph val random_many_edges : loops:bool -> v:int -> e:int -> graph end module Make(B: Builder.INT) : S with type graph = B.G.t and type vertex = B.G.V.t and type edge_label = B.G.E.label (** Random graphs *) module P (G : Sig.P with type V.label = int) : S with type graph = G.t and type vertex = G.V.t and type edge_label = G.E.label (** Random persistent graphs *) module I (G : Sig.I with type V.label = int) : S with type graph = G.t and type vertex = G.V.t and type edge_label = G.E.label (** Random imperative graphs *) (** {2 Random planar graphs} *) module Planar : sig module type S = sig type graph val graph : ?loops:bool -> xrange:int*int -> yrange:int*int -> prob:float -> int -> graph (** [graph xrange yrange prob v] generates a random planar graph with exactly [v] vertices. Vertices are labeled with integer coordinates, randomly distributed according to [xrange] and [yrange]. Edges are built as follows: the full Delaunay triangulation is constructed and then each edge is discarded with probabiblity [prob] (which should lie in [0..1]). In particular [prob = 0.0] gives the full triangulation. Edges are labeled with the (rounded) Euclidean distance between the two vertices. The boolean [loops] indicates whether loops are allowed; default value is no loop ([false]). *) end module Make (B : Builder.S with type G.V.label = int * int and type G.E.label = int) : S with type graph = B.G.t (** Random planar graphs *) module P (G : Sig.P with type V.label = int * int and type E.label = int) : S with type graph = G.t (** Random persistent planar graphs *) module I (G : Sig.I with type V.label = int * int and type E.label = int) : S with type graph = G.t (** Random imperative planar graphs *) end ocamlgraph-1.8.3/src/oper.mli0000644000175000017500000001120212133565071015034 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (** Basic operations over graphs *) (** {2 Basic operations over graphs} *) module type S = sig type g val transitive_closure : ?reflexive:bool -> g -> g (** [transitive_closure ?reflexive g] returns the transitive closure of [g] (as a new graph). Loops (i.e. edges from a vertex to itself) are added only if [reflexive] is [true] (default is [false]). *) val add_transitive_closure : ?reflexive:bool -> g -> g (** [add_transitive_closure ?reflexive g] replaces [g] by its transitive closure. Meaningless for persistent implementations (then acts as [transitive_closure]). *) val mirror : g -> g (** [mirror g] returns a new graph which is the mirror image of [g]: each edge from [u] to [v] has been replaced by an edge from [v] to [u]. For undirected graphs, it simply returns [g]. Note: Vertices are shared between [g] and [mirror g]; you may need to make a copy of [g] before using [mirror] *) val complement : g -> g (** [complement g] returns a new graph which is the complement of [g]: each edge present in [g] is not present in the resulting graph and vice-versa. Edges of the returned graph are unlabeled. *) val intersect : g -> g -> g (** [intersect g1 g2] returns a new graph which is the intersection of [g1] and [g2]: each vertex and edge present in [g1] *and* [g2] is present in the resulting graph. *) val union : g -> g -> g (** [union g1 g2] returns a new graph which is the union of [g1] and [g2]: each vertex and edge present in [g1] *or* [g2] is present in the resulting graph. *) end module Make(B : Builder.S) : S with type g = B.G.t (** Basic operations over graphs *) module P(G : Sig.P) : S with type g = G.t (** Basic operations over persistent graphs *) module I(G : Sig.I) : S with type g = G.t (** Basic operations over imperative graphs *) (** {2 Choose} *) (** Choose an element in a graph *) module Choose(G : sig type t type vertex type edge val iter_vertex : (vertex -> unit) -> t -> unit val iter_edges_e : (edge -> unit) -> t -> unit end) : sig val choose_vertex : G.t -> G.vertex (** [choose_vertex g] returns a vertex from the graph. @raise Invalid_argument if the graph is empty. *) val choose_edge : G.t -> G.edge (** [choose_edge g] returns an edge from the graph. @raise Invalid_argument if the graph has no edge. *) end (** {2 Neighbourhood} *) (** Neighbourhood of vertex / vertices *) module Neighbourhood(G : sig type t module V : Sig.COMPARABLE val fold_succ: (V.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a val succ: t -> V.t -> V.t list end) : sig module Vertex_Set : Set.S with type elt = G.V.t (** The neighbourhood of a vertex [v] is \{ v' | (succ g v) and (v <> v') \} *) val list_from_vertex : G.t -> G.V.t -> G.V.t list (** Neighbourhood of a vertex as a list. *) val set_from_vertex : G.t -> G.V.t -> Vertex_Set.t (** Neighbourhood of a vertex as a set. Less efficient that [list_from_vertex]. *) (** The neighbourhood of a set [S] of vertices is [U \ S] where [U] is the union of neighbourhoods of each vertex of [S]. *) val list_from_vertices : G.t -> G.V.t list -> G.V.t list (** Neighbourhood of a list of vertices as a list. *) val set_from_vertices : G.t -> G.V.t list -> Vertex_Set.t (** Neighbourhood of a list of vertices as a set. More efficient that [list_from_vertices]. *) end ocamlgraph-1.8.3/COPYING0000644000175000017500000000114112133565072013632 0ustar mehdimehdiOcamlgraph: a generic graph library for ocaml Copyright (C) 2004-2010 Sylvain Conchon, Jean-Christophe Filliâtre and Julien Signoles This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2.1, as published by the Free Software Foundation. This library 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 Library General Public License version 2.1 for more details (enclosed in the file LICENSE). ocamlgraph-1.8.3/LICENSE0000644000175000017500000006561612133565072013625 0ustar mehdimehdiThe Library is distributed under the terms of the GNU Library General Public License version 2.1 (included below). As a special exception to the GNU Library General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Library General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Library General Public License. ====================================================================== GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; 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; either version 2.1 of the License, or (at your option) any later version. This library 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. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! ocamlgraph-1.8.3/README0000644000175000017500000000640612133565071013467 0ustar mehdimehdi************************************************************************** * * * Ocamlgraph: a generic graph library for OCaml * * Copyright (C) 2004-2010 * * Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles * * * * This software is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License version 2.1, with the special exception on linking * * described in file LICENSE. * * * * This software 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. * * * ************************************************************************** Ocamlgraph is a graph library for Ocaml. Its contribution is three-fold: 1. It provides an easy-to-use graph implementation together with several operations and algorithms over graphs, in Graph.Pack.Digraph. It is a reasonably efficient imperative data structure for directed graphs with vertices and edges labeled with integers. Have a look at this module first in order to get an overview of what this library provides. See also `demo.ml'. 2. Then ocamlgraph provides several other graph implementations for those not satisfied with the one above. Some are persistent (imutable) and other imperative (mutable). Some are directed and other are not. Some have labels for vertices, or labels for edges, or both. Some have abstract types for vertices. etc. See interface Sig for the graph signatures and modules Persistent and Imperative for the implementations. These implementations are written as functors: you give the types of vertices labels, edge labels, etc. and you get the data structure as a result. 3. Finally, ocamlgraph provides several classic operations and algorithms over graphs. They are also written as functors i.e. independently of the data structure for graphs. One consequence is that you can define your own data structure for graphs and yet re-use all the algorithms from this library -- you only need to provide a few operations such as iterating over all vertices, over the successors of a vertex, etc. How to link with ocamlgraph --------------------------- ocamlgraph is packaged as a single module `Graph'. Link is done as follows: - bytecode ocamlc graph.cma - native code ocamlopt graph.cmxa Examples -------- You'll find examples of ocamlgraph use in demo.ml, demo_planar.ml and color.ml (you can compile these programs with "make demo.opt", "make demo_planar.opt" and "make color.opt" respectively). Bug reports ----------- Bug reports can be sent to Sylvain Conchon Jean-Christophe Filliatre Julien Signoles ocamlgraph-1.8.3/lib/0000755000175000017500000000000012133565071013347 5ustar mehdimehdiocamlgraph-1.8.3/lib/unionfind.mli0000644000175000017500000000346312133565071016051 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* Unionfind structure over hash-ordered types. This module implements a unionfind data structure, given a total ordering function and a hash function over the elements. *) module type HashedOrderedType = sig (* The type of the elements*) type t val equal : t -> t -> bool val hash : t -> int val compare : t -> t -> int end (* Input signature of the functor Unionfind.Make *) module type S = sig type elt type t val init : elt list -> t val find : elt -> t -> elt val union : elt -> elt -> t -> unit end module Make (X : HashedOrderedType) : S with type elt = X.t ocamlgraph-1.8.3/lib/heap.ml0000644000175000017500000001537312133565071014627 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id:$ *) module type Ordered = sig type t val compare : t -> t -> int end exception EmptyHeap (*s Imperative implementation *) module Imperative(X : Ordered) = struct (* The heap is encoded in the array [data], where elements are stored from [0] to [size - 1]. From an element stored at [i], the left (resp. right) subtree, if any, is rooted at [2*i+1] (resp. [2*i+2]). *) type t = { mutable size : int; mutable data : X.t array } (* When [create n] is called, we cannot allocate the array, since there is no known value of type [X.t]; we'll wait for the first addition to do it, and we remember this situation with a negative size. *) let create n = if n <= 0 then invalid_arg "create"; { size = -n; data = [||] } let is_empty h = h.size <= 0 (* [resize] doubles the size of [data] *) let resize h = let n = h.size in assert (n > 0); let n' = 2 * n in let d = h.data in let d' = Array.create n' d.(0) in Array.blit d 0 d' 0 n; h.data <- d' let add h x = (* first addition: we allocate the array *) if h.size < 0 then begin h.data <- Array.create (- h.size) x; h.size <- 0 end; let n = h.size in (* resizing if needed *) if n == Array.length h.data then resize h; let d = h.data in (* moving [x] up in the heap *) let rec moveup i = let fi = (i - 1) / 2 in if i > 0 && X.compare d.(fi) x < 0 then begin d.(i) <- d.(fi); moveup fi end else d.(i) <- x in moveup n; h.size <- n + 1 let maximum h = if h.size <= 0 then raise EmptyHeap; h.data.(0) let remove h = if h.size <= 0 then raise EmptyHeap; let n = h.size - 1 in h.size <- n; let d = h.data in let x = d.(n) in (* moving [x] down in the heap *) let rec movedown i = let j = 2 * i + 1 in if j < n then let j = let j' = j + 1 in if j' < n && X.compare d.(j') d.(j) > 0 then j' else j in if X.compare d.(j) x > 0 then begin d.(i) <- d.(j); movedown j end else d.(i) <- x else d.(i) <- x in movedown 0 let pop_maximum h = let m = maximum h in remove h; m let iter f h = let d = h.data in for i = 0 to h.size - 1 do f d.(i) done let fold f h x0 = let n = h.size in let d = h.data in let rec foldrec x i = if i >= n then x else foldrec (f d.(i) x) (succ i) in foldrec x0 0 end (*s Functional implementation *) module type FunctionalSig = sig type elt type t val empty : t val add : elt -> t -> t val maximum : t -> elt val remove : t -> t val iter : (elt -> unit) -> t -> unit val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a end module Functional(X : Ordered) = struct (* Heaps are encoded as complete binary trees, i.e., binary trees which are full expect, may be, on the bottom level where it is filled from the left. These trees also enjoy the heap property, namely the value of any node is greater or equal than those of its left and right subtrees. There are 4 kinds of complete binary trees, denoted by 4 constructors: [FFF] for a full binary tree (and thus 2 full subtrees); [PPF] for a partial tree with a partial left subtree and a full right subtree; [PFF] for a partial tree with a full left subtree and a full right subtree (but of different heights); and [PFP] for a partial tree with a full left subtree and a partial right subtree. *) type elt = X.t type t = | Empty | FFF of t * X.t * t (* full (full, full) *) | PPF of t * X.t * t (* partial (partial, full) *) | PFF of t * X.t * t (* partial (full, full) *) | PFP of t * X.t * t (* partial (full, partial) *) let empty = Empty (* smart constructors for insertion *) let p_f l x r = match l with | Empty | FFF _ -> PFF (l, x, r) | _ -> PPF (l, x, r) let pf_ l x = function | Empty | FFF _ as r -> FFF (l, x, r) | r -> PFP (l, x, r) let rec add x = function | Empty -> FFF (Empty, x, Empty) (* insertion to the left *) | FFF (l, y, r) | PPF (l, y, r) -> if X.compare x y > 0 then p_f (add y l) x r else p_f (add x l) y r (* insertion to the right *) | PFF (l, y, r) | PFP (l, y, r) -> if X.compare x y > 0 then pf_ l x (add y r) else pf_ l y (add x r) let maximum = function | Empty -> raise EmptyHeap | FFF (_, x, _) | PPF (_, x, _) | PFF (_, x, _) | PFP (_, x, _) -> x (* smart constructors for removal; note that they are different from the ones for insertion! *) let p_f l x r = match l with | Empty | FFF _ -> FFF (l, x, r) | _ -> PPF (l, x, r) let pf_ l x = function | Empty | FFF _ as r -> PFF (l, x, r) | r -> PFP (l, x, r) let rec remove = function | Empty -> raise EmptyHeap | FFF (Empty, _, Empty) -> Empty | PFF (l, _, Empty) -> l (* remove on the left *) | PPF (l, x, r) | PFF (l, x, r) -> let xl = maximum l in let xr = maximum r in let l' = remove l in if X.compare xl xr >= 0 then p_f l' xl r else p_f l' xr (add xl (remove r)) (* remove on the right *) | FFF (l, x, r) | PFP (l, x, r) -> let xl = maximum l in let xr = maximum r in let r' = remove r in if X.compare xl xr > 0 then pf_ (add xr (remove l)) xl r' else pf_ l xr r' let rec iter f = function | Empty -> () | FFF (l, x, r) | PPF (l, x, r) | PFF (l, x, r) | PFP (l, x, r) -> iter f l; f x; iter f r let rec fold f h x0 = match h with | Empty -> x0 | FFF (l, x, r) | PPF (l, x, r) | PFF (l, x, r) | PFP (l, x, r) -> fold f l (fold f r (f x x0)) end ocamlgraph-1.8.3/lib/unionfind.ml0000644000175000017500000000612012133565071015671 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id$ *) module type HashedOrderedType = sig type t val equal : t -> t -> bool val hash : t -> int val compare : t -> t -> int end module type S = sig type elt type t val init : elt list -> t val find : elt -> t -> elt val union : elt -> elt -> t -> unit end module Make(X:HashedOrderedType) = struct type elt = X.t module H = Hashtbl.Make(X) type cell = { mutable c : int; data : elt; mutable father : cell } type t = cell H.t (* a forest *) let init l = let h = H.create 997 in List.iter (fun x -> let rec cell = { c = 0; data = x; father = cell } in H.add h x cell) l; h let rec find_aux cell = if cell.father == cell then cell else let r = find_aux cell.father in cell.father <- r; r let find x h = (find_aux (H.find h x)).data let union x y h = let rx = find_aux (H.find h x) in let ry = find_aux (H.find h y) in if rx != ry then begin if rx.c > ry.c then ry.father <- rx else if rx.c < ry.c then rx.father <- ry else begin rx.c <- rx.c + 1; ry.father <- rx end end end (*** test ***) (*** module M = Make (struct type t = int let hash = Hashtbl.hash let compare = compare let equal = (=) end) open Printf let saisir s = printf "%s = " s; flush stdout; let x = read_int () in x let h = M.init [0;1;2;3;4;5;6;7;8;9] let () = if not !Sys.interactive then while true do printf "1) find\n2) union\n"; match read_int () with 1 -> begin let x = saisir "x" in printf "%d\n" (M.find x h) end | 2 -> begin let x, y = saisir "x", saisir "y" in M.union x y h end | _ -> () done ***) ocamlgraph-1.8.3/lib/bitv.ml0000644000175000017500000004447112133565071014657 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (*i $Id: bitv.ml,v 1.18 2008/04/01 09:59:03 filliatr Exp $ i*) (*s Bit vectors. The interface and part of the code are borrowed from the [Array] module of the ocaml standard library (but things are simplified here since we can always initialize a bit vector). This module also provides bitwise operations. *) (*s We represent a bit vector by a vector of integers (field [bits]), and we keep the information of the size of the bit vector since it can not be found out with the size of the array (field [length]). *) type t = { length : int; bits : int array } let length v = v.length (*s Each element of the array is an integer containing [bpi] bits, where [bpi] is determined according to the machine word size. Since we do not use the sign bit, [bpi] is 30 on a 32-bits machine and 62 on a 64-bits machines. We maintain the following invariant: {\em The unused bits of the last integer are always zeros.} This is ensured by [create] and maintained in other functions using [normalize]. [bit_j], [bit_not_j], [low_mask] and [up_mask] are arrays used to extract and mask bits in a single integer. *) let bpi = Sys.word_size - 2 let max_length = Sys.max_array_length * bpi let bit_j = Array.init bpi (fun j -> 1 lsl j) let bit_not_j = Array.init bpi (fun j -> max_int - bit_j.(j)) let low_mask = Array.create (succ bpi) 0 let _ = for i = 1 to bpi do low_mask.(i) <- low_mask.(i-1) lor bit_j.(pred i) done let keep_lowest_bits a j = a land low_mask.(j) let high_mask = Array.init (succ bpi) (fun j -> low_mask.(j) lsl (bpi-j)) let keep_highest_bits a j = a land high_mask.(j) (*s Creating and normalizing a bit vector is easy: it is just a matter of taking care of the invariant. Copy is immediate. *) let create n b = let initv = if b then max_int else 0 in let r = n mod bpi in if r = 0 then { length = n; bits = Array.create (n / bpi) initv } else begin let s = n / bpi in let b = Array.create (succ s) initv in b.(s) <- b.(s) land low_mask.(r); { length = n; bits = b } end let normalize v = let r = v.length mod bpi in if r > 0 then let b = v.bits in let s = Array.length b in b.(s-1) <- b.(s-1) land low_mask.(r) let copy v = { length = v.length; bits = Array.copy v.bits } (*s Access and assignment. The [n]th bit of a bit vector is the [j]th bit of the [i]th integer, where [i = n / bpi] and [j = n mod bpi]. Both [i] and [j] and computed by the function [pos]. Accessing a bit is testing whether the result of the corresponding mask operation is non-zero, and assigning it is done with a bitwiwe operation: an {\em or} with [bit_j] to set it, and an {\em and} with [bit_not_j] to unset it. *) let pos n = let i = n / bpi and j = n mod bpi in if j < 0 then (i - 1, j + bpi) else (i,j) let unsafe_get v n = let (i,j) = pos n in ((Array.unsafe_get v.bits i) land (Array.unsafe_get bit_j j)) > 0 let unsafe_set v n b = let (i,j) = pos n in if b then Array.unsafe_set v.bits i ((Array.unsafe_get v.bits i) lor (Array.unsafe_get bit_j j)) else Array.unsafe_set v.bits i ((Array.unsafe_get v.bits i) land (Array.unsafe_get bit_not_j j)) (*s The corresponding safe operations test the validiy of the access. *) let get v n = if n < 0 or n >= v.length then invalid_arg "Bitv.get"; let (i,j) = pos n in ((Array.unsafe_get v.bits i) land (Array.unsafe_get bit_j j)) > 0 let set v n b = if n < 0 or n >= v.length then invalid_arg "Bitv.set"; let (i,j) = pos n in if b then Array.unsafe_set v.bits i ((Array.unsafe_get v.bits i) lor (Array.unsafe_get bit_j j)) else Array.unsafe_set v.bits i ((Array.unsafe_get v.bits i) land (Array.unsafe_get bit_not_j j)) (*s [init] is implemented naively using [unsafe_set]. *) let init n f = let v = create n false in for i = 0 to pred n do unsafe_set v i (f i) done; v (*s Handling bits by packets is the key for efficiency of functions [append], [concat], [sub] and [blit]. We start by a very general function [blit_bits a i m v n] which blits the bits [i] to [i+m-1] of a native integer [a] onto the bit vector [v] at index [n]. It assumes that [i..i+m-1] and [n..n+m-1] are respectively valid subparts of [a] and [v]. It is optimized when the bits fit the lowest boundary of an integer (case [j == 0]). *) let blit_bits a i m v n = let (i',j) = pos n in if j == 0 then Array.unsafe_set v i' ((keep_lowest_bits (a lsr i) m) lor (keep_highest_bits (Array.unsafe_get v i') (bpi - m))) else let d = m + j - bpi in if d > 0 then begin Array.unsafe_set v i' (((keep_lowest_bits (a lsr i) (bpi - j)) lsl j) lor (keep_lowest_bits (Array.unsafe_get v i') j)); Array.unsafe_set v (succ i') ((keep_lowest_bits (a lsr (i + bpi - j)) d) lor (keep_highest_bits (Array.unsafe_get v (succ i')) (bpi - d))) end else Array.unsafe_set v i' (((keep_lowest_bits (a lsr i) m) lsl j) lor ((Array.unsafe_get v i') land (low_mask.(j) lor high_mask.(-d)))) (*s [blit_int] implements [blit_bits] in the particular case when [i=0] and [m=bpi] i.e. when we blit all the bits of [a]. *) let blit_int a v n = let (i,j) = pos n in if j == 0 then Array.unsafe_set v i a else begin Array.unsafe_set v i ( (keep_lowest_bits (Array.unsafe_get v i) j) lor ((keep_lowest_bits a (bpi - j)) lsl j)); Array.unsafe_set v (succ i) ((keep_highest_bits (Array.unsafe_get v (succ i)) (bpi - j)) lor (a lsr (bpi - j))) end (*s When blitting a subpart of a bit vector into another bit vector, there are two possible cases: (1) all the bits are contained in a single integer of the first bit vector, and a single call to [blit_bits] is the only thing to do, or (2) the source bits overlap on several integers of the source array, and then we do a loop of [blit_int], with two calls to [blit_bits] for the two bounds. *) let unsafe_blit v1 ofs1 v2 ofs2 len = if len > 0 then let (bi,bj) = pos ofs1 in let (ei,ej) = pos (ofs1 + len - 1) in if bi == ei then blit_bits (Array.unsafe_get v1 bi) bj len v2 ofs2 else begin blit_bits (Array.unsafe_get v1 bi) bj (bpi - bj) v2 ofs2; let n = ref (ofs2 + bpi - bj) in for i = succ bi to pred ei do blit_int (Array.unsafe_get v1 i) v2 !n; n := !n + bpi done; blit_bits (Array.unsafe_get v1 ei) 0 (succ ej) v2 !n end let blit v1 ofs1 v2 ofs2 len = if len < 0 or ofs1 < 0 or ofs1 + len > v1.length or ofs2 < 0 or ofs2 + len > v2.length then invalid_arg "Bitv.blit"; unsafe_blit v1.bits ofs1 v2.bits ofs2 len (*s Extracting the subvector [ofs..ofs+len-1] of [v] is just creating a new vector of length [len] and blitting the subvector of [v] inside. *) let sub v ofs len = if ofs < 0 or len < 0 or ofs + len > v.length then invalid_arg "Bitv.sub"; let r = create len false in unsafe_blit v.bits ofs r.bits 0 len; r (*s The concatenation of two bit vectors [v1] and [v2] is obtained by creating a vector for the result and blitting inside the two vectors. [v1] is copied directly. *) let append v1 v2 = let l1 = v1.length and l2 = v2.length in let r = create (l1 + l2) false in let b1 = v1.bits in let b2 = v2.bits in let b = r.bits in for i = 0 to Array.length b1 - 1 do Array.unsafe_set b i (Array.unsafe_get b1 i) done; unsafe_blit b2 0 b l1 l2; r (*s The concatenation of a list of bit vectors is obtained by iterating [unsafe_blit]. *) let concat vl = let size = List.fold_left (fun sz v -> sz + v.length) 0 vl in let res = create size false in let b = res.bits in let pos = ref 0 in List.iter (fun v -> let n = v.length in unsafe_blit v.bits 0 b !pos n; pos := !pos + n) vl; res (*s Filling is a particular case of blitting with a source made of all ones or all zeros. Thus we instanciate [unsafe_blit], with 0 and [max_int]. *) let blit_zeros v ofs len = if len > 0 then let (bi,bj) = pos ofs in let (ei,ej) = pos (ofs + len - 1) in if bi == ei then blit_bits 0 bj len v ofs else begin blit_bits 0 bj (bpi - bj) v ofs; let n = ref (ofs + bpi - bj) in for i = succ bi to pred ei do blit_int 0 v !n; n := !n + bpi done; blit_bits 0 0 (succ ej) v !n end let blit_ones v ofs len = if len > 0 then let (bi,bj) = pos ofs in let (ei,ej) = pos (ofs + len - 1) in if bi == ei then blit_bits max_int bj len v ofs else begin blit_bits max_int bj (bpi - bj) v ofs; let n = ref (ofs + bpi - bj) in for i = succ bi to pred ei do blit_int max_int v !n; n := !n + bpi done; blit_bits max_int 0 (succ ej) v !n end let fill v ofs len b = if ofs < 0 or len < 0 or ofs + len > v.length then invalid_arg "Bitv.fill"; if b then blit_ones v.bits ofs len else blit_zeros v.bits ofs len (*s All the iterators are implemented as for traditional arrays, using [unsafe_get]. For [iter] and [map], we do not precompute [(f true)] and [(f false)] since [f] is likely to have side-effects. *) let iter f v = for i = 0 to v.length - 1 do f (unsafe_get v i) done let map f v = let l = v.length in let r = create l false in for i = 0 to l - 1 do unsafe_set r i (f (unsafe_get v i)) done; r let iteri f v = for i = 0 to v.length - 1 do f i (unsafe_get v i) done let mapi f v = let l = v.length in let r = create l false in for i = 0 to l - 1 do unsafe_set r i (f i (unsafe_get v i)) done; r let fold_left f x v = let r = ref x in for i = 0 to v.length - 1 do r := f !r (unsafe_get v i) done; !r let fold_right f v x = let r = ref x in for i = v.length - 1 downto 0 do r := f (unsafe_get v i) !r done; !r let foldi_left f x v = let r = ref x in for i = 0 to v.length - 1 do r := f !r i (unsafe_get v i) done; !r let foldi_right f v x = let r = ref x in for i = v.length - 1 downto 0 do r := f i (unsafe_get v i) !r done; !r let iteri_true f v = Array.iteri (fun i n -> if n != 0 then begin let i_bpi = i * bpi in for j = 0 to bpi - 1 do if n land (Array.unsafe_get bit_j j) > 0 then f (i_bpi + j) done end) v.bits (*s Bitwise operations. It is straigthforward, since bitwise operations can be realized by the corresponding bitwise operations over integers. However, one has to take care of normalizing the result of [bwnot] which introduces ones in highest significant positions. *) let bw_and v1 v2 = let l = v1.length in if l <> v2.length then invalid_arg "Bitv.bw_and"; let b1 = v1.bits and b2 = v2.bits in let n = Array.length b1 in let a = Array.create n 0 in for i = 0 to n - 1 do a.(i) <- b1.(i) land b2.(i) done; { length = l; bits = a } let bw_or v1 v2 = let l = v1.length in if l <> v2.length then invalid_arg "Bitv.bw_or"; let b1 = v1.bits and b2 = v2.bits in let n = Array.length b1 in let a = Array.create n 0 in for i = 0 to n - 1 do a.(i) <- b1.(i) lor b2.(i) done; { length = l; bits = a } let bw_xor v1 v2 = let l = v1.length in if l <> v2.length then invalid_arg "Bitv.bw_xor"; let b1 = v1.bits and b2 = v2.bits in let n = Array.length b1 in let a = Array.create n 0 in for i = 0 to n - 1 do a.(i) <- b1.(i) lxor b2.(i) done; { length = l; bits = a } let bw_not v = let b = v.bits in let n = Array.length b in let a = Array.create n 0 in for i = 0 to n - 1 do a.(i) <- max_int land (lnot b.(i)) done; let r = { length = v.length; bits = a } in normalize r; r (*s Shift operations. It is easy to reuse [unsafe_blit], although it is probably slightly less efficient than a ad-hoc piece of code. *) let rec shiftl v d = if d == 0 then copy v else if d < 0 then shiftr v (-d) else begin let n = v.length in let r = create n false in if d < n then unsafe_blit v.bits 0 r.bits d (n - d); r end and shiftr v d = if d == 0 then copy v else if d < 0 then shiftl v (-d) else begin let n = v.length in let r = create n false in if d < n then unsafe_blit v.bits d r.bits 0 (n - d); r end (*s Testing for all zeros and all ones. *) let all_zeros v = let b = v.bits in let n = Array.length b in let rec test i = (i == n) || ((Array.unsafe_get b i == 0) && test (succ i)) in test 0 let all_ones v = let b = v.bits in let n = Array.length b in let rec test i = if i == n - 1 then let m = v.length mod bpi in (Array.unsafe_get b i) == (if m == 0 then max_int else low_mask.(m)) else ((Array.unsafe_get b i) == max_int) && test (succ i) in test 0 (*s Conversions to and from strings. *) let to_string v = let n = v.length in let s = String.make n '0' in for i = 0 to n - 1 do if unsafe_get v i then s.[i] <- '1' done; s let print fmt v = Format.pp_print_string fmt (to_string v) let of_string s = let n = String.length s in let v = create n false in for i = 0 to n - 1 do let c = String.unsafe_get s i in if c = '1' then unsafe_set v i true else if c <> '0' then invalid_arg "Bitv.of_string" done; v (*s Iteration on all bit vectors of length [n] using a Gray code. *) let first_set v n = let rec lookup i = if i = n then raise Not_found ; if unsafe_get v i then i else lookup (i + 1) in lookup 0 let gray_iter f n = let bv = create n false in let rec iter () = f bv; unsafe_set bv 0 (not (unsafe_get bv 0)); f bv; let pos = succ (first_set bv n) in if pos < n then begin unsafe_set bv pos (not (unsafe_get bv pos)); iter () end in if n > 0 then iter () (*s Coercions to/from lists of integers *) let of_list l = let n = List.fold_left max 0 l in let b = create (succ n) false in let add_element i = (* negative numbers are invalid *) if i < 0 then invalid_arg "Bitv.of_list"; unsafe_set b i true in List.iter add_element l; b let of_list_with_length l len = let b = create len false in let add_element i = if i < 0 || i >= len then invalid_arg "Bitv.of_list_with_length"; unsafe_set b i true in List.iter add_element l; b let to_list b = let n = length b in let rec make i acc = if i < 0 then acc else make (pred i) (if unsafe_get b i then i :: acc else acc) in make (pred n) [] (*s To/from integers. *) (* [int] *) let of_int_us i = { length = bpi; bits = [| i land max_int |] } let to_int_us v = if v.length < bpi then invalid_arg "Bitv.to_int_us"; v.bits.(0) let of_int_s i = { length = succ bpi; bits = [| i land max_int; (i lsr bpi) land 1 |] } let to_int_s v = if v.length < succ bpi then invalid_arg "Bitv.to_int_s"; v.bits.(0) lor (v.bits.(1) lsl bpi) (* [Int32] *) let of_int32_us i = match Sys.word_size with | 32 -> { length = 31; bits = [| (Int32.to_int i) land max_int; let hi = Int32.shift_right_logical i 30 in (Int32.to_int hi) land 1 |] } | 64 -> { length = 31; bits = [| (Int32.to_int i) land 0x7fffffff |] } | _ -> assert false let to_int32_us v = if v.length < 31 then invalid_arg "Bitv.to_int32_us"; match Sys.word_size with | 32 -> Int32.logor (Int32.of_int v.bits.(0)) (Int32.shift_left (Int32.of_int (v.bits.(1) land 1)) 30) | 64 -> Int32.of_int (v.bits.(0) land 0x7fffffff) | _ -> assert false (* this is 0xffffffff (ocaml >= 3.08 checks for literal overflow) *) let ffffffff = (0xffff lsl 16) lor 0xffff let of_int32_s i = match Sys.word_size with | 32 -> { length = 32; bits = [| (Int32.to_int i) land max_int; let hi = Int32.shift_right_logical i 30 in (Int32.to_int hi) land 3 |] } | 64 -> { length = 32; bits = [| (Int32.to_int i) land ffffffff |] } | _ -> assert false let to_int32_s v = if v.length < 32 then invalid_arg "Bitv.to_int32_s"; match Sys.word_size with | 32 -> Int32.logor (Int32.of_int v.bits.(0)) (Int32.shift_left (Int32.of_int (v.bits.(1) land 3)) 30) | 64 -> Int32.of_int (v.bits.(0) land ffffffff) | _ -> assert false (* [Int64] *) let of_int64_us i = match Sys.word_size with | 32 -> { length = 63; bits = [| (Int64.to_int i) land max_int; (let mi = Int64.shift_right_logical i 30 in (Int64.to_int mi) land max_int); let hi = Int64.shift_right_logical i 60 in (Int64.to_int hi) land 1 |] } | 64 -> { length = 63; bits = [| (Int64.to_int i) land max_int; let hi = Int64.shift_right_logical i 62 in (Int64.to_int hi) land 1 |] } | _ -> assert false let to_int64_us v = failwith "todo" let of_int64_s i = failwith "todo" let to_int64_s v = failwith "todo" (* [Nativeint] *) let select_of f32 f64 = match Sys.word_size with | 32 -> (fun i -> f32 (Nativeint.to_int32 i)) | 64 -> (fun i -> f64 (Int64.of_nativeint i)) | _ -> assert false let of_nativeint_s = select_of of_int32_s of_int64_s let of_nativeint_us = select_of of_int32_us of_int64_us let select_to f32 f64 = match Sys.word_size with | 32 -> (fun i -> Nativeint.of_int32 (f32 i)) | 64 -> (fun i -> Int64.to_nativeint (f64 i)) | _ -> assert false let to_nativeint_s = select_to to_int32_s to_int64_s let to_nativeint_us = select_to to_int32_us to_int64_us ocamlgraph-1.8.3/lib/bitv.mli0000644000175000017500000001732712133565071015030 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (*s {\bf Module Bitv}. This module implements bit vectors, as an abstract datatype [t]. Since bit vectors are particular cases of arrays, this module provides the same operations as the module [Array] (Sections~\ref{barray} up to \ref{earray}). It also provides bitwise operations (Section~\ref{bitwise}). In the following, [false] stands for the bit 0 and [true] for the bit 1. *) type t (*s {\bf Creation, access and assignment.} \label{barray} [(Bitv.create n b)] creates a new bit vector of length [n], initialized with [b]. [(Bitv.init n f)] returns a fresh vector of length [n], with bit number [i] initialized to the result of [(f i)]. [(Bitv.set v n b)] sets the [n]th bit of [v] to the value [b]. [(Bitv.get v n)] returns the [n]th bit of [v]. [Bitv.length] returns the length (number of elements) of the given vector. *) val create : int -> bool -> t val init : int -> (int -> bool) -> t val set : t -> int -> bool -> unit val get : t -> int -> bool val length : t -> int (*s [max_length] is the maximum length of a bit vector (System dependent). *) val max_length : int (*s {\bf Copies and concatenations.} [(Bitv.copy v)] returns a copy of [v], that is, a fresh vector containing the same elements as [v]. [(Bitv.append v1 v2)] returns a fresh vector containing the concatenation of the vectors [v1] and [v2]. [Bitv.concat] is similar to [Bitv.append], but catenates a list of vectors. *) val copy : t -> t val append : t -> t -> t val concat : t list -> t (*s {\bf Sub-vectors and filling.} [(Bitv.sub v start len)] returns a fresh vector of length [len], containing the bits number [start] to [start + len - 1] of vector [v]. Raise [Invalid_argument "Bitv.sub"] if [start] and [len] do not designate a valid subvector of [v]; that is, if [start < 0], or [len < 0], or [start + len > Bitv.length a]. [(Bitv.fill v ofs len b)] modifies the vector [v] in place, storing [b] in elements number [ofs] to [ofs + len - 1]. Raise [Invalid_argument "Bitv.fill"] if [ofs] and [len] do not designate a valid subvector of [v]. [(Bitv.blit v1 o1 v2 o2 len)] copies [len] elements from vector [v1], starting at element number [o1], to vector [v2], starting at element number [o2]. It {\em does not work} correctly if [v1] and [v2] are the same vector with the source and destination chunks overlapping. Raise [Invalid_argument "Bitv.blit"] if [o1] and [len] do not designate a valid subvector of [v1], or if [o2] and [len] do not designate a valid subvector of [v2]. *) val sub : t -> int -> int -> t val fill : t -> int -> int -> bool -> unit val blit : t -> int -> t -> int -> int -> unit (*s {\bf Iterators.} \label{earray} [(Bitv.iter f v)] applies function [f] in turn to all the elements of [v]. Given a function [f], [(Bitv.map f v)] applies [f] to all the elements of [v], and builds a vector with the results returned by [f]. [Bitv.iteri] and [Bitv.mapi] are similar to [Bitv.iter] and [Bitv.map] respectively, but the function is applied to the index of the element as first argument, and the element itself as second argument. [(Bitv.fold_left f x v)] computes [f (... (f (f x (get v 0)) (get v 1)) ...) (get v (n-1))], where [n] is the length of the vector [v]. [(Bitv.fold_right f a x)] computes [f (get v 0) (f (get v 1) ( ... (f (get v (n-1)) x) ...))], where [n] is the length of the vector [v]. *) val iter : (bool -> unit) -> t -> unit val map : (bool -> bool) -> t -> t val iteri : (int -> bool -> unit) -> t -> unit val mapi : (int -> bool -> bool) -> t -> t val fold_left : ('a -> bool -> 'a) -> 'a -> t -> 'a val fold_right : (bool -> 'a -> 'a) -> t -> 'a -> 'a val foldi_left : ('a -> int -> bool -> 'a) -> 'a -> t -> 'a val foldi_right : (int -> bool -> 'a -> 'a) -> t -> 'a -> 'a (*s [gray_iter f n] iterates function [f] on all bit vectors of length [n], once each, using a Gray code. The order in which bit vectors are processed is unspecified. *) val gray_iter : (t -> unit) -> int -> unit (*s {\bf Bitwise operations.} \label{bitwise} [bwand], [bwor] and [bwxor] implement logical and, or and exclusive or. They return fresh vectors and raise [Invalid_argument "Bitv.xxx"] if the two vectors do not have the same length (where \texttt{xxx} is the name of the function). [bwnot] implements the logical negation. It returns a fresh vector. [shiftl] and [shiftr] implement shifts. They return fresh vectors. [shiftl] moves bits from least to most significant, and [shiftr] from most to least significant (think [lsl] and [lsr]). [all_zeros] and [all_ones] respectively test for a vector only containing zeros and only containing ones. *) val bw_and : t -> t -> t val bw_or : t -> t -> t val bw_xor : t -> t -> t val bw_not : t -> t val shiftl : t -> int -> t val shiftr : t -> int -> t val all_zeros : t -> bool val all_ones : t -> bool (*s {\bf Conversions to and from strings.} Least significant bit comes first. *) val to_string : t -> string val of_string : string -> t val print : Format.formatter -> t -> unit (*s {\bf Conversions to and from lists of integers.} The list gives the indices of bits which are set (ie [true]). *) val to_list : t -> int list val of_list : int list -> t val of_list_with_length : int list -> int -> t (*s Interpretation of bit vectors as integers. Least significant bit comes first (ie is at index 0 in the bit vector). [to_xxx] functions truncate when the bit vector is too wide, and raise [Invalid_argument] when it is too short. Suffix [_s] indicates that sign bit is kept, and [_us] that it is discarded. *) (* type [int] (length 31/63 with sign, 30/62 without) *) val of_int_s : int -> t val to_int_s : t -> int val of_int_us : int -> t val to_int_us : t -> int (* type [Int32.t] (length 32 with sign, 31 without) *) val of_int32_s : Int32.t -> t val to_int32_s : t -> Int32.t val of_int32_us : Int32.t -> t val to_int32_us : t -> Int32.t (* type [Int64.t] (length 64 with sign, 63 without) *) val of_int64_s : Int64.t -> t val to_int64_s : t -> Int64.t val of_int64_us : Int64.t -> t val to_int64_us : t -> Int64.t (* type [Nativeint.t] (length 32/64 with sign, 31/63 without) *) val of_nativeint_s : Nativeint.t -> t val to_nativeint_s : t -> Nativeint.t val of_nativeint_us : Nativeint.t -> t val to_nativeint_us : t -> Nativeint.t (*s Only if you know what you are doing... *) val unsafe_set : t -> int -> bool -> unit val unsafe_get : t -> int -> bool ocamlgraph-1.8.3/lib/heap.mli0000644000175000017500000000651312133565071014774 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2010 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2.1, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) module type Ordered = sig type t val compare : t -> t -> int end exception EmptyHeap (*S Imperative implementation. *) module Imperative(X: Ordered) : sig (* Type of imperative heaps. (In the following [n] refers to the number of elements in the heap) *) type t (* [create c] creates a new heap, with initial capacity of [c] *) val create : int -> t (* [is_empty h] checks the emptiness of [h] *) val is_empty : t -> bool (* [add x h] adds a new element [x] in heap [h]; size of [h] is doubled when maximum capacity is reached; complexity $O(log(n))$ *) val add : t -> X.t -> unit (* [maximum h] returns the maximum element of [h]; raises [EmptyHeap] when [h] is empty; complexity $O(1)$ *) val maximum : t -> X.t (* [remove h] removes the maximum element of [h]; raises [EmptyHeap] when [h] is empty; complexity $O(log(n))$ *) val remove : t -> unit (* [pop_maximum h] removes the maximum element of [h] and returns it; raises [EmptyHeap] when [h] is empty; complexity $O(log(n))$ *) val pop_maximum : t -> X.t (* usual iterators and combinators; elements are presented in arbitrary order *) val iter : (X.t -> unit) -> t -> unit val fold : (X.t -> 'a -> 'a) -> t -> 'a -> 'a end (*S Functional implementation. *) module type FunctionalSig = sig (* heap elements *) type elt (* Type of functional heaps *) type t (* The empty heap *) val empty : t (* [add x h] returns a new heap containing the elements of [h], plus [x]; complexity $O(log(n))$ *) val add : elt -> t -> t (* [maximum h] returns the maximum element of [h]; raises [EmptyHeap] when [h] is empty; complexity $O(1)$ *) val maximum : t -> elt (* [remove h] returns a new heap containing the elements of [h], except the maximum of [h]; raises [EmptyHeap] when [h] is empty; complexity $O(log(n))$ *) val remove : t -> t (* usual iterators and combinators; elements are presented in arbitrary order *) val iter : (elt -> unit) -> t -> unit val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a end module Functional(X: Ordered) : FunctionalSig with type elt = X.t ocamlgraph-1.8.3/configure.in0000644000175000017500000001655612133565071015127 0ustar mehdimehdi########################################################################## # # # Ocamlgraph: a generic graph library for OCaml # # Copyright (C) 2004-2010 # # Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles # # # # This software is free software; you can redistribute it and/or # # modify it under the terms of the GNU Library General Public # # License version 2.1, with the special exception on linking # # described in file LICENSE. # # # # This software 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. # # # ########################################################################## # the script generated by autoconf from this input will set the following # variables: # OCAMLC "ocamlc" if present in the path, or a failure # or "ocamlc.opt" if present with same version number as ocamlc # OCAMLOPT "ocamlopt" (or "ocamlopt.opt" if present), or "no" # OCAMLBEST either "byte" if no native compiler was found, # or "opt" otherwise # OCAMLDEP "ocamldep" # OCAMLLEX "ocamllex" (or "ocamllex.opt" if present) # OCAMLYACC "ocamlyac" # OCAMLLIB the path to the ocaml standard library # OCAMLVERSION the ocaml version number # OCAMLWEB "ocamlweb" (not mandatory) # OCAMLWIN32 "yes"/"no" depending on Sys.os_type = "Win32" # EXE ".exe" if OCAMLWIN32=yes, "" otherwise # check for one particular file of the sources # ADAPT THE FOLLOWING LINE TO YOUR SOURCES! AC_INIT(src/sig.mli) # Check for Ocaml compilers # we first look for ocamlc in the path; if not present, we fail AC_CHECK_PROG(OCAMLC,ocamlc,ocamlc,no) if test "$OCAMLC" = no ; then AC_MSG_ERROR(Cannot find ocamlc.) fi # we extract Ocaml version number and library path OCAMLVERSION=`$OCAMLC -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` echo "ocaml version is $OCAMLVERSION" case $OCAMLVERSION in 0.*|1.*|2.*|3.0*) AC_MSG_ERROR(ocamlgraph needs ocaml version 3.10.0 or higher);; *) ;; esac # OCAMLLIB=`$OCAMLC -v | tail -n 1 | cut -f 4 -d " "` # OCAMLLIB=`$OCAMLC -v | tail -n 1 | sed -e 's|[[^:]]*: \(.*\)|\1|' ` OCAMLLIB=`$OCAMLC -where | tr -d '\r'` echo "ocaml library path is $OCAMLLIB" # then we look for ocamlopt; if not present, we issue a warning # if the version is not the same, we also discard it # we set OCAMLBEST to "opt" or "byte", whether ocamlopt is available or not AC_CHECK_PROG(OCAMLOPT,ocamlopt,ocamlopt,no) OCAMLBEST=byte if test "$OCAMLOPT" = no ; then AC_MSG_WARN(Cannot find ocamlopt; bytecode compilation only.) else AC_MSG_CHECKING(ocamlopt version) TMPVERSION=`$OCAMLOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlopt discarded.) OCAMLOPT=no else AC_MSG_RESULT(ok) OCAMLBEST=opt fi fi # checking for ocamlc.opt AC_CHECK_PROG(OCAMLCDOTOPT,ocamlc.opt,ocamlc.opt,no) if test "$OCAMLCDOTOPT" != no ; then AC_MSG_CHECKING(ocamlc.opt version) TMPVERSION=`$OCAMLCDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVERSION" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlc.opt discarded.) else AC_MSG_RESULT(ok) OCAMLC=$OCAMLCDOTOPT fi fi # checking for ocamlopt.opt if test "$OCAMLOPT" != no ; then AC_CHECK_PROG(OCAMLOPTDOTOPT,ocamlopt.opt,ocamlopt.opt,no) if test "$OCAMLOPTDOTOPT" != no ; then AC_MSG_CHECKING(ocamlc.opt version) TMPVER=`$OCAMLOPTDOTOPT -v | sed -n -e 's|.*version *\(.*\)$|\1|p' ` if test "$TMPVER" != "$OCAMLVERSION" ; then AC_MSG_RESULT(differs from ocamlc; ocamlopt.opt discarded.) else AC_MSG_RESULT(ok) OCAMLOPT=$OCAMLOPTDOTOPT fi fi fi # ocamldep, ocamllex and ocamlyacc should also be present in the path AC_CHECK_PROG(OCAMLDEP,ocamldep,ocamldep,no) if test "$OCAMLDEP" = no ; then AC_MSG_ERROR(Cannot find ocamldep.) fi AC_CHECK_PROG(OCAMLLEX,ocamllex,ocamllex,no) if test "$OCAMLLEX" = no ; then AC_MSG_ERROR(Cannot find ocamllex.) else AC_CHECK_PROG(OCAMLLEXDOTOPT,ocamllex.opt,ocamllex.opt,no) if test "$OCAMLLEXDOTOPT" != no ; then OCAMLLEX=$OCAMLLEXDOTOPT fi fi AC_CHECK_PROG(OCAMLYACC,ocamlyacc,ocamlyacc,no) if test "$OCAMLYACC" = no ; then AC_MSG_ERROR(Cannot find ocamlyacc.) fi AC_CHECK_PROG(OCAMLDOC,ocamldoc,ocamldoc,true) if test "$OCAMLDOC" = true ; then AC_MSG_WARN(Cannot find ocamldoc) else AC_CHECK_PROG(OCAMLDOCOPT,ocamldoc.opt,ocamldoc.opt,no) if test "$OCAMLDOCOPT" != no ; then OCAMLDOC=$OCAMLDOCOPT fi fi AC_CHECK_PROG(OCAMLWEB,ocamlweb,ocamlweb,true) AC_CHECK_PROG(OCAMLFIND,ocamlfind,ocamlfind) if test "$OCAMLFIND" = "" ; then echo "No ocamlfind detected" else OCAMLLIB_BY_FINDLIB=`ocamlfind query stdlib | tr -d '\\r'` if test "$OCAMLLIB_BY_FINDLIB" = "$OCAMLLIB" ; then echo "OCamlfind detected and enabled" else echo "OCamlfind detected but disabled. Standard libraries differ." OCAMLFIND="" fi fi if test "$OCAMLBEST" = "opt"; then SUFFIX=cmxa; else SUFFIX=cma; fi # checking for lablgtk2 and lablgnomecanvas ########################################### # lablgtk2 now uses ocamlfind while older version uses `ocamlc -where ` # its installation path is not the same if test "$OCAMLFIND" = "" ; then LABLGTK_PATH=+lablgtk2 LABLGTKPATH_FOR_CONFIGURE=$OCAMLLIB/lablgtk2 else LABLGTK_PATH=`ocamlfind query lablgtk2 | tr -d '\\r\\n'` if test "$LABLGTK_PATH" = "" -o "$LABLGTK_PATH" -ef "$OCAMLLIB/lablgtk2" ; \ then LABLGTK_PATH=+lablgtk2 LABLGTKPATH_FOR_CONFIGURE=$OCAMLLIB/lablgtk2 else LABLGTKPATH_FOR_CONFIGURE=$LABLGTK_PATH fi fi AC_CHECK_FILE($LABLGTKPATH_FOR_CONFIGURE/lablgtk.$SUFFIX, LABLGTK2=yes, LABLGTK2=no) if test "$LABLGTK2" = yes ; then INCLUDEGTK2="-I $LABLGTK_PATH" AC_CHECK_FILE($LABLGTKPATH_FOR_CONFIGURE/lablgnomecanvas.$SUFFIX, LABLGNOMECANVAS=yes, LABLGNOMECANVAS=no) else LABLGTK2=no LABLGNOMECANVAS=no fi # platform AC_MSG_CHECKING(Win32 platform) echo "print_endline Sys.os_type" > check_arch.ml if ocaml check_arch.ml | grep -q Win32; then AC_MSG_RESULT(yes) OCAMLWIN32=yes EXE=.exe else AC_MSG_RESULT(no) OCAMLWIN32=no EXE= fi rm -f check_arch.ml LIBEXT=`ocamlc -config | grep ext_lib | sed -e 's/.*\(\..*\)/\1/' ` OBJEXT=`ocamlc -config | grep ext_obj | sed -e 's/.*\(\..*\)/\1/' ` if test "$LABLGNOMECANVAS" = no ; then AC_MSG_WARN([lablgnomecanvas not found: the graph editor and view_graph will not be compiled]) fi # substitutions to perform AC_SUBST(OCAMLC) AC_SUBST(OCAMLOPT) AC_SUBST(OCAMLDEP) AC_SUBST(OCAMLLEX) AC_SUBST(OCAMLDOC) AC_SUBST(OCAMLYACC) AC_SUBST(OCAMLBEST) AC_SUBST(OCAMLVERSION) AC_SUBST(OCAMLLIB) AC_SUBST(OCAMLWEB) AC_SUBST(LABLGTK2) AC_SUBST(LABLGNOMECANVAS) AC_SUBST(OCAMLWIN32) AC_SUBST(EXE) AC_SUBST(LIBEXT) AC_SUBST(OBJEXT) AC_SUBST(INCLUDEGTK2) # Finally create the Makefile from Makefile.in AC_OUTPUT(Makefile) chmod a-w Makefile ocamlgraph-1.8.3/tests/0000755000175000017500000000000012133565071013743 5ustar mehdimehdiocamlgraph-1.8.3/tests/dot.ml0000644000175000017500000000377712133565071015101 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id:$ *) open Graph module G = Imperative.Digraph.Abstract(String) module B = Builder.I(G) module DotInput = Dot.Parse (B) (struct let node (id,_) _ = match id with | Dot_ast.Ident s | Dot_ast.Number s | Dot_ast.String s | Dot_ast.Html s -> s let edge _ = () end) module Display = struct include G let vertex_name v = "\"" ^ String.escaped (V.label v) ^ "\"" let graph_attributes _ = [] let default_vertex_attributes _ = [] let vertex_attributes _ = [] let default_edge_attributes _ = [] let edge_attributes _ = [] let get_subgraph _ = None end module DotOutput = Graphviz.Dot(Display) let g = DotInput.parse Sys.argv.(1) let () = let oc = open_out "tmp.dot" in DotOutput.output_graph oc g; close_out oc let _ = Sys.command "dot -Tps tmp.dot | gv -" ocamlgraph-1.8.3/tests/check.ml0000644000175000017500000004133412133565071015357 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Graph module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module W = struct type label = int type t = int let weight x = x let zero = 0 let add = (+) let compare = compare end (********************************************) (* Generic functions *) (********************************************) module Generic = struct (* Generic tests for imperative graphs *) module Make (G : Sig.I with type V.label = int) (V : sig val v: int val e: int end) = struct module O = Oper.I(G) let test_mirror g = if G.is_directed then begin (* TODO: remove *) let g' = O.mirror g in assert (G.nb_vertex g = G.nb_vertex g'); G.iter_edges (fun v1 v2 -> assert (G.mem_edge g' v2 v1)) g; G.iter_edges (fun v1 v2 -> assert (G.mem_edge g v2 v1)) g'; () end let g = G.create () let () = let v1 = G.V.create 1 in let v2 = G.V.create 2 in let v3 = G.V.create 3 in test_mirror g; G.add_edge g v1 v2; G.add_edge g v1 v3; G.add_edge g v2 v1; G.add_edge g v2 v2; G.add_edge g v2 v2; test_mirror g; assert (G.nb_vertex g = V.v && G.nb_edges g = V.e); G.remove_vertex g v1; assert (G.nb_vertex g = 2 && G.nb_edges g = 1); G.remove_vertex g v2; assert (G.nb_vertex g = 1 && G.nb_edges g = 0); test_mirror g; G.clear g; assert (G.nb_vertex g = 0 && G.nb_edges g = 0) end let () = let module A = Make (Imperative.Digraph.ConcreteLabeled(Int)(Int)) (struct let v = 3 let e = 4 end) in let module A = Make (Imperative.Graph.ConcreteLabeled(Int)(Int)) (struct let v = 3 let e = 3 end) in let module A = Make (Imperative.Digraph.AbstractLabeled(Int)(Int)) (struct let v = 3 let e = 4 end) in let module A = Make (Imperative.Graph.AbstractLabeled(Int)(Int)) (struct let v = 3 let e = 3 end) in let module A = Make (Imperative.Digraph.Concrete(Int)) (struct let v = 3 let e = 4 end) in let module A = Make (Imperative.Graph.Concrete(Int)) (struct let v = 3 let e = 3 end) in let module A = Make (Imperative.Digraph.Abstract(Int)) (struct let v = 3 let e = 4 end) in let module A = Make (Imperative.Graph.Abstract(Int)) (struct let v = 3 let e = 3 end) in let module A = Make (Imperative.Digraph.ConcreteBidirectional(Int)) (struct let v = 3 let e = 4 end) in let module A = Make (Imperative.Digraph.ConcreteBidirectionalLabeled(Int)(Int)) (struct let v = 3 let e = 4 end) in () (* Generic tests for persistent graphs *) module MakeP (G : Sig.P with type V.label = int) (V : sig val v: int val e: int end) = struct module O = Oper.P(G) let test_mirror g = let g' = O.mirror g in assert (G.nb_vertex g = G.nb_vertex g') let () = let g = G.empty in let v1 = G.V.create 1 in let v2 = G.V.create 2 in let v3 = G.V.create 3 in test_mirror g; let g = G.add_edge g v1 v2 in let g = G.add_edge g v1 v3 in let g = G.add_edge g v2 v1 in let g = G.add_edge g v2 v2 in let g = G.add_edge g v2 v2 in test_mirror g; assert (G.nb_vertex g = V.v && G.nb_edges g = V.e); let g = G.remove_vertex g v1 in assert (G.nb_vertex g = 2 && G.nb_edges g = 1); let g = G.remove_vertex g v2 in assert (G.nb_vertex g = 1 && G.nb_edges g = 0); test_mirror g end let () = let module A = MakeP (Persistent.Digraph.ConcreteLabeled(Int)(Int)) (struct let v = 3 let e = 4 end) in let module A = MakeP (Persistent.Graph.ConcreteLabeled(Int)(Int)) (struct let v = 3 let e = 3 end) in let module A = MakeP (Persistent.Digraph.AbstractLabeled(Int)(Int)) (struct let v = 3 let e = 4 end) in let module A = MakeP (Persistent.Graph.AbstractLabeled(Int)(Int)) (struct let v = 3 let e = 3 end) in let module A = MakeP (Persistent.Digraph.Concrete(Int)) (struct let v = 3 let e = 4 end) in let module A = MakeP (Persistent.Graph.Concrete(Int)) (struct let v = 3 let e = 3 end) in let module A = MakeP (Persistent.Digraph.Abstract(Int)) (struct let v = 3 let e = 4 end) in let module A = MakeP (Persistent.Graph.Abstract(Int)) (struct let v = 3 let e = 3 end) in let module A = MakeP (Persistent.Digraph.ConcreteBidirectional(Int)) (struct let v = 3 let e = 4 end) in let module A = MakeP (Persistent.Digraph.ConcreteBidirectionalLabeled(Int)(Int)) (struct let v = 3 let e = 4 end) in () (* find_edge *) module Make2 (G : Sig.I with type V.t = int and type E.label = int and type E.t = int * int * int) = struct let g = G.create () let test_exn v1 v2 = assert (G.find_all_edges g v1 v2 = []); try let _ = G.find_edge g v1 v2 in assert false with Not_found -> () let () = let e1 = 1, 0, 2 in let e2 = 1, 1, 3 in let e2' = 1, 2, 3 in let e3 = 2, 2, 1 in G.add_edge_e g e1; G.add_edge_e g e2; G.add_edge_e g e2'; G.add_edge_e g e3; G.add_edge_e g e3; assert (G.find_edge g 1 2 = e1); assert (List.length (G.find_all_edges g 1 3) = 2); test_exn 2 3; test_exn 2 4; test_exn 5 2; G.remove_vertex g 2; assert (G.nb_vertex g = 2 && G.nb_edges g = 2) end let () = let module D = Make2(Imperative.Digraph.ConcreteLabeled(Int)(Int)) in D.test_exn 3 1; let module G = Imperative.Graph.ConcreteLabeled(Int)(Int) in let module G2 = Make2(G) in assert (G.find_edge G2.g 3 1 = (3, 1, 1)) end (********************************************) (* Dijkstra *) (********************************************) module Dijkstra = struct module TestDijkstra (G : Sig.G with type V.label = int and type E.label = int) (B : Builder.S with module G = G) = struct let g = B.empty () let v1 = G.V.create 1 let g = B.add_vertex g v1 let v2 = G.V.create 2 let g = B.add_vertex g v2 let v3 = G.V.create 3 let g = B.add_vertex g v3 let v4 = G.V.create 4 let g = B.add_vertex g v4 let v5 = G.V.create 5 let g = B.add_vertex g v5 let g = B.add_edge_e g (G.E.create v1 10 v2) let g = B.add_edge_e g (G.E.create v2 50 v3) let g = B.add_edge_e g (G.E.create v1 30 v4) let g = B.add_edge_e g (G.E.create v1 100 v5) let g = B.add_edge_e g (G.E.create v3 10 v5) let g = B.add_edge_e g (G.E.create v4 20 v3) let g = B.add_edge_e g (G.E.create v4 60 v5) module Dij = Path.Dijkstra(G)(W) module Dfs = Traverse.Dfs(G) let test g i j w l = let p,w' = Dij.shortest_path g i j in assert (w' = w && List.length p = l) let test_not_found g i j = try let _ = Dij.shortest_path g i j in assert false with Not_found -> () let () = test g v1 v5 60 3 let () = test g v1 v1 0 0 let () = if G.is_directed then test_not_found g v5 v1 let () = assert (not (Dfs.has_cycle g)) let gc = B.add_edge_e g (G.E.create v5 10 v1) let v6 = G.V.create 6 let gc = B.add_vertex gc v6 let () = if G.is_directed then test gc v1 v5 60 3 let () = test gc v5 v1 10 1 let () = test_not_found gc v1 v6 let () = assert (Dfs.has_cycle gc) end (* Dijkstra on Persistent Directed Labeled Graphs *) module G = Persistent.Digraph.ConcreteLabeled(Int)(Int) module Test1 = TestDijkstra(G)(Builder.P(G)) (* Dijkstra on Persistent Directed Abstract Labeled Graphs *) module G2 = Persistent.Digraph.AbstractLabeled(Int)(Int) module Test2 = TestDijkstra(G2)(Builder.P(G2)) (* Dijkstra on Imperative Hashed Directed Labeled Graphs *) module G3 = Imperative.Digraph.ConcreteLabeled(Int)(Int) module Test3 = TestDijkstra(G3)(Builder.I(G3)) end (********************************************) (* Traversal *) (********************************************) module Traversal = struct module G = Imperative.Digraph.AbstractLabeled(Int)(Int) module Dfs = Traverse.Dfs(G) module Mark = Traverse.Mark(G) let g = G.create () let newv g = let v = G.V.create 0 in G.add_vertex g v; v let v1 = newv g let v2 = newv g let v3 = newv g let v4 = newv g let v5 = newv g let add_edge g v1 l v2 = G.add_edge_e g (G.E.create v1 l v2) let () = add_edge g v1 10 v2; add_edge g v2 50 v3; add_edge g v1 30 v4; add_edge g v1 100 v5; add_edge g v3 10 v5; add_edge g v4 20 v3; add_edge g v4 60 v5 let () = assert (not (Mark.has_cycle g) && not (Dfs.has_cycle g)) let v6 = newv g let () = assert (not (Mark.has_cycle g) && not (Dfs.has_cycle g)) let () = add_edge g v5 10 v1 let () = assert (Mark.has_cycle g && Dfs.has_cycle g) (* debug dfs / Cormen p 479 *) let g = G.create () let newv i = let v = G.V.create i in G.add_vertex g v; v let u = newv 1 let v = newv 2 let w = newv 3 let x = newv 4 let y = newv 5 let z = newv 6 let edge a b = add_edge g a 0 b let () = edge u v; edge u x; edge v y; edge w y; edge w z; edge x v; edge y x; edge z z open Format let pre v = printf "pre %d@." (G.V.label v) let post v = printf "post %d@." (G.V.label v) let () = printf "iter:@."; Dfs.iter_component ~pre ~post g w let () = printf "prefix:@."; Dfs.prefix_component pre g w let () = printf "step:@."; let rec visit it = let v = Dfs.get it in printf "visit %d@." (G.V.label v); visit (Dfs.step it) in try visit (Dfs.start g) with Exit -> () end (********************************************) (* Ford-Fulkerson and Goldberg *) (********************************************) module FF_Goldberg = struct module G = Persistent.Digraph.ConcreteLabeled(Int)(Int) let add_edge g v1 l v2 = G.add_edge_e g (G.E.create v1 l v2) let g = G.empty let g = add_edge g 1 16 2 let g = add_edge g 1 13 3 let g = add_edge g 2 10 3 let g = add_edge g 3 4 2 let g = add_edge g 2 12 4 let g = add_edge g 4 9 3 let g = add_edge g 3 14 5 let g = add_edge g 5 7 4 let g = add_edge g 4 20 6 let g = add_edge g 5 4 6 module F = struct type label = int type t = int let max_capacity x = x let min_capacity _ = 0 let flow _ = 0 let add = (+) let sub = (-) let compare = compare let zero = 0 end module FF = Flow.Ford_Fulkerson(G)(F) module Gold = Flow.Goldberg(G)(F) let () = assert (snd (FF.maxflow g 1 6) = 23); assert (snd (Gold.maxflow g 1 6) = 23); assert (snd (FF.maxflow g 1 1) = 0); assert (snd (Gold.maxflow g 1 1) = 0) module G2 = Persistent.Digraph.ConcreteLabeled (Int) (struct include Util.OTProduct(Int)(Int) let default = 0, 0 end) let add_edge g v1 l v2 = G2.add_edge_e g (G2.E.create v1 l v2) let g = G2.empty let g = add_edge g 1 (1, 1) 2 let g = add_edge g 1 (3, 0) 3 let g = add_edge g 2 (1, 1) 3 let g = add_edge g 3 (1, 0) 2 let g = add_edge g 2 (3, 0) 4 let g = add_edge g 3 (1, 1) 4 module F2 = struct type label = int * int type t = int let max_capacity = fst let min_capacity _ = 0 let flow = snd let add = (+) let sub = (-) let compare = compare let zero = 0 end module FF2 = Flow.Ford_Fulkerson(G2)(F2) module Gold2 = Flow.Goldberg(G2)(F2) let () = assert (snd (FF2.maxflow g 1 4) = 2); assert (snd (Gold2.maxflow g 1 4) = 2) end (********************************************) (* Neighbourhood *) (********************************************) module Neighbourhood = struct module G = Graph.Imperative.Graph.Concrete(Int) open G let g = create () let add = add_edge g let () = add 1 2; add 1 3; add 1 4; add 2 5; add 3 5; add 4 5; add 5 6 module N = Oper.Neighbourhood(G) module V = N.Vertex_Set let s2 = V.add 1 (V.singleton 5) let () = assert (V.equal (N.set_from_vertex g 2) s2) let s25 = V.add 1 (V.add 3 (V.add 4 (V.singleton 6))) let () = assert (V.equal (N.set_from_vertices g [ 2; 5 ]) s25) end (********************************************) (* Minimal seperators *) (********************************************) module Minsep = struct module P = struct module G = Graph.Persistent.Graph.Concrete(Int) open G let g = empty let g = add_edge g 1 2 let g = add_edge g 1 3 let g = add_edge g 1 4 let g = add_edge g 2 5 let g = add_edge g 3 5 let g = add_edge g 4 5 let g = add_edge g 5 6 module M = Minsep.P(G) module S = M.Vertex_Set module VS = M.VSetset let s5 = S.singleton 5 let s15 = S.add 1 s5 let s234 = S.add 2 (S.add 3 (S.singleton 4)) let bigs = VS.add s5 (VS.add s15 (VS.singleton s234)) let () = assert (VS.equal (M.set_of_allminsep g) bigs) end module I = struct module G = Graph.Imperative.Graph.Abstract(struct type t = unit end) open G let g = create () let v1 = V.create () let v2 = V.create () let v3 = V.create () let v4 = V.create () let v5 = V.create () let v6 = V.create () let add = add_edge g let () = add v1 v2; add v1 v3; add v1 v4; add v2 v5; add v3 v5; add v4 v5; add v5 v6 module M = Minsep.I(G) module S = M.Vertex_Set module VS = M.VSetset let s5 = S.singleton v5 let s15 = S.add v1 s5 let s234 = S.add v2 (S.add v3 (S.singleton v4)) let bigs = VS.add s5 (VS.add s15 (VS.singleton s234)) let () = let _ = G.copy g in assert (VS.equal (M.set_of_allminsep g) bigs) end end (********************************************) (* Checking signature *) (********************************************) (* check that signature [Sig_pack.S] (which is manually expanded) does not forget anything *) module type RightSigPack = sig include Sig.IM with type V.label = int and type E.label = int val find_vertex : t -> int -> V.t include Oper.S with type g = t module Dfs : sig val iter : ?pre:(V.t -> unit) -> ?post:(V.t -> unit) -> t -> unit val prefix : (V.t -> unit) -> t -> unit val postfix : (V.t -> unit) -> t -> unit val iter_component : ?pre:(V.t -> unit) -> ?post:(V.t -> unit) -> t -> V.t -> unit val prefix_component : (V.t -> unit) -> t -> V.t -> unit val postfix_component : (V.t -> unit) -> t -> V.t -> unit val has_cycle : t -> bool end module Bfs : sig val iter : (V.t -> unit) -> t -> unit val iter_component : (V.t -> unit) -> t -> V.t -> unit end module Marking : sig val dfs : t -> unit val has_cycle : t -> bool end module Classic : sig val divisors : int -> t val de_bruijn : int -> t val vertex_only : int -> t val full : ?self:bool -> int -> t end module Rand : sig val graph : ?loops:bool -> v:int -> e:int -> unit -> t val labeled : (V.t -> V.t -> E.label) -> ?loops:bool -> v:int -> e:int -> unit -> t end module Components : sig val scc : t -> int*(V.t -> int) val scc_array : t -> V.t list array val scc_list : t -> V.t list list end val shortest_path : t -> V.t -> V.t -> E.t list * int val ford_fulkerson : t -> V.t -> V.t -> (E.t -> int) * int val goldberg : t -> V.t -> V.t -> (E.t -> int) * int val dot_output : t -> string -> unit end module TestSigPack : RightSigPack = struct include Pack.Digraph type g = t end (* Local Variables: compile-command: "make -C .. check" End: *) ocamlgraph-1.8.3/tests/bench.ml0000644000175000017500000000542012133565071015355 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format (* bench program for Ocamlgraph *) module Time = struct open Unix let utime f x = let u = (times()).tms_utime in let y = f x in let ut = (times()).tms_utime -. u in (y,ut) let print f x = let (y,ut) = utime f x in printf "user time: %2.2f@." ut; y end open Graph module Bench (G : Sig.G with type V.label = int) (B : Builder.S with module G = G) = struct module R = Rand.Make(B) (*1. Parcours *) module Dfs = Traverse.Dfs(G) (* détection de cycle *) let has_cycle v e = let g = R.graph ~v ~e () in let b,t = Time.utime Dfs.has_cycle g in printf "v = %d e = %d cycle = %b time = %2.2f@." v e b t; b let bench1 () = (* on augmente E jusqu'à trouver un cycle *) let v = 20000 in let e = ref 1 in while not (has_cycle v !e) do e := 2 * !e done (* résultats : le temps d'une recherche de cycle négative ne dépend pas de E et est d'environ 1s pour 10^6 noeuds *) (* 2. composantes fortement connexes *) module C = Components.Make(G) let bench2 () = for i = 1 to 100 do let v = i * i in let d = Random.float 1.0 in let e = truncate (let x = d *. (float v -. 1.0) in x *. x) in let g = R.graph ~v ~e () in let _,t = Time.utime C.scc g in printf "v = %d e = %d d = %1.2f time = %2.2f@." v e d t done (* résultats : voir results.bench2.txt *) let () = bench2 () end module B1 = Bench(Pack.Digraph)(Builder.I(Pack.Digraph)) ocamlgraph-1.8.3/tests/nonneg.ml0000644000175000017500000000474012133565071015566 0ustar mehdimehdi (* Test file for module [Nonnegative] *) open Printf open Graph open Pack.NonnegDigraph open Nonnegative let test () = let v = Array.init 10 V.create in let g = create () in let test result op = begin try op g; with | Assert_failure _ -> print_string "bug bug bug?"; assert false | exc -> let exc_name = Printexc.to_string exc in if exc_name = "Nonnegative.Imperative(G)(W).Negative_cycle(_)" then assert (not result) else begin print_endline exc_name; Printexc.print_backtrace stdout; assert false end end; flush_all (); display_with_gv g in let add s t g = add_edge g v.(s) v.(t) in let add_e s w t g = add_edge_e g (E.create v.(s) w v.(t)) in let rem s t g = remove_edge g v.(s) v.(t) in let rem_v s g = remove_vertex g v.(s) in let rem_e s w t g = remove_edge_e g (E.create v.(s) w v.(t)) in test true (add 0 1); test true (rem 0 1); clear g; test true (add_e 0 1 1); test true (add_e 0 1 1); test true (rem 0 1); clear g; test true (add 0 1); test true (add_e 0 1 1); test true (rem 0 1); test true (rem_v 0 ); test true (rem_v 1 ); clear g; test true (add_e 2 1 3); test true (add_e 3 2 4); test true (add_e 0 (-1) 2); test true (add_e 3 1 4); test false (add_e 4 (-4) 2); test false (add_e 4 (-3) 2); test true (add_e 4 (-2) 2); test true (add_e 1 3 2); test true (add_e 5 (-2) 4); test false (add 2 5); test true (add_e 2 4 5); test true (rem 2 3); test true (rem_v 2 ); clear g; test false (add_e 1 (-1) 1); test true (add 1 1); test true (add_e 1 1 1); test true (add_e 1 1 2); test false (add_e 2 (-2) 1); test true (rem_v 1 ); clear g; test true (add 1 2); test true (add_e 2 1 3); test true (add_e 3 2 4); test true (add_e 4 3 1); test true (add 5 6); test true (add_e 6 1 7); test true (add_e 7 2 8); test true (add_e 8 3 5); test true (add_e 1 (-3) 5); test false (add_e 8 (-4) 4); test true (add_e 8 (-3) 4); test true (rem 1 5); assert false; (* FIXME: Bug in choosing new source *) clear g; printf "All test succeeded.\n"; () let _ = test () ocamlgraph-1.8.3/tests/test_topsort.ml0000644000175000017500000000433312133565071017051 0ustar mehdimehdi (* Test file for topological sort *) open Format open Graph open Pack.Digraph let test ?(check=true) iter n edges = let v = Array.init n V.create in let g = create () in let () = Array.iter (add_vertex g) v in let build (s,t) = add_edge g v.(s) v.(t) in List.iter build edges; (* run top sort *) let num = Array.make n 0 in let i = ref 0 in iter (fun v -> incr i; num.(V.label v) <- !i) g; let r = Array.init n (fun i -> i) in Array.sort (fun i j -> num.(i) - num.(j)) r; if check then for v = 0 to n-1 do printf "%d " r.(v) done; printf "@."; (* check *) let path = PathCheck.check_path (PathCheck.create g) in let check_edge (x,y) = let vx = v.(x) and vy = v.(y) in printf "x=%d y=%d num(x)=%d num(y)=%d@." x y num.(x) num.(y); printf "x-->y=%b y-->x=%b@." (path vx vy) (path vy vx); assert (num.(x) > 0 && num.(y) > 0); assert (num.(x) >= num.(y) || path vx vy || not (path vy vx)) in if check then for x = 0 to n-1 do for y = 0 to n-1 do check_edge (x,y) done done; (* display_with_gv g; *) () let tests iter = let test = test iter in test 3 [0,1; 1,2]; test 3 []; (* 1-cycle *) test 1 [0,0]; (* 2-cycle *) test 2 [0,1; 1,0]; (* 2-cycle with out edge *) test 3 [0,1; 1,0; 1,2]; test 3 [2,0; 0,2; 0,1]; test 3 [1,2; 2,1; 2,0]; (* 2 loops *) test 5 [1,2; 2,1; 2,0; 3,4; 4,3]; (* 2-cycle with in edge *) test 3 [1,2; 2,1; 0,2]; test 3 [1,2; 2,1; 0,1]; (* 2 cycles connected *) test 4 [0,1; 1,0; 2,3; 3,2; 2,1]; test 4 [0,1; 1,0; 2,3; 3,2; 1,2]; test 4 [0,1; 1,0; 2,3; 3,2; 1,2; 2,1]; (* 3-cycle with in and out edges *) test 5 [0,1; 1,2; 2,0; 3,0; 2,4]; (* 3 cycles in a row *) test 7 [0,1; 1,0; 1,2; 2,3; 3,2; 3,4; 4,5; 5,6; 6,4]; (* 3 cycles with 2 cycles in a cycle *) test 7 [0,1; 1,0; 1,2; 2,3; 3,2; 3,4; 4,5; 5,6; 6,4; 5,2]; printf "All tests succeeded.@." let () = tests Topological.iter (* let () = tests Topological.iter_stable *) let n = int_of_string Sys.argv.(1) let () = let el = ref [] in (* linear graph *) (* for i = 0 to n-2 do el := (i,i+1) :: !el done; *) (* for i = 0 to n-2 do el := (i+1,i) :: !el done; *) el := [n-1,0]; for i = 0 to n-2 do el := (i,i+1) :: !el done; test ~check:false Topological.iter n !el ocamlgraph-1.8.3/tests/test.ml0000644000175000017500000001667112133565071015267 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) open Format open Graph module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 let tostring v = string_of_int v end module G = Imperative.Digraph.AbstractLabeled(Int)(Int) module T = Traverse.Dfs(G) let test_hash_cycle n = let g = G.create () in let h = Hashtbl.create 5003 in for i = 0 to n-1 do Hashtbl.add h i (G.V.create i) done; Hashtbl.iter (fun _ v -> G.add_vertex g v) h; let v = Hashtbl.find h in for i = 0 to n-2 do G.add_edge g (v i) (v (i+1)) done; assert (not (T.has_cycle g)); G.add_edge g (v (n-1)) (v 0); assert (T.has_cycle g) let () = test_hash_cycle 1_000 (* module Int = struct type t = int let compare = compare let hash = Hashtbl.hash end module G = Fun.DirectedLabeled(Int)(Int) let g = G.empty let g = G.add_vertex 1 g let g = G.add_edge_and_vertex 1 10 2 g let g = G.add_edge_and_vertex 2 50 3 g let g = G.add_edge_and_vertex 1 30 4 g let g = G.add_edge_and_vertex 1 100 5 g let g = G.add_edge_and_vertex 3 10 5 g let g = G.add_edge_and_vertex 4 20 3 g let g = G.add_edge_and_vertex 4 60 5 g let g = G.remove_vertex 4 g let gc = G.add_edge_and_vertex 5 10 1 g let gc = G.add_vertex 6 gc module W = struct type label = int type t = int let weight x = x let zero = 0 let add = (+) let compare = compare end module Dij = Dijkstra.Make(G)(Int)(W) let p,w = Dij.shortest_path gc 1 5 open G.Edge open Printf let () = List.iter (fun e -> printf "[%d -> %d]" (src e) (dst e)) p; printf "\n" *) (* module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) end module G = Fun.Simple(Int) let g = G.empty let g = G.add_vertex 1 g let g = G.add_vertex 2 g let g = G.add_vertex 3 g let g = G.add_vertex 4 g let g = G.add_vertex 5 g let g = G.add_vertex 6 g let g = G.add_vertex 7 g let g = G.add_vertex 8 g let g = G.add_vertex 9 g let g = G.add_vertex 10 g let g = G.add_vertex 11 g let g = G.add_vertex 12 g let g = G.add_vertex 13 g let g = G.add_vertex 14 g let g = G.add_vertex 15 g let g = G.add_edge 1 2 g let g = G.add_edge 1 6 g let g = G.add_edge 2 3 g let g = G.add_edge 2 4 g let g = G.add_edge 2 5 g let g = G.add_edge 3 1 g let g = G.add_edge 4 3 g let g = G.add_edge 4 5 g let g = G.add_edge 5 1 g let g = G.add_edge 6 7 g let g = G.add_edge 6 10 g let g = G.add_edge 6 11 g let g = G.add_edge 7 5 g let g = G.add_edge 7 8 g let g = G.add_edge 7 9 g let g = G.add_edge 8 5 g let g = G.add_edge 9 8 g let g = G.add_edge 10 11 g let g = G.add_edge 12 10 g let g = G.add_edge 12 11 g let g = G.add_edge 13 9 g let g = G.add_edge 13 11 g let g = G.add_edge 13 15 g let g = G.add_edge 14 13 g let g = G.add_edge 15 14 g module Conv = Components.Make(G) open Printf let l = Conv.strongly_connected_components g let _ = List.iter (fun c -> Conv.S.iter (printf "%d ") c; printf "\n") l *) (* module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 let tostring v = string_of_int v end module UF = Unionfind.Make(Int) module G = Persistent.Graph.ConcreteLabeled(Int)(Int) let g = G.empty let v1 = G.V.create 1 let g = G.add_vertex g v1 let v2 = G.V.create 2 let g = G.add_vertex g v2 let v3 = G.V.create 3 let g = G.add_vertex g v3 let v4 = G.V.create 4 let g = G.add_vertex g v4 let v5 = G.V.create 5 let g = G.add_vertex g v5 let v6 = G.V.create 6 let g = G.add_vertex g v6 let v7 = G.V.create 7 let g = G.add_vertex g v7 let v8 = G.V.create 8 let g = G.add_vertex g v8 let v9 = G.V.create 9 let g = G.add_vertex g v9 let v10 = G.V.create 10 let g = G.add_vertex g v10 let g = G.add_edge_e g (G.E.create v1 4 v4) let g = G.add_edge_e g (G.E.create v1 11 v5) let g = G.add_edge_e g (G.E.create v1 8 v2) let g = G.add_edge_e g (G.E.create v2 7 v3) let g = G.add_edge_e g (G.E.create v2 13 v5) let g = G.add_edge_e g (G.E.create v2 9 v6) let g = G.add_edge_e g (G.E.create v3 12 v6) let g = G.add_edge_e g (G.E.create v3 11 v7) let g = G.add_edge_e g (G.E.create v4 14 v5) let g = G.add_edge_e g (G.E.create v4 17 v8) let g = G.add_edge_e g (G.E.create v5 13 v8) let g = G.add_edge_e g (G.E.create v5 5 v9) let g = G.add_edge_e g (G.E.create v5 10 v6) let g = G.add_edge_e g (G.E.create v6 9 v7) let g = G.add_edge_e g (G.E.create v6 6 v9) let g = G.add_edge_e g (G.E.create v6 2 v10) let g = G.add_edge_e g (G.E.create v7 10 v10) let g = G.add_edge_e g (G.E.create v8 3 v9) let g = G.add_edge_e g (G.E.create v9 12 v10) module K = Kruskal.Make(G)(Int)(UF) open Printf let l = K.spanningtree g let _ = List.iter (fun e -> printf "%d - %d\n" (G.E.src e) (G.E.dst e) ) l *) (* open Graph *) (* module IntInt = struct *) (* type t = int * int *) (* end *) (* module String = struct *) (* type t = string *) (* let compare = compare *) (* let hash = Hashtbl.hash *) (* let equal = (=) *) (* let default = "" *) (* end *) (* module G = Imperative.Graph.AbstractLabeled(IntInt)(String) *) (* module Display = struct *) (* include G *) (* let vertex_name v = *) (* let x,y = V.label v in string_of_int x^","^string_of_int y *) (* let graph_attributes _ = [] *) (* let default_vertex_attributes _ = [] *) (* let vertex_attributes _ = [] *) (* let default_edge_attributes _ = [] *) (* let edge_attributes e = let s = E.label e in [`Label s] *) (* let get_subgraph _ = None *) (* end *) (* module Dot = Graphviz.Dot(Display) *) (* module Neato = Graphviz.Neato(Display) *) (* module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 let tostring v = string_of_int v end module G = Persistent.Digraph.Concrete(Int) let g = G.empty let v1 = G.V.create 1 let g = G.add_vertex g v1 let v2 = G.V.create 2 let g = G.add_vertex g v2 let v3 = G.V.create 3 let g = G.add_vertex g v3 let v4 = G.V.create 4 let g = G.add_vertex g v4 let v5 = G.V.create 5 let g = G.add_vertex g v5 let v6 = G.V.create 6 let g = G.add_vertex g v6 let v7 = G.V.create 7 let g = G.add_vertex g v7 let v8 = G.V.create 8 let g = G.add_vertex g v8 let v9 = G.V.create 9 let g = G.add_vertex g v9 let v10 = G.V.create 10 let g = G.add_vertex g v10 let g = G.add_edge g v1 v8 let g = G.add_edge g v8 v1 module Toposort = Topological.Make(G) let _ = Toposort.iter (fun v-> Printf.printf "%d " v) g *) ocamlgraph-1.8.3/tests/strat.ml0000644000175000017500000001014012133565071015426 0ustar mehdimehdi(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2004-2007 *) (* Sylvain Conchon, Jean-Christophe Filliatre and Julien Signoles *) (* *) (* This software is free software; you can redistribute it and/or *) (* modify it under the terms of the GNU Library General Public *) (* License version 2, with the special exception on linking *) (* described in file LICENSE. *) (* *) (* This software 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. *) (* *) (**************************************************************************) (* $Id:$ *) open Graph module V = struct type t = bool * int let compare = compare let hash = Hashtbl.hash let equal = (=) end module G = Persistent.Digraph.Concrete(V) module P = struct type vertex = V.t type t = vertex * (vertex list) * (vertex -> bool) let get_initial (i, _, _) = i let is_final (_, f, _) v = List.mem v f let turn (_, _, f) v = f v end module S = struct type vertex = V.t type t = vertex -> vertex let empty = fun _ -> raise (Invalid_argument "Strategy definition") let next f v = f v let add s v v' = fun e -> if V.equal e v then v' else next s e end module A = Strat.Algo(G)(P)(S);; (* Match game : n matches in line, two players. Each player takes one, two or three matches in order. The player who takes the last match loses. *) (* States are given by the remaining number of matches and the player whose turn it is to play. Edges are the possible moves. *) let rec trans_aux g (j, n) = if n = 0 then g else if n = 1 then let g = G.add_edge g (j, n) (not j, n - 1) in (if j then trans_aux g (not j, n) else trans_aux g (not j, n - 1)) else if n = 2 then let g = G.add_edge g (j, n) (not j, n - 1) in let g = G.add_edge g (j, n) (not j, n - 2) in (if j then trans_aux g (not j, n) else trans_aux g (not j, n - 1)) else let g = G.add_edge g (j, n) (not j, n - 1) in let g = G.add_edge g (j, n) (not j, n - 2) in let g = G.add_edge g (j, n) (not j, n - 3) in (if j then trans_aux g (not j, n) else trans_aux g (not j, n - 1));; let trans n = trans_aux G.empty (true, n);; let p n = ((true, n), [(true, 0)], fun (b, _) -> b);; (* ex n = ((true, _), _) if there is a winning strategy for the first player to play. In this case, it provides a strategy. *) let ex n = let t = trans n in (A.strategyA t (p n), t);; let n1 = 15;; let n2 = 13;; let ex1 = ex n1;; let ex2 = ex n2;; (* Printing on the standard out channel ; simply uncomment to see the results. *) (* let rec couple_of_strat g s = let f v l = try let v' = S.next s v in (v, v') :: l with Invalid_argument _ -> l in G.fold_vertex f g [];; let string_of_couple ((_, i1), (_, i2)) = "(" ^ (string_of_int i1) ^ ", " ^ (string_of_int i2) ^ ") ";; let rec string_of_couple_list l = match l with [] -> "" | e :: l' -> (string_of_couple e) ^ (string_of_couple_list l');; print_newline();; print_string ("For " ^ (string_of_int n1) ^ " matches, is there a winning strategy for the first player ?");; print_newline();; print_string (string_of_bool (fst (fst ex1)));; print_string " --- ";; print_string (string_of_couple_list (couple_of_strat (snd ex1) (snd (fst ex1))));; print_newline();; print_newline();; print_string ("For " ^ (string_of_int n2) ^ " matches, is there a winning strategy for the first player ?");; print_newline();; print_string (string_of_bool (fst (fst ex2)));; print_newline();; print_newline();; *) ocamlgraph-1.8.3/tests/testgraphml.ml0000644000175000017500000000336412133565071016635 0ustar mehdimehdi(******************************************************************************) (* *) (* Copyright (C) 2012 Pietro Abate *) (* *) (* This library is free software: 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, either version 3 of the *) (* License, or (at your option) any later version. A special linking *) (* exception to the GNU Lesser General Public License applies to this *) (* library, see the COPYING file for more information. *) (* *) (******************************************************************************) module V = struct type t = int let compare = compare let hash i = i let equal = (=) end module G = Graph.Imperative.Digraph.ConcreteBidirectional(V) module Gr = struct include G let vertex_properties = ["id1","string",None; "id2","string",Some "2"] let edge_properties = ["ed", "string",Some "3"] let map_edge e = ["ed", string_of_int (E.dst e)] let map_vertex v = [ "id1", string_of_int v ; "id2", string_of_int v] let vertex_uid = G.V.hash let edge_uid e = Hashtbl.hash (vertex_uid (G.E.src e), G.E.label e, vertex_uid (G.E.dst e)) end module GraphPrinter = Graph.Graphml.Printer(Gr) let print g = GraphPrinter.fprintf stdout g let () = let g = G.create () in G.add_vertex g 1; G.add_vertex g 2; G.add_vertex g 3; G.add_edge g 1 2; G.add_edge g 1 3; print g;; ocamlgraph-1.8.3/tests/test_bf.ml0000644000175000017500000000237012133565071015725 0ustar mehdimehdi (* Test file for Bellman-Ford *) open Printf open Graph open Pack.Digraph let test has_cycle spec = let v = Array.init 5 V.create in let g = create () in let () = Array.iter (add_vertex g) v in let build (s,w,t) = add_edge_e g (E.create v.(s) w v.(t)) in List.iter build spec; begin try let cycle = bellman_ford g v.(1) in let print_edge e = printf "%d --(%d)--> %d\n" (V.label (E.src e)) (E.label e) (V.label (E.dst e)) in List.iter print_edge cycle; assert has_cycle with Not_found -> printf "Not found \n"; assert (not has_cycle) end; flush stdout; display_with_gv g let () = test true [ 0, (-3), 1; 1, 1, 2; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test true [ 0, (-10), 1; 1, 1, 2; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test true [ 0, (-10), 1; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test true [ 0, (-10), 1; 1, 1, 2; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test true [ 0, (-10), 1; 1, 1, 2; 2, 1, 0; 3, 1, 4; 4, 1, 0 ]; test true [ 0, (-10), 1; 1, 1, 2; 2, 1, 0; 1, 1, 3; 4, 1, 0 ]; test false [ 1, 1, 2; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test false [ 0, (-10), 1; 1, 1, 2; 1, 1, 3; 3, 1, 4; ]; printf "All tests succeeded.\n"