ocamlgraph-2.0.0/0000755000175000001440000000000013735627615012211 5ustar rtusersocamlgraph-2.0.0/src/0000755000175000001440000000000013735627615013000 5ustar rtusersocamlgraph-2.0.0/src/dot.mli0000644000175000001440000000371613735627615014300 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/md.mli0000644000175000001440000000441013735627615014102 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/dGraphSubTree.ml0000644000175000001440000002420513735627615016034 0ustar rtusers(**************************************************************************) (* *) (* This file is part of OcamlGraph. *) (* *) (* Copyright (C) 2009-2010 *) (* CEA (Commissariat � l'�nergie Atomique) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation, version 2.1, with a linking exception. *) (* *) (* It is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) (* See the file ../LICENSE for more details. *) (* *) (* Authors: *) (* - Julien Signoles (Julien.Signoles@cea.fr) *) (* - Jean-Denis Koeck (jdkoeck@gmail.com) *) (* - Benoit Bataille (benoit.bataille@gmail.com) *) (* *) (**************************************************************************) module type G = sig type t module V : sig type t type label val label : t -> label val hash : t -> int val equal : t -> t -> bool end module E : sig type t end val iter_succ : (V.t -> unit) -> t -> V.t -> unit val iter_pred : (V.t -> unit) -> t -> V.t -> unit val find_edge : t -> V.t -> V.t -> E.t end module type Tree = sig type t module V : sig type t type label val create : label -> t val label : t -> label val hash: t -> int val equal: t -> t -> bool end module E : Sig.EDGE with type vertex = V.t val create : ?size:int -> unit -> t val add_vertex : t -> V.t -> unit val add_edge_e : t -> E.t -> unit end module type S = sig module Tree: Tree with type E.label = unit type t val get_structure : t -> Tree.t val get_root : t -> Tree.V.t val get_tree_vertices : Tree.V.label -> t -> Tree.V.t list val is_ghost_node : Tree.V.t -> t -> bool val is_ghost_edge : Tree.E.t -> t -> bool exception Ghost_node val get_graph_vertex : Tree.V.t -> t -> Tree.V.label end module Build (G : G) (Tree : Tree with type V.label = G.V.t and type E.label = unit) (GA: sig type t val iter_succ: (G.V.t -> unit) -> t -> G.V.t -> unit val iter_pred: (G.V.t -> unit) -> t -> G.V.t -> unit end) = struct module Tree = Tree module H = Hashtbl.Make(G.V) module HT = Hashtbl.Make(Tree.V) module HE = Hashtbl.Make (struct type t = Tree.E.t let equal x y = Tree.E.compare x y = 0 let hash = Hashtbl.hash end) type t = { structure: Tree.t; (* the tree itself *) root : Tree.V.t; (* the root *) (* nodes of the tree corresponding to the original nodes *) assoc_vertex_table: Tree.V.t H.t; ghost_vertices: unit HT.t; ghost_edges: unit HE.t; } (* Getter *) let get_structure t = t.structure;; let get_root t = t.root;; (** Give the list of vertices in the tree graph representing a vertex from the old graph *) let get_tree_vertices vertex tree = try H.find_all tree.assoc_vertex_table vertex with Not_found -> assert false;; (** True if the vertex is not to be shown *) let is_ghost_node v tree = HT.mem tree.ghost_vertices v;; (** True if the edge is not to be shown *) let is_ghost_edge e tree = HE.mem tree.ghost_edges e;; exception Ghost_node;; (** Give the old graph vertex represented by a vertex in the tree - @raise Ghost_node if the vertex is a ghost vertex *) let get_graph_vertex vertex tree = if is_ghost_node vertex tree then raise Ghost_node else Tree.V.label vertex;; (* Explore the graph from a vertex and build a tree - Will be used forward and backward *) let build src_graph tree src_vertex tree_root backward_flag depth = let complete_to_depth v missing = let pred_vertex = ref v in let next_vertex = ref v in for _i = 1 to missing - 1 do next_vertex := Tree.V.create (Tree.V.label v); HT.add tree.ghost_vertices !next_vertex (); let new_ghost_edge = if backward_flag then Tree.E.create !next_vertex () !pred_vertex else Tree.E.create !pred_vertex () !next_vertex in Tree.add_edge_e tree.structure new_ghost_edge; HE.add tree.ghost_edges new_ghost_edge (); pred_vertex := !next_vertex; done in let has_succ = ref false in let vertex_visited = H.create 97 in let queue = Queue.create () in H.add vertex_visited src_vertex true; (* Initialize queue *) if depth <> 0 then if backward_flag then GA.iter_pred (fun a -> Queue.add (a, tree_root, depth) queue) src_graph src_vertex else GA.iter_succ (fun a -> Queue.add (a, tree_root, depth) queue) src_graph src_vertex; (* Empty queue *) let rec empty_queue () = if not(Queue.is_empty queue) then begin let vertex, origin_vertex, depth = Queue.take queue in if depth > 0 then begin let new_vertex = Tree.V.create vertex in H.add tree.assoc_vertex_table vertex new_vertex; if backward_flag then begin let new_edge = Tree.E.create new_vertex () origin_vertex in Tree.add_edge_e tree.structure new_edge end else begin let new_edge = Tree.E.create origin_vertex () new_vertex in Tree.add_edge_e tree.structure new_edge end; if not(H.mem vertex_visited vertex) then begin H.add vertex_visited vertex true; let iter f = f (fun a -> Queue.add (a, new_vertex, depth - 1) queue; has_succ := true) src_graph vertex in if backward_flag then iter GA.iter_pred else iter GA.iter_succ; if not !has_succ then complete_to_depth new_vertex depth; has_succ := false; end else if depth <> 1 then begin if backward_flag then GA.iter_pred (fun _ -> has_succ := true) src_graph vertex else GA.iter_succ (fun _ -> has_succ := true) src_graph vertex; if !has_succ then begin let ghost_vertex = Tree.V.create vertex in HT.add tree.ghost_vertices ghost_vertex (); let new_edge = if backward_flag then Tree.E.create ghost_vertex () new_vertex else Tree.E.create new_vertex () ghost_vertex in Tree.add_edge_e tree.structure new_edge; complete_to_depth ghost_vertex (depth-1) end else complete_to_depth new_vertex depth; has_succ := false; end end; empty_queue () end in empty_queue () (* [JS 2010/11/10] trying to simplify the algorithm. Not finish yet let new_build graph tree root troot depth backward = let first = ref true in let q = Queue.create () in (* invariant: [h] contains exactly the vertices which have been pushed *) let must_add_ghost = ref true in let add_tree_vertex v = let tv = if !first then troot else Tree.V.create v in first := false; Tree.add_vertex tree.structure tv; H.add tree.assoc_vertex_table v tv; tv in let add_tree_edge tsrc dst = let tdst = add_tree_vertex dst in let tsrc, tdst = if backward then tdst, tsrc else tsrc, tdst in let e = Tree.E.create tsrc () tdst in Tree.add_edge_e tree.structure e; tdst, e in let push n src dst = if n < depth then Queue.add (dst, n + 1) q; ignore (add_tree_edge src dst); must_add_ghost := false in let loop () = while not (Queue.is_empty q) do let v, n = Queue.pop q in let tv = add_tree_vertex v in must_add_ghost := true; (if backward then GA.iter_pred else GA.iter_succ) (push n tv) graph v; if !must_add_ghost then let tsrc = ref tv in for i = n to depth do let tdst, te = add_tree_edge !tsrc v in HT.add tree.ghost_vertices tdst (); HE.add tree.ghost_edges te (); tsrc := tdst done done in Queue.add (root, 0) q; loop () *) (** Build a tree graph centered on a vertex and containing its predecessors and successors *) let make src_graph src_vertex depth_forward depth_backward = let tree = { structure = Tree.create (); root = Tree.V.create src_vertex; assoc_vertex_table = H.create 97; ghost_vertices = HT.create 17; ghost_edges = HE.create 17; } in H.add tree.assoc_vertex_table src_vertex tree.root; Tree.add_vertex tree.structure tree.root; build src_graph tree src_vertex tree.root false depth_forward; build src_graph tree src_vertex tree.root true depth_backward; (* new_build src_graph tree src_vertex tree.root depth_forward false; new_build src_graph tree src_vertex tree.root depth_backward true;*) tree end module Make (G : G) (Tree : Tree with type V.label = G.V.t and type E.label = unit) = Build(G)(Tree)(G) module Make_from_dot_model (Tree : Tree with type V.label = DGraphModel.DotG.V.t and type E.label = unit) = Build (DGraphModel.DotG) (Tree) (struct type t = DGraphModel.dotg_model let iter_succ f g = g#iter_succ f let iter_pred f g = g#iter_pred f end) ocamlgraph-2.0.0/src/dot_ast.mli0000644000175000001440000000374513735627615015151 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/imperative.mli0000644000175000001440000001316113735627615015652 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/dGraphModel.ml0000644000175000001440000002146113735627615015524 0ustar rtusers(**************************************************************************) (* *) (* 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 XDot 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 exception Multiple_layouts of (G.E.t * edge_layout) list type cluster = string module X = XDot.Make(G) class model layout g : [G.vertex, G.edge, cluster] abstract_model = object (self) (* 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 _ -> 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 e layout.X.edge_layouts with Not_found -> (* if there are several edges from a vertex [v1] to a vertex [v2], they can share the same layout. In that case, one these edges is unfortunately not in the layout table because of key sharing. Try to recover it when possible by creating a list of all possible layouts for the given edge. If there is only one, easy win, otherwise return them all in an exception and let the caller decide what to do *) let layouts = ref [] in self#iter_succ_e (fun e' -> if G.V.equal (self#dst e) (self#dst e') then try let layout = X.HE.find e' layout.X.edge_layouts in if not (List.exists (fun (_, l) -> layout = l) !layouts) then layouts := (e', layout) :: !layouts with Not_found -> ()) (self#src e); match !layouts with | [] -> assert false | [ _, x ] -> x | _ :: _ :: _ -> raise (Multiple_layouts !layouts) 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 = Stdlib.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 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-2.0.0/src/sig.mli0000644000175000001440000003055213735627615014272 0ustar rtusers(**************************************************************************) (* *) (* 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 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 (** {2 Signatures for graph implementations} *) (** Signature for vertices. *) module type VERTEX = sig (** Vertices are {!COMPARABLE}. *) type t include COMPARABLE with type t := t (** 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 edges' weights. *) module type WEIGHT = sig type edge (** Type for graph edges. *) type t (** Type of edges' weights. *) val weight : edge -> 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 (** 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 (* Local Variables: compile-command: "make -C .." End: *) ocamlgraph-2.0.0/src/classic.mli0000644000175000001440000000475213735627615015134 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/graphml.ml0000644000175000001440000000730313735627615014767 0ustar rtusers(******************************************************************************) (* *) (* 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 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 "" prop t 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-2.0.0/src/dot_lexer.mll0000644000175000001440000000631013735627615015473 0ustar rtusers(**************************************************************************) (* *) (* 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 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_ascii 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-2.0.0/src/pack.ml0000644000175000001440000001314613735627615014255 0ustar rtusers(**************************************************************************) (* *) (* 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 Coloring = Coloring.Mark(G) module Classic = Classic.I(G) module Rand = Rand.I(G) module Components = Components.Make(G) module W = struct type edge = G.E.t type t = int let weight e = G.E.label e let zero = 0 let add = (+) let sub = (-) let compare : t -> t -> int = Stdlib.compare end include Path.Dijkstra(G)(W) include Path.Johnson(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 = Stdlib.compare 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_Tarjan(G)(F) let goldberg_tarjan 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 = Stdlib.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 (* 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 = Stdlib.compare let default = 0 end module Digraph = Generic(Imperative.Digraph.AbstractLabeled(I)(I)) module Graph = Generic(Imperative.Graph.AbstractLabeled(I)(I)) ocamlgraph-2.0.0/src/contraction.mli0000644000175000001440000000426213735627615016032 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/dot.ml0000644000175000001440000001556013735627615014127 0ustar rtusers(**************************************************************************) (* *) (* 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 = Stdlib.compare end) 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 _ = 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_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-2.0.0/src/dGraphRandModel.ml0000644000175000001440000000604713735627615016334 0ustar rtusers(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) 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 = Stdlib.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-2.0.0/src/dGraphTreeLayout.mli0000644000175000001440000000514613735627615016734 0ustar rtusers(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) type cluster = string module Make (Tree: Graphviz.GraphWithDotAttrs) (TreeManipulation: sig val is_ghost_node: Tree.V.t -> bool end): sig val from_tree: fontMeasure:( fontName:string -> fontSize:int -> string -> int * int ) -> 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-2.0.0/src/xDot.ml0000644000175000001440000003021213735627615014246 0ustar rtusers(**************************************************************************) (* *) (* 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 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 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 *) (** 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 : Graphviz.GraphWithDotAttrs) = struct module HV = Hashtbl.Make(G.V) (* cannot use an hashtable because no hash function for edges *) module HE = Map.Make (struct type t = G.E.t let compare = G.E.compare 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 = ref HE.empty 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 edge_layouts := HE.add e (read_edge_layout al) !edge_layouts | 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-2.0.0/src/nonnegative.ml0000644000175000001440000006160113735627615015653 0ustar rtusers(**************************************************************************) (* *) (* 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 *) module Imperative (G: Sig.IM) (W: Sig.WEIGHT with type edge = G.E.t) = 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 (G.V.equal 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 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: Sig.WEIGHT with type edge = G.E.t) = 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 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-2.0.0/src/merge.ml0000644000175000001440000002134513735627615014436 0ustar rtusers(**************************************************************************) (* *) (* 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 [] (* – former buggy version – the case where v is neither the source nor the destination of some arrow was not taken into account, so that vertices were just removed 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_vertex g vl = match vl with | [] -> g | v :: vl' -> let to_be_added = identify_extremities g vl in let g = List.fold_left B.remove_vertex g vl' in if to_be_added = [] then B.add_vertex g v else 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 (* To deduce a comparison function on labels from a comparison function on edges *) let compare_label g = try let default_vertex = let a_vertex_of_g = ref None in (try B.G.iter_vertex (fun v -> a_vertex_of_g := Some v ; raise Exit) g with Exit -> ()); match !a_vertex_of_g with | Some v -> v | None -> raise Exit (*hence g is empty*) in fun l1 l2 -> let e1 = B.G.E.create default_vertex l1 default_vertex in let e2 = B.G.E.create default_vertex l2 default_vertex in B.G.E.compare e1 e2 with Exit -> (fun _ _ -> 0) 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 ... DONE – yet not so clean *) Map.Make(struct type t = B.G.E.label let compare = compare_label g 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-2.0.0/src/minsep.ml0000644000175000001440000001105013735627615014622 0ustar rtusers(**************************************************************************) (* *) (* 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: Set.S with type t = N.Vertex_Set.t and type elt = G.V.t = N.Vertex_Set module VSetset = Set.Make(N.Vertex_Set) (* Use [N.Vertex_Set] instead of [Vertex_Set] in order to avoid an error with ocamldoc 4.02. However this change requires to add extra type annotations to module [Vertex_Set] above in order to prevent compilation error with OCaml <= 4.0 :-(. *) 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 _ -> 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-2.0.0/src/graphml.mli0000644000175000001440000000466613735627615015151 0ustar rtusers(******************************************************************************) (* *) (* 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-2.0.0/src/clique.ml0000644000175000001440000000365113735627615014621 0ustar rtusers(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2014-2015 *) (* Giselle Reis *) (* *) (* 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 fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a end module Bron_Kerbosch(G : G) = struct let rec bron_kerbosch cliquelst graph clique candidates used = match (candidates, used) with | ([], []) -> clique :: cliquelst | ([], _) -> cliquelst | (c, u) -> let (_, _, cliques) = List.fold_left ( fun (c, u, acc) v -> (* Get the neighbors ignoring self-loops *) let n = List.filter (fun nb -> not (G.V.equal nb v)) (G.succ graph v) in let c' = List.filter (fun cv -> List.exists (fun v -> G.V.equal v cv) n) c in let u' = List.filter (fun cv -> List.exists (fun v -> G.V.equal v cv) n) u in let c_minus_v = List.filter (fun cv -> not (G.V.equal cv v)) c in ( c_minus_v, (v :: u), bron_kerbosch acc graph (v :: clique) c' u') ) (c, u, []) c in cliques @ cliquelst let maximalcliques g = let vertices = G.fold_vertex (fun v acc -> v :: acc) g [] in bron_kerbosch [] g [] vertices [] end ocamlgraph-2.0.0/src/builder.ml0000644000175000001440000000450513735627615014764 0ustar rtusers(**************************************************************************) (* *) (* 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 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:97 () 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-2.0.0/src/oper.ml0000644000175000001440000001357313735627615014310 0ustar rtusers(**************************************************************************) (* *) (* 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 transitive_reduction : ?reflexive:bool -> g -> g val replace_by_transitive_reduction : ?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) 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) let replace_by_transitive_reduction ?(reflexive=false) g0 = (* first compute reachability in g0 using a DFS from each vertex *) let module H = Hashtbl.Make(G.V) in let module D = Traverse.Dfs(G) in let reachable = H.create (G.nb_vertex g0) in let path_from v = let s = H.create 8 in H.add reachable v s; D.prefix_component (fun w -> H.add s w ()) g0 v in G.iter_vertex path_from g0; let path u v = H.mem (H.find reachable u) v in (* then remove redundant edges *) let phi v g = let g = if reflexive then B.remove_edge g v v else g in G.fold_succ (fun sv g -> G.fold_succ (fun sv' g -> if not (G.V.equal sv sv') && path sv sv' then B.remove_edge g v sv' else g) g v g) g v g in G.fold_vertex phi g0 g0 let transitive_reduction ?(reflexive=false) g0 = replace_by_transitive_reduction ~reflexive (B.copy g0) 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-2.0.0/src/fixpoint.mli0000644000175000001440000001210013735627615015335 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/weakTopological.mli0000644000175000001440000001122313735627615016626 0ustar rtusers(**************************************************************************) (* *) (* 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 © 2015 Thibault Suzanne * École Normale Supérieure, Département d'Informatique * Paris Sciences et Lettres *) (* Original algorithm by François Bourdoncle. See : * "Efficient chaotic iteration strategies with widenings", * Formal Methods in Programming and their Applications, * Springer Berlin Heidelberg, 1993. *) (** Weak topological ordering of the vertices of a graph, as described by François Bourdoncle. Weak topological ordering is an extension of topological ordering for potentially cyclic graphs. A hierarchical ordering of a set is a well-parenthesized permutation of its elements with no consecutive [(]. The elements between two parentheses are called a {e component}, and the first elements of a component is called the {e head}. A weak topological ordering of a graph is a hierarchical ordering of its vertices such that for every edge [u -> v] of the graph, either [u] comes (strictly) before [v], or [v] is the head of a component containing [u]. One may notice that : - For an acyclic graph, every topological ordering is also a weak topological ordering. - For any graph with the vertices [v1, ..., vN], the following trivial weak topological ordering is valid : [(v1 (v2 (... (vN))...))]. Weak topological ordering are useful for fixpoint computation (see {!ChaoticIteration}). This module aims at computing weak topological orderings which improve the precision and the convergence speed of these analyses. @author Thibault Suzanne @see "Efficient chaotic iteration strategies with widenings", François Bourdoncle, Formal Methods in Programming and their Applications, Springer Berlin Heidelberg, 1993 *) (** Minimal graph signature for the algorithm *) 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 (** The type of the elements of a weak topological ordering over a set of ['a]. - [Vertex v] represents a single vertex. - [Component (head, cs)] is a component of the wto, that is a sequence of elements between two parentheses. [head] is the head of the component, that is the first element, which is guaranteed to be a vertex by definition. [cs] is the rest of the component. *) type 'a element = | Vertex of 'a | Component of 'a * 'a t and 'a t (** The type of a sequence of outermost elements in a weak topological ordering. This is also the type of a weak topological ordering over a set of ['a]. *) val fold_left : ('a -> 'b element -> 'a) -> 'a -> 'b t -> 'a (** Folding over the elements of a weak topological ordering. They are given to the accumulating function according to their order. Note that as [element]s present in an ordering of type [t] can contain values of type [t] itself due to the [Component] variant, this function should be used by defining a recursive function [f], which will call [fold_left] with [f] used to define the first parameter. *) module Make : functor (G : G) -> sig val recursive_scc : G.t -> G.V.t -> G.V.t t (** [recursive_scc g root_g] computes a weak topological ordering of the vertices of [g], with the general algorithm recursively computing the strongly connected components of [g]. [root_g] is taken as the root of the graph and must be a valid vertex of [g]. *) end ocamlgraph-2.0.0/src/dGraphRandModel.mli0000644000175000001440000000407313735627615016502 0ustar rtusers(**************************************************************************) (* *) (* 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: Sig.G module GraphAttrs: 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-2.0.0/src/mcs_m.mli0000644000175000001440000000457313735627615014612 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/traverse.ml0000644000175000001440000002457113735627615015176 0ustar rtusers(**************************************************************************) (* *) (* 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 fold f i g = let h = H.create 97 in let s = Stack.create () in let push v = if not (H.mem h v) then begin H.add h v (); Stack.push v s end in let rec loop acc = if not (Stack.is_empty s) then let v = Stack.pop s in let ns = f v acc in G.iter_succ push g v; loop ns else acc in G.fold_vertex (fun v s -> push v; loop s) g i let iter ?(pre=fun _ -> ()) ?(post=fun _ -> ()) g = let h = H.create 97 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 fold_component f i g v0 = let h = H.create 97 in let s = Stack.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 (); Stack.push v s end in push v0; let rec loop acc = if not (Stack.is_empty s) then let v = Stack.pop s in let ns = f v acc in G.iter_succ push g v; loop ns else acc in loop i let iter_component ?(pre=fun _ -> ()) ?(post=fun _ -> ()) g v = let h = H.create 97 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 postfix_component post g = iter_component ~post g module Tail = struct let has_cycle g = let h = H.create 97 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 97 in let father = H.create 97 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 97 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 97 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 (_,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 fold f i (g : G.t) = let h = H.create 97 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 rec loop s = if not (Queue.is_empty q) then let v = Queue.pop q in let ns = f v s in (* Sticking to OCamlGraph's fold conv *) G.iter_succ push g v; loop ns else s in G.fold_vertex (fun v s -> push v; loop s) g i let iter f = fold (fun v () -> f v) () let fold_component f i g v0 = let h = H.create 97 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; let rec loop s = if not (Queue.is_empty q) then let v = Queue.pop q in let ns = f v s in G.iter_succ push g v; loop ns else s in loop i let iter_component f = fold_component (fun v () -> f v) () (* 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,_) = 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-2.0.0/src/topological.ml0000644000175000001440000001202313735627615015644 0ustar rtusers(**************************************************************************) (* *) (* 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: G.V.t * int) = 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) 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 (* 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 97 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-2.0.0/src/delaunay.ml0000644000175000001440000002772213735627615015146 0ustar rtusers(**************************************************************************) (* *) (* 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]. *) 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.make 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-2.0.0/src/classic.ml0000644000175000001440000000624413735627615014761 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/chaoticIteration.mli0000644000175000001440000001470513735627615017003 0ustar rtusers(**************************************************************************) (* *) (* 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 © 2015 Thibault Suzanne * École Normale Supérieure, Département d'Informatique * Paris Sciences et Lettres *) (** Fixpoint computation with widenings using weak topological orderings as defined by François Bourdoncle and implemented in {!WeakTopological}. {!Fixpoint} is another (simpler) fixpoint computation module, with general references. The general idea of fixpoint computation is to iteratively compute the result of the analysis a vertex from the results of its predecessors, until stabilisation is achieved on every vertex. The way to determine, at each step, the next vertex to analyse is called a {e chaotic iteration strategy}. A good strategy can make the analysis much faster. To enforce the termination of the analyse and speed it up when it terminates in too many steps, one can also use a {e widening}, to ensure that there is no infinite (nor too big) sequence of intermediary results for a given vertex. However, it usually results in a loss of precision, which is why choosing a good widening set (the set of points on which the widening will be performed) is mandatory. This module computes a fixpoint over a graph using weak topological ordering, which can be used to get both the iteration strategy and the widening set. The module {!WeakTopological} aims to compute weak topological orderings which are known to be excellent decompositions w.r.t these two critical points. @author Thibault Suzanne @see "Efficient chaotic iteration strategies with widenings", François Bourdoncle, Formal Methods in Programming and their Applications, Springer Berlin Heidelberg, 1993 *) (** How to determine which vertices are to be considered as widening points. - [FromWto] indicates to use as widening points the heads of the weak topological ordering given as a parameter of the analysis function. This will always be a safe choice, and in most cases it will also be a good one with respect to the precision of the analysis. - [Predicate f] indicates to use [f] as the characteristic function of the widening set. [Predicate (fun _ -> false)] can be used if a widening is not needed. This variant can be used when there is a special knowledge of the graph to achieve a better precision of the analysis. For instance, if the graph happens to be the flow graph of a program, the predicate should be true for control structures heads. In any case, a condition for a safe widening predicate is that every cycle of the graph should go through at least one widening point. Otherwise, the analysis may not terminate. Note that even with a safe predicate, ensuring the termination does still require a correct widening definition. *) type 'a widening_set = | FromWto | Predicate of ('a -> bool) (** Minimal graph signature for the algorithm. Sub-signature of [Traverse.G]. *) module type G = sig type t module V : Sig.COMPARABLE module E : sig type t val src : t -> V.t end val fold_pred_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end (** Parameters of the analysis. *) module type Data = sig type t (** Information stored at each vertex. *) type edge (** Edge of the graph. *) val join : t -> t -> t (** Operation to join data when several paths meet. *) val equal : t -> t -> bool (** Equality test for data. *) val analyze : edge -> t -> t (** How to analyze one edge: given an edge and the data stored at its origin, it must compute the resulting data to be stored at its destination. *) val widening : t -> t -> t (** The widening operator. [fun _ x -> x] is correct and is equivalent to not doing widening. Note that to enforce termination, the following property should hold: for all sequence [x_0, x_1, ...] of data, the sequence defined by [y_0 = x_0; y_{i+1} = widening y_i x_i] stabilizes in finite time. *) end module Make (G : G) (D : Data with type edge = G.E.t) : sig module M : Map.S with type key = G.V.t and type 'a t = 'a Map.Make(G.V).t (** Map used to store the result of the analysis *) val recurse : G.t -> G.V.t WeakTopological.t -> (G.V.t -> D.t) -> G.V.t widening_set -> int -> D.t M.t (** [recurse g wto init widening_set widening_delay] computes the fixpoint of the analysis of a graph. This function uses the recursive iteration strategy: it recursively stabilizes the subcomponents of every component every time the component is stabilized (cf. Bourdoncle's paper). @param g The graph to analyse. @param wto A weak topological ordering of the vertices of [g]. @param widening_set On which points to do the widening. @param widening_delay How many computations steps will be done before using widening to speed up the stabilisation. This counter is reset when entering each component, and is shared between all outermost vertices of this component. A negative value means [0]. @param init How to compute the initial analysis data. @return A map from vertices of [g] to their analysis result. *) end ocamlgraph-2.0.0/src/builder.mli0000644000175000001440000000430413735627615015132 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (** {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-2.0.0/src/topological.mli0000644000175000001440000000702213735627615016020 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/strat.ml0000644000175000001440000001406513735627615014475 0ustar rtusers(**************************************************************************) (* *) (* 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' -> (G.V.compare e1 e2 = 0) && (eq l1' l2') | _ -> false let rec eq_mem i l1 l2 = match l1, l2 with [], [] -> (true, false) | e1 :: l1', e2 :: l2' -> if G.V.compare e1 e2 = 0 then if G.V.compare e1 i = 0 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 _ 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 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 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 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 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-2.0.0/src/chaoticIteration.ml0000644000175000001440000001076613735627615016635 0ustar rtusers(**************************************************************************) (* *) (* 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 © 2015 Thibault Suzanne * École Normale Supérieure, Département d'Informatique * Paris Sciences et Lettres *) (* Original algorithm by François Bourdoncle. See : * "Efficient chaotic iteration strategies with widenings", * Formal Methods in Programming and their Applications, * Springer Berlin Heidelberg, 1993. *) let ( |> ) x f = f x type 'a widening_set = | FromWto | Predicate of ('a -> bool) module type G = sig type t module V : Sig.COMPARABLE module E : sig type t val src : t -> V.t end val fold_pred_e : (E.t -> 'a -> 'a) -> t -> V.t -> 'a -> 'a end module type Data = sig type t type edge val join : t -> t -> t val equal : t -> t -> bool val analyze : edge -> t -> t val widening : t -> t -> t end module Make (G : G) (D : Data with type edge = G.E.t) = struct module M = Map.Make (G.V) let recurse g wto init widening_set widening_delay = (* The following two functions are predicates used to know whether to compute a widening when analysing a vertex which is not (resp. is) the head of a WTO component. They will be called only if the specified number of steps before widening has been done. *) let do_nonhead_widen v = match widening_set with | FromWto -> false | Predicate f -> f v in let do_head_widen v = match widening_set with | FromWto -> true | Predicate f -> f v in let find vertex data = try M.find vertex data with Not_found -> init vertex in let analyze_vertex widening_steps do_widen v data = (* Computes the result of the analysis for one vertex *) let result = G.fold_pred_e (fun edge acc -> let src = G.E.src edge in let data_src = find src data in let data_dst = D.analyze edge data_src in D.join data_dst acc) g v (init v) in if widening_steps <= 0 && do_widen v then D.widening (find v data) result else result in let rec analyze_elements widening_steps comp data = (* Computes the result of one iteration of the analysis of the elements of a component. *) WeakTopological.fold_left (analyze_element widening_steps) data comp and stabilize can_stop widening_steps head comps data = (* Iterates the analysis of a component until stabilisation. [can_stop] is [false] if no iteration has been made so far, since at least one is needed before ending with stabilisation. *) let old_data_head = find head data in let new_data_head = analyze_vertex widening_steps do_head_widen head data in if can_stop && D.equal old_data_head new_data_head then data else data |> M.add head new_data_head |> analyze_elements widening_steps comps |> stabilize true (widening_steps - 1) head comps and analyze_element widening_steps data = function (* Computes the result of the analysis of one element *) | WeakTopological.Vertex v -> M.add v (analyze_vertex widening_steps do_nonhead_widen v data) data | WeakTopological.Component (head, comps) -> stabilize false widening_delay head comps data in analyze_elements widening_delay wto M.empty end ocamlgraph-2.0.0/src/pack.mli0000644000175000001440000000327713735627615014432 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/lib/0000755000175000001440000000000013735627615013546 5ustar rtusersocamlgraph-2.0.0/src/lib/heap.ml0000644000175000001440000000702513735627615015021 0ustar rtusers(**************************************************************************) (* *) (* 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 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.make 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.make (- 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 ocamlgraph-2.0.0/src/lib/unionfind.ml0000644000175000001440000000606213735627615016075 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/lib/bitv.ml0000644000175000001440000004447013735627615015055 0ustar rtusers(**************************************************************************) (* *) (* 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.make (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.make (n / bpi) initv } else begin let s = n / bpi in let b = Array.make (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 || 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 || 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 || ofs1 < 0 || ofs1 + len > v1.length || ofs2 < 0 || 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 || len < 0 || 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 || len < 0 || 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 (*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.make 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.make 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.make 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.make 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 = Buffer.create n in for i = 0 to n - 1 do Buffer.add_char s (if unsafe_get v i then '1' else '0') done; Buffer.contents 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 _ = failwith "todo" let of_int64_s _ = failwith "todo" let to_int64_s _ = 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-2.0.0/src/lib/persistentQueue.ml0000644000175000001440000000355213735627615017312 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (** Purely applicative queues implemented in a standard way using a pair of lists (Hood & Melville 1981) *) type 'a t = 'a list * 'a list (** a queue is a pair (prefix, xiffus), with elements popped from prefix and inserted into xiffus invariant: prefix=[] -> xiffus=[] *) let empty = [], [] let is_empty (prefix, _) = prefix = [] let add queue elt = match queue with | [], [] -> [elt], [] | prefix, xiffus -> prefix, elt :: xiffus let head = function | head :: _, _-> head | [], _ -> raise Not_found let tail = function | [_], xiffus -> List.rev xiffus, [] | _ :: prefix, xiffus -> prefix, xiffus | [], _ -> raise Not_found ocamlgraph-2.0.0/src/lib/persistentQueue.mli0000644000175000001440000000256513735627615017466 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (** Purely applicative queues *) type 'a t val empty : 'a t val is_empty : 'a t -> bool val add : 'a t -> 'a -> 'a t val head : 'a t -> 'a val tail : 'a t -> 'a t ocamlgraph-2.0.0/src/lib/unionfind.mli0000644000175000001440000000345413735627615016250 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/lib/heap.mli0000644000175000001440000000466613735627615015202 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (** Priority queues *) module type Ordered = sig type t val compare : t -> t -> int end exception EmptyHeap 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 ocamlgraph-2.0.0/src/lib/bitv.mli0000644000175000001440000001730113735627615015217 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/dGraphTreeModel.ml0000644000175000001440000001751513735627615016351 0ustar rtusers(**************************************************************************) (* *) (* 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: 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 type graph_layout class tree_model : 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) type graph_layout = X.graph_layout 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 e layout.X.edge_layouts 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) ~fontMeasure 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 ~fontMeasure (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-2.0.0/src/dGraphModel.mli0000644000175000001440000000775413735627615015706 0ustar rtusers(**************************************************************************) (* *) (* 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 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 (** @raise Multiple_layouts when there are several possible layouts for the given edge *) 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 : Graphviz.GraphWithDotAttrs) : sig type cluster = string exception Multiple_layouts of (G.E.t * edge_layout) list 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-2.0.0/src/delaunay.mli0000644000175000001440000000654713735627615015321 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/rand.ml0000644000175000001440000002010213735627615014251 0ustar rtusers(**************************************************************************) (* *) (* 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 val gnp : ?loops:bool -> v:int -> prob:float -> unit -> graph val gnp_labeled : (vertex -> vertex -> edge_label) -> ?loops:bool -> v:int -> prob:float -> unit -> 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 (** G(n,p) graphs See https://en.wikipedia.org/wiki/Random_graph *) let gnp_generic add_edge ?(loops=false) ~v ~prob () = if not (0.0 <= prob && prob <= 1.0) then invalid_arg "gnp"; let vertices = Array.init v (fun i -> B.G.V.create i) in let g = Array.fold_left B.add_vertex (B.empty ()) vertices in let g = ref g in for i = 0 to v-1 do for j = 0 to (if G.is_directed then v-1 else i) do if (loops || j <> i) && (prob = 1.0 || Random.float 1.0 < prob) then g := add_edge !g vertices.(i) vertices.(j) done done; !g let gnp ?(loops=false) ~v ~prob () = gnp_generic B.add_edge ~loops ~v ~prob () let gnp_labeled f ?(loops=false) ~v ~prob () = gnp_generic (fun g v1 v2 -> B.add_edge_e g (G.E.create v1 (f v1 v2) v2)) ~loops ~v ~prob () 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 (* Local Variables: compile-command: "make -C .. src/rand.cmo" End: *) ocamlgraph-2.0.0/src/mincut.ml0000644000175000001440000000703113735627615014632 0ustar rtusers(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2013-2014 *) (* David Monniaux, Gabriel Radanne *) (* *) (* 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.VERTEX val succ : t -> V.t -> V.t list end module Make (G : G) = struct module H = Hashtbl.Make (G.V) let find_default htbl x = try H.find htbl x with Not_found -> false let min_cutset gr first_node = let n_labels = H.create 97 in let l_labels = H.create 97 in let already_processed = H.create 97 in let is_already_processed x = find_default already_processed x in let on_the_stack = H.create 97 in let is_on_the_stack x = find_default on_the_stack x in let cut_set = ref [] in let counter = ref 1 in let rec step2 top rest_of_stack = assert (not (is_already_processed top)); assert (not (is_on_the_stack top)); H.add on_the_stack top true; H.add n_labels top !counter; counter := !counter + 1; H.add l_labels top 0; H.add already_processed top true; step3 (G.succ gr top) top rest_of_stack and step3 successors top rest_of_stack = match successors with | successor :: other_successors -> if not (is_already_processed successor) (* step 4 *) then step2 successor ((top,successors)::rest_of_stack) (* step 5 *) else begin let x = if is_on_the_stack successor then H.find n_labels successor else H.find l_labels successor in H.add l_labels top (max (H.find l_labels top) x) ; step3 other_successors top rest_of_stack end | [] -> begin (* step 7 *) if H.find l_labels top = H.find n_labels top then begin cut_set := top::!cut_set ; H.add l_labels top 0 ; end ; (* check added between algorithms C and D *) if H.find l_labels top > H.find n_labels top then raise (Invalid_argument "Graph.Mincut: graph not reducible") (* step 8 *) else match rest_of_stack with | [] -> !cut_set (* SUCCESS *) | (new_top, new_successors)::new_tail -> begin H.add on_the_stack top false; H.add l_labels new_top (max (H.find l_labels top) (H.find l_labels new_top)) ; step3 new_successors new_top new_tail end end in (* step 2 *) step2 first_node [] end ocamlgraph-2.0.0/src/path.mli0000644000175000001440000001275113735627615014445 0ustar rtusers(**************************************************************************) (* *) (* 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 val create : V.t -> label -> V.t -> t end 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 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: Sig.WEIGHT with type edge = G.E.t) : 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: Sig.WEIGHT with type edge = G.E.t) : sig module H : Hashtbl.S with type key = G.V.t and type 'a t = 'a Hashtbl.Make(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 (** Weight signature for Johnson's algorithm. *) module type WJ = sig include Sig.WEIGHT val sub : t -> t -> t (** Subtraction of weights. *) end module Johnson (G: G) (W: WJ with type edge = G.E.t) : sig module HVV : Hashtbl.S with type key = (G.V.t * G.V.t) val all_pairs_shortest_paths : G.t -> W.t HVV.t (** [all_pairs_shortest_paths g] computes the distance of shortest path between all pairs of vertices in [g]. They are returned as a hash table mapping each pair of vertices to their distance. If [g] contains a negative-cycle, raises [NegativeCycle l] where [l] is such a cycle. Complexity: at most O(VElog(V)) *) 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-2.0.0/src/gml.mll0000644000175000001440000001236513735627615014274 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/blocks.ml0000644000175000001440000006567613735627615014633 0ustar rtusers(**************************************************************************) (* *) (* 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 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 _ 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 *) (* Was unused *) 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 = if mem_edge g v1 v2 then g else 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 find v g = try HM.find v g with Not_found -> S.empty, S.empty in let in_set, out_set = find v1 g in let g = HM.add v1 (in_set,S.add v2 out_set) g in let in_set, out_set = find v2 g in HM.add v2 (S.add v1 in_set,out_set) g let add_edge g v1 v2 = if mem_edge g v1 v2 then g else 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 as e) = if mem_edge_e g e then g else 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 find v g = try HM.find v g with Not_found -> S.empty, S.empty in let in_set, out_set = find v1 g in let g = HM.add v1 (in_set,S.add (v2,l) out_set) g in let in_set, out_set = find v2 g in HM.add v2 (S.add (v1,l) in_set,out_set) g let add_edge_e g e = if mem_edge_e g e then g else unsafe_add_edge_e g e 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-2.0.0/src/fixpoint.ml0000644000175000001440000001414013735627615015172 0ustar rtusers(**************************************************************************) (* *) (* 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 initial xs = List.fold_left A.join initial 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 (* get some node from the node-set -- this will eventually trigger an exception *) match (try Some (N.choose wl) with Not_found -> None) with | None -> data | Some n -> (* 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 (initial node) 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 (initial node) 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 in let data = worklist data nodes in (fun n -> M.find n data) end ocamlgraph-2.0.0/src/leaderlist.ml0000644000175000001440000000700713735627615015466 0ustar rtusers(**************************************************************************) (* *) (* 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 G.V.equal 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 *) | _::[] -> 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::_ -> 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-2.0.0/src/dGraphTreeLayout.ml0000644000175000001440000007656213735627615016575 0ustar rtusers(**************************************************************************) (* *) (* 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) *) (* *) (**************************************************************************) 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 html_label : string option; mutable orientation : float option; mutable peripheries : int option; mutable regular : bool option; mutable shape : [ `Ellipse | `Box | `Circle | `Doublecircle | `Diamond | `Oval | `Egg | `Triangle | `Invtriangle | `Trapezium | `Invtrapezium | `House | `Invhouse | `Oval | `Egg | `Triangle | `Invtriangle | `Trapezium | `Invtrapezium | `House | `Invhouse | `Parallelogram | `Doubleoctagon | `Tripleoctagon | `Mdiamond | `Mcircle | `Msquare | `Star | `Underline | `Note | `Tab | `Folder | `Box3d | `Component | `Promoter | `Cds | `Terminator | `Utr | `Primersite | `Restrictionsite | `Fivepoverhang | `Threepoverhang | `Noverhang | `Assembly | `Signature | `Insulator | `Ribosite | `Rnastab | `Proteasesite | `Proteinstab | `Rpromoter | `Rarrow | `Larrow | `Lpromoter | `Plaintext | `Record | `Polygon of int * float ] option; mutable style : [ `Rounded | `Filled | `Solid | `Dashed | `Dotted | `Bold | `Invis ] list; mutable width : float option; mutable fillcolor : int32 option; } let set_vattribute vattrs : Graphviz.DotAttributes.vertex -> _ = 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 | `HtmlLabel l -> vattrs.html_label <- set_if_none vattrs.html_label l | `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 _ | `Penwidth _ | `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; html_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 ~fontMeasure font ptsize s = let width_margin = 20. in let height_margin = 0. in let width, height = fontMeasure ~fontName:font ~fontSize:ptsize s in float width +. width_margin, float height +. height_margin let fill_dimensions ~fontMeasure 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 ~fontMeasure (the vattrs.fontname) (the vattrs.fontsize) (the vattrs.label) 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 | `Rounded -> XDotDraw.Rounded (* 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 (* 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 html_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:eattributes) : edge list -> _ = 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 | `HtmlLabel l :: q -> eattrs.html_label <- set_if_none eattrs.html_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 _ | `Penwidth _ | `Samehead _ | `Sametail _ | `Taillabel _ | `Tailport _ | `Tailurl _ | `Weight _ ) :: 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; html_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 ~fontMeasure 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 ~fontMeasure 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 = ref HE.empty in Tree.iter_edges_e (fun e -> let e_layout = edge_to_edge_layout tree e geometry_info in edge_layouts := HE.add e e_layout !edge_layouts) 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 ((_,_), (_,_) 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 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 (_,_ 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 (_,_ 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 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 = ref HE.empty 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 edge_layouts := HE.add e e_layout !edge_layouts) 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 ((_,_), (_,_) 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-2.0.0/src/minsep.mli0000644000175000001440000000560713735627615015006 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/weakTopological.ml0000644000175000001440000000673713735627615016473 0ustar rtusers(**************************************************************************) (* *) (* 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 © 2015 Thibault Suzanne * École Normale Supérieure, Département d'Informatique * Paris Sciences et Lettres *) (* Original algorithm by François Bourdoncle. See : * "Efficient chaotic iteration strategies with widenings", * Formal Methods in Programming and their Applications, * Springer Berlin Heidelberg, 1993. *) 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 type 'a element = | Vertex of 'a | Component of 'a * 'a t and 'a t = 'a element list let fold_left = List.fold_left module Make (G : G) = struct module HT = Hashtbl.Make(G.V) let recursive_scc g root_g = (* Straight OCaml implementation of the Section 4.3, fig. 4 algorithm in Bourdoncle's paper *) let stack = Stack.create () in let dfn = HT.create 1024 in let num = ref 0 in let partition = ref [] in G.iter_vertex (fun v -> HT.add dfn v 0) g; let rec visit vertex partition = let head = ref 0 in let loop = ref false in Stack.push vertex stack; incr num; HT.replace dfn vertex !num; head := !num; G.iter_succ (fun succ -> let dfn_succ = HT.find dfn succ in let min = if dfn_succ = 0 then visit succ partition else dfn_succ in if min <= !head then begin head := min; loop := true end) g vertex; if !head = HT.find dfn vertex then begin HT.replace dfn vertex max_int; let element = ref (Stack.pop stack) in if !loop then begin while G.V.compare !element vertex <> 0 do HT.replace dfn !element 0; element := Stack.pop stack; done; partition := component vertex :: !partition; end else partition := Vertex vertex :: !partition end; !head and component vertex = let partition = ref [] in G.iter_succ (fun succ -> if HT.find dfn succ = 0 then ignore (visit succ partition : int)) g vertex; Component (vertex, !partition) in let (_ : int) = visit root_g partition in !partition end ocamlgraph-2.0.0/src/xDot.mli0000644000175000001440000001251713735627615014427 0ustar rtusers(**************************************************************************) (* *) (* 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 *) (** 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 : Graphviz.GraphWithDotAttrs) : sig module HV: Hashtbl.S with type key = G.V.t module HE: Map.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-2.0.0/src/kruskal.ml0000644000175000001440000000470113735627615015010 0ustar rtusers(**************************************************************************) (* *) (* 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 $ *) 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-2.0.0/src/util.mli0000644000175000001440000000401313735627615014456 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/xDotDraw.ml0000644000175000001440000002704313735627615015074 0ustar rtusers(**************************************************************************) (* *) (* 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 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 _ -> "" (** 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 ~(fontMeasure: fontName: string -> fontSize:int -> string -> (int * int) ) font size s = let width, height = fontMeasure ~fontName:font ~fontSize:(int_of_float size) s 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 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 get_int state = match get_word state with | Some w -> begin (*let w' = filter_int w in*) try int_of_string w with Failure _ -> raise (ParseError "Cannot parse int") end | None -> raise (ParseError "Cannot parse int") let get_float state = match get_word state with | Some w -> begin try float_of_string w with Failure _ -> raise (ParseError "Cannot parse float") end | None -> raise (ParseError "Cannot parse float") let 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-2.0.0/src/gml.mli0000644000175000001440000000527413735627615014272 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/persistent.mli0000644000175000001440000000752413735627615015713 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/coloring.ml0000644000175000001440000001174113735627615015152 0ustar rtusers(**************************************************************************) (* *) (* 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 exception NoColoring (** Graph coloring with marking. Only applies to imperative graphs with marks. *) module Mark(G : GM) = struct module Bfs = Traverse.Bfs(G) let coloring g k = if G.is_directed then invalid_arg "coloring: directed graph"; (* 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 let two_color g = if G.is_directed then invalid_arg "coloring: directed graph"; (* first, set all colors to 0 *) let erase v = G.Mark.set v 0 in G.iter_vertex erase g; (* then, use dfs to color the nodes *) let rec dfs c v = match G.Mark.get v with | 1 | 2 as cv -> if cv <> c then raise NoColoring (* check for cycles *) | _ -> G.Mark.set v c; G.iter_succ (dfs (1-c)) g v in let start v = match G.Mark.get v with 1 | 2 -> () | _ -> dfs 1 v in G.iter_vertex start g end (** Graph coloring for graphs without marks: we use an external hash table *) 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 add_marks () = let h = H.create 97 in h, (module 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 : GM with type t = G.t and type V.t = G.V.t) let coloring g k = let h, (module GM) = add_marks () in let module M = Mark(GM) in M.coloring g k; h let two_color g = let h, (module GM) = add_marks () in let module M = Mark(GM) in M.two_color g; h end ocamlgraph-2.0.0/src/gmap.mli0000644000175000001440000000572613735627615014441 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/leaderlist.mli0000644000175000001440000000406713735627615015642 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/persistent.ml0000644000175000001440000002366313735627615015544 0ustar rtusers(**************************************************************************) (* *) (* 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 (** 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 = Stdlib.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 = Stdlib.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 = Stdlib.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 = Stdlib.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 = Stdlib.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 Blocks.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 Blocks.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 Blocks.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 Blocks.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-2.0.0/src/mcs_m.ml0000644000175000001440000001406313735627615014434 0ustar rtusers(**************************************************************************) (* *) (* 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) 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 G.V.equal x v then true else if NewV.weight x < maxw || G.V.equal 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 G.V.equal 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) 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 G.V.equal x v then true else if NewV.weight x < maxw || G.V.equal 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 G.V.equal 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-2.0.0/src/prim.ml0000644000175000001440000000575113735627615014311 0ustar rtusers(**************************************************************************) (* *) (* 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 module E : sig type t type label val label : t -> label val dst : t -> V.t val src : t -> V.t val compare : t -> t -> int end val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit end module Make (G: G) (W: Sig.WEIGHT with type edge = G.E.t) = struct open G.E module H = Hashtbl.Make(G.V) module Elt = struct type t = W.t * G.V.t (* 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 Q = Heap.Imperative(Elt) let spanningtree_from g r = let visited = H.create 97 in let key = H.create 97 in let q = Q.create 17 in Q.add q (W.zero, r); while not (Q.is_empty q) do let (_,u) = Q.pop_maximum q in if not (H.mem visited u) then begin H.add visited u (); G.iter_succ_e (fun e -> let v = dst e in if not (H.mem visited v) then begin let wuv = W.weight e in let improvement = try W.compare wuv (fst (H.find key v)) < 0 with Not_found -> true in if improvement then begin H.replace key v (wuv, e); Q.add q (wuv, v) end; end) g u end done; H.fold (fun _ (_, e) acc -> e :: acc) key [] let spanningtree g = let r = ref None in try G.iter_vertex (fun v -> r := Some v; raise Exit) g; invalid_arg "spanningtree" with Exit -> match !r with | None -> assert false | Some r -> spanningtree_from g r end ocamlgraph-2.0.0/src/traverse.mli0000644000175000001440000001263613735627615015346 0ustar rtusers(**************************************************************************) (* *) (* 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 (** It is enough to iter over all the roots (vertices without predecessor) of the graph, even if iterating over the other vertices is correct. *) val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a (** It is enough to fold over all the roots (vertices without predecessor) of the graph, even if folding over the other vertices is correct. *) 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 Classical folds} *) val fold : (G.V.t -> 'a -> 'a) -> 'a -> G.t -> 'a (** The function is applied each time a node is reached for the first time, before idoterating over its successors. Tail-recursive. *) val fold_component : (G.V.t -> 'a -> 'a) -> 'a -> G.t -> G.V.t -> 'a (** Idem, but limited to a single root vertex. *) (** {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 Classical folds} *) val fold : (G.V.t -> 'a -> 'a) -> 'a -> G.t -> 'a val fold_component : (G.V.t -> 'a -> 'a) -> 'a -> G.t -> G.V.t -> 'a (** {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-2.0.0/src/flow.mli0000644000175000001440000000730313735627615014455 0ustar rtusers(**************************************************************************) (* *) (* 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 (** 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-Tarjan maximal flow algorithm} *) (** Minimal graph signature for Goldberg-Tarjan. Sub-signature of {!Sig.G}. *) module type G_GOLDBERG_TARJAN = sig type t module V : Sig.COMPARABLE module E : Sig.EDGE with type vertex = V.t val nb_vertex : t -> int val nb_edges : t -> int val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a 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_Tarjan (G: G_GOLDBERG_TARJAN) (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 Goldberg-Tarjan algorithm (with gap detection heuristic). It returns the flow on each edge 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 type FLOWMIN = sig include FLOW val min_capacity : label -> t end module Ford_Fulkerson (G: G_FORD_FULKERSON) (F: FLOWMIN 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-2.0.0/src/sig_pack.mli0000644000175000001440000003534213735627615015272 0ustar rtusers(**************************************************************************) (* *) (* 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 transitive_reduction : ?reflexive:bool -> t -> t (** [transitive_reduction ?reflexive g] returns the transitive reduction of [g] (as a new graph). Loops (i.e. edges from a vertex to itself) are removed only if [reflexive] is [true] (default is [false]). *) val replace_by_transitive_reduction : ?reflexive:bool -> t -> t (** [replace_by_transitive_reduction ?reflexive g] replaces [g] by its transitive reduction. Meaningless for persistent implementations (then acts as [transitive_reduction]). *) 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 *) val fold : (V.t -> 'a -> 'a) -> 'a -> t -> 'a (** 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 fold_component : (V.t -> 'a -> 'a) -> 'a -> t -> V.t -> 'a 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 (** Coloring *) module Coloring : sig val coloring: t -> int -> unit (** [coloring g k] colors the nodes of graph [g] using [k] colors, assigning the marks integer values between 1 and [k]. *) val two_color: t -> unit (** [two_color g] attemps to color [g] with colors 1 and 2. *) 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] *) val gnp : ?loops:bool -> v:int -> prob:float -> unit -> t (** [gnp v prob] generates a random graph with [v] vertices and where each edge is selected with probality [prob] (G(n,p) model) *) val gnp_labeled : (V.t -> V.t -> E.label) -> ?loops:bool -> v:int -> prob:float -> unit -> t (** [gnp_labeled add_edge v prob] is similar to [gnp] 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_tarjan : t -> V.t -> V.t -> (E.t -> int) * int (** Goldberg-Tarjan 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-2.0.0/src/clique.mli0000644000175000001440000000301413735627615014763 0ustar rtusers(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2014-2015 *) (* Giselle Reis *) (* *) (* 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 cliques *) (** {1 Clique algorithms} *) (** {2 Bron-Kerbosch Algorithm} This algorithm will find and return all maximal cliques in an undirected graph. *) (** Minimal graph signature for Bron-Kerbosch. Sub-signature of {!Sig.G}. *) module type G = sig type t module V : Sig.COMPARABLE val succ : t -> V.t -> V.t list val fold_vertex : (V.t -> 'a -> 'a) -> t -> 'a -> 'a end module Bron_Kerbosch(G : G) : sig val maximalcliques : G.t -> G.V.t list list (** [maximalcliques g] computes all the maximal cliques of [g] using the Bron-Kerbosch algorithm. It returns the sets of vertices belonging to the same maximal clique. *) end ocamlgraph-2.0.0/src/graph.ml0000644000175000001440000000236413735627615014440 0ustar rtusersmodule Sig = Sig module Sig_pack = Sig_pack module Dot_ast = Dot_ast module Util = Util module Blocks = Blocks module Persistent = Persistent module Imperative = Imperative module Delaunay = Delaunay module Builder = Builder module Classic = Classic module Rand = Rand module Oper = Oper module Components = Components module Path = Path module Nonnegative = Nonnegative module Traverse = Traverse module Coloring = Coloring module Topological = Topological module Kruskal = Kruskal module Flow = Flow module Prim = Prim module Dominator = Dominator module Graphviz = Graphviz module Gml = Gml module Dot = Dot module Pack = Pack module Gmap = Gmap module Minsep = Minsep module Cliquetree = Cliquetree module Mcs_m = Mcs_m module Md = Md module Strat = Strat module Fixpoint = Fixpoint module Leaderlist = Leaderlist module Contraction = Contraction module Graphml = Graphml module Merge = Merge module Mincut = Mincut module Clique = Clique module WeakTopological = WeakTopological module ChaoticIteration = ChaoticIteration module XDotDraw = XDotDraw module XDot = XDot module DGraphModel = DGraphModel module DGraphTreeLayout = DGraphTreeLayout module DGraphSubTree = DGraphSubTree module DGraphTreeModel = DGraphTreeModel module DGraphRandModel = DGraphRandModel ocamlgraph-2.0.0/src/dune0000644000175000001440000000032413735627615013655 0ustar rtusers(include_subdirs unqualified) (library (name graph) (public_name ocamlgraph) (libraries stdlib-shims) (modules_without_implementation dot_ast sig sig_pack)) (ocamlyacc dot_parser) (ocamllex gml dot_lexer) ocamlgraph-2.0.0/src/components.mli0000644000175000001440000000630413735627615015673 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (** 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 g] 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 g] computes the strongly connected components of [g]. The result is a partition of the set of the vertices of [g]. The [n]-th components is [(scc_array g).(n-1)]. *) end (** Connected components (for undirected graphs). The implementation uses union-find. Time complexity is (quasi) O(V+E). Space complexity is O(V). *) module type U = sig type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges : (V.t -> V.t -> unit) -> t -> unit end module Undirected(G: U) : sig val components: G.t -> int * (G.V.t -> int) val components_array: G.t -> G.V.t list array val components_list: G.t -> G.V.t list list end ocamlgraph-2.0.0/src/dominator.mli0000644000175000001440000001407013735627615015501 0ustar rtusers(**************************************************************************) (* *) (* 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 Modified by OCamlGraph's authors. *) (** 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 iter_succ : (V.t -> unit) -> t -> V.t -> unit val nb_vertex : t -> int end module type S = sig type t (** type of graphs *) type vertex (** type of vertices *) module S: Set.S with type elt = vertex (** function from [n] to [n]'s immediate dominator *) type idom = vertex -> vertex (** [idoms x y] is true when [x] is [y]'s immediate dominator *) type idoms = vertex -> vertex -> bool (** function from [x] to a list of nodes immediately dominated by [x] *) type dom_tree = vertex -> vertex list (** function from node to a list of nodes that dominate it. *) type dominators = vertex -> vertex list (** [dom x y] returns true iff [x] dominates [y] *) type dom = vertex -> vertex -> bool (** [sdom x y] returns true iff [x] strictly dominates [y]. *) type sdom = vertex -> vertex -> bool (** function from [x] to a list of nodes not dominated by [x], but with predecessors which are dominated by [x] *) type dom_frontier = vertex -> vertex list (** 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: t -> vertex -> vertex -> vertex (** 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) -> vertex -> '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: (vertex -> S.t) -> vertex -> vertex -> bool val dom_to_sdom: (vertex -> vertex -> bool) -> vertex -> vertex -> 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: (vertex -> S.t) -> vertex -> S.t (** Given a function from a node to it's dominators, returns a function [idoms : vertex -> vertex -> bool] s.t. [idoms x y] returns true when [x] is the immediate dominator of [y]. *) val dominators_to_idoms : (vertex -> S.t) -> vertex -> vertex -> 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: t -> ?pred:(t -> vertex -> vertex list) -> (vertex -> S.t) -> vertex -> 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: t -> (vertex -> vertex) -> vertex -> vertex list val idom_to_idoms: idom -> vertex -> vertex -> bool (** Computes the dominance frontier. As specified in section 19.1 of Modern Compiler Implementation in ML by Andrew Appel. *) val compute_dom_frontier: t -> dom_tree -> idom -> vertex -> vertex list val idom_to_dominators: ('a -> 'a) -> 'a -> 'a list val idom_to_dom: (vertex -> vertex) -> vertex -> vertex -> bool end module Make(G : G) : S with type t = G.t and type vertex = G.V.t module type I = sig include G val empty: unit -> t val add_edge: t -> V.t -> V.t -> t end module Make_graph(G:I): sig include S with type t = G.t and type vertex = G.V.t type dom_graph = unit -> 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 } 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 -> vertex -> dom_functions end ocamlgraph-2.0.0/src/merge.mli0000644000175000001440000001621013735627615014602 0ustar rtusers(**************************************************************************) (* *) (* 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 (* Local Variables: compile-command: "make -C .." End: *) (*OCaml >= 3.12*) ocamlgraph-2.0.0/src/oper.mli0000644000175000001440000001220613735627615014451 0ustar rtusers(**************************************************************************) (* *) (* 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 transitive_reduction : ?reflexive:bool -> g -> g (** [transitive_reduction ?reflexive g] returns the transitive reduction of [g] (as a new graph). Loops (i.e. edges from a vertex to itself) are removed only if [reflexive] is [true] (default is [false]). *) val replace_by_transitive_reduction : ?reflexive:bool -> g -> g (** [replace_by_transitive_reduction ?reflexive g] replaces [g] by its transitive reduction. Meaningless for persistent implementations (then acts as [transitive_reduction]). *) 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-2.0.0/src/contraction.ml0000644000175000001440000000604713735627615015664 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/graphviz.ml0000644000175000001440000010540113735627615015165 0ustar rtusers(**************************************************************************) (* *) (* 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 (***************************************************************************) (** {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 let fprint_htmlstring_user ppf s = fprintf ppf "<%s>" s let fprint_square_not_empty printer ppf = function | [] -> () | l -> fprintf ppf " [%a]" printer l type arrow_style = [ `None | `Normal | `Onormal | `Inv | `Dot | `Odot | `Invdot | `Invodot ] let fprint_arrow_style ppf = function `None -> fprintf ppf "none" | `Normal -> fprintf ppf "normal" | `Onormal -> fprintf ppf "onormal" | `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" | `BottomToTop -> fprintf ppf "BT" | `LeftToRight -> fprintf ppf "LR" | `RightToLeft -> fprintf ppf "RL" type symbseq = | COMMA | SEMI let fprint_symbseq ppf = function | COMMA -> pp_print_string ppf "," | SEMI -> pp_print_string ppf ";" (** 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. *) sg_parent : string option; (** Nested subgraphs. *) } 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. *) | `HtmlLabel of string | `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 { | }. *) | `HtmlLabel of string | `Orientation of float (** Node rotation angle, in degrees. Default value is [0.0]. *) | `Penwidth of float (** Width of the pen (in points) used to draw the border of the node. Default value is [1.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 | `Oval | `Egg | `Triangle | `Invtriangle | `Trapezium | `Invtrapezium | `House | `Invhouse | `Parallelogram | `Doubleoctagon | `Tripleoctagon | `Mdiamond | `Mcircle | `Msquare | `Star | `Underline | `Note | `Tab | `Folder | `Box3d | `Component | `Promoter | `Cds | `Terminator | `Utr | `Primersite | `Restrictionsite | `Fivepoverhang | `Threepoverhang | `Noverhang | `Assembly | `Signature | `Insulator | `Ribosite | `Rnastab | `Proteasesite | `Proteinstab | `Rpromoter | `Rarrow | `Larrow | `Lpromoter | `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 [ `Rounded | `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. *) | `HtmlLabel of string | `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]. *) | `Penwidth of float (** Width of the pen (in points) used to draw the edge. Default value is [1.0]. *) | `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 | `HtmlLabel s -> fprintf ppf "label=%a" fprint_htmlstring_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" | `Egg -> fprintf ppf "egg" | `House -> fprintf ppf "house" | `Invhouse -> fprintf ppf "invhouse" | `Trapezium -> fprintf ppf "trapezium" | `Invtrapezium -> fprintf ppf "invtrapezium" | `Triangle -> fprintf ppf "triangle" | `Invtriangle -> fprintf ppf "invtriangle" | `Oval -> fprintf ppf "oval" | `Assembly -> fprintf ppf "assembly" | `Box3d -> fprintf ppf "box3d" | `Cds -> fprintf ppf "cds" | `Component -> fprintf ppf "component" | `Doubleoctagon -> fprintf ppf "doubleoctagon" | `Fivepoverhang -> fprintf ppf "fivepoverhang" | `Folder -> fprintf ppf "folder" | `Insulator -> fprintf ppf "insulator" | `Larrow -> fprintf ppf "larrow" | `Lpromoter -> fprintf ppf "lpromoter" | `Mcircle -> fprintf ppf "mcircle" | `Mdiamond -> fprintf ppf "mdiamond" | `Msquare -> fprintf ppf " msquare" | `Note -> fprintf ppf "note" | `Noverhang -> fprintf ppf "noverhang" | `Parallelogram -> fprintf ppf "parallelogram" | `Primersite -> fprintf ppf "primersite" | `Promoter -> fprintf ppf "promoter" | `Proteasesite -> fprintf ppf "proteasesite" | `Proteinstab -> fprintf ppf "proteinstab" | `Rarrow -> fprintf ppf "rarrow" | `Restrictionsite -> fprintf ppf "restrictionsite" | `Ribosite -> fprintf ppf "ribosite" | `Rnastab -> fprintf ppf "rnastab" | `Rpromoter -> fprintf ppf "rpromoter" | `Signature -> fprintf ppf "signature" | `Star -> fprintf ppf "star" | `Tab -> fprintf ppf "tab" | `Terminator -> fprintf ppf "terminator" | `Threepoverhang -> fprintf ppf "threepoverhang" | `Tripleoctagon -> fprintf ppf "tripleoctagon" | `Underline -> fprintf ppf "underline" | `Utr -> fprintf ppf "utr" | `Polygon (i, f) -> fprintf ppf "polygon, sides=%i, skew=%f" i f let rec fprint_string_list ppf = function | [] -> () | [hd] -> fprintf ppf "%s" hd | hd :: tl -> fprintf ppf "%s,%a" hd fprint_string_list tl let node_style_str = function | `Rounded -> "rounded" | `Filled -> "filled" | `Solid -> "solid" | `Dashed -> "dashed" | `Dotted -> "dotted" | `Bold -> "bold" | `Invis -> "invis" let fprint_style_list sep ppf a = fprintf ppf "style=\"%a\"%a@ " fprint_string_list (List.map node_style_str a) fprint_symbseq sep 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 | `HtmlLabel s -> fprintf ppf "label=%a" fprint_htmlstring_user s | `Orientation f -> fprintf ppf "orientation=%f" f | `Penwidth f -> fprintf ppf "penwidth=%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 _ -> assert false | `Width f -> fprintf ppf "width=%f" f 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 | `HtmlLabel s -> fprintf ppf "label=%a" fprint_htmlstring_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 | `Penwidth f -> fprintf ppf "penwidth=%f" f | `Style _ -> assert false let rec filter_style al sl l = match l with | [] -> al, sl | `Style s :: l -> filter_style al (s :: sl) l | a :: l -> filter_style (a :: al) sl l (** [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_style_list fprint_attribute sep ppf list = if list <> [] then begin let list, styles = filter_style [] [] list in let rec fprint_attributes_rec ppf = function | [] -> () | hd :: tl -> fprintf ppf "%a%a@ " fprint_attribute hd fprint_symbseq sep; fprint_attributes_rec ppf tl in fprintf ppf "@[%a" fprint_attributes_rec list; if styles <> [] then begin fprint_style_list sep ppf styles end; fprintf ppf "@]" end 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_list: symbseq -> formatter -> vertex list -> unit val fprint_edge_list: symbseq -> formatter -> edge list -> 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 ppf graph] pretty prints the graph [graph] in the CGL language on the formatter [ppf]. *) let fprint_graph ppf graph = let module SG = Map.Make(String) in let subgraphs = ref SG.empty 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_square_not_empty (EN.Attributes.fprint_vertex_list COMMA)) default_node_attributes; X.iter_vertex (function node -> begin match X.get_subgraph node with | None -> () | Some sg -> let (sg, nodes) = if SG.mem sg.EN.Attributes.sg_name !subgraphs then SG.find sg.EN.Attributes.sg_name !subgraphs else (sg, []) in subgraphs := SG.add sg.EN.Attributes.sg_name (sg, node :: nodes) !subgraphs end; fprintf ppf "%s%a;@ " (X.vertex_name node) (fprint_square_not_empty (EN.Attributes.fprint_vertex_list COMMA)) (X.vertex_attributes node) ) graph in (* Printing subgraphs *) let rec print_nested_subgraphs ppf = function | [] -> () (* no more work to do, so terminate *) | name :: worklist -> let sg, nodes = SG.find name !subgraphs in let children = SG.filter (fun _ (sg, _) -> sg.EN.Attributes.sg_parent = Some name) !subgraphs in fprintf ppf "@[subgraph cluster_%s { %a%t@ %t };@]@\n" name (EN.Attributes.fprint_vertex_list SEMI) sg.EN.Attributes.sg_attributes (fun ppf -> (List.iter (fun n -> fprintf ppf "%s;" (X.vertex_name n)) nodes) ) (fun ppf -> print_nested_subgraphs ppf (List.map fst (SG.bindings children)) ); print_nested_subgraphs ppf worklist in let print_subgraphs ppf = let root_worklist = SG.filter (fun _ (sg, _) -> sg.EN.Attributes.sg_parent = None) !subgraphs in print_nested_subgraphs ppf (List.map fst (SG.bindings root_worklist)) 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_square_not_empty (EN.Attributes.fprint_edge_list COMMA)) 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_square_not_empty (EN.Attributes.fprint_edge_list COMMA)) (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 | `BottomToTop | `LeftToRight | `RightToLeft ] (** 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; sg_parent : string option; } (** {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 "bgcolor=%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 let fprint_vertex_list = CommonAttributes.fprint_attributes CommonAttributes.fprint_style_list fprint_vertex let fprint_edge_list = CommonAttributes.fprint_attributes CommonAttributes.fprint_style_list fprint_edge 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; sg_parent : string option; } (** {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 let fprint_vertex_list = CommonAttributes.fprint_attributes CommonAttributes.fprint_style_list fprint_vertex let fprint_edge_list = CommonAttributes.fprint_attributes CommonAttributes.fprint_style_list fprint_edge end module Neato = MakeEngine (struct module Attributes = NeatoAttributes let name = "neato" let opening = "graph" let edge_arrow = "--" end) ocamlgraph-2.0.0/src/graphviz.mli0000644000175000001440000005235313735627615015345 0ustar rtusers(**************************************************************************) (* *) (* 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 | `Onormal | `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. *) sg_parent : string option; (** Nested subgraphs. *) } 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. *) | `HtmlLabel of string (** Caption for graph drawing. In HTML strings, angle brackets must occur in matched pairs, and newlines and other formatting whitespace characters are allowed. In addition, the content must be legal XML, so that the special XML escape sequences for ", &, <, and > may be necessary in order to embed these characters in attribute values or raw text." *) | `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 { | }. *) | `HtmlLabel of string (** Like label, in html style. In HTML strings, angle brackets must occur in matched pairs, and newlines and other formatting whitespace characters are allowed. In addition, the content must be legal XML, so that the special XML escape sequences for ", &, <, and > may be necessary in order to embed these characters in attribute values or raw text." *) | `Orientation of float (** Vertex rotation angle, in degrees. Default value is [0.0]. *) | `Penwidth of float (** Width of the pen (in points) used to draw the border of the node. Default value is [1.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 (* Addition through http://www.graphviz.org/doc/info/shapes.html *) | `Oval | `Egg | `Triangle | `Invtriangle | `Trapezium | `Invtrapezium | `House | `Invhouse | `Parallelogram | `Doubleoctagon | `Tripleoctagon | `Mdiamond | `Mcircle | `Msquare | `Star | `Underline | `Note | `Tab | `Folder | `Box3d | `Component | `Promoter | `Cds | `Terminator | `Utr | `Primersite | `Restrictionsite | `Fivepoverhang | `Threepoverhang | `Noverhang | `Assembly | `Signature | `Insulator | `Ribosite | `Rnastab | `Proteasesite | `Proteinstab | `Rpromoter | `Rarrow | `Larrow | `Lpromoter (* Addition ends here *) | `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 [ `Rounded | `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. *) | `HtmlLabel of string (** Like label, in html style. In HTML strings, angle brackets must occur in matched pairs, and newlines and other formatting whitespace characters are allowed. In addition, the content must be legal XML, so that the special XML escape sequences for ", &, <, and > may be necessary in order to embed these characters in attribute values or raw text." *) | `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]. *) | `Penwidth of float (** Width of the pen (in points) used to draw the edge. Default value is [1.0]. *) | `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 | `BottomToTop | `LeftToRight | `RightToLeft ] (** 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; sg_parent : string option; } 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; sg_parent : string option; } 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-2.0.0/src/imperative.ml0000644000175000001440000004721013735627615015503 0ustar rtusers(**************************************************************************) (* *) (* 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 = Stdlib.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 = ignore (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 = ignore (add_edge g v1 v2) let add_edge_e g (v1, l, v2) = ignore (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 <- Stdlib.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 <- Stdlib.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 <- Stdlib.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 <- Stdlib.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 Blocks.Graph(G) (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge g v1 v2 = if not (mem_edge g v1 v2) then begin 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) end 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 Blocks.Graph(G) (* Redefine the [add_edge] and [remove_edge] operations *) let add_edge_e g (v1, l, v2 as e) = if not (mem_edge_e g e) then begin 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)) end 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 Blocks.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 Blocks.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 = Stdlib.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 = Stdlib.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 _ _ = () let add_vertex _ _ = () 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 = Stdlib.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 clear g = g.vertices <- S.empty 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 let succ_e _ v = List.map (fun w -> (v, w)) (S.elements v.succ) let iter_succ f _ v = S.iter f v.succ let iter_succ_e f _ v = S.iter (fun w -> f (v, w)) v.succ let fold_succ f _ v acc = S.fold f v.succ acc let fold_succ_e f _ v acc = S.fold (fun w acc -> f (v, w) acc) v.succ acc let add_edge _ v1 v2 = v1.succ <- S.add v2 v1.succ let add_edge_e g (v1, v2) = add_edge g v1 v2 let mem_edge _ v1 v2 = S.mem v2 v1.succ let mem_edge_e g (v1, v2) = mem_edge g v1 v2 let remove_edge _ v1 v2 = v1.succ <- S.remove v2 v1.succ let remove_edge_e g (v1, v2) = remove_edge g v1 v2 let nb_edges g = fold_vertex (fun v n -> n + S.cardinal v.succ) g 0 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 -> [] module Mark = struct type graph = t type vertex = V.t let clear g = S.iter (fun v -> v.mark <- 0) g.vertices let get v = v.mark let set v m = v.mark <- m end 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-2.0.0/src/xDotDraw.mli0000644000175000001440000000756113735627615015250 0ustar rtusers(**************************************************************************) (* *) (* 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: fontMeasure:( fontName: string -> fontSize:int -> string -> (int * int) ) -> string -> float -> string -> width*height (** [string_scale_size ~fontMeasure 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-2.0.0/src/nonnegative.mli0000644000175000001440000000434613735627615016027 0ustar rtusers(**************************************************************************) (* *) (* 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 *) (** 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. *) module Imperative (G: Sig.IM) (W: Sig.WEIGHT with type edge = G.E.t) : 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: Sig.WEIGHT with type edge = G.E.t) : 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-2.0.0/src/dGraphSubTree.mli0000644000175000001440000000651713735627615016213 0ustar rtusers(**************************************************************************) (* *) (* This file is part of OcamlGraph. *) (* *) (* Copyright (C) 2009-2010 *) (* CEA (Commissariat � l'�nergie Atomique) *) (* *) (* you can redistribute it and/or modify it under the terms of the GNU *) (* Lesser General Public License as published by the Free Software *) (* Foundation, version 2.1, with a linking exception. *) (* *) (* It is distributed in the hope that it will be useful, *) (* but WITHOUT ANY WARRANTY; without even the implied warranty of *) (* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *) (* GNU Lesser General Public License for more details. *) (* *) (* See the file ../LICENSE for more details. *) (* *) (* Authors: *) (* - Julien Signoles (Julien.Signoles@cea.fr) *) (* - Jean-Denis Koeck (jdkoeck@gmail.com) *) (* - Benoit Bataille (benoit.bataille@gmail.com) *) (* *) (**************************************************************************) module type G = sig type t module V : sig type t type label val label : t -> label val hash : t -> int val equal : t -> t -> bool end module E : sig type t end val iter_succ : (V.t -> unit) -> t -> V.t -> unit val iter_pred : (V.t -> unit) -> t -> V.t -> unit val find_edge : t -> V.t -> V.t -> E.t end module type Tree = sig type t module V : sig type t type label val create : label -> t val label : t -> label val hash : t -> int val equal : t -> t -> bool end module E : Sig.EDGE with type vertex = V.t val create : ?size:int -> unit -> t val add_vertex : t -> V.t -> unit val add_edge_e : t -> E.t -> unit end module type S = sig module Tree: Tree with type E.label = unit type t val get_structure : t -> Tree.t val get_root : t -> Tree.V.t val get_tree_vertices : Tree.V.label -> t -> Tree.V.t list val is_ghost_node : Tree.V.t -> t -> bool val is_ghost_edge : Tree.E.t -> t -> bool exception Ghost_node val get_graph_vertex : Tree.V.t -> t -> Tree.V.label end module 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-2.0.0/src/flow.ml0000644000175000001440000005406013735627615014306 0ustar rtusers(**************************************************************************) (* *) (* 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 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_TARJAN = sig type t module V : Sig.COMPARABLE module E : Sig.EDGE with type vertex = V.t val nb_vertex : t -> int val nb_edges : t -> int val fold_edges_e : (E.t -> 'a -> 'a) -> t -> 'a -> 'a 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_Tarjan (G: G_GOLDBERG_TARJAN) (F: FLOW with type label = G.E.label) = struct (* This code is a contribution of Guyslain Naves Design notes: This is an implementation of the classical Goldberg-Tarjan push-relabel algorithm to compute maximum flow in directed graphs with upper capacities on arcs. Several common optimizations are implemented to make it more efficient than the pseudocode found in most textbooks on algorithms. About the push-relabel algorithm. -------------------------------------- Instead of keeping a valid flow and improving it by iteration (similar to Ford-Fulkerson algorithm and its variants), the push-relabel always keep a preflow and try make it becoe a flow. A preflow is a function on arcs that violates the flow condition: "flow that enters = flow that leaves (in every non-terminal vertex)" and replaces it by: " flow that enters >= flow that leaves (in every non-source vertex)" That means that any vertex may have *excessive* flow entering it. The algorithm proceed by making flow going down. Here down is defined by a *potential*, an integer attached to every vertex. The excess at some vertex can be routed to a successor in the residual graph with lower potential. This is a *push* operation on the corresponding arc. Pushing along all arcs leaving a vertex is a *discharge* of this vertex. If a vertex is excessive, but no successor has lower potential, then we increase the potential to make it slightly higher than at least one of its successor. This is a *relabel* operation of that vertex. The source (potential = n) and sink (potential = 0) may never be relabel. The algorithm consists in doing push and relabel steps, until no more are possible. Then the preflow is a maximum flow. Optimizations. -------------- - The simplest (and less efficient) way to optimize this algorithm is to play with the order on which push and relabel operations are performed. Here, the strategy used is the following: 1) sort excessive vertices by decreasing potential 2) for each vertex in that order: a) discharge it b) if still in excess, relabel it (see [augmenting_step] and [discharge]) This is a basic strategy that could be improved. - Textbook algorithms starts with non-source vertices with potential 0. This forces the algorithm to perform a lot of relabel operations to get to a more realistic and usable potential function. Here we use as initial potential the distance from a vertex to the sink (even for the source). (see [initialize_potential]) - The most important optimization: empirically one can check that the push-relabel algorithm converges very quickly toward a preflow that maximizes the flow sent to the sink. But then it takes very long to send back the excessive flow to the source. Here we detect every few iterations if the preflow is maximal. This is done by a bfs in the reversal of the residual graph, by determining whether the source is reachable. (see [is_maximum_preflow]). Once the preflow is maximum (first pahse), we compute a maximum preflow from sink to source in the reversed graph, with maximum capacities given by the values of the maximum preflow just computed (second phase). This will compute a reversed maximum preflow that must be actually a flow. (see [compute_maximum_flow], and the use of [forward_context] and [backward_context] for each of the two phases) Implementation. --------------- The most important thing is to understand that we are interested only in the residual graph, and not by the original graph. Original arcs may appears in one or two directions in the residual graph. This is why we manipulate almost only [residual_arc] and no [arc = G.E.t]. It also implies that the incident arcs of a vertex are not those in the original graph. Because we will work with both the residual graph and its reversal, and that it depends on the current flow values, we define two functions [incidence_residual] and [incidence_reversal]. Notice that their roles interchanged during the second phase. [Forward] and [Backward] only refers to the orientation compared to the orientation in the graph. Hence, in a reversed graph, backward residual arcs are [Forward], and forward residual arcs are [Backward]. We define a type [context] containing the current state of computation. We hide the data structures in [context] by providing [set] and [get] functions. It makes the code more readable, and easier to modify if one would like to change the data structures. Structure of the code: The first part of the code contains mostly helpers, up to the bfs algorithm. With the bfs comes the function to compute the initial potential and check the maximality of a preflow. Then we define the push, relabel, discharge operations, and the functions computing maximal preflows. Finally we define how to initialize a context, and the max flow algorithm. We choose to require by a functor the implementations for the main data structures used by the algorithm. VMap and EMap could be replaced by arrays for better efficiency, or using vertex and edge labels. They are used to record potentials, excesses and flows. VSet is used to track vertices that are still in excess. Because we sort those vertices, using search trees would not be a problem, but an array of size [G.nb_vertex] could degrade the performance. The default is a hash table densely filled, hence [sort_by_potential] is the asymptotical bottleneck. Parameter: - [param_freq_check_preflow]: used to parametrized how often one should check whether the current preflow is maximum. *) type vertex = G.V.t type arc = G.E.t type flow = F.t let (|>) x f = f x open G module Q = PersistentQueue module VH = Hashtbl.Make(G.V) module EM = Map.Make(G.E) module VMap = struct type 'a t = 'a VH.t let create = VH.create let add tbl key value = VH.add tbl key value let remove tbl key = VH.remove tbl key let find tbl key = try Some (VH.find tbl key) with Not_found -> None end module VSet = struct type t = unit VH.t let create () = VH.create 16 let add tbl v = if not (VH.mem tbl v) then VH.add tbl v () let elements tbl = VH.fold (fun v () list -> v::list) tbl [] end module EMap = struct type 'a t = 'a EM.t ref let create _ = ref EM.empty let add map edge value = map := EM.add edge value !map let find map edge = try Some (EM.find edge !map) with Not_found -> None end let min_flow a b = if F.compare a b < 0 then a else b let (+-) = F.add let (--) = F.sub let is_positive a = F.compare a F.zero > 0 let max_capacity e = F.max_capacity (E.label e) type residual_arc = | Forward of arc | Backward of arc (* context for computations *) type context = { nb_vertices : int; source : vertex; sink : vertex; reversed : bool; incident : context -> vertex -> residual_arc list; reverse_incident : context -> vertex -> residual_arc list; max_capacity : arc -> F.t; excess : flow VMap.t; potential : int VMap.t; mutable excessives : VSet.t; flow : flow EMap.t } let get_excess ctxt vertex = match VMap.find ctxt.excess vertex with | Some value -> value | None -> F.zero let get_potential ctxt vertex = match VMap.find ctxt.potential vertex with | Some value -> value | None -> 2 * ctxt.nb_vertices (* sink is not reachable from vertex *) let set_excess ctxt vertex value = VMap.remove ctxt.excess vertex; VMap.add ctxt.excess vertex value let set_potential ctxt vertex pi = VMap.remove ctxt.potential vertex; VMap.add ctxt.potential vertex pi let mark_excessive ctxt vertex = VSet.add ctxt.excessives vertex let extract_excessives ctxt = let in_excess = VSet.elements ctxt.excessives in ctxt.excessives <- VSet.create (); in_excess let get_flow context arc = match EMap.find context.flow arc with | Some value -> value | None -> F.zero let set_flow context arc value = EMap.add context.flow arc value let get_capacity context = function | Backward arc | Forward arc -> context.max_capacity arc (* residual graph helpers *) let origin : residual_arc -> vertex = function | Forward arc -> E.src arc | Backward arc -> E.dst arc let destination : residual_arc -> vertex = function | Forward arc -> E.dst arc | Backward arc -> E.src arc let forward arc = Forward arc let backward arc = Backward arc let residual_capacity : context -> residual_arc -> flow = fun context residual_arc -> match context.reversed, residual_arc with | true, Forward arc | false, Backward arc -> get_flow context arc | _, Backward arc | _, Forward arc -> F.sub (context.max_capacity arc) (get_flow context arc) let is_forward context arc = is_positive (context.max_capacity arc -- get_flow context arc) let is_backward context arc = is_positive (get_flow context arc) let augment : context -> residual_arc -> F.t -> unit = fun context residual_arc delta -> match context.reversed, residual_arc with | true, Backward arc | false, Forward arc -> get_flow context arc +- delta |> set_flow context arc | _, Backward arc | _, Forward arc -> get_flow context arc -- delta |> set_flow context arc let cons e l = e::l (* incidence function in the residual graph and in the reversal of the residual of the reversed graph *) let incidence_residual graph context vertex = begin fold_succ_e cons graph vertex [] |> List.filter (is_forward context) |> List.map forward end @ begin fold_pred_e cons graph vertex [] |> List.filter (is_backward context) |> List.map backward end (* incidence function in the reversal of the residual graph and in the residual of the reversed graph *) let incidence_reversal graph context vertex = begin fold_succ_e cons graph vertex [] |> List.filter (is_backward context) |> List.map forward end @ begin fold_pred_e cons graph vertex [] |> List.filter (is_forward context) |> List.map backward end (* Breadth-first search algorithm, with application of * a function on each arc of the BFS tree. *) let generic_bfs : int -> (vertex -> residual_arc list) -> (residual_arc -> unit) -> vertex -> unit = fun nb_vertices incidence iter_fun source -> let reached = VMap.create nb_vertices in let frontier = ref Q.empty in let add_arc arc = let dest = destination arc in if VMap.find reached dest = None then ( VMap.add reached dest (); iter_fun arc; frontier := Q.add !frontier dest ) in let explore vertex = List.iter add_arc (incidence vertex) in VMap.add reached source (); explore source; while not (Q.is_empty !frontier) do explore (Q.head !frontier); frontier := Q.tail !frontier done (* labels the vertices by their distance to the sink. This is used to initial the potential of vertices, and drastically improve the performance of the algorithm. *) let initialize_potential context sink = let update arc = get_potential context (origin arc) + 1 |> set_potential context (destination arc) in set_potential context sink 0; generic_bfs context.nb_vertices (context.reverse_incident context) update sink (* checks whether a preflow is maximum. Happens if no excessive vertex is reverse-reachable from the sink. *) exception Break let is_maximum_preflow context = let check_arc arc = if F.compare (get_excess context (destination arc)) F.zero <> 0 then raise Break in try generic_bfs context.nb_vertices (context.reverse_incident context) check_arc context.sink; true with Break -> false (* Push-relabel operations *) (* push excessive flow along an residual arc *) let push context arc = let (u,v) = (origin arc, destination arc) in let exc_u = get_excess context u in if is_positive exc_u then begin let delta = min_flow exc_u (residual_capacity context arc) in exc_u -- delta |> set_excess context u; get_excess context v +- delta |> set_excess context v; augment context arc delta; mark_excessive context v end (* Augment potential of a vertex to get a lower-potential successor *) let relabel context vertex = context.incident context vertex |> List.map (fun arc -> get_potential context (destination arc)) |> List.fold_left min (get_potential context vertex) |> fun pi -> set_potential context vertex (pi+1) (* push can be done only on arc with difference of potential = -1 *) let is_admissible context arc = let (u,v) = (origin arc, destination arc) in get_potential context v - get_potential context u = -1 (* push as much flow from a vertex as allowed. *) let discharge context vertex = context.incident context vertex |> List.filter (is_admissible context) |> List.iter (push context) |> fun () -> if is_positive (get_excess context vertex) then begin relabel context vertex; mark_excessive context vertex end (* Optimization: push vertices ordered by their potential. (better strategies may be possible). *) let compare_potential context u v = get_potential context v - get_potential context u let sort_by_potential context = List.sort (compare_potential context) let is_dischargeable context v = v <> context.source && v <> context.sink && is_positive (get_excess context v) let augmenting_step context currently_in_excess = context.excessives <- VSet.create (); currently_in_excess |> List.filter (is_dischargeable context) |> sort_by_potential context |> List.iter (discharge context) let param_freq_check_preflow = ref 1000 let compute_max_preflow context = let nb_steps = ref 0 in let in_excess = ref (extract_excessives context) in let check_freq = context.nb_vertices / !param_freq_check_preflow + 1 in let is_maximum () = ( !in_excess = [] ) || ( !nb_steps mod check_freq = 0 && is_maximum_preflow context ) in while not (is_maximum ()) do augmenting_step context !in_excess; in_excess := extract_excessives context; incr nb_steps done (* Maximally push each arc leaving the source, set the potential of any vertex at distance to sink (optimization). *) let init_context context = let out_source = context.incident context context.source in initialize_potential context context.sink; set_potential context context.source context.nb_vertices; out_source |> List.map (get_capacity context) |> List.fold_left F.add F.zero |> set_excess context context.source; out_source |> List.iter (push context); context let new_context graph ~source ~sink ~reversed ~max_capacity ~flow = let nb_vertices = G.nb_vertex graph in init_context { nb_vertices; source; sink; reversed; max_capacity; flow; incident = if reversed then incidence_reversal graph else incidence_residual graph; reverse_incident = if reversed then incidence_residual graph else incidence_reversal graph; excess = VMap.create nb_vertices; potential = VMap.create nb_vertices; excessives = VSet.create (); } let maxflow graph source sink = let init_flow () = let flow = EMap.create (G.nb_edges graph) in G.fold_edges_e (fun e () -> EMap.add flow e F.zero) graph (); flow in let forward_context = new_context graph ~source ~sink ~reversed:false ~max_capacity ~flow:(init_flow ()) in compute_max_preflow forward_context; let backward_context = new_context graph ~source:sink ~sink:source ~reversed:true ~max_capacity:(get_flow forward_context) ~flow:(init_flow ()) in compute_max_preflow backward_context; let max_flow_value = fold_succ_e cons graph source [] |> List.map (get_flow backward_context) |> List.fold_left F.add F.zero in let f e = match EMap.find backward_context.flow e with | Some x -> x | None -> F.zero in f, max_flow_value 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 type FLOWMIN = sig include FLOW val min_capacity : label -> t end module Ford_Fulkerson (G: G_FORD_FULKERSON) (F: FLOWMIN 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 97 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 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 97 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 Queue.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 F.compare a a' = 0 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-2.0.0/src/dGraphTreeModel.mli0000644000175000001440000000603213735627615016512 0ustar rtusers(**************************************************************************) (* *) (* 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: 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 type graph_layout class tree_model : 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 : Graphviz.GraphWithDotAttrs) : sig include S with type Tree.V.label = G.V.t val from_graph : ?depth_forward:int -> ?depth_backward:int -> fontMeasure:( fontName:string -> fontSize:int -> string -> int * int ) -> 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-2.0.0/src/util.ml0000644000175000001440000000414113735627615014307 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/coloring.mli0000644000175000001440000000776213735627615015333 0ustar rtusers(**************************************************************************) (* *) (* 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]. *) exception NoColoring (** {2 Graph coloring for graphs 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 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]. 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. Worst-case time complexity is exponential. Space complexity is O(V). *) val two_color: G.t -> unit (** [two_color g] attemps to color [g] with colors 1 and 2. @raise NoColoring if this is not possible (i.e., if the graph is not bipartite). Runs in O(V+E). *) end (** {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 and type 'a t = 'a Hashtbl.Make(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. Colors are integers from 1 to [k]. @raise NoColoring if [g] cannot be [k]-colored. Worst-case time complexity is exponential. Space complexity is O(V). *) val two_color : G.t -> int H.t end ocamlgraph-2.0.0/src/cliquetree.ml0000644000175000001440000001777213735627615015512 0ustar rtusers(**************************************************************************) (* *) (* 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 (* 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 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 let compare : t -> t -> int = Stdlib.compare let hash (x:t) = Hashtbl.hash x let equal (x:int) (y:int) = x = y end) module CliqueTreeE = struct type t = int * CVS.t let compare (x, _ : t) (y, _ : t) = Stdlib.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) (* Creates the intermediate graph from the original *) module Copy = Gmap.Vertex(Gr)(struct include G include Builder.P(G) end) open CliqueV 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 test_simpliciality_first' l sons = List.for_all (fun son -> match !son with | [] -> false | xi :: _ -> 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,_) -> 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-2.0.0/src/strat.mli0000644000175000001440000000720013735627615014637 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/components.ml0000644000175000001440000001033213735627615015516 0ustar rtusers(**************************************************************************) (* *) (* 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 H = Hashtbl.Make(G.V) (* iterative code using a stack (variable [cont] below) *) type action = | Finish of G.V.t * int | Visit of G.V.t * G.V.t | Test of G.V.t * G.V.t 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: int), w) :: l when y > x -> H.add hashcomp w !numcomp; pop x l | l -> l in let cont = ref [] in let visit v = if not (H.mem root v) then begin let n = incr numdfs; !numdfs in H.add root v n; cont := Finish (v, n) :: !cont; G.iter_succ (fun w -> cont := Visit (v, w) :: Test (v, w) :: !cont) g v; end in let rec finish () = match !cont with | [] -> () | action :: tail -> cont := tail; begin match action with | Finish (v, n) -> 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; | Visit (_, w) -> visit w | Test (v, w) -> if not (H.mem hashcomp w) then H.replace root v (min (H.find root v) (H.find root w)) end; finish () in let visit_and_finish v = visit v; finish () in G.iter_vertex visit_and_finish 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 a = scc_array g in Array.fold_right (fun l acc -> l :: acc) a [] end (** Connected components (for undirected graphs) *) module type U = sig type t module V : Sig.COMPARABLE val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges : (V.t -> V.t -> unit) -> t -> unit end module Undirected(G: U) = struct module UF = Unionfind.Make(G.V) module H = Hashtbl.Make(G.V) let components g = let vertices = ref [] in G.iter_vertex (fun v -> vertices := v :: !vertices) g; let uf = UF.init !vertices in let visit u v = UF.union u v uf in G.iter_edges visit g; let count = ref 0 in let comp = H.create 5003 in let visit v = let v = UF.find v uf in if not (H.mem comp v) then begin H.add comp v !count; incr count end in G.iter_vertex visit g; !count, (fun v -> H.find comp (UF.find v uf)) let components_array g = let n,f = components 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 components_list g = let a = components_array g in Array.fold_right (fun l acc -> l :: acc) a [] end ocamlgraph-2.0.0/src/md.ml0000644000175000001440000001054413735627615013736 0ustar rtusers(**************************************************************************) (* *) (* 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 CT = Cliquetree.CliqueTree(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 (_,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 CT = Cliquetree.CliqueTree(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 (_,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-2.0.0/src/gmap.ml0000644000175000001440000000577313735627615014272 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/cliquetree.mli0000644000175000001440000000614713735627615015655 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/prim.mli0000644000175000001440000000356613735627615014464 0ustar rtusers(**************************************************************************) (* *) (* 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 module E : sig type t type label val label : t -> label val dst : t -> V.t val src : t -> V.t val compare : t -> t -> int end val iter_vertex : (V.t -> unit) -> t -> unit val iter_edges_e : (E.t -> unit) -> t -> unit val iter_succ_e : (E.t -> unit) -> t -> V.t -> unit end (** Functor providing an implementation of Prim's minimum-spanning-tree algorithm. Parameter [W] ensures that label on edges are comparable. *) module Make(G: G)(W: Sig.WEIGHT with type edge = G.E.t) : sig val spanningtree : G.t -> G.E.t list val spanningtree_from : G.t -> G.V.t -> G.E.t list end ocamlgraph-2.0.0/src/mincut.mli0000644000175000001440000000352313735627615015005 0ustar rtusers(**************************************************************************) (* *) (* Ocamlgraph: a generic graph library for OCaml *) (* Copyright (C) 2013-2014 *) (* David Monniaux, Gabriel Radanne *) (* *) (* 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 cutset of a graph Compute a minimal vertex cutset of a reducible oriented graph. The set [S] of vertices is a cutset of [G] if [G \ S] doesn't contain any cycle. Based on the article: A linear time algorithm for finding minimum cutsets in reducible graphs by A. Shamir (1979). *) (** Minimal signature for computing the minimal separators *) module type G = sig type t module V : Sig.VERTEX val succ : t -> V.t -> V.t list end module Make (G : G) : sig (** Find a minimal cutset. @raise Invalid_argument if the graph is not reducible. *) val min_cutset : G.t -> G.V.t -> G.V.t list end ocamlgraph-2.0.0/src/path.ml0000644000175000001440000002426113735627615014273 0ustar rtusers(**************************************************************************) (* *) (* 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 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 val create : V.t -> label -> V.t -> t end 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 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 (** Weight signature for Johnson's algorithm. *) module type WJ = sig include Sig.WEIGHT val sub : t -> t -> t (** Subtraction of weights. *) end module Dijkstra (G: G) (W: Sig.WEIGHT with type edge = G.E.t) = 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 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: Sig.WEIGHT with type edge = G.E.t) = 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 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 Johnson (G: G) (W: WJ with type edge = G.E.t) = struct module HVV = Hashtbl.Make(Util.HTProduct(G.V)(G.V)) module G' = struct type t = G.t module V = struct type t = New | Old of G.V.t let compare v u = match v, u with | New, New -> 0 | New, Old _ -> -1 | Old _, New -> 1 | Old v, Old u -> G.V.compare v u let hash v = match v with | Old v -> G.V.hash v | New -> 42 let equal v u = match v, u with | New, New -> true | New, Old _ | Old _, New -> false | Old v, Old u -> G.V.equal v u end module E = struct type label = G.E.label type t = NewE of V.t | OldE of G.E.t let src e = match e with | NewE _ -> V.New | OldE e -> V.Old (G.E.src e) let dst e = match e with | NewE v -> v | OldE e -> V.Old (G.E.dst e) let label e = match e with | NewE _ -> assert false | OldE e -> G.E.label e let create v l u = match v, u with | V.New, V.Old u -> NewE (V.Old u) | V.Old v, V.Old u -> OldE (G.E.create v l u) | _, _ -> assert false end let iter_vertex f g = f V.New; G.iter_vertex (fun v -> f (V.Old v)) g let fold_vertex f g acc = let acc' = f V.New acc in G.fold_vertex (fun v a -> f (V.Old v) a) g acc' let iter_succ f g v = match v with | V.New -> G.iter_vertex (fun u -> f (V.Old u)) g | V.Old v -> G.iter_succ (fun u -> f (V.Old u)) g v let iter_succ_e f g v = match v with | V.New -> G.iter_vertex (fun u -> f (E.NewE (V.Old u))) g | V.Old v -> G.iter_succ_e (fun e -> f (E.OldE e)) g v let fold_edges_e f g acc = let acc' = G.fold_vertex (fun x _ -> f (E.NewE (V.Old x)) acc) g acc in G.fold_edges_e (fun edg -> let v1 = G.E.src edg in let v2 = G.E.dst edg in let l = G.E.label edg in f (E.create (V.Old v1) l (V.Old v2))) g acc' let nb_vertex g = G.nb_vertex g + 1 end module W' = struct open G'.E type edge = G'.E.t type t = W.t let zero = W.zero let weight e = match e with | NewE _ -> zero | OldE e -> W.weight e let compare = W.compare let add = W.add end module BF = BellmanFord(G')(W') let all_pairs_shortest_paths g = let pairs_dist = HVV.create 97 in let bf_res = BF.all_shortest_paths g G'.V.New in let module W'' = struct type edge = W.edge type t = W.t let add = W.add let sub = W.sub let weight e = let v1 = G.E.src e in let v2 = G.E.dst e in add (W.weight e) (W.sub (BF.H.find bf_res (G'.V.Old v1)) (BF.H.find bf_res (G'.V.Old v2))) let compare = W.compare let zero = W.zero end in let module D = Dijkstra(G)(W'') in G.iter_vertex (fun v -> G.iter_vertex (fun u -> try let (_, d) = D.shortest_path g v u in HVV.add pairs_dist (v, u) (W''.add d (W''.sub (BF.H.find bf_res (G'.V.Old u)) (BF.H.find bf_res (G'.V.Old v)) )) with Not_found -> () ) g) g; pairs_dist 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 a BFS *) 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-2.0.0/src/dominator.ml0000644000175000001440000003304113735627615015327 0ustar rtusers(**************************************************************************) (* *) (* 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 Modified by OCamlGraph's authors. *) (* 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 iter_succ : (V.t -> unit) -> t -> V.t -> unit val nb_vertex : t -> int end module type I = sig include G val empty: unit -> t val add_edge: t -> V.t -> V.t -> t end module type S = sig type t type vertex module S : Set.S with type elt = vertex type idom = vertex -> vertex type idoms = vertex -> vertex -> bool type dom_tree = vertex -> vertex list type dominators = vertex -> vertex list type dom = vertex -> vertex -> bool type sdom = vertex -> vertex -> bool type dom_frontier = vertex -> vertex list val compute_idom: t -> vertex -> vertex -> vertex val dominators_to_dom: ('a -> S.t) -> vertex -> 'a -> bool val dominators_to_sdom: (vertex -> S.t) -> vertex -> vertex -> bool val dom_to_sdom: (vertex -> vertex -> bool) -> vertex -> vertex -> bool val dominators_to_sdominators: (vertex -> S.t) -> vertex -> S.t val dominators_to_idoms: (vertex -> S.t) -> vertex -> vertex -> bool val dominators_to_dom_tree: t -> ?pred:(t -> vertex -> vertex list) -> (vertex -> S.t) -> vertex -> S.t val idom_to_dom_tree: t -> (vertex -> vertex) -> vertex -> vertex list val idom_to_idoms: idom -> vertex -> vertex -> bool val compute_dom_frontier: t -> dom_tree -> idom -> vertex -> vertex list val idom_to_dominators: ('a -> 'a) -> 'a -> 'a list val idom_to_dom: (vertex -> vertex) -> vertex -> vertex -> bool end module Make(G : G) = struct type t = G.t type vertex = G.V.t module H = Hashtbl.Make(G.V) module S = Set.Make(G.V) (** function from [n] to [n]'s immediate dominator *) type idom = vertex -> vertex (** [idoms x y] is true when [x] is [y]'s immediate dominator *) type idoms = vertex -> vertex -> bool (** function from [x] to a list of nodes immediately dominated by [x] *) type dom_tree = vertex -> vertex list (** function from node to a list of nodes that dominate it. *) type dominators = vertex -> vertex list (** [dom x y] returns true iff [x] dominates [y] *) type dom = vertex -> vertex -> bool (** [sdom x y] returns true iff [x] strictly dominates [y]. *) type sdom = vertex -> vertex -> bool (** function from [x] to a list of nodes not dominated by [x], but with predecessors which are dominated by [x] *) type dom_frontier = vertex -> vertex list let set_of_list x = List.fold_left (fun set v -> S.add v set) S.empty x (** 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 dfs n0 = let stack = Stack.create () in let loop () = while not (Stack.is_empty stack) do let n,p = Stack.pop stack in if not (H.mem dfnum_h n) then begin let enn = !nn in H.add dfnum_h n enn; vertex.(enn) <- n; begin match p with | Some p -> H.add parent n p | None -> () end; nn := enn + 1; G.iter_succ (fun m -> if not (H.mem dfnum_h m) then Stack.push (m, Some n) stack) cfg n end done in Stack.push (n0,None) stack; loop () 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 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 G.V.equal (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 97 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 (* written in CPS to prevent stack overflow *) let rec df n k = match try Some (H.find df_cache n) with Not_found -> None with | Some r -> k r | None -> let s = df_local n in add_df_ups s n (fun res -> H.add df_cache n res; k res) (children n) and add_df_ups s n k = function | [] -> k s | c :: chl -> df c (fun dfc -> add_df_ups (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 dfc) n k chl) in fun n -> df n (fun x -> x) 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 end module Make_graph(G: I) = struct include Make(G) type dom_graph = unit -> 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 compute_dom_graph cfg dom_tree = G.fold_vertex (fun p g -> try List.fold_left (fun g u -> (G.add_edge g p u)) g (dom_tree p) with Not_found -> g ) cfg (G.empty ()) (** 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-2.0.0/src/kruskal.mli0000644000175000001440000000504313735627615015161 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/src/dot_parser.mly0000644000175000001440000000732613735627615015675 0ustar rtusers/**************************************************************************/ /* */ /* 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 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-2.0.0/src/rand.mli0000644000175000001440000001126013735627615014427 0ustar rtusers(**************************************************************************) (* *) (* 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 val gnp : ?loops:bool -> v:int -> prob:float -> unit -> graph (** random graph using the G(n,p) model. [gnp v prob] generates a random graph with exactly [v] vertices and where each edge is selected with probability [prob] *) val gnp_labeled : (vertex -> vertex -> edge_label) -> ?loops:bool -> v:int -> prob:float -> unit -> graph (** [gnp_labeled add_edge v e] is similar to [gnp] except that edges are labeled using function [f]. *) 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-2.0.0/TODO.md0000644000175000001440000000122413735627615013277 0ustar rtusers - has_cycle: return the cycle as a list of vertices - Better graph viewer and editor - Improve the website - It should be possible to specify the first vertex to visit in traversal algorithm (suggestion of Fabrice Derepas) - Implementations for graph with unlabeled vertices (exactly like graph with unlabeled edges) - Provide more bidirectional graph implementation: only Imperative.Digraph.ConcreteBidirectional exists at this day. - Provide generic marks (instead of only integer marks) ## DGraph ### mode Tree - texte trop bas - texte multi-ligne - gros zoom déviant - mauvaise borne polygone & rectangle Un bon exemple est 'examples/fancy.dot' ocamlgraph-2.0.0/CHANGES.md0000644000175000001440000004120313735627615013603 0ustar rtusers # 2.0.0 (October 2, 2020) - port to dune and opam 2.0 - :exclamation: opam package now split into two packages: ocamlgraph and ocamlgraph_gtk - [WeakTopological] fixed incorrect use of generic hash tables (#99, Tomáš Dacík) - [Oper] fixed transitive_reduction (#91) - fix incorrect uses of polymorphic equality (Steffen Smolka, Boris Yakobowski) - [Coloring] fixed generation of OCamlDoc documentation (contributed by Earnestly) - :exclamation: [Coloring] functions now fail if the graph is directed - :exclamation: [Coloring] now uses a single, global exception [NoColoring] - [Coloring] new function two_color to 2-color a graph (or fail) - :exclamation: [Fixpoint] Take initial labeling of nodes into account (Johannes Kloos) # 1.8.8, October 17, 2017 - fixed installation (Virgile Prevosto, Jacques-Pascal Deplaix) - safe-string compatible (Jacques-Pascal Deplaix) - :exclamation: fixed method get_edge_layout of class abstract_model of DGraphModel.Make. The bug could have occured when there are several edges between two vertices. - [Traverse/Pack] added Dfs.fold and Dfs.fold_component (tail-recursive) (contributed by Guillaume Chelfi) - :exclamation: fixed implementation of Golberg-Tarjan maximal flow algorithm (contributed by Guyslain Naves) No more function min_capacity in the input interface. Renaming as follows: Flow.Goldberg -> Flow.Goldberg_Tarjan and Pack.goldberg -> Pack.goldberg_tarjan - new functors [WeakTopological] and [ChaoticIteration] to compute fixpoints with widening, following Bourdoncle's algorithms (contributed by Thibault Suzanne) # 1.8.7, April 12, 2016 - fixed examples/demo.ml so that it also compiles with an installed OCamlGraph - [Components] fixed stack overflow with [scc] (patch by Albin Coquereau) - [Dominator] fixed stack overflow (patch by Albin Coquereau) - new functor [Path.Johnson] to compute all pairs of shortest paths using Johnson's algorithm (contributed by Mário Pereira) - fixed configuration on Windows (patch by Martin R. Neuhäußer) - new functor [Components.Undirected] to compute connected components - Graphviz: fixed printing of attribute BgcolorWithTransparency - :exclamation: Prim, Nonnegative: function weight now has the more general type "edge -> t" (to be consistent with Path) - new module type Sig.WEIGHT (used in Path, Prim, and Nonnegative) - Fixpoint: do not catch Not_found raised by a user-provided function. - Adding folds to BFS. # 1.8.6, January 23, 2015 - :exclamation: Dominator: new functor [Make_graph] with may use graph building operations, while the old functor [Make] now only requires a read-only graph. Function [compute_all] and [compute_dom_graph] are now only defined in the new [Make_graph] functor. - Graphviz: support for additional polygonal-shapes - New module Clique (contributed by Giselle Reis) - Avoid ocamldoc error with OCaml 4.02 - :exclamation: Path: function weight now has the more general type "edge -> t" (contributed by Steffen Smolka) update your code by turning "weight l" into "weight (G.E.label e)" - installation: "make install-findlib" now uses DESTDIR when defined - Traverse: documentation is clarified: providing iterators over the roots of the graph is enough. - Imperative concreate (di)graph: fix bug of functions add_edge* of imperative concrete (di)graphs which appears when the added edge [e] was already in the graph [g] and one of the vertices of [e] is equal to another vertex of [g] (when using the user-defined equality [G.V.equal]), but not physically equal to it. This bug only occurs with OCaml version >= 4.0. - functions in modules Components, Dominator, Flow, Topological and Traverse now create smaller auxiliary hash tables - Graphviz: add the attribute `HtmlLabel to specify html strings. # 1.8.5, March 4, 2014 - Graphviz: reverted to the old API where edges and vertices are given a single style attribute; but such attributes are collected and output in the DOT file into a list (thus allowing multiple style attributes) - fixed issue in ./configure with ocamlfind on Win32. - fixed compilation when laglgnomecanvas is missing (bug introduced in 1.8.4). - fixed more issues with 'make -j'. # version 1.8.4, February 4, 2014 - fixed [Graphml] printer (contributed by Johannes Schauer) - Components: the components of [scc_list] are provided in the same order than the ones of [scc_array]. - fix compilation with 'make -j' - Graphviz: handle attribute penwidth on edges and vertices - also install graph.o and graph.cmxs - fixed installation with ocamlfind (thanks to Virgile Prevosto) - new functions [gnp] and [gnp_labeled] in module [Rand] to generate random graphs using the G(n,p) model (contributed by Thomas Aubry) - Prim's algorithm (in module [Prim]; not exported in [Pack]) (contributed by Thomas Aubry) - Graphviz: support for nested subgraphs. (Backward-incompatible change: add 'sg_parent = None' to obtain subgraphs whose parents are the main graph) - Graphviz: edges and vertices can now receive multiple styles. (Backward-incompatible change: constructors `Style now require a list as argument) - Graphviz: new vertex style 'rounded' - Merge: fixed bug with vertices with no incoming nor outcoming edge. - fixed compilation issue with OCaml 3.12.1 # 1.8.3, April 17, 2013 - new module Merge implementing several different merges of vertices and edges into a graph (contributed by Emmanuel Haucourt) - fixed DOT parser (contributed by Alex Reece) - Topological: fixed bug in presence of disjoint cycles; new implementation - new module [Graphml] to export graphs into the graphml format (contributed by Pietro Abate) - Builder.S now contains functions remove_*. - modified Fixpoint module so that it also works with unlabeled graphs, break backward compatibility yet (contributed by Markus W. Weissmann) - support of lablgtk2 installed with findlib (contributed by B. Monate) - new module [Dominator] to compute dominators (contributed by David Brumley and Ivan Jager) # 1.8.2, May 12, 2012 - new module [Path.BellmanFord] implementing Bellman-Ford algorithm (contributed by Yuto Takei) - new module Contraction implementing edge contraction (contributed by Markus W. Weissmann) - Gmap: new function [filter_map] (contributed by Markus W. Weissmann) - Topological: fix bug when a cycle depends on another cycle. That breaks compatibility: the input graph must implement Sig.COMPARABLE instead of Sig.HASHABLE - 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. - new module Leaderlist to compute the leader list algorithm (see the Dragon) (contributed by Markus W. Weissmann ) # 1.8.1, October 17, 2011 - 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 ) - new module Fixpoint to compute fixpoints using the work-list algorithm, e.g. for data flow analysis (contributed by Markus W. Weissmann ) # 1.8, October 4, 2011 - removed ocamlyacc shift/reduce conflict in dot_parser.mly (patch contributed by Till Varoquaux) - Dgraph: Correct height and width-related problems with text - DGraph: many bug fixes. Patch by Benjamin Monate - Sig.G: new function [find_all_edges] for each graph implementation - Oper: fixed bug with function [intersect]: now use G.E.compare instead of (=) - fixed "make install-findlib" # 1.7, February 23, 2011 - Makefile: fixed bug when installing ocamlgraph with ocamlfind - DGraph: fixed bug with colors on some windows manager - Configure: fixed issue with automatic detection of extension under Windows/Mingw # 1.6, December 13, 2010 - DGraph: new viewer mode (called `tree') which focus on a subset part of the graph centered on a given node - Graphviz: fixed bug with attribute `Constraint (was `Constraints) (patch by Boris Yakobowski) - DGraph: fixed font size issue when zooming - DGraph: now interpret text anchors and espaced sequences correctly - DGraph: offer possibility to disable the default callbacks on nodes - 'make -j' works again - new implementation Persistent.Digraph.ConcreteBidirectionalLabeled - new implementation Persistent.Digraph.ConcreteBidirectional - Makefile: bug fixed when ocamlc (resp. ocamlopt) and ocamlc.opt (resp. ocamlopt.opt) are unconsistent # 1.5, April 29, 2010 - Makefile: bug fixed when installing ocamlgraph with ocamlfind (patch by Virgile Prevosto) - DGraph: new method set_zoom_padding in DgraphView.view - Traverse.Dfs.has_cycle: can now be used on undirected graphs as well, and is now tail recursive - DGraph: handle dotted ellipse # 1.4, March 24, 2010 - new function [clear] for imperative graphs - new implementation Imperative.Digraph.ConcreteBidirectionalLabeled (contribution of Jaap Boender) - Dgraph displays graphs faster - DGraph: several bugs fixed - DGraph: several API changes (may break compatibility with existing development) # 1.3, October 2, 2009 - Oper.mirror: undirected graphs are not copied anymore - Oper.mirror: fixed bug (isolated vertices were lost) - Graphviz: new signature GraphWithDotAttrs - Improvements of Dgraph - Configure: better test for detecting lablgtk - OcamlGraph is now installed by default in `ocamlc -where`/ocamlgraph - Viewgraph is now packed in a single module Viewgraph (break compatibility with previous version) - Dgraph is now packed in a single module Dgraph (break compatibility with previous version) - Makefile: fixed bug when the installation directory of binaries does not exist - Makefile: fixed bug of ocamldep under Windows # 1.2, August 31, 2009 - experimental: new GTK-based graph viewer called Dgraph (viewGraph is now deprecated) - added Delaunay.iter_triangles (not of use in Ocamlgraph, actually) # 1.1, June 23, 2009 - added constraint "type E.label = unit" to unlabeled graph data structure - viewGraph: new module viewGraph_utils; fixed compilation (gtkInit was missing; patch by Mehdi Dogguy) - configure: fixed bug under Cygwin (patch by Julien Bernet) - configure: look for lablgnomecanvas.cmxa when compiling in native code - Makefile: fixed make install-findlib when lablgtk and/or lablgnomecanvas not installed (patch by Peter Hawkins) # 1.0, October 14, 2008 - license: LGPL updated to version 2.1 - ocamlgraph now requires ocaml 3.10 or higher - experimental: GTK-based graph viewer based on dot (contribution of Anne Pacalet) - 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 - new function Blocks.after_unserialization in order to be able to safely serialize abstract vertices (see the FAQ) - Dot: - fixed bug in the parsing of attributes - fixed bug in the parsing of subgraphs (patch by Anne Pacalet) - Oper: fixed bug in intersect - Path: improved efficiency of Dijkstra - Topological: - fixed bug in Make.{iter,fold} - folding is now tail-recursive (patch by Michael Furr) # 0.99c, April 3rd, 2008 - replicated a bug fix of Bitv (could not affect Matrix, though) - fixed DFS traversal in Traverse.Dfs.{prefix,prefix_component,iterator} # 0.99b, December 18th, 2007 - fixed link bug with ocaml 3.09 (see http://caml.inria.fr/mantis/view.php?id=4124) # 0.99a, November 21st, 2007 - fixed bug in Makefile when lablgtk2 is not installed - 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 # 0.99, June 27th, 2007 - experimental: GTK-based graph editor based on hyperbolic geometry; to build it and test it, cd to editor/ and type make - [Components.Make] functor: function [scc] as a new profile and a more precise specification. New function [scc_array]. - fixed configure to set ocaml's standard library using "ocamlc -where" - new module Dot to parse files in Graphviz's DOT format - slight change in the license (no more clause 6 of the LGPL; see LICENSE) - new module Strat implementing simple game strategies - Graphviz: little refactoring and improved documentation # 0.98, Sep 27th, 2006 - rename Sig.IA to Sig.IM - 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) # 0.97, July 20th, 2006 - fixed compilation under Windows/Cygwin (contributed by Denis Berthod) - fixed bug with escaped string in Graphviz # 0.96, May 2nd, 2006 - new demo program: sudoku.ml (solving the Sudoku using graph coloring) - new module Coloring for (rather brute force) graph coloring - 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) # 0.95, November 2nd, 2005 - compatibility with ocaml 3.09 - new module Path.Check to check for paths # 0.94, July 6th, 2005 - 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 - added display_with_gv in Pack - improved implementation of Unionfind (patch by Marc Lasson) # 0.93, March 31st, 2005 - fixed bug in Rand (integer overflow causing Invalid_argument "random"); improved code in Rand - bug fixed in the META file - add find_edge in Sig.G (and so in all graph implementations) # 0.92, January 18th, 2005 - fixed escaped labels in Graphviz output (patch by Boris Yakobowski) - new Graphviz option OrderingOut (patch by Boris Yakobowski) - fixed sharing bugs in Oper (patch by Boris Yakobowski) - fixed bug in nb_edges for undirected graphs - improvement of iterators of undirected concrete graphs # 0.91, December 16th, 2004 - more precise specifications of remove_edge and shortest_path. - bug fixed in mem_edge_e of labelled graphs - generation of random graphs improved - add Rand.Make and Rand.Planar.Make (generic functors) - add signatures Persistent.S and Imperative.S # 0.90, November 30th, 2004 - graph.cma graph.cmxa - version.ml and META files are now writable - add interfaces Sig.VERTEX and Sig.EDGE - "sig.ml" and "sig_pack.ml" removed; ocamlgraph now requires ocaml 3.08.0 - improvement of Minsep - add Components.scc_list - Oper.Neighbourhood replaces Neighborhood - Gmap replaces Copy - add types Sig_pack.vertex and Sig_pack.edge - fixed bug in Ford-Fulkerson: G.V.equal instead of = in two asserts # 0.81, July 13th, 2004 - compatibility with ocaml 3.08 - Oper.Choose.choose_edge: choose an edge in a graph - add types Sig.G.edge and Sig.G.vertex resp. equal to Sig.G.V.t and Sig.G.E.t - fixed typos in invalid_arg arguments (in Bitv) # 0.80, June 28th, 2004 - 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 - out_degree: raises Invalid_argument if v not in g (instead of Not_found) - Pack.Graph: golberg/ford_fulkerson fail ("not a directed graph") # 0.70, Feb 27th, 2004 - Makefile.in: dependences ("make -j" works) - union and intersection (see Oper.S.union and Oper.S.intersection) - Golberg/Ford_fulkerson algorithms in a single module Flow - step-by-step iterators in Traverse.{Dfs,Bfs} - Ford_fulkerson: maxflow now returns a flow function over edges # 0.60, Feb 18th, 2004 - fixed bug in Ford-Fulkerson - random planar graphs (see Rand.Planar) - Delaunay triangulation (see Delaunay) - implementations with adjacency matrices (see Imperative.Matrix) - operations on predecessors for undirected graphs optimized - Traverse.Dfs.{prefix,prefix_component} optimized (now tail recursive) # 0.50, Feb 4th, 2004 - first release ocamlgraph-2.0.0/dgraph/0000755000175000001440000000000013735627615013456 5ustar rtusersocamlgraph-2.0.0/dgraph/dGraphContainer.mli0000644000175000001440000001243213735627615017233 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/dgraph/dGraphMake.ml0000644000175000001440000000357113735627615016021 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/dgraph/dGraphView.ml0000644000175000001440000002647113735627615016062 0ustar rtusers(**************************************************************************) (* *) (* 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 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 ~callback:self#zoom_keys_ev; ignore $ self#event#connect#scroll ~callback: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 ~callback:(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-2.0.0/dgraph/dGraphViewItem.ml0000644000175000001440000003731313735627615016676 0ustar rtusers(**************************************************************************) (* *) (* 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 XDot open XDotDraw 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 _ :: 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 ] (* 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 ~fontMeasure:(PangoMeasure.withContext ~context:(Gdk.Screen.get_pango_context ())) 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-2.0.0/dgraph/dGraphViewer.ml0000644000175000001440000001246313735627615016405 0ustar rtusers(**************************************************************************) (* *) (* 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_gtk 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-2.0.0/dgraph/dGraphContainer.ml0000644000175000001440000003546513735627615017075 0ustar rtusers(**************************************************************************) (* *) (* 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 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 context = GtkBase.Widget.create_pango_context w in let fontMeasure = PangoMeasure.withContext ~context in let model = FullTreeModel.from_graph ~depth_forward ~depth_backward ~fontMeasure 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-2.0.0/dgraph/headers/0000755000175000001440000000000013735627615015071 5ustar rtusersocamlgraph-2.0.0/dgraph/headers/CEA_LGPL0000644000175000001440000000130313735627615016217 0ustar rtusers 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) ocamlgraph-2.0.0/dgraph/headers/headache_config.txt0000644000175000001440000000142413735627615020702 0ustar rtusers# Objective Caml source | ".*\\.mly" -> frame open:"/*" line:"*" close:"*/" | ".*\\.ml[il4]?.*" -> frame open:"(*" line:"*" close:"*)" # C source | ".*\\.c" -> frame open:"/*" line:"*" close:"*/" | ".*\\.ast" -> frame open:"//" line:" " close:" " | ".*\\.cc" -> frame open:"/*" line:"*" close:"*/" # Asm source | ".*\\.S" -> frame open:"/*" line:"*" close:"*/" # Configure | "config\\.h\\.in" -> frame open:"/*" line:"*" close:"*/" | "configure\\.in" -> frame open:"#" line:"#" close:"#" # Makefile | "Makefile" -> frame open:"#" line:"#" close:"#" # Sh | ".*\\.sh" -> frame open:"#" line:"#" close:"#" # Misc | "make_release" -> frame open:"#" line:"#" close:"#" | "FAQ" -> frame open:"#" line:"#" close:"#" | ".*\\.el" -> frame open: ";" line: ";" close:";" ocamlgraph-2.0.0/dgraph/headers/headers.sh0000755000175000001440000000013013735627615017035 0ustar rtusers#! /bin/sh headache -c headers/headache_config.txt -h headers/CEA_LGPL *.ml* *Makefile* ocamlgraph-2.0.0/dgraph/dGraphViewItem.mli0000644000175000001440000001221413735627615017040 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/dgraph/doc/0000755000175000001440000000000013735627615014223 5ustar rtusersocamlgraph-2.0.0/dgraph/doc/style.css0000755000175000001440000000433113735627615016101 0ustar rtusersa:visited {color : #416DFF; text-decoration : none; } a:link {color : #416DFF; text-decoration : none;} a:hover {color : Red; text-decoration : none; background-color: #5FFF88} a:active {color : Red; text-decoration : underline; } .keyword { font-weight : bold ; color : Red } .keywordsign { color : #C04600 } .superscript { font-size : 4 } .subscript { font-size : 4 } .comment { color : Green } .constructor { color : Blue } .type { color : #5C6585 } .string { color : Maroon } .warning { color : Red ; font-weight : bold } .info { margin-left : 3em; margin-right : 3em } .param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em } .code { color : #465F91 ; } h1 { font-size : 20pt ; text-align: center; } h2 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; } h3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; } h4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; } h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; } h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #C0FFFF ; padding: 2px; } div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #E0FFFF ; padding: 2px; } div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; } div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; } .typetable { border-style : hidden } .indextable { border-style : hidden } .paramstable { border-style : hidden ; padding: 5pt 5pt} body { background-color : White } tr { background-color : White } td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;} pre { margin-bottom: 4px } div.sig_block {margin-left: 2em}ocamlgraph-2.0.0/dgraph/dune0000644000175000001440000000044613735627615014340 0ustar rtusers(library (name graph_gtk) (public_name ocamlgraph_gtk) (modules :standard \ dGraphViewer) (libraries ocamlgraph stdlib-shims lablgtk2.gnomecanvas lablgtk2) (flags -open Graph)) (executable (name dGraphViewer) (modules dGraphViewer) (libraries graph_gtk lablgtk2.gnomecanvas lablgtk2)) ocamlgraph-2.0.0/dgraph/dGraphView.mli0000644000175000001440000001263313735627615016226 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/dgraph/pangoMeasure.ml0000644000175000001440000000056713735627615016446 0ustar rtuserslet withContext ~context ~fontName ~fontSize text = let font_description = Pango.Font.from_string fontName in Pango.Font.modify font_description ~size:(fontSize * Pango.scale) (); Pango.Context.set_font_description context font_description; let layout = Pango.Layout.create context in Pango.Layout.set_text layout text; Pango.Layout.get_pixel_size layout ocamlgraph-2.0.0/dgraph/pangoMeasure.mli0000644000175000001440000000014113735627615016603 0ustar rtusersval withContext : context:Pango.context -> fontName:string -> fontSize:int -> string -> int * intocamlgraph-2.0.0/dgraph/examples/0000755000175000001440000000000013735627615015274 5ustar rtusersocamlgraph-2.0.0/dgraph/examples/siblings.dot0000755000175000001440000007364313735627615017636 0ustar rtusers/* This is a graphviz-produced layout of the "family tree" of a fraternity and sorority. Each member in the graph was assigned a "big brother" from one organization and a "big sister" from the other. Blue icons represent Brothers from the fraternity, Pink represents Sisters from the sorority (Purple members are in both organizations - like honoraries.) Charter members (who can have no parent nodes) are outlined. ... dot -Tgif -Goverlap=false -o siblings.gif siblings.dot We're experimenting with different ways of coloring and graphing, but found this the easiest for now. When we have more people in, we might look at different shades depending on generation number -- earlier people would get lighter colors, more recent members darker. Thumbnail images would be an interesting alteration as well. from Japheth Cleaver */ digraph sdsu { size="36,36"; node [color=grey, style=filled]; node [fontname="Verdana", size="30,30"]; graph [ fontname = "Arial", fontsize = 36, style = "bold", label = "\nKappa Kappa Psi/Tau Beta Sigma\nSan Diego State University\nEta Mu and Zeta Xi Family Tree\n\nto date: November 30th, 2008\n", ssize = "30,60" ]; "Lori Brede" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=10"]; "Michael Griffith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=24"]; "Amie Holston" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=30"]; "Michael Griffith" -> "Lori Brede" "Amie Holston" -> "Lori Brede" "Casey Carter" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=11"]; "Laura De'Armond" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=14"]; "Laura De'Armond" -> "Casey Carter" "Japheth Cleaver" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=12"]; "Chuk Gawlik" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=22"]; "Stacy Snyder" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=309"]; "Chuk Gawlik" -> "Japheth Cleaver" "Stacy Snyder" -> "Japheth Cleaver" "Jillian Clifton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=13"]; "David Guthrie" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=25"]; "David Guthrie" -> "Jillian Clifton" "Japheth Cleaver" -> "Jillian Clifton" "Tony Sacco" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=55"]; "Heather Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=59"]; "Tony Sacco" -> "Laura De'Armond" "Heather Smith" -> "Laura De'Armond" "Kevin Decker" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=15"]; "Alex Hansen" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=26"]; "Wanda Livelsberger" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=53"]; "Alex Hansen" -> "Kevin Decker" "Wanda Livelsberger" -> "Kevin Decker" "Patrick Doerr" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=16"]; "Deanna Jagow" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=23"]; "Alex Hansen" -> "Patrick Doerr" "Deanna Jagow" -> "Patrick Doerr" "Lori Asaro" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=178"]; "Mark Pearson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=169"]; "Lori Ball" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=167"]; "Mark Pearson" -> "Lori Asaro" "Lori Ball" -> "Lori Asaro" "Ryan Farris" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=18"]; "Rob Reiner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=51"]; "Cindy Teel" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=62"]; "Rob Reiner" -> "Ryan Farris" "Cindy Teel" -> "Ryan Farris" "Ginger Palmer" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=180"]; "Mark Newton-John" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=46"]; "Mark Newton-John" -> "Ginger Palmer" "Matthew FitzGerald" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=19"]; "Mervin Maniago" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=41"]; "Mervin Maniago" -> "Matthew FitzGerald" "Amie Holston" -> "Matthew FitzGerald" "Tani Miller" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=195"]; "Mark Pearson" -> "Tani Miller" "Vienna McMurtry" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=196"]; "Robert Walwick" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=153"]; "Robert Walwick" -> "Vienna McMurtry" "Ginger Palmer" -> "Vienna McMurtry" "Chuck Foster" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=20"]; "Karen Saye" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=56"]; "Kevin Decker" -> "Chuck Foster" "Karen Saye" -> "Chuck Foster" "Gary Frampton" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=201"]; "Ginger Palmer" -> "Gary Frampton" "Pat Norris" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=207"]; "Sean Tipps" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=204"]; "Teresa Long" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=194"]; "Sean Tipps" -> "Pat Norris" "Teresa Long" -> "Pat Norris" "Marc Martin-ez" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=208"]; "Mark Pearson" -> "Marc Martin-ez" "Tani Miller" -> "Marc Martin-ez" "Kristen Villone" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=209"]; "Kelly Erickson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=199"]; "Anna Pedroza" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=197"]; "Kelly Erickson" -> "Kristen Villone" "Anna Pedroza" -> "Kristen Villone" "Geoff Frank" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=21"]; "Chris Livelsberger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=40"]; "Amy Price" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=57"]; "Chris Livelsberger" -> "Geoff Frank" "Amy Price" -> "Geoff Frank" "Tracy Murray" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=210"]; "John FitzGibbon" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=92"]; "Judy Dulcich" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=177"]; "John FitzGibbon" -> "Tracy Murray" "Judy Dulcich" -> "Tracy Murray" "Ian McIntosh" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=215"]; "Barbara Tollison" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=172"]; "Robert Walwick" -> "Ian McIntosh" "Barbara Tollison" -> "Ian McIntosh" "Jayson Smith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=58"]; "Jayson Smith" -> "Chuk Gawlik" "Heather Smith" -> "Chuk Gawlik" "Kelly McKinney" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=222"]; "Mark Nadeau" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=183"]; "Mark Nadeau" -> "Kelly McKinney" "Judy Dulcich" -> "Kelly McKinney" "Chris Livelsberger" -> "Deanna Jagow" "Amy Price" -> "Deanna Jagow" "Renee Thompson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=231"]; "J. Angeles" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=3"]; "Kelley Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=223"]; "J. Angeles" -> "Renee Thompson" "Kelley Smith" -> "Renee Thompson" "Steven Smith" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=233"]; "John FitzGibbon" -> "Steven Smith" "Charlene Andrews" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=234"]; "Diane Reoch" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=227"]; "Diane Reoch" -> "Charlene Andrews" "Tonya Alexander" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=238"]; "Gail Vasquez" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=225"]; "Gail Vasquez" -> "Tonya Alexander" "Spencer Caldwell" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=239"]; "Becky Bernal" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=218"]; "Becky Bernal" -> "Spencer Caldwell" "Chuk Gawlik" -> "Michael Griffith" "Wanda Livelsberger" -> "Michael Griffith" "Russell Grant" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=242"]; "Steven Smith" -> "Russell Grant" "Tiffany Worthington" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=66"]; "Chuck Foster" -> "David Guthrie" "Tiffany Worthington" -> "David Guthrie" "Jerry Maya" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=250"]; "John FitzGibbon" -> "Jerry Maya" "Melissa Schwartz" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=252"]; "Russell Grant" -> "Melissa Schwartz" "Delphy Shaulis" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=255"]; "Renee Thompson" -> "Delphy Shaulis" "Martin Naiman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=45"]; "Janean Angeles" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=86"]; "Martin Naiman" -> "Alex Hansen" "Janean Angeles" -> "Alex Hansen" "Leslie Harlow" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=265"]; "Dennis McColl" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=251"]; "Denise Luna" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=236"]; "Dennis McColl" -> "Leslie Harlow" "Denise Luna" -> "Leslie Harlow" "Jonathan Yudman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=267"]; "April Ortiz-cloninger" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=258"]; "April Ortiz-cloninger" -> "Jonathan Yudman" "Michael Elgo" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=268"]; "Carol Kropp" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=254"]; "Spencer Caldwell" -> "Michael Elgo" "Carol Kropp" -> "Michael Elgo" "Denmark Vea" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=269"]; "Marc Martin-ez" -> "Denmark Vea" "Kelley Smith" -> "Denmark Vea" "Kathleen Hansen" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=27"]; "Martin Naiman" -> "Kathleen Hansen" "Heather Smith" -> "Kathleen Hansen" "Laura Stegner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=274"]; "April Ortiz-cloninger" -> "Laura Stegner" "Kathy Jones" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=28"]; "J. Angeles" -> "Kathy Jones" "Eric Gates" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=282"]; "Erick Sugimura" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=280"]; "Erick Sugimura" -> "Eric Gates" "Laura Stegner" -> "Eric Gates" "Jennifer Stoewe" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=288"]; "Eric Gates" -> "Jennifer Stoewe" "Karen Helbling" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=29"]; "Regan Ashker" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=5"]; "Kevin Decker" -> "Karen Helbling" "Regan Ashker" -> "Karen Helbling" "Scott Wood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=295"]; "Eric Gates" -> "Scott Wood" "Greg Flood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=200"]; "Greg Flood" -> "J. Angeles" "Ginger Palmer" -> "J. Angeles" "Lynn Reeves" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=48"]; "Chuk Gawlik" -> "Amie Holston" "Lynn Reeves" -> "Amie Holston" "Susan Colwell" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=302"]; "Michael Elgo" -> "Susan Colwell" "Christopher Jouan" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=306"]; "Kevin Owens" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=245"]; "Kevin Owens" -> "Christopher Jouan" "Kristianna Reynante" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=308"]; "Michael Elgo" -> "Kristianna Reynante" "Janean Angeles" -> "Kristianna Reynante" "Amy Berner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=300"]; "Amy Berner" -> "Stacy Snyder" "Deanna Johnson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=31"]; "Alex Hansen" -> "Deanna Johnson" "Laura De'Armond" -> "Deanna Johnson" "Johnny Richardson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=310"]; "Russell Grant" -> "Johnny Richardson" "Nathan Fellhauer" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=313"]; "James Rowland" [color=thistle, URL="http://sdsu.kkytbs.net/members/profile.html?who=52"]; "James Rowland" -> "Nathan Fellhauer" "Kristianna Reynante" -> "Nathan Fellhauer" "Brian Raneses" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=314"]; "Sean McHenry" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=42"]; "Sean McHenry" -> "Brian Raneses" "Penny Lewis" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=315"]; "Martin Naiman" -> "Penny Lewis" "Becky Graham" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=316"]; "Kristen Elgo" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=7"]; "Kristen Elgo" -> "Becky Graham" "Steven Gross" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=318"]; "Rob Reiner" -> "Steven Gross" "Stacy Snyder" -> "Steven Gross" "Sedona Reynolds" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=32"]; "Mark Newton-John" -> "Sedona Reynolds" "Cindy Teel" -> "Sedona Reynolds" "Klair Mayerchak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=320"]; "Nathan Fellhauer" -> "Klair Mayerchak" "Becky Graham" -> "Klair Mayerchak" "Shari VerBerkmoes" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=321"]; "Sean McHenry" -> "Shari VerBerkmoes" "Janean Angeles" -> "Shari VerBerkmoes" "Anson Summers" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=326"]; "James Rowland" -> "Anson Summers" "Dusty Jolliff" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=33"]; "Rob Reiner" -> "Dusty Jolliff" "Stacy Snyder" -> "Dusty Jolliff" "Jennifer Garman" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=331"]; "James Rowland" -> "Jennifer Garman" "Kelly Greenhill" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=333"]; "Rob Reiner" -> "Kelly Greenhill" "Kristen Elgo" -> "Kelly Greenhill" "Lucinda Farless" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=334"]; "J. Angeles" -> "Lucinda Farless" "Susan Colwell" -> "Lucinda Farless" "Alfredo Cardenas" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=335"]; "Chuk Gawlik" -> "Alfredo Cardenas" "Kathleen Hansen" -> "Alfredo Cardenas" "Jennifer Jouan" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=34"]; "Andrea Owens" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=276"]; "Andrea Owens" -> "Jennifer Jouan" "Tamara Scrivner" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=345"]; "Joseph Butler" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=69"]; "Sarah Maltese" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=83"]; "Joseph Butler" -> "Tamara Scrivner" "Sarah Maltese" -> "Tamara Scrivner" "Bradley Stouse" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=346"]; "Ryan Underwood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=74"]; "Ryan Underwood" -> "Bradley Stouse" "Cindy Teel" -> "Bradley Stouse" "Casondra Brimmage" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=347"]; "Kristopher Lininger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=85"]; "Ilana Melcher" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=73"]; "Kristopher Lininger" -> "Casondra Brimmage" "Ilana Melcher" -> "Casondra Brimmage" "Cassiopeia Guthrie" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=348"]; "Jeremy Frazier" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=79"]; "Christine Mount" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=76"]; "Jeremy Frazier" -> "Cassiopeia Guthrie" "Christine Mount" -> "Cassiopeia Guthrie" "Kathleen Moran" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=349"]; "Matthew FitzGerald" -> "Kathleen Moran" "Lori Brede" -> "Kathleen Moran" "Tiffany Kalland" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=35"]; "Tony Sacco" -> "Tiffany Kalland" "Karen Helbling" -> "Tiffany Kalland" "Kristen Anderson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=350"]; "Jennie Bogart" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=78"]; "David Guthrie" -> "Kristen Anderson" "Jennie Bogart" -> "Kristen Anderson" "Laura Simonette" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=351"]; "Jon Weisel" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=89"]; "Jon Weisel" -> "Laura Simonette" "Japheth Cleaver" -> "Laura Simonette" "Nathan Williams" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=352"]; "David Guthrie" -> "Nathan Williams" "Karen Helbling" -> "Nathan Williams" "Rebecca Hippert" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=353"]; "Ryan Underwood" -> "Rebecca Hippert" "Tiffany Kalland" -> "Rebecca Hippert" "Samuel Wallace" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=354"]; "Joseph Butler" -> "Samuel Wallace" "Deanna Jagow" -> "Samuel Wallace" "Scott Gardner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=355"]; "Jeremy Frazier" -> "Scott Gardner" "Christine Mount" -> "Scott Gardner" "Alberto Ayon" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=356"]; "Bradley Stouse" -> "Alberto Ayon" "Jennie Bogart" -> "Alberto Ayon" "Susannah Clayton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=357"]; "Nathan Williams" -> "Susannah Clayton" "Karen Helbling" -> "Susannah Clayton" "Lisa Gochnauer" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=358"]; "Scott Gardner" -> "Lisa Gochnauer" "Casondra Brimmage" -> "Lisa Gochnauer" "Jamie Jackson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=359"]; "Samuel Wallace" -> "Jamie Jackson" "Tamara Scrivner" -> "Jamie Jackson" "Christina Kelly" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=36"]; "Matthew FitzGerald" -> "Christina Kelly" "Lori Brede" -> "Christina Kelly" "Gara Thornton" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=360"]; "Mark Newton-John" -> "Gara Thornton" "Laura Simonette" -> "Gara Thornton" "Robert Winebarger" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=361"]; "Robin Ellison" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=90"]; "Scott Gardner" -> "Robert Winebarger" "Robin Ellison" -> "Robert Winebarger" "Jeremy Kirchner" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=37"]; "Rob Reiner" -> "Jeremy Kirchner" "Sandy Konar" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=38"]; "Jennifer Brandon" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=9"]; "Jennifer Brandon" -> "Sandy Konar" "Dan Kuhlman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=39"]; "Rob Reiner" -> "Dan Kuhlman" "Dusty Jolliff" -> "Dan Kuhlman" "Lindsay Arehart" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=4"]; "Martin Naiman" -> "Lindsay Arehart" "Jennifer Brandon" -> "Lindsay Arehart" "J. Angeles" -> "Mervin Maniago" "Kathy Jones" -> "Mervin Maniago" "Jarrod Monroe" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=43"]; "Jamie Fratacci" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=44"]; "Mark Newton-John" -> "Jarrod Monroe" "Jamie Fratacci" -> "Jarrod Monroe" "Chuk Gawlik" -> "Jamie Fratacci" "Tiffany Worthington" -> "Jamie Fratacci" "Russell Grant" -> "Martin Naiman" "Tonya Alexander" -> "Martin Naiman" "Edward Givens" [color=lightblue, outline=bold, style=bold, URL="http://sdsu.kkytbs.net/members/profile.html?who=106"]; "Edward Givens" -> "Mark Newton-John" "Veronica Nickel" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=47"]; "Regan Ashker" -> "Veronica Nickel" "Wanda Livelsberger" -> "Lynn Reeves" "Bryan Ransom" [color=thistle, URL="http://sdsu.kkytbs.net/members/profile.html?who=49"]; "Jayson Smith" -> "Bryan Ransom" "Tony Sacco" -> "Regan Ashker" "Dusty Jolliff" -> "Regan Ashker" "Jennifer Stout" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=50"]; "Matthew FitzGerald" -> "Jennifer Stout" "Deanna Jagow" -> "Jennifer Stout" "Sean McHenry" -> "James Rowland" "James Rowland" -> "Wanda Livelsberger" "Janean Angeles" -> "Wanda Livelsberger" "Melissa Roy" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=54"]; "Mervin Maniago" -> "Melissa Roy" "Christina Kelly" -> "Melissa Roy" "Dennis McColl" -> "Tony Sacco" "April Ortiz-cloninger" -> "Tony Sacco" "Tony Sacco" -> "Karen Saye" "Tony Sacco" -> "Amy Price" "Kathleen Hansen" -> "Amy Price" "James Rowland" -> "Jayson Smith" "Brian Raneses" -> "Heather Smith" "Kristen Elgo" -> "Heather Smith" "Josh Atwood" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=6"]; "David Guthrie" -> "Josh Atwood" "Lori Brede" -> "Josh Atwood" "Katie Browne" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=60"]; "Patrick Doerr" -> "Katie Browne" "Jamie Fratacci" -> "Katie Browne" "Kristin Tang" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=61"]; "James Rowland" -> "Kristin Tang" "Heather Smith" -> "Kristin Tang" "Mervin Maniago" -> "Cindy Teel" "Veronica Nickel" -> "Cindy Teel" "Mike Tulumello" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=63"]; "Matthew FitzGerald" -> "Mike Tulumello" "Katie Browne" -> "Mike Tulumello" "Veronica Villanueva" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=64"]; "Ryan Farris" -> "Veronica Villanueva" "Sedona Reynolds" -> "Veronica Villanueva" "Mervin Maniago" -> "Tiffany Worthington" "Jennifer Jouan" -> "Tiffany Worthington" "Scott Wright" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=67"]; "James Rowland" -> "Scott Wright" "Kristen Elgo" -> "Scott Wright" "Jeremy Browne" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=68"]; "Matthew FitzGerald" -> "Jeremy Browne" "Japheth Cleaver" -> "Jeremy Browne" "James Fogelman" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=688"]; "Alberto Ayon" -> "James Fogelman" "Susannah Clayton" -> "James Fogelman" "Sandra Chase" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=689"]; "David Guthrie" -> "Sandra Chase" "Japheth Cleaver" -> "Sandra Chase" "Patrick Doerr" -> "Joseph Butler" "Deanna Jagow" -> "Joseph Butler" "Laura Fisher" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=690"]; "Nathan Williams" -> "Laura Fisher" "Casondra Brimmage" -> "Laura Fisher" "Katie Kozma" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=691"]; "Scott Wright" -> "Katie Kozma" "Robin Ellison" -> "Katie Kozma" "Rachel Perkins" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=692"]; "Joseph Butler" -> "Rachel Perkins" "Cassiopeia Guthrie" -> "Rachel Perkins" "Sarah Titilah" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=693"]; "Robert Winebarger" -> "Sarah Titilah" "Karen Helbling" -> "Sarah Titilah" "Ashley Rehart" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=694"]; "Laura Fisher" -> "Ashley Rehart" "Cara Yancey" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=695"]; "Katie Kozma" -> "Cara Yancey" "Ashley Presley" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=698"]; "Cara Yancey" -> "Ashley Presley" "Leila Wilhelm" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=699"]; "Robin Ellison" -> "Leila Wilhelm" "Sean McHenry" -> "Kristen Elgo" "Stacy Snyder" -> "Kristen Elgo" "Greg Moody" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=70"]; "Ryan Farris" -> "Greg Moody" "Jennifer Stout" -> "Greg Moody" "Lisa Fleck" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=700"]; "Rachel Perkins" -> "Lisa Fleck" "Christine Coyne" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=701"]; "Rachel Perkins" -> "Christine Coyne" "Jennifer Cooley" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=702"]; "Laura Fisher" -> "Jennifer Cooley" "Elizabeth Larios" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=703"]; "Ashley Rehart" -> "Elizabeth Larios" "Cate Threlkeld" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=707"]; "Katie Kozma" -> "Cate Threlkeld" "Erika Tapia" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=71"]; "Patrick Doerr" -> "Erika Tapia" "Melissa Roy" -> "Erika Tapia" "Robbyn Rozelle" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=72"]; "Jarrod Monroe" -> "Robbyn Rozelle" "Tiffany Kalland" -> "Robbyn Rozelle" "Ryan Farris" -> "Ilana Melcher" "Veronica Villanueva" -> "Ilana Melcher" "Greg Moody" -> "Ryan Underwood" "Katie Browne" -> "Ryan Underwood" "Cameron Brown" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=75"]; "Joseph Butler" -> "Cameron Brown" "Tiffany Kalland" -> "Cameron Brown" "Ryan Underwood" -> "Christine Mount" "Lori Brede" -> "Christine Mount" "Janay Rabe" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=77"]; "Greg Moody" -> "Janay Rabe" "Cindy Teel" -> "Janay Rabe" "Jeremy Browne" -> "Jennie Bogart" "Tiffany Kalland" -> "Jennie Bogart" "Ryan Farris" -> "Jeremy Frazier" "Ilana Melcher" -> "Jeremy Frazier" "Crystal Bozak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=8"]; "Patrick Doerr" -> "Crystal Bozak" "Katie Browne" -> "Crystal Bozak" "Kameka Smith" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=80"]; "Matthew FitzGerald" -> "Kameka Smith" "Ilana Melcher" -> "Kameka Smith" "Kyra Sacco" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=81"]; "Joseph Butler" -> "Kyra Sacco" "Robbyn Rozelle" -> "Kyra Sacco" "Samuel Behar" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=82"]; "Ryan Underwood" -> "Samuel Behar" "Lori Brede" -> "Samuel Behar" "Patrick Doerr" -> "Sarah Maltese" "Deanna Jagow" -> "Sarah Maltese" "David Bronson" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=84"]; "Kristin Alongi-Hutchins" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=87"]; "Tony Sacco" -> "David Bronson" "Kristin Alongi-Hutchins" -> "David Bronson" "Cameron Brown" -> "Kristopher Lininger" "Kameka Smith" -> "Kristopher Lininger" "Rakan Abu-Rahma" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=852"]; "Christine Coyne" -> "Rakan Abu-Rahma" "Jennifer Berry" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=270"]; "Jennifer Berry" -> "Janean Angeles" "Penny Lewis" -> "Kristin Alongi-Hutchins" "Melissa Bebak" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=88"]; "Greg Moody" -> "Melissa Bebak" "Sarah Maltese" -> "Melissa Bebak" "Scott Wright" -> "Jennifer Brandon" "Japheth Cleaver" -> "Jennifer Brandon" "Samuel Behar" -> "Robin Ellison" "Kyra Sacco" -> "Robin Ellison" "Teresa Simms" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=91"]; "Joseph Butler" -> "Teresa Simms" "Janay Rabe" -> "Teresa Simms" "Robert Schmidtke" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=188"]; "Jean Newman" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=166"]; "Robert Schmidtke" -> "John FitzGibbon" "Jean Newman" -> "John FitzGibbon" "Brittany DePew" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=928"]; "Elizabeth Larios" -> "Brittany DePew" "Kathleen Halberg" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=929"]; "Ashley Rehart" -> "Kathleen Halberg" "Terrance Hirsch" [color=lightblue, URL="http://sdsu.kkytbs.net/members/profile.html?who=96"]; "J. Angeles" -> "Terrance Hirsch" "Susan Colwell" -> "Terrance Hirsch" "Monique Arellano" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=972"]; "Ashley Presley" -> "Monique Arellano" "Anthony Henderson" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=973"]; "Jennifer Cooley" -> "Anthony Henderson" "Amethyst Tagle" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=974"]; "Cate Threlkeld" -> "Amethyst Tagle" "Mallory Williams" [color=lightpink, URL="http://sdsu.kkytbs.net/members/profile.html?who=975"]; "Lisa Fleck" -> "Mallory Williams" }ocamlgraph-2.0.0/dgraph/examples/polygonal.dot0000644000175000001440000000036713735627615020016 0ustar rtusersdigraph G { a -> b -> c; b -> d; a [shape=polygon,sides=5,peripheries=3,color=lightblue,style=filled]; c [shape=polygon,sides=4,skew=.4,label="hello world"] d [shape=invtriangle]; e [shape=polygon,sides=4,distortion=.7]; } ocamlgraph-2.0.0/dgraph/examples/clusters.svg0000755000175000001440000001623213735627615017670 0ustar rtusers ]> G cluster0 process #1 cluster1 process #2 a0 a0 a1 a1 a0->a1 a2 a2 a1->a2 b3 b3 a1->b3 a3 a3 a2->a3 a3->a0 end end a3->end b0 b0 b1 b1 b0->b1 b2 b2 b1->b2 b2->a3 b2->b3 start start start->a0 start->b0 ocamlgraph-2.0.0/dgraph/examples/clusters_with_edges.dot0000644000175000001440000000047513735627615022060 0ustar rtusersdigraph G { compound=true; subgraph cluster0 { a -> b; a -> c; b -> d; c -> d; } subgraph cluster1 { e -> g; e -> f; } b -> f [lhead=cluster1]; d -> e; c -> g [ltail=cluster0, lhead=cluster1]; c -> e [ltail=cluster0]; d -> h; } ocamlgraph-2.0.0/dgraph/examples/pmpipe.gv0000755000175000001440000000665313735627615017141 0ustar rtusersdigraph g { graph [ ]; node [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" shape = "box" color = "black" width = "0.5" ]; edge [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" color = "black" ]; "23296" [ label = "23296\n?" pname = "?" kind = "proc" ]; "182948-1" [ label = "182948-1\n182949-1\npipe" fontsize = "7" fname = "pipe" shape = "doublecircle" subkind = "pipe" kind = "file" ]; "23310" [ label = "23310\ncat" pname = "cat" kind = "proc" ]; "182950-1" [ label = "182950-1\n182951-1\npipe" fontsize = "7" fname = "pipe" shape = "doublecircle" subkind = "pipe" kind = "file" ]; "23311" [ label = "23311\ncat" pname = "cat" kind = "proc" ]; "182952-1" [ label = "182952-1\n182953-1\npipe" fontsize = "7" fname = "pipe" shape = "doublecircle" subkind = "pipe" kind = "file" ]; "23312" [ label = "23312\ncat" pname = "cat" kind = "proc" ]; "182954-1" [ label = "182954-1\n182955-1\npipe" fontsize = "7" fname = "pipe" shape = "doublecircle" subkind = "pipe" kind = "file" ]; "23313" [ label = "23313\ncat" pname = "cat" kind = "proc" ]; "79893+2568" [ label = "79893+2568\n/usr/share/lib/termcap" fname = "/usr/share/lib/termcap" shape = "ellipse" kind = "file" ]; "85+2560" [ label = "85+2560\n?" fname = "?" shape = "ellipse" kind = "file" ]; "23314" [ label = "23314\ncat" pname = "cat" kind = "proc" ]; "4151865284+0" [ label = "4151865284+0\n/tmp/termcap" fname = "/tmp/termcap" shape = "ellipse" kind = "file" ]; "23296" -> "23310" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" color = "black" ]; "23296" -> "23311" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" color = "black" ]; "23311" -> "182948-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "back" color = "black" ]; "23310" -> "182948-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "forward" color = "black" ]; "23296" -> "23312" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" color = "black" ]; "23312" -> "182952-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "forward" color = "black" ]; "23312" -> "182950-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "back" color = "black" ]; "23296" -> "23313" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" color = "black" ]; "23313" -> "182954-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "forward" color = "black" ]; "23311" -> "182950-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "forward" color = "black" ]; "23310" -> "79893+2568" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "back" color = "black" ]; "23296" -> "85+2560" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "both" color = "black" ]; "23296" -> "23314" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" color = "black" ]; "23314" -> "85+2560" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "both" color = "black" ]; "23314" -> "182954-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "back" color = "black" ]; "23296" -> "85+2560" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "both" color = "black" ]; "23314" -> "4151865284+0" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "forward" color = "black" ]; "23313" -> "182952-1" [ fontsize = "14" fontname = "Times-Roman" fontcolor = "black" dir = "back" color = "black" ]; } ocamlgraph-2.0.0/dgraph/examples/clusters.dot0000755000175000001440000000062113735627615017652 0ustar rtusersdigraph G { subgraph cluster_0 { style=filled; color=lightgrey; node [style=filled,color=white]; a0 -> a1 -> a2 -> a3; label = "process #1"; } subgraph cluster_1 { node [style=filled]; b0 -> b1 -> b2 -> b3; label = "process #2"; color=blue } start -> a0; start -> b0; a1 -> b3; b2 -> a3; a3 -> a0; a3 -> end; b3 -> end; start [shape=Mdiamond]; end [shape=Msquare]; } ocamlgraph-2.0.0/dgraph/examples/fsm.dot0000755000175000001440000000115013735627615016571 0ustar rtusersdigraph finite_state_machine { rankdir=LR; size="8,5" node [shape = doublecircle]; LR_0 LR_3 LR_4 LR_8; node [shape = circle]; 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-2.0.0/dgraph/examples/awilliams.gv0000755000175000001440000001621113735627615017620 0ustar rtusersdigraph pvn { ordering=out; node_1 -> node_2; node_1 [label="ID: 1\ntype: 48\nnbr out: 0\nnbr chi: 11"]; node_2 [label="ID: 2\ntype: 8\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_3; node_3 [label="ID: 3\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_4; node_4 [label="ID: 4\ntype: 6\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_5; node_5 [label="ID: 5\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_6; node_6 [label="ID: 6\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_7; node_7 [label="ID: 7\ntype: 49\nnbr out: 0\nnbr chi: 0"]; node_7 -> node_8; node_8 [label="ID: 8\ntype: 45\nnbr out: 2\nnbr chi: 0"]; node_8 -> node_9; node_9 [label="ID: 9\ntype: 48\nnbr out: 0\nnbr chi: 4"]; node_9 -> node_10; node_10 [label="ID: 10\ntype: 8\nnbr out: 0\nnbr chi: 0"]; node_9 -> node_11; node_11 [label="ID: 11\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_9 -> node_12; node_12 [label="ID: 12\ntype: 5\nnbr out: 0\nnbr chi: 0"]; node_9 -> node_13; node_13 [label="ID: 13\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_8 -> node_14; node_14 [label="ID: 14\ntype: 39\nnbr out: 1\nnbr chi: 0"]; node_14 -> node_15; node_15 [label="ID: 15\ntype: 55\nnbr out: 0\nnbr chi: 0"]; node_15 -> node_16; node_16 [label="ID: 16\ntype: 48\nnbr out: 0\nnbr chi: 3"]; node_16 -> node_17; node_17 [label="ID: 17\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_16 -> node_18; node_18 [label="ID: 18\ntype: 6\nnbr out: 0\nnbr chi: 0"]; node_16 -> node_19; node_19 [label="ID: 19\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_19 -> node_20; node_20 [label="ID: 20\ntype: 48\nnbr out: 0\nnbr chi: 5"]; node_20 -> node_21; node_21 [label="ID: 21\ntype: 38\nnbr out: 0\nnbr chi: 0"]; node_20 -> node_22; node_22 [label="ID: 22\ntype: 8\nnbr out: 0\nnbr chi: 0"]; node_20 -> node_23; node_23 [label="ID: 23\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_20 -> node_24; node_24 [label="ID: 24\ntype: 5\nnbr out: 0\nnbr chi: 0"]; node_20 -> node_25; node_25 [label="ID: 25\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_19 -> node_26; node_26 [label="ID: 26\ntype: 41\nnbr out: 12\nnbr chi: 0"]; node_26 -> node_27; node_27 [label="ID: 27\ntype: 48\nnbr out: 0\nnbr chi: 5"]; node_27 -> node_28; node_28 [label="ID: 28\ntype: 38\nnbr out: 0\nnbr chi: 0"]; node_27 -> node_29; node_29 [label="ID: 29\ntype: 8\nnbr out: 0\nnbr chi: 0"]; node_27 -> node_30; node_30 [label="ID: 30\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_27 -> node_31; node_31 [label="ID: 31\ntype: 5\nnbr out: 0\nnbr chi: 0"]; node_27 -> node_32; node_32 [label="ID: 32\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_27; node_26 -> node_33; node_33 [label="ID: 33\ntype: 48\nnbr out: 0\nnbr chi: 5"]; node_33 -> node_34; node_34 [label="ID: 34\ntype: 38\nnbr out: 0\nnbr chi: 0"]; node_33 -> node_35; node_35 [label="ID: 35\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_33 -> node_36; node_36 [label="ID: 36\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_33 -> node_37; node_37 [label="ID: 37\ntype: 20\nnbr out: 0\nnbr chi: 0"]; node_33 -> node_38; node_38 [label="ID: 38\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_15 -> node_39; node_39 [label="ID: 39\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_39 -> node_40; node_40 [label="ID: 40\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_39 -> node_41; node_41 [label="ID: 41\ntype: 48\nnbr out: 0\nnbr chi: 3"]; node_41 -> node_42; node_42 [label="ID: 42\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_41 -> node_43; node_43 [label="ID: 43\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_41 -> node_44; node_44 [label="ID: 44\ntype: 6\nnbr out: 0\nnbr chi: 0"]; node_15 -> node_45; node_45 [label="ID: 45\ntype: 48\nnbr out: 0\nnbr chi: 4"]; node_45 -> node_46; node_46 [label="ID: 46\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_45 -> node_47; node_47 [label="ID: 47\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_47 -> node_48; node_48 [label="ID: 48\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_47 -> node_49; node_49 [label="ID: 49\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_45 -> node_50; node_50 [label="ID: 50\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_45 -> node_51; node_51 [label="ID: 51\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_51 -> node_52; node_52 [label="ID: 52\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_52 -> node_53; node_53 [label="ID: 53\ntype: 54\nnbr out: 0\nnbr chi: 0"]; node_52 -> node_54; node_54 [label="ID: 54\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_51 -> node_55; node_55 [label="ID: 55\ntype: 48\nnbr out: 0\nnbr chi: 3"]; node_55 -> node_56; node_56 [label="ID: 56\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_55 -> node_57; node_57 [label="ID: 57\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_55 -> node_58; node_58 [label="ID: 58\ntype: 6\nnbr out: 0\nnbr chi: 0"]; node_15 -> node_59; node_59 [label="ID: 59\ntype: 48\nnbr out: 0\nnbr chi: 5"]; node_59 -> node_60; node_60 [label="ID: 60\ntype: 38\nnbr out: 0\nnbr chi: 0"]; node_59 -> node_61; node_61 [label="ID: 61\ntype: 8\nnbr out: 0\nnbr chi: 0"]; node_59 -> node_62; node_62 [label="ID: 62\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_59 -> node_63; node_63 [label="ID: 63\ntype: 5\nnbr out: 0\nnbr chi: 0"]; node_59 -> node_64; node_64 [label="ID: 64\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_15 -> node_65; node_65 [label="ID: 65\ntype: 48\nnbr out: 0\nnbr chi: 5"]; node_65 -> node_66; node_66 [label="ID: 66\ntype: 38\nnbr out: 0\nnbr chi: 0"]; node_65 -> node_67; node_67 [label="ID: 67\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_65 -> node_68; node_68 [label="ID: 68\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_65 -> node_69; node_69 [label="ID: 69\ntype: 20\nnbr out: 0\nnbr chi: 0"]; node_65 -> node_70; node_70 [label="ID: 70\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_14 -> node_71; node_71 [label="ID: 71\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_71 -> node_72; node_72 [label="ID: 72\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_71 -> node_73; node_73 [label="ID: 73\ntype: 48\nnbr out: 0\nnbr chi: 3"]; node_73 -> node_74; node_74 [label="ID: 74\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_73 -> node_75; node_75 [label="ID: 75\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_73 -> node_76; node_76 [label="ID: 76\ntype: 6\nnbr out: 0\nnbr chi: 0"]; node_8 -> node_77; node_77 [label="ID: 77\ntype: 45\nnbr out: 1\nnbr chi: 0"]; node_77 -> node_78; node_78 [label="ID: 78\ntype: 16\nnbr out: 0\nnbr chi: 0"]; node_77 -> node_79; node_79 [label="ID: 79\ntype: 48\nnbr out: 0\nnbr chi: 3"]; node_79 -> node_80; node_80 [label="ID: 80\ntype: 14\nnbr out: 0\nnbr chi: 0"]; node_79 -> node_81; node_81 [label="ID: 81\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_79 -> node_82; node_82 [label="ID: 82\ntype: 6\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_83; node_83 [label="ID: 83\ntype: 38\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_84; node_84 [label="ID: 84\ntype: 8\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_85; node_85 [label="ID: 85\ntype: 1\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_86; node_86 [label="ID: 86\ntype: 5\nnbr out: 0\nnbr chi: 0"]; node_1 -> node_87; node_87 [label="ID: 87\ntype: 16\nnbr out: 0\nnbr chi: 0"]; } ocamlgraph-2.0.0/dgraph/examples/switch.gv0000755000175000001440000000250013735627615017133 0ustar rtusersdigraph G { graph [center=true rankdir=LR bgcolor="#808080"] edge [dir=none] node [width=0.3 height=0.3 label=""] { node [shape=circle style=invis] 1 2 3 4 5 6 7 8 10 20 30 40 50 60 70 80 } { node [shape=circle] a b c d e f g h i j k l m n o p q r s t u v w x } { node [shape=diamond] A B C D E F G H I J K L M N O P Q R S T U V W X } 1 -> a -> {A B} [color="#0000ff"] 2 -> b -> {B A} [color="#ff0000"] 3 -> c -> {C D} [color="#ffff00"] 4 -> d -> {D C} [color="#00ff00"] 5 -> e -> {E F} [color="#000000"] 6 -> f -> {F E} [color="#00ffff"] 7 -> g -> {G H} [color="#ffffff"] 8 -> h -> {H G} [color="#ff00ff"] { edge [color="#ff0000:#0000ff"] A -> i -> {I K} B -> j -> {J L} } { edge [color="#00ff00:#ffff00"] C -> k -> {K I} D -> l -> {L J} } { edge [color="#00ffff:#000000"] E -> m -> {M O} F -> n -> {N P} } { edge [color="#ff00ff:#ffffff"] G -> o -> {O M} H -> p -> {P N} } { edge [color="#00ff00:#ffff00:#ff0000:#0000ff"] I -> q -> {Q U} J -> r -> {R V} K -> s -> {S W} L -> t -> {T X} } { edge [color="#ff00ff:#ffffff:#00ffff:#000000"] M -> u -> {U Q} N -> v -> {V R} O -> w -> {W S} P -> x -> {X T} } { edge [color="#ff00ff:#ffffff:#00ffff:#000000:#00ff00:#ffff00:#ff0000:#0000ff"] Q -> 10 R -> 20 S -> 30 T -> 40 U -> 50 V -> 60 W -> 70 X -> 80 } } ocamlgraph-2.0.0/dgraph/examples/gzip_annot.dot0000755000175000001440000054165213735627615020174 0ustar rtusersdigraph G { node [label="\N"]; graph [bb="0,0,9334,994", _draw_="c 5 -white C 5 -white P 4 0 0 0 994 9334 994 9334 0 ", xdotversion="1.2"]; subgraph cluster_36 { graph [label="S 36", color="#C00000", style=bold, lp="3856,421", bb="3803,356,3909,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3856 416 0 32 4 -S 36 ", _draw_="S 4 -bold c 7 -#C00000 p 4 3803 356 3803 433 3909 433 3909 356 ", xdotversion=""]; "UV error (32)" [label=error, width="1.00", height="0.49", style=bold, color="#C00000", pos="3847,382", _draw_="S 4 -bold c 7 -#C00000 e 3847 382 36 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3847 377 0 35 5 -error "]; "UV error (32)" -> "UV error (32)" [style=invis, minlen=0, pos="e,3869,368 3869,396 3885,401 3901,396 3901,382 3901,371 3891,366 3879,366"]; } subgraph cluster_37 { graph [label="S 37", color="#C00080", style=bold, lp="2354,421", bb="2287,356,2421,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2354 416 0 32 4 -S 37 ", _draw_="S 4 -bold c 7 -#C00080 p 4 2287 356 2287 433 2421 433 2421 356 ", xdotversion=""]; "UV memset (47)" [label=memset, width="1.39", height="0.49", style=dotted, color="#C00080", pos="2345,382", _draw_="S 6 -dotted c 7 -#C00080 e 2345 382 50 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2345 377 0 55 6 -memset "]; "UV memset (47)" -> "UV memset (47)" [style=invis, minlen=0, pos="e,2374,368 2374,396 2394,400 2413,396 2413,382 2413,370 2400,366 2384,367"]; } subgraph cluster_50 { graph [label="S 50", color="#40C000", style=bold, lp="8479,251", bb="8421,186,8537,263", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8479 246 0 32 4 -S 50 ", _draw_="S 4 -bold c 7 -#40C000 p 4 8421 186 8421 263 8537 263 8537 186 ", xdotversion=""]; "UV unlink (111)" [label=unlink, width="1.14", height="0.49", style=dotted, color="#40C000", pos="8470,212", _draw_="S 6 -dotted c 7 -#40C000 e 8470 212 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8470 207 0 43 6 -unlink "]; "UV unlink (111)" -> "UV unlink (111)" [style=invis, minlen=0, pos="e,8494,198 8494,226 8512,231 8529,226 8529,212 8529,201 8518,195 8504,196"]; } subgraph cluster_38 { graph [label="S 38", color="#C08000", style=bold, lp="2179,421", bb="2111,356,2247,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2179 416 0 32 4 -S 38 ", _draw_="S 4 -bold c 7 -#C08000 p 4 2111 356 2111 433 2247 433 2247 356 ", xdotversion=""]; "UV memcpy (48)" [label=memcpy, width="1.42", height="0.49", style=dotted, color="#C08000", pos="2170,382", _draw_="S 6 -dotted c 7 -#C08000 e 2170 382 51 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2170 377 0 57 6 -memcpy "]; "UV memcpy (48)" -> "UV memcpy (48)" [style=invis, minlen=0, pos="e,2200,368 2200,396 2220,400 2239,396 2239,382 2239,370 2226,366 2210,367"]; } subgraph cluster_51 { graph [label="S 51", color="#40C080", style=bold, lp="6036,336", bb="5980,271,6092,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6036 331 0 32 4 -S 51 ", _draw_="S 4 -bold c 7 -#40C080 p 4 5980 271 5980 348 6092 348 6092 271 ", xdotversion=""]; "UV isatty (103)" [label=isatty, width="1.08", height="0.49", style=dotted, color="#40C080", pos="6027,297", _draw_="S 6 -dotted c 7 -#40C080 e 6027 297 39 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6027 292 0 39 6 -isatty "]; "UV isatty (103)" -> "UV isatty (103)" [style=invis, minlen=0, pos="e,6050,283 6050,311 6067,316 6084,311 6084,297 6084,286 6073,280 6060,281"]; } subgraph cluster_52 { graph [label="S 52", color="#C04000", style=bold, lp="5742,421", bb="5691,356,5793,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5742 416 0 32 4 -S 52 ", _draw_="S 4 -bold c 7 -#C04000 p 4 5691 356 5691 433 5793 433 5793 356 ", xdotversion=""]; "UV fstat (104)" [label=fstat, width="0.94", height="0.49", style=dotted, color="#C04000", pos="5733,382", _draw_="S 6 -dotted c 7 -#C04000 e 5733 382 34 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5733 377 0 32 5 -fstat "]; "UV fstat (104)" -> "UV fstat (104)" [style=invis, minlen=0, pos="e,5754,368 5754,396 5769,401 5785,396 5785,382 5785,371 5775,366 5764,366"]; } subgraph cluster_39 { graph [label="S 39", color="#C08080", style=bold, lp="1368,336", bb="1308,271,1428,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1368 331 0 32 4 -S 39 ", _draw_="S 4 -bold c 7 -#C08080 p 4 1308 271 1308 348 1428 348 1428 271 ", xdotversion=""]; "UV updcrc (2)" [label=updcrc, width="1.19", height="0.49", style=bold, color="#C08080", pos="1359,297", _draw_="S 4 -bold c 7 -#C08080 e 1359 297 43 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1359 292 0 45 6 -updcrc "]; "UV updcrc (2)" -> "UV updcrc (2)" [style=invis, minlen=0, pos="e,1385,283 1385,311 1402,316 1420,311 1420,297 1420,286 1408,280 1395,281"]; } subgraph cluster_53 { graph [label="S 53", color="#C04080", style=bold, lp="4524,251", bb="4461,186,4587,263", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4524 246 0 32 4 -S 53 ", _draw_="S 4 -bold c 7 -#C04080 p 4 4461 186 4461 263 4587 263 4587 186 ", xdotversion=""]; "UV strcspn (29)" [label=strcspn, width="1.28", height="0.49", style=dotted, color="#C04080", pos="4515,212", _draw_="S 6 -dotted c 7 -#C04080 e 4515 212 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4515 207 0 50 7 -strcspn "]; "UV strcspn (29)" -> "UV strcspn (29)" [style=invis, minlen=0, pos="e,4542,198 4542,226 4561,230 4579,226 4579,212 4579,201 4567,196 4552,197"]; } subgraph cluster_54 { graph [label="S 54", color="#C0C000", style=bold, lp="3766,166", bb="3719,101,3813,178", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3766 161 0 32 4 -S 54 ", _draw_="S 4 -bold c 7 -#C0C000 p 4 3719 101 3719 178 3813 178 3813 101 ", xdotversion=""]; "UV free (30)" [label=free, width="0.83", height="0.49", style=dotted, color="#C0C000", pos="3757,127", _draw_="S 6 -dotted c 7 -#C0C000 e 3757 127 30 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3757 122 0 27 4 -free "]; "UV free (30)" -> "UV free (30)" [style=invis, minlen=0, pos="e,3776,113 3776,141 3790,146 3805,141 3805,127 3805,116 3796,111 3786,111"]; } subgraph cluster_20 { graph [label="S 20", color="#804000", style=bold, lp="5605,421", bb="5559,356,5651,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5605 416 0 32 4 -S 20 ", _draw_="S 4 -bold c 7 -#804000 p 4 5559 356 5559 433 5651 433 5651 356 ", xdotversion=""]; "UV lzw (78)" [label=lzw, width="0.81", height="0.49", style=bold, color="#804000", pos="5596,382", _draw_="S 4 -bold c 7 -#804000 e 5596 382 29 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5596 377 0 25 3 -lzw "]; "UV lzw (78)" -> "UV lzw (78)" [style=invis, minlen=0, pos="e,5614,368 5614,396 5628,401 5643,396 5643,382 5643,371 5634,366 5624,366"]; } subgraph cluster_55 { graph [label="S 55", color="#C0C080", style=bold, lp="7888,166", bb="7831,101,7945,178", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7888 161 0 32 4 -S 55 ", _draw_="S 4 -bold c 7 -#C0C080 p 4 7831 101 7831 178 7945 178 7945 101 ", xdotversion=""]; "UV strlwr (19)" [label=strlwr, width="1.11", height="0.49", style=bold, color="#C0C080", pos="7879,127", _draw_="S 4 -bold c 7 -#C0C080 e 7879 127 40 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7879 122 0 41 6 -strlwr "]; "UV strlwr (19)" -> "UV strlwr (19)" [style=invis, minlen=0, pos="e,7903,113 7903,141 7920,146 7937,141 7937,127 7937,116 7926,110 7913,111"]; } subgraph cluster_56 { graph [label="S 56", color="#404040", style=bold, lp="5181,336", bb="5072,271,5290,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5181 331 0 32 4 -S 56 ", _draw_="S 4 -bold c 7 -#404040 p 4 5072 271 5072 348 5290 348 5290 271 ", xdotversion=""]; "UV __errno_location (11)" [label=__errno_location, width="2.56", height="0.49", style=dotted, color="#404040", pos="5172,297", _draw_="S 6 -dotted c 7 -#404040 e 5172 297 92 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5172 292 0 114 16 -__errno_location "]; "UV __errno_location (11)" -> "UV __errno_location (11)" [style=invis, minlen=0, pos="e,5222,282 5222,312 5253,315 5282,310 5282,297 5282,285 5259,280 5232,281"]; } subgraph cluster_21 { graph [label="S 21", color="#804080", style=bold, lp="658,974", bb="29,356,1287,986", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 658 969 0 32 4 -S 21 ", _draw_="S 4 -bold c 7 -#804080 p 4 29 356 29 986 1287 986 1287 356 ", xdotversion=""]; "UV zip (0)" [label=zip, width="0.69", height="0.49", style=bold, color="#804080", pos="640,935", _draw_="S 4 -bold c 7 -#804080 e 640 935 25 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 640 930 0 20 3 -zip "]; "UV flush_outbuf (1)" [label=flush_outbuf, width="1.97", height="0.50", style=bold, color="#804080", pos="1050,382", _draw_="S 4 -bold c 7 -#804080 e 1050 382 71 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1050 377 0 86 12 -flush_outbuf "]; "UV bi_init (3)" [label=bi_init, width="1.11", height="0.50", style=bold, color="#804080", pos="100,863", _draw_="S 4 -bold c 7 -#804080 e 100 863 40 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 100 858 0 42 7 -bi_init "]; "UV ct_init (4)" [label=ct_init, width="1.14", height="0.50", style=bold, color="#804080", pos="119,714", _draw_="S 4 -bold c 7 -#804080 e 119 714 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 119 709 0 43 7 -ct_init "]; "UV lm_init (5)" [label=lm_init, width="1.22", height="0.50", style=bold, color="#804080", pos="1234,863", _draw_="S 4 -bold c 7 -#804080 e 1234 863 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1234 858 0 47 7 -lm_init "]; "UV deflate (7)" [label=deflate, width="1.22", height="0.50", style=bold, color="#804080", pos="487,863", _draw_="S 4 -bold c 7 -#804080 e 487 863 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 487 858 0 48 7 -deflate "]; "UV fill_window (133)" [label=fill_window, width="1.81", height="0.50", style=bold, color="#804080", pos="1214,714", _draw_="S 4 -bold c 7 -#804080 e 1214 714 65 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1214 709 0 78 11 -fill_window "]; "UV longest_match (134)" [label=longest_match, width="2.25", height="0.50", style=bold, color="#804080", pos="444,714", _draw_="S 4 -bold c 7 -#804080 e 444 714 81 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 444 709 0 101 13 -longest_match "]; "UV deflate_fast (135)" [label=deflate_fast, width="1.86", height="0.50", style=bold, color="#804080", pos="444,786", _draw_="S 4 -bold c 7 -#804080 e 444 786 67 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 444 781 0 81 12 -deflate_fast "]; "UV gen_codes (61)" [label=gen_codes, width="1.67", height="0.50", style=bold, color="#804080", pos="137,467", _draw_="S 4 -bold c 7 -#804080 e 137 467 60 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 137 462 0 71 9 -gen_codes "]; "UV bi_reverse (62)" [label=bi_reverse, width="1.67", height="0.50", style=bold, color="#804080", pos="97,382", _draw_="S 4 -bold c 7 -#804080 e 97 382 60 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 97 377 0 71 10 -bi_reverse "]; "UV init_block (63)" [label=init_block, width="1.56", height="0.50", style=bold, color="#804080", pos="173,637", _draw_="S 4 -bold c 7 -#804080 e 173 637 56 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 173 632 0 65 10 -init_block "]; "UV pqdownheap (64)" [label=pqdownheap, width="2.03", height="0.50", style=bold, color="#804080", pos="1023,467", _draw_="S 4 -bold c 7 -#804080 e 1023 467 73 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1023 462 0 89 10 -pqdownheap "]; "UV gen_bitlen (65)" [label=gen_bitlen, width="1.69", height="0.50", style=bold, color="#804080", pos="1183,467", _draw_="S 4 -bold c 7 -#804080 e 1183 467 61 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1183 462 0 72 10 -gen_bitlen "]; "UV build_tree_0 (66)" [label=build_tree_0, width="1.97", height="0.50", style=bold, color="#804080", pos="1016,552", _draw_="S 4 -bold c 7 -#804080 e 1016 552 71 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1016 547 0 86 12 -build_tree_0 "]; "UV scan_tree (67)" [label=scan_tree, width="1.58", height="0.50", style=bold, color="#804080", pos="1162,552", _draw_="S 4 -bold c 7 -#804080 e 1162 552 57 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1162 547 0 67 9 -scan_tree "]; "UV send_tree (68)" [label=send_tree, width="1.61", height="0.50", style=bold, color="#804080", pos="534,552", _draw_="S 4 -bold c 7 -#804080 e 534 552 58 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 534 547 0 68 9 -send_tree "]; "UV send_bits (69)" [label=send_bits, width="1.56", height="0.50", style=bold, color="#804080", pos="621,467", _draw_="S 4 -bold c 7 -#804080 e 621 467 56 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 621 462 0 65 9 -send_bits "]; "UV build_bl_tree (70)" [label=build_bl_tree, width="2.03", height="0.50", style=bold, color="#804080", pos="1126,637", _draw_="S 4 -bold c 7 -#804080 e 1126 637 73 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1126 632 0 89 13 -build_bl_tree "]; "UV send_all_trees (71)" [label=send_all_trees, width="2.19", height="0.50", style=bold, color="#804080", pos="534,637", _draw_="S 4 -bold c 7 -#804080 e 534 637 79 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 534 632 0 98 14 -send_all_trees "]; "UV flush_block (72)" [label=flush_block, width="1.78", height="0.50", style=bold, color="#804080", pos="647,714", _draw_="S 4 -bold c 7 -#804080 e 647 714 64 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 647 709 0 77 11 -flush_block "]; "UV set_file_type (73)" [label=set_file_type, width="1.97", height="0.50", style=bold, color="#804080", pos="924,637", _draw_="S 4 -bold c 7 -#804080 e 924 637 71 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 924 632 0 87 13 -set_file_type "]; "UV copy_block (74)" [label=copy_block, width="1.72", height="0.50", style=bold, color="#804080", pos="753,637", _draw_="S 4 -bold c 7 -#804080 e 753 637 62 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 753 632 0 74 10 -copy_block "]; "UV compress_block (75)" [label=compress_block, width="2.36", height="0.50", style=bold, color="#804080", pos="332,637", _draw_="S 4 -bold c 7 -#804080 e 332 637 85 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 332 632 0 107 14 -compress_block "]; "UV bi_windup (76)" [label=bi_windup, width="1.67", height="0.50", style=bold, color="#804080", pos="858,552", _draw_="S 4 -bold c 7 -#804080 e 858 552 60 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 858 547 0 71 9 -bi_windup "]; "UV ct_tally (77)" [label=ct_tally, width="1.28", height="0.50", style=bold, color="#804080", pos="299,714", _draw_="S 4 -bold c 7 -#804080 e 299 714 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 299 709 0 50 8 -ct_tally "]; "UV zip (0)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,658,923 658,947 671,951 683,947 683,935 683,926 677,922 668,922"]; "UV zip (0)" -> "UV flush_outbuf (1)" [pos="e,1108,392 665,933 753,927 1046,906 1079,881 1113,854 1100,724 1131,696 1150,679 1166,701 1187,688 1227,663 1234,647 1248,603 12\ 71,534 1289,497 1244,441 1228,420 1168,404 1118,394", _draw_="c 5 -black B 19 665 933 753 927 1046 906 1079 881 1113 854 1100 724 1131 696 1150 679 1166 701 1187 688 1227 663 1234 647 1248 6\ 03 1271 534 1289 497 1244 441 1228 420 1168 404 1118 394 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1118 391 1108 392 1117 397 "]; "UV zip (0)" -> "UV bi_init (3)" [pos="e,128,876 615,934 541,931 322,919 145,881 142,881 140,880 137,879", _draw_="c 5 -black B 7 615 934 541 931 322 919 145 881 142 881 140 880 137 879 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 139 876 128 876 136 882 "]; "UV zip (0)" -> "UV ct_init (4)" [pos="e,118,732 615,934 522,929 200,909 165,881 144,863 124,785 119,742", _draw_="c 5 -black B 7 615 934 522 929 200 909 165 881 144 863 124 785 119 742 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 122 742 118 732 116 742 "]; "UV zip (0)" -> "UV lm_init (5)" [pos="e,1197,873 665,934 741,931 977,919 1167,881 1174,880 1180,878 1187,876", _draw_="c 5 -black B 7 665 934 741 931 977 919 1167 881 1174 880 1180 878 1187 876 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1188 879 1197 873 1186 873 "]; "UV zip (0)" -> "UV deflate (7)" [pos="e,513,878 618,927 593,916 551,897 522,883", _draw_="c 5 -black B 4 618 927 593 916 551 897 522 883 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 523 880 513 878 520 886 "]; "UV flush_outbuf (1)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,934 1112,391 1168,400 1244,418 1262,441 1307,497 1289,534 1266,603 1252,647 1245,663 1205,688 1184,701 1168,679 1149,696 1\ 118,724 1131,854 1097,881 1064,906 777,927 675,933"]; "UV bi_init (3)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,934 134,872 144,876 154,879 163,881 326,916 525,929 605,933"]; "UV ct_init (4)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,933 127,732 139,771 160,861 183,881 217,907 503,927 605,932"]; "UV ct_init (4)" -> "UV gen_codes (61)" [pos="e,119,485 100,698 97,695 95,692 93,688 66,621 71,594 93,526 97,514 104,502 112,493", _draw_="c 5 -black B 10 100 698 97 695 95 692 93 688 66 621 71 594 93 526 97 514 104 502 112 493 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 115 495 119 485 110 490 "]; "UV ct_init (4)" -> "UV bi_reverse (62)" [pos="e,86,400 88,702 82,699 76,694 72,688 44,641 56,494 68,441 71,430 76,418 81,409", _draw_="c 5 -black B 10 88 702 82 699 76 694 72 688 44 641 56 494 68 441 71 430 76 418 81 409 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 84 410 86 400 78 407 "]; "UV ct_init (4)" -> "UV init_block (63)" [pos="e,161,655 131,697 138,687 147,674 155,663", _draw_="c 5 -black B 4 131 697 138 687 147 674 155 663 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 158 665 161 655 152 661 "]; "UV lm_init (5)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,934 1204,876 1198,878 1191,880 1185,881 996,919 763,931 675,934"]; "UV lm_init (5)" -> "UV fill_window (133)" [pos="e,1216,732 1232,845 1228,819 1222,772 1217,742", _draw_="c 5 -black B 4 1232 845 1228 819 1222 772 1217 742 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1220 742 1216 732 1214 742 "]; "UV deflate (7)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,621,924 519,876 547,888 585,906 612,919"]; "UV deflate (7)" -> "UV flush_block (72)" [pos="e,633,732 514,849 520,845 526,841 531,837 568,807 605,766 627,740", _draw_="c 5 -black B 7 514 849 520 845 526 841 531 837 568 807 605 766 627 740 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 630 742 633 732 624 738 "]; "UV deflate (7)" -> "UV ct_tally (77)" [pos="e,304,732 445,857 416,853 380,846 368,837 336,813 317,770 307,742", _draw_="c 5 -black B 7 445 857 416 853 380 846 368 837 336 813 317 770 307 742 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 310 741 304 732 304 743 "]; "UV deflate (7)" -> "UV fill_window (133)" [pos="e,1162,725 526,855 646,831 1006,757 1152,727", _draw_="c 5 -black B 4 526 855 646 831 1006 757 1152 727 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1153 730 1162 725 1152 724 "]; "UV deflate (7)" -> "UV longest_match (134)" [pos="e,480,730 511,848 515,845 518,841 520,837 534,809 535,795 520,768 513,755 501,744 489,735", _draw_="c 5 -black B 10 511 848 515 845 518 841 520 837 534 809 535 795 520 768 513 755 501 744 489 735 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 490 732 480 730 487 738 "]; "UV deflate (7)" -> "UV deflate_fast (135)" [pos="e,454,804 477,845 472,836 465,823 459,813", _draw_="c 5 -black B 4 477 845 472 836 465 823 459 813 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 462 811 454 804 456 814 "]; "UV fill_window (133)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,934 1210,732 1201,771 1179,862 1155,881 1117,910 785,928 675,933"]; "UV longest_match (134)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,932 408,730 393,739 377,752 368,768 354,795 355,809 368,837 382,864 395,867 422,881 483,911 560,925 605,931"]; "UV deflate_fast (135)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,932 435,804 427,825 418,859 434,881 455,907 552,924 605,931"]; "UV deflate_fast (135)" -> "UV flush_block (72)" [pos="e,607,728 485,772 517,760 563,744 597,732", _draw_="c 5 -black B 4 485 772 517 760 563 744 597 732 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 599 735 607 728 596 728 "]; "UV deflate_fast (135)" -> "UV ct_tally (77)" [pos="e,328,728 412,770 390,759 360,744 337,733", _draw_="c 5 -black B 4 412 770 390 759 360 744 337 733 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 338 730 328 728 335 736 "]; "UV deflate_fast (135)" -> "UV fill_window (133)" [pos="e,1152,720 507,780 650,767 992,735 1142,721", _draw_="c 5 -black B 4 507 780 650 767 992 735 1142 721 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1142 724 1152 720 1142 718 "]; "UV deflate_fast (135)" -> "UV longest_match (134)" [pos="e,444,732 444,768 444,760 444,751 444,742", _draw_="c 5 -black B 4 444 768 444 760 444 751 444 742 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 448 742 444 732 441 742 "]; "UV gen_codes (61)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,934 131,485 117,532 82,657 108,688 127,708 149,677 169,696 181,706 195,822 201,837 212,859 213,868 234,881 297,917 518,930\ 605,934"]; "UV gen_codes (61)" -> "UV bi_reverse (62)" [pos="e,106,400 129,449 123,438 116,422 110,409", _draw_="c 5 -black B 4 129 449 123 438 116 422 110 409 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 113 408 106 400 107 411 "]; "UV bi_reverse (62)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,934 81,399 72,410 61,425 54,441 36,487 38,502 38,552 38,786 38,786 38,786 38,828 21,851 51,881 92,919 484,931 605,934"]; "UV init_block (63)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,933 177,655 186,698 209,806 229,837 248,863 258,868 287,881 344,905 527,924 605,932"]; "UV pqdownheap (64)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,933 1047,484 1064,496 1089,510 1113,518 1126,521 1220,516 1228,526 1281,581 1237,648 1171,688 1146,703 1127,676 1105,696 1\ 074,724 1095,853 1063,881 1034,906 771,926 675,932"]; "UV gen_bitlen (65)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,933 1210,483 1223,494 1239,508 1246,526 1260,557 1257,570 1246,603 1233,647 1226,664 1186,688 1163,702 1146,677 1125,696 1\ 094,724 1108,853 1075,881 1045,906 773,927 675,932"]; "UV build_tree_0 (66)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,933 1019,570 1028,632 1056,838 1010,881 986,903 762,924 675,932"]; "UV build_tree_0 (66)" -> "UV gen_codes (61)" [pos="e,191,475 975,537 960,533 943,528 927,526 846,513 639,523 556,518 429,508 283,489 201,477", _draw_="c 5 -black B 10 975 537 960 533 943 528 927 526 846 513 639 523 556 518 429 508 283 489 201 477 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 201 474 191 475 200 480 "]; "UV build_tree_0 (66)" -> "UV pqdownheap (64)" [pos="e,1022,485 1017,534 1019,523 1020,508 1021,495", _draw_="c 5 -black B 4 1017 534 1019 523 1020 508 1021 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1024 495 1022 485 1018 495 "]; "UV build_tree_0 (66)" -> "UV gen_bitlen (65)" [pos="e,1160,484 1059,538 1074,532 1091,525 1105,518 1121,510 1138,499 1152,490", _draw_="c 5 -black B 7 1059 538 1074 532 1091 525 1105 518 1121 510 1138 499 1152 490 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1154 493 1160 484 1150 487 "]; "UV scan_tree (67)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,933 1181,569 1191,580 1203,595 1208,611 1220,643 1232,663 1208,688 1190,707 1106,677 1085,696 1055,724 1083,853 1051,881 1\ 023,904 770,925 675,932"]; "UV send_tree (68)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,630,919 498,566 479,576 457,590 446,611 430,641 423,662 446,688 460,702 519,683 534,696 547,706 573,822 579,837 589,857 594,86\ 1 606,881 612,891 619,901 625,911"]; "UV send_tree (68)" -> "UV send_bits (69)" [pos="e,603,484 552,535 565,522 582,505 596,491", _draw_="c 5 -black B 4 552 535 565 522 582 505 596 491 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 598 494 603 484 593 489 "]; "UV send_bits (69)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,649,919 626,485 640,537 681,686 682,688 695,699 710,682 720,696 731,708 723,716 720,732 707,799 673,872 654,910"]; "UV send_bits (69)" -> "UV flush_outbuf (1)" [pos="e,994,393 669,457 746,442 897,412 984,395", _draw_="c 5 -black B 4 669 457 746 442 897 412 984 395 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 985 398 994 393 984 392 "]; "UV build_bl_tree (70)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,933 1102,654 1089,664 1074,679 1065,696 1027,769 1095,822 1035,881 1010,905 768,925 675,932"]; "UV build_bl_tree (70)" -> "UV build_tree_0 (66)" [pos="e,1038,569 1104,620 1087,607 1065,589 1046,575", _draw_="c 5 -black B 4 1104 620 1087 607 1065 589 1046 575 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1048 572 1038 569 1044 578 "]; "UV build_bl_tree (70)" -> "UV scan_tree (67)" [pos="e,1154,570 1134,619 1139,608 1145,592 1150,579", _draw_="c 5 -black B 4 1134 619 1139 608 1145 592 1150 579 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1153 581 1154 570 1147 578 "]; "UV send_all_trees (71)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,634,918 540,655 558,706 609,848 631,908"]; "UV send_all_trees (71)" -> "UV send_tree (68)" [pos="e,534,570 534,619 534,608 534,593 534,580", _draw_="c 5 -black B 4 534 619 534 608 534 593 534 580 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 538 580 534 570 531 580 "]; "UV send_all_trees (71)" -> "UV send_bits (69)" [pos="e,623,485 578,622 587,617 595,611 601,603 624,571 626,525 624,495", _draw_="c 5 -black B 7 578 622 587 617 595 611 601 603 624 571 626 525 624 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 627 495 623 485 621 495 "]; "UV flush_block (72)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,641,917 646,732 645,771 642,861 641,907"]; "UV flush_block (72)" -> "UV init_block (63)" [pos="e,189,654 594,704 575,701 554,698 534,696 502,692 269,699 238,688 223,682 208,671 196,661", _draw_="c 5 -black B 10 594 704 575 701 554 698 534 696 502 692 269 699 238 688 223 682 208 671 196 661 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 199 659 189 654 194 664 "]; "UV flush_block (72)" -> "UV build_tree_0 (66)" [pos="e,993,569 708,708 756,703 816,696 824,688 851,664 818,633 844,611 859,598 910,608 927,603 947,596 968,585 985,574", _draw_="c 5 -black B 13 708 708 756 703 816 696 824 688 851 664 818 633 844 611 859 598 910 608 927 603 947 596 968 585 985 574 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 986 577 993 569 983 571 "]; "UV flush_block (72)" -> "UV send_bits (69)" [pos="e,623,485 645,696 640,653 630,546 624,495", _draw_="c 5 -black B 4 645 696 640 653 630 546 624 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 627 495 623 485 621 495 "]; "UV flush_block (72)" -> "UV build_bl_tree (70)" [pos="e,1095,653 711,712 798,708 950,701 1004,688 1033,681 1063,669 1086,657", _draw_="c 5 -black B 7 711 712 798 708 950 701 1004 688 1033 681 1063 669 1086 657 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1087 660 1095 653 1084 654 "]; "UV flush_block (72)" -> "UV send_all_trees (71)" [pos="e,559,654 622,697 606,687 585,672 567,660", _draw_="c 5 -black B 4 622 697 606 687 585 672 567 660 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 569 657 559 654 565 663 "]; "UV flush_block (72)" -> "UV set_file_type (73)" [pos="e,901,654 708,708 755,704 816,696 839,688 858,681 877,670 893,660", _draw_="c 5 -black B 7 708 708 755 704 816 696 839 688 858 681 877 670 893 660 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 895 663 901 654 891 657 "]; "UV flush_block (72)" -> "UV copy_block (74)" [pos="e,730,654 670,697 685,686 705,671 722,660", _draw_="c 5 -black B 4 670 697 685 686 705 671 722 660 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 724 663 730 654 720 657 "]; "UV flush_block (72)" -> "UV compress_block (75)" [pos="e,363,654 593,704 574,701 553,698 534,696 496,691 484,697 446,688 421,681 394,669 372,658", _draw_="c 5 -black B 10 593 704 574 701 553 698 534 696 496 691 484 697 446 688 421 681 394 669 372 658 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 374 655 363 654 371 661 "]; "UV flush_block (72)" -> "UV bi_windup (76)" [pos="e,801,558 648,696 651,673 659,634 682,611 711,582 755,567 791,560", _draw_="c 5 -black B 7 648 696 651 673 659 634 682 611 711 582 755 567 791 560 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 792 563 801 558 791 557 "]; "UV set_file_type (73)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,665,933 939,655 974,698 1054,812 995,881 974,905 761,925 675,932"]; "UV copy_block (74)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,649,919 751,655 749,675 744,706 735,732 714,798 676,872 654,910"]; "UV copy_block (74)" -> "UV flush_outbuf (1)" [pos="e,995,393 756,619 761,596 771,556 789,526 818,480 830,469 875,441 909,420 951,406 985,396", _draw_="c 5 -black B 10 756 619 761 596 771 556 789 526 818 480 830 469 875 441 909 420 951 406 985 396 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 986 399 995 393 984 393 "]; "UV copy_block (74)" -> "UV bi_windup (76)" [pos="e,837,569 774,620 790,607 812,590 829,576", _draw_="c 5 -black B 4 774 620 790 607 812 590 829 576 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 832 578 837 569 827 573 "]; "UV compress_block (75)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,933 292,653 274,663 255,677 244,696 201,777 261,831 338,881 383,909 535,925 605,932"]; "UV compress_block (75)" -> "UV send_bits (69)" [pos="e,579,479 350,619 374,595 421,553 467,526 499,507 538,492 569,482", _draw_="c 5 -black B 7 350 619 374 595 421 553 467 526 499 507 538 492 569 482 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 570 485 579 479 568 479 "]; "UV bi_windup (76)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,663,928 879,569 894,581 915,595 936,603 951,608 994,599 1004,611 1027,636 1021,657 1004,688 932,823 748,898 672,925"]; "UV bi_windup (76)" -> "UV flush_outbuf (1)" [pos="e,1012,397 868,534 882,510 910,468 941,441 959,425 982,411 1003,401", _draw_="c 5 -black B 7 868 534 882 510 910 468 941 441 959 425 982 411 1003 401 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1004 404 1012 397 1001 398 "]; "UV ct_tally (77)" -> "UV zip (0)" [style=invis, minlen=0, pos="e,615,933 301,732 307,767 323,842 370,881 406,909 541,925 605,932"]; } subgraph cluster_22 { graph [label="S 22", color="#80C000", style=bold, lp="6315,591", bb="6229,526,6401,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6315 586 0 32 4 -S 22 ", _draw_="S 4 -bold c 7 -#80C000 p 4 6229 526 6229 603 6401 603 6401 526 ", xdotversion=""]; "UV getopt_long (96)" [label=getopt_long, width="1.92", height="0.49", style=dotted, color="#80C000", pos="6306,552", _draw_="S 6 -dotted c 7 -#80C000 e 6306 552 69 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6306 547 0 82 11 -getopt_long "]; "UV getopt_long (96)" -> "UV getopt_long (96)" [style=invis, minlen=0, pos="e,6345,537 6345,567 6369,570 6393,565 6393,552 6393,541 6375,536 6355,536"]; } subgraph cluster_57 { graph [label="S 57", color="#4040C0", style=bold, lp="2596,421", bb="2537,356,2655,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2596 416 0 32 4 -S 57 ", _draw_="S 4 -bold c 7 -#4040C0 p 4 2537 356 2537 433 2655 433 2655 356 ", xdotversion=""]; "UV malloc (39)" [label=malloc, width="1.17", height="0.49", style=dotted, color="#4040C0", pos="2587,382", _draw_="S 6 -dotted c 7 -#4040C0 e 2587 382 42 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2587 377 0 44 6 -malloc "]; "UV malloc (39)" -> "UV malloc (39)" [style=invis, minlen=0, pos="e,2612,368 2612,396 2630,401 2647,396 2647,382 2647,371 2636,365 2622,366"]; } subgraph cluster_23 { graph [label="S 23", color="#80C080", style=bold, lp="5400,506", bb="5343,441,5457,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5400 501 0 32 4 -S 23 ", _draw_="S 4 -bold c 7 -#80C080 p 4 5343 441 5343 518 5457 518 5457 441 ", xdotversion=""]; "UV usage (87)" [label=usage, width="1.11", height="0.49", style=bold, color="#80C080", pos="5391,467", _draw_="S 4 -bold c 7 -#80C080 e 5391 467 40 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5391 462 0 41 5 -usage "]; "UV usage (87)" -> "UV usage (87)" [style=invis, minlen=0, pos="e,5415,453 5415,481 5432,486 5449,481 5449,467 5449,456 5438,450 5425,451"]; } subgraph cluster_58 { graph [label="S 58", color="#40C040", style=bold, lp="7966,81", bb="7903,16,8029,93", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7966 76 0 32 4 -S 58 ", _draw_="S 4 -bold c 7 -#40C040 p 4 7903 16 7903 93 8029 93 8029 16 ", xdotversion=""]; "UV isupper (20)" [label=isupper, width="1.28", height="0.49", style=dotted, color="#40C040", pos="7957,42", _draw_="S 6 -dotted c 7 -#40C040 e 7957 42 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7957 37 0 50 7 -isupper "]; "UV isupper (20)" -> "UV isupper (20)" [style=invis, minlen=0, pos="e,7984,28 7984,56 8003,60 8021,56 8021,42 8021,31 8009,26 7994,27"]; } subgraph cluster_24 { graph [label="S 24", color="#004040", style=bold, lp="5497,421", bb="5443,356,5551,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5497 416 0 32 4 -S 24 ", _draw_="S 4 -bold c 7 -#004040 p 4 5443 356 5443 433 5551 433 5551 356 ", xdotversion=""]; "UV warn (35)" [label=warn, width="1.03", height="0.49", style=bold, color="#004040", pos="5488,382", _draw_="S 4 -bold c 7 -#004040 e 5488 382 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5488 377 0 36 4 -warn "]; "UV warn (35)" -> "UV warn (35)" [style=invis, minlen=0, pos="e,5510,368 5510,396 5527,401 5543,396 5543,382 5543,371 5533,365 5520,366"]; } subgraph cluster_25 { graph [label="S 25", color="#0040C0", style=bold, lp="3058,506", bb="3007,441,3109,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3058 501 0 32 4 -S 25 ", _draw_="S 4 -bold c 7 -#0040C0 p 4 3007 441 3007 518 3109 518 3109 441 ", xdotversion=""]; "UV copy (10)" [label=copy, width="0.94", height="0.49", style=bold, color="#0040C0", pos="3049,467", _draw_="S 4 -bold c 7 -#0040C0 e 3049 467 34 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3049 462 0 32 4 -copy "]; "UV copy (10)" -> "UV copy (10)" [style=invis, minlen=0, pos="e,3070,453 3070,481 3085,486 3101,481 3101,467 3101,456 3091,451 3080,451"]; } subgraph cluster_26 { graph [label="S 26", color="#00C040", style=bold, lp="5400,591", bb="5351,526,5449,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5400 586 0 32 4 -S 26 ", _draw_="S 4 -bold c 7 -#00C040 p 4 5351 526 5351 603 5449 603 5449 526 ", xdotversion=""]; "UV help (88)" [label=help, width="0.89", height="0.49", style=bold, color="#00C040", pos="5391,552", _draw_="S 4 -bold c 7 -#00C040 e 5391 552 32 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5391 547 0 29 4 -help "]; "UV help (88)" -> "UV help (88)" [style=invis, minlen=0, pos="e,5411,538 5411,566 5426,571 5441,566 5441,552 5441,541 5432,536 5421,536"]; } subgraph cluster_27 { graph [label="S 27", color="#00C0C0", style=bold, lp="3184,591", bb="3117,356,3251,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3184 586 0 32 4 -S 27 ", _draw_="S 4 -bold c 7 -#00C0C0 p 4 3117 356 3117 603 3251 603 3251 356 ", xdotversion=""]; "UV read_tree (43)" [label=read_tree, width="1.58", height="0.50", style=bold, color="#00C0C0", pos="3182,552", _draw_="S 4 -bold c 7 -#00C0C0 e 3182 552 57 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3182 547 0 67 9 -read_tree "]; "UV build_tree (44)" [label=build_tree, width="1.64", height="0.50", style=bold, color="#00C0C0", pos="3184,382", _draw_="S 4 -bold c 7 -#00C0C0 e 3184 382 59 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3184 377 0 69 10 -build_tree "]; "UV unpack (45)" [label=unpack, width="1.28", height="0.49", style=bold, color="#00C0C0", pos="3179,467", _draw_="S 4 -bold c 7 -#00C0C0 e 3179 467 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3179 462 0 50 6 -unpack "]; "UV read_tree (43)" -> "UV unpack (45)" [style=invis, minlen=0, pos="e,3174,484 3176,534 3174,522 3173,507 3174,494"]; "UV build_tree (44)" -> "UV unpack (45)" [style=invis, minlen=0, pos="e,3186,449 3189,400 3189,411 3188,426 3187,439"]; "UV unpack (45)" -> "UV read_tree (43)" [pos="e,3187,534 3185,484 3187,496 3188,511 3187,524", _draw_="c 5 -black B 4 3185 484 3187 496 3188 511 3187 524 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3184 524 3187 534 3191 524 "]; "UV unpack (45)" -> "UV build_tree (44)" [pos="e,3177,400 3174,449 3173,438 3174,423 3176,410", _draw_="c 5 -black B 4 3174 449 3173 438 3174 423 3176 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3179 410 3177 400 3173 410 "]; "UV unpack (45)" -> "UV unpack (45)" [style=invis, minlen=0, pos="e,3206,453 3206,481 3225,485 3243,481 3243,467 3243,456 3231,451 3216,452"]; } subgraph cluster_40 { graph [label="S 40", color="#400040", style=bold, lp="1421,421", bb="1325,356,1517,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1421 416 0 32 4 -S 40 ", _draw_="S 4 -bold c 7 -#400040 p 4 1325 356 1325 433 1517 433 1517 356 ", xdotversion=""]; "UV flush_window (16)" [label=flush_window, width="2.19", height="0.49", style=bold, color="#400040", pos="1412,382", _draw_="S 4 -bold c 7 -#400040 e 1412 382 79 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1412 377 0 96 12 -flush_window "]; "UV flush_window (16)" -> "UV flush_window (16)" [style=invis, minlen=0, pos="e,1456,367 1456,397 1483,400 1509,395 1509,382 1509,371 1489,365 1466,366"]; } subgraph cluster_28 { graph [label="S 28", color="#804040", style=bold, lp="5518,591", bb="5457,526,5579,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5518 586 0 32 4 -S 28 ", _draw_="S 4 -bold c 7 -#804040 p 4 5457 526 5457 603 5579 603 5579 526 ", xdotversion=""]; "UV license (89)" [label=license, width="1.22", height="0.49", style=bold, color="#804040", pos="5509,552", _draw_="S 4 -bold c 7 -#804040 e 5509 552 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5509 547 0 47 7 -license "]; "UV license (89)" -> "UV license (89)" [style=invis, minlen=0, pos="e,5535,538 5535,566 5553,571 5571,566 5571,552 5571,541 5559,535 5545,536"]; } subgraph cluster_41 { graph [label="S 41", color="#4000C0", style=bold, lp="7566,251", bb="7505,186,7627,263", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7566 246 0 32 4 -S 41 ", _draw_="S 4 -bold c 7 -#4000C0 p 4 7505 186 7505 263 7627 263 7627 186 ", xdotversion=""]; "UV strrchr (21)" [label=strrchr, width="1.22", height="0.49", style=dotted, color="#4000C0", pos="7557,212", _draw_="S 6 -dotted c 7 -#4000C0 e 7557 212 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7557 207 0 47 7 -strrchr "]; "UV strrchr (21)" -> "UV strrchr (21)" [style=invis, minlen=0, pos="e,7583,198 7583,226 7601,231 7619,226 7619,212 7619,201 7607,195 7593,196"]; } subgraph cluster_42 { graph [label="S 42", color="#408040", style=bold, lp="5595,506", bb="5518,441,5672,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5595 501 0 32 4 -S 42 ", _draw_="S 4 -bold c 7 -#408040 p 4 5518 441 5518 518 5672 518 5672 441 ", xdotversion=""]; "UV clear_bufs (14)" [label=clear_bufs, width="1.67", height="0.49", style=bold, color="#408040", pos="5586,467", _draw_="S 4 -bold c 7 -#408040 e 5586 467 60 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5586 462 0 69 10 -clear_bufs "]; "UV clear_bufs (14)" -> "UV clear_bufs (14)" [style=invis, minlen=0, pos="e,5620,453 5620,481 5642,485 5664,481 5664,467 5664,455 5648,450 5630,452"]; } subgraph cluster_29 { graph [label="S 29", color="#8040C0", style=bold, lp="4525,421", bb="4455,356,4595,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4525 416 0 32 4 -S 29 ", _draw_="S 4 -bold c 7 -#8040C0 p 4 4455 356 4455 433 4595 433 4595 356 ", xdotversion=""]; "UV file_read (8)" [label=file_read, width="1.47", height="0.49", style=bold, color="#8040C0", pos="4516,382", _draw_="S 4 -bold c 7 -#8040C0 e 4516 382 53 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4516 377 0 59 9 -file_read "]; "UV file_read (8)" -> "UV file_read (8)" [style=invis, minlen=0, pos="e,4546,368 4546,396 4567,400 4587,396 4587,382 4587,370 4573,366 4556,367"]; } subgraph cluster_43 { graph [label="S 43", color="#4080C0", style=bold, lp="5351,421", bb="5267,356,5435,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5351 416 0 32 4 -S 43 ", _draw_="S 4 -bold c 7 -#4080C0 p 4 5267 356 5267 433 5435 433 5435 356 ", xdotversion=""]; "UV write_error (18)" [label=write_error, width="1.86", height="0.49", style=bold, color="#4080C0", pos="5342,382", _draw_="S 4 -bold c 7 -#4080C0 e 5342 382 67 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5342 377 0 79 11 -write_error "]; "UV write_error (18)" -> "UV write_error (18)" [style=invis, minlen=0, pos="e,5380,367 5380,397 5404,400 5427,395 5427,382 5427,371 5410,366 5390,366"]; } subgraph cluster_44 { graph [label="S 44", color="#C00040", style=bold, lp="8189,336", bb="8131,271,8247,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8189 331 0 32 4 -S 44 ", _draw_="S 4 -bold c 7 -#C00040 p 4 8131 271 8131 348 8247 348 8247 271 ", xdotversion=""]; "UV perror (36)" [label=perror, width="1.14", height="0.49", style=dotted, color="#C00040", pos="8180,297", _draw_="S 6 -dotted c 7 -#C00040 e 8180 297 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8180 292 0 43 6 -perror "]; "UV perror (36)" -> "UV perror (36)" [style=invis, minlen=0, pos="e,8204,283 8204,311 8222,316 8239,311 8239,297 8239,286 8228,280 8214,281"]; } subgraph cluster_10 { graph [label="S 10", color="#008040", style=bold, lp="8260,166", bb="8199,101,8321,178", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8260 161 0 32 4 -S 10 ", _draw_="S 4 -bold c 7 -#008040 p 4 8199 101 8199 178 8321 178 8321 101 ", xdotversion=""]; "UV strcmp (92)" [label=strcmp, width="1.22", height="0.49", style=dotted, color="#008040", pos="8251,127", _draw_="S 6 -dotted c 7 -#008040 e 8251 127 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8251 122 0 47 6 -strcmp "]; "UV strcmp (92)" -> "UV strcmp (92)" [style=invis, minlen=0, pos="e,8277,113 8277,141 8295,146 8313,141 8313,127 8313,116 8301,110 8287,111"]; } subgraph cluster_1 { graph [label="S 1", color="#000080", style=bold, lp="2404,506", bb="2346,441,2462,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2404 501 0 23 3 -S 1 ", _draw_="S 4 -bold c 7 -#000080 p 4 2346 441 2346 518 2462 518 2462 441 ", xdotversion=""]; "UV unlzw (46)" [label=unlzw, width="1.14", height="0.49", style=bold, color="#000080", pos="2395,467", _draw_="S 4 -bold c 7 -#000080 e 2395 467 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2395 462 0 43 5 -unlzw "]; "UV unlzw (46)" -> "UV unlzw (46)" [style=invis, minlen=0, pos="e,2419,453 2419,481 2437,486 2454,481 2454,467 2454,456 2443,450 2429,451"]; } subgraph cluster_45 { graph [label="S 45", color="#C000C0", style=bold, lp="4693,421", bb="4603,271,4783,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4693 416 0 32 4 -S 45 ", _draw_="S 4 -bold c 7 -#C000C0 p 4 4603 271 4603 433 4783 433 4783 271 ", xdotversion=""]; "UV display_ratio (37)" [label=display_ratio, width="2.03", height="0.49", style=bold, color="#C000C0", pos="4684,382", _draw_="S 4 -bold c 7 -#C000C0 e 4684 382 73 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4684 377 0 87 13 -display_ratio "]; "UV _IO_putc (38)" [label=_IO_putc, width="1.47", height="0.50", style=dotted, color="#C000C0", pos="4684,297", _draw_="S 6 -dotted c 7 -#C000C0 e 4684 297 53 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4684 292 0 61 8 -_IO_putc "]; "UV display_ratio (37)" -> "UV display_ratio (37)" [style=invis, minlen=0, pos="e,4725,367 4725,397 4750,400 4775,395 4775,382 4775,371 4756,366 4735,366"]; "UV display_ratio (37)" -> "UV _IO_putc (38)" [pos="e,4679,315 4678,364 4677,353 4677,338 4678,325", _draw_="c 5 -black B 4 4678 364 4677 353 4677 338 4678 325 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4681 325 4679 315 4675 325 "]; "UV _IO_putc (38)" -> "UV display_ratio (37)" [style=invis, minlen=0, pos="e,4690,364 4689,315 4691,326 4691,341 4691,354"]; } subgraph cluster_46 { graph [label="S 46", color="#C08040", style=bold, lp="2917,506", bb="2835,441,2999,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2917 501 0 32 4 -S 46 ", _draw_="S 4 -bold c 7 -#C08040 p 4 2835 441 2835 518 2999 518 2999 441 ", xdotversion=""]; "UV (86)" [label="", width="1.81", height="0.49", style=bold, color="#C08040", pos="2908,467", _draw_="S 4 -bold c 7 -#C08040 e 2908 467 65 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2908 462 0 76 10 - "]; "UV (86)" -> "UV (86)" [style=invis, minlen=0, pos="e,2944,452 2944,482 2968,485 2991,480 2991,467 2991,456 2974,451 2954,451"]; } subgraph cluster_2 { graph [label="S 2", color="#008000", style=bold, lp="1814,825", bb="1525,356,2103,837", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1814 820 0 23 3 -S 2 ", _draw_="S 4 -bold c 7 -#008000 p 4 1525 356 1525 837 2103 837 2103 356 ", xdotversion=""]; "UV unzip (41)" [label=unzip, width="1.06", height="0.49", style=bold, color="#008000", pos="1695,786", _draw_="S 4 -bold c 7 -#008000 e 1695 786 38 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1695 781 0 38 5 -unzip "]; "UV inflate (42)" [label=inflate, width="1.14", height="0.50", style=bold, color="#008000", pos="1574,714", _draw_="S 4 -bold c 7 -#008000 e 1574 714 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1574 709 0 44 7 -inflate "]; "UV huft_build (79)" [label=huft_build, width="1.64", height="0.50", style=bold, color="#008000", pos="2036,467", _draw_="S 4 -bold c 7 -#008000 e 2036 467 59 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2036 462 0 69 10 -huft_build "]; "UV huft_free (80)" [label=huft_free, width="1.53", height="0.50", style=bold, color="#008000", pos="1958,382", _draw_="S 4 -bold c 7 -#008000 e 1958 382 55 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1958 377 0 63 9 -huft_free "]; "UV inflate_codes (81)" [label=inflate_codes, width="2.03", height="0.50", style=bold, color="#008000", pos="1800,467", _draw_="S 4 -bold c 7 -#008000 e 1800 467 73 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1800 462 0 90 13 -inflate_codes "]; "UV inflate_stored (82)" [label=inflate_stored, width="2.14", height="0.50", style=bold, color="#008000", pos="1806,552", _draw_="S 4 -bold c 7 -#008000 e 1806 552 77 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1806 547 0 95 14 -inflate_stored "]; "UV inflate_fixed (83)" [label=inflate_fixed, width="1.92", height="0.50", style=bold, color="#008000", pos="1642,552", _draw_="S 4 -bold c 7 -#008000 e 1642 552 69 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1642 547 0 84 13 -inflate_fixed "]; "UV inflate_dynamic (84)" [label=inflate_dynamic, width="2.42", height="0.50", style=bold, color="#008000", pos="1988,552", _draw_="S 4 -bold c 7 -#008000 e 1988 552 87 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1988 547 0 109 15 -inflate_dynamic "]; "UV inflate_block (85)" [label=inflate_block, width="1.97", height="0.50", style=bold, color="#008000", pos="1803,637", _draw_="S 4 -bold c 7 -#008000 e 1803 637 71 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 1803 632 0 87 13 -inflate_block "]; "UV unzip (41)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1721,773 1721,799 1737,801 1751,797 1751,786 1751,777 1742,773 1731,773"]; "UV unzip (41)" -> "UV inflate (42)" [pos="e,1594,730 1668,773 1649,763 1623,748 1603,735", _draw_="c 5 -black B 4 1668 773 1649 763 1623 748 1603 735 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1604 732 1594 730 1601 738 "]; "UV inflate (42)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1675,771 1602,727 1621,738 1647,753 1666,766"]; "UV inflate (42)" -> "UV inflate_block (85)" [pos="e,1760,652 1607,703 1644,691 1706,670 1750,655", _draw_="c 5 -black B 4 1607 703 1644 691 1706 670 1750 655 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1751 658 1760 652 1749 652 "]; "UV huft_build (79)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1732,782 2056,485 2066,495 2078,510 2084,526 2096,558 2102,573 2084,603 2011,726 1829,768 1742,781"]; "UV huft_build (79)" -> "UV huft_free (80)" [pos="e,1974,399 2020,449 2009,436 1994,420 1981,406", _draw_="c 5 -black B 4 2020 449 2009 436 1994 420 1981 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1984 404 1974 399 1979 409 "]; "UV huft_free (80)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1676,771 1903,385 1841,390 1737,403 1655,441 1601,466 1576,471 1549,526 1535,556 1545,569 1549,603 1550,606 1551,607 1551,611 \ 1559,645 1541,664 1566,688 1585,705 1604,680 1624,696 1638,706 1630,717 1639,732 1647,744 1658,755 1668,764"]; "UV inflate_codes (81)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1685,769 1733,474 1671,483 1585,499 1564,526 1543,552 1553,570 1564,603 1582,653 1609,652 1639,696 1654,717 1670,741 1680,760"]; "UV inflate_stored (82)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1694,768 1771,568 1754,578 1734,592 1723,611 1695,656 1692,721 1694,758"]; "UV inflate_fixed (83)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1691,768 1646,570 1655,611 1678,710 1689,758"]; "UV inflate_fixed (83)" -> "UV huft_build (79)" [pos="e,2001,482 1680,537 1693,532 1707,528 1720,526 1791,512 1812,531 1882,518 1920,511 1961,496 1992,485", _draw_="c 5 -black B 10 1680 537 1693 532 1707 528 1720 526 1791 512 1812 531 1882 518 1920 511 1961 496 1992 485 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1993 488 2001 482 1990 482 "]; "UV inflate_fixed (83)" -> "UV huft_free (80)" [pos="e,1908,390 1649,534 1660,509 1684,465 1718,441 1747,420 1837,402 1898,392", _draw_="c 5 -black B 7 1649 534 1660 509 1684 465 1718 441 1747 420 1837 402 1898 392 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1899 395 1908 390 1898 389 "]; "UV inflate_fixed (83)" -> "UV inflate_codes (81)" [pos="e,1769,483 1672,536 1697,523 1733,503 1760,488", _draw_="c 5 -black B 4 1672 536 1697 523 1733 503 1760 488 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1762 491 1769 483 1759 485 "]; "UV inflate_dynamic (84)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1725,775 1978,570 1961,598 1925,652 1883,688 1838,726 1775,755 1734,771"]; "UV inflate_dynamic (84)" -> "UV huft_build (79)" [pos="e,2026,485 1998,534 2004,523 2013,507 2021,494", _draw_="c 5 -black B 4 1998 534 2004 523 2013 507 2021 494 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2024 495 2026 485 2018 492 "]; "UV inflate_dynamic (84)" -> "UV huft_free (80)" [pos="e,1957,400 1976,534 1973,529 1970,523 1968,518 1956,482 1956,438 1957,410", _draw_="c 5 -black B 7 1976 534 1973 529 1970 523 1968 518 1956 482 1956 438 1957 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1961 410 1957 400 1954 410 "]; "UV inflate_dynamic (84)" -> "UV inflate_codes (81)" [pos="e,1835,483 1952,536 1921,522 1877,502 1844,487", _draw_="c 5 -black B 4 1952 536 1921 522 1877 502 1844 487 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1846 484 1835 483 1843 490 "]; "UV inflate_block (85)" -> "UV unzip (41)" [style=invis, minlen=0, pos="e,1707,769 1790,655 1771,681 1734,731 1713,761"]; "UV inflate_block (85)" -> "UV inflate_stored (82)" [pos="e,1806,570 1804,619 1805,608 1805,593 1805,580", _draw_="c 5 -black B 4 1804 619 1805 608 1805 593 1805 580 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1808 580 1806 570 1802 580 "]; "UV inflate_block (85)" -> "UV inflate_fixed (83)" [pos="e,1666,569 1763,622 1749,616 1734,610 1720,603 1704,595 1688,584 1675,575", _draw_="c 5 -black B 7 1763 622 1749 616 1734 610 1720 603 1704 595 1688 584 1675 575 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1676 572 1666 569 1672 577 "]; "UV inflate_block (85)" -> "UV inflate_dynamic (84)" [pos="e,1958,569 1844,622 1860,617 1877,610 1892,603 1911,595 1932,583 1949,574", _draw_="c 5 -black B 7 1844 622 1860 617 1877 610 1892 603 1911 595 1932 583 1949 574 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1951 577 1958 569 1948 571 "]; } subgraph cluster_11 { graph [label="S 11", color="#0080C0", style=bold, lp="4312,506", bb="4177,356,4447,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4312 501 0 32 4 -S 11 ", _draw_="S 4 -bold c 7 -#0080C0 p 4 4177 356 4177 518 4447 518 4447 356 ", xdotversion=""]; "UV do_list (101)" [label=do_list, width="1.17", height="0.49", style=bold, color="#0080C0", pos="4312,467", _draw_="S 4 -bold c 7 -#0080C0 e 4312 467 42 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4312 462 0 44 7 -do_list "]; "UV printf (122)" [label=printf, width="1.03", height="0.50", style=dotted, color="#0080C0", pos="4222,382", _draw_="S 6 -dotted c 7 -#0080C0 e 4222 382 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4222 377 0 38 6 -printf "]; "UV lseek (123)" [label=lseek, width="0.97", height="0.50", style=dotted, color="#0080C0", pos="4312,382", _draw_="S 6 -dotted c 7 -#0080C0 e 4312 382 35 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4312 377 0 35 5 -lseek "]; "UV ctime (124)" [label=ctime, width="1.03", height="0.50", style=dotted, color="#0080C0", pos="4402,382", _draw_="S 6 -dotted c 7 -#0080C0 e 4402 382 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4402 377 0 38 5 -ctime "]; "UV do_list (101)" -> "UV do_list (101)" [style=invis, minlen=0, pos="e,4337,453 4337,481 4355,486 4372,481 4372,467 4372,456 4361,450 4347,451"]; "UV do_list (101)" -> "UV printf (122)" [pos="e,4229,400 4285,453 4276,447 4267,440 4259,433 4251,426 4242,416 4236,408", _draw_="c 5 -black B 7 4285 453 4276 447 4267 440 4259 433 4251 426 4242 416 4236 408 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4238 405 4229 400 4233 410 "]; "UV do_list (101)" -> "UV lseek (123)" [pos="e,4307,400 4306,449 4305,438 4305,423 4306,410", _draw_="c 5 -black B 4 4306 449 4305 438 4305 423 4306 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4309 410 4307 400 4303 410 "]; "UV do_list (101)" -> "UV ctime (124)" [pos="e,4382,397 4326,450 4333,445 4340,439 4347,433 4356,424 4366,414 4375,405", _draw_="c 5 -black B 7 4326 450 4333 445 4340 439 4347 433 4356 424 4366 414 4375 405 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4378 407 4382 397 4373 402 "]; "UV printf (122)" -> "UV do_list (101)" [style=invis, minlen=0, pos="e,4298,450 4242,397 4253,408 4265,422 4277,433 4281,437 4286,440 4290,443"]; "UV lseek (123)" -> "UV do_list (101)" [style=invis, minlen=0, pos="e,4318,449 4317,400 4319,411 4319,426 4319,439"]; "UV ctime (124)" -> "UV do_list (101)" [style=invis, minlen=0, pos="e,4339,453 4395,400 4388,410 4376,423 4365,433 4359,438 4354,443 4347,447"]; } subgraph cluster_12 { graph [label="S 12", color="#800040", style=bold, lp="5650,591", bb="5587,526,5713,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5650 586 0 32 4 -S 12 ", _draw_="S 4 -bold c 7 -#800040 p 4 5587 526 5587 603 5713 603 5713 526 ", xdotversion=""]; "UV version (90)" [label=version, width="1.28", height="0.49", style=bold, color="#800040", pos="5641,552", _draw_="S 4 -bold c 7 -#800040 e 5641 552 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5641 547 0 50 7 -version "]; "UV version (90)" -> "UV version (90)" [style=invis, minlen=0, pos="e,5668,538 5668,566 5687,570 5705,566 5705,552 5705,541 5693,536 5678,537"]; } subgraph cluster_47 { graph [label="S 47", color="#C080C0", style=bold, lp="7960,336", bb="7905,271,8015,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7960 331 0 32 4 -S 47 ", _draw_="S 4 -bold c 7 -#C080C0 p 4 7905 271 7905 348 8015 348 8015 271 ", xdotversion=""]; "UV fileno (102)" [label=fileno, width="1.06", height="0.49", style=dotted, color="#C080C0", pos="7951,297", _draw_="S 6 -dotted c 7 -#C080C0 e 7951 297 38 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7951 292 0 38 6 -fileno "]; "UV fileno (102)" -> "UV fileno (102)" [style=invis, minlen=0, pos="e,7974,283 7974,311 7990,316 8007,311 8007,297 8007,286 7996,281 7984,281"]; } subgraph cluster_3 { graph [label="S 3", color="#008080", style=bold, lp="7628,336", bb="7505,271,7751,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7628 331 0 23 3 -S 3 ", _draw_="S 4 -bold c 7 -#008080 p 4 7505 271 7505 348 7751 348 7751 271 ", xdotversion=""]; "UV make_simple_name (22)" [label=make_simple_name, width="2.94", height="0.49", style=bold, color="#008080", pos="7619,297", _draw_="S 4 -bold c 7 -#008080 e 7619 297 106 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7619 292 0 134 16 -make_simple_name "]; "UV make_simple_name (22)" -> "UV make_simple_name (22)" [style=invis, minlen=0, pos="e,7676,282 7676,312 7711,315 7743,310 7743,297 7743,285 7717,280 7686,281"]; } subgraph cluster_48 { graph [label="S 48", color="#404000", style=bold, lp="4238,336", bb="4158,271,4318,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4238 331 0 32 4 -S 48 ", _draw_="S 4 -bold c 7 -#404000 p 4 4158 271 4158 348 4318 348 4318 271 ", xdotversion=""]; "UV abort_gzip (34)" [label=abort_gzip, width="1.75", height="0.49", style=bold, color="#404000", pos="4229,297", _draw_="S 4 -bold c 7 -#404000 e 4229 297 63 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4229 292 0 73 10 -abort_gzip "]; "UV abort_gzip (34)" -> "UV abort_gzip (34)" [style=invis, minlen=0, pos="e,4265,282 4265,312 4288,315 4310,310 4310,297 4310,286 4294,281 4275,281"]; } subgraph cluster_13 { graph [label="S 13", color="#8000C0", style=bold, lp="3669,591", bb="3465,441,3873,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3669 586 0 32 4 -S 13 ", _draw_="S 4 -bold c 7 -#8000C0 p 4 3465 441 3465 603 3873 603 3873 441 ", xdotversion=""]; "UV add_envopt (23)" [label=add_envopt, width="1.89", height="0.49", style=bold, color="#8000C0", pos="3779,552", _draw_="S 4 -bold c 7 -#8000C0 e 3779 552 68 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3779 547 0 80 10 -add_envopt "]; "UV getenv (24)" [label=getenv, width="1.22", height="0.50", style=dotted, color="#8000C0", pos="3517,467", _draw_="S 6 -dotted c 7 -#8000C0 e 3517 467 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3517 462 0 48 6 -getenv "]; "UV xmalloc (26)" [label=xmalloc, width="1.31", height="0.50", style=bold, color="#8000C0", pos="3626,467", _draw_="S 4 -bold c 7 -#8000C0 e 3626 467 47 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3626 462 0 52 7 -xmalloc "]; "UV strspn (28)" [label=strspn, width="1.14", height="0.50", style=dotted, color="#8000C0", pos="3732,467", _draw_="S 6 -dotted c 7 -#8000C0 e 3732 467 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3732 462 0 43 6 -strspn "]; "UV calloc (31)" [label=calloc, width="1.03", height="0.50", style=dotted, color="#8000C0", pos="3828,467", _draw_="S 6 -dotted c 7 -#8000C0 e 3828 467 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3828 462 0 38 6 -calloc "]; "UV add_envopt (23)" -> "UV add_envopt (23)" [style=invis, minlen=0, pos="e,3817,537 3817,567 3841,570 3865,565 3865,552 3865,541 3847,536 3827,536"]; "UV add_envopt (23)" -> "UV getenv (24)" [pos="e,3523,485 3714,546 3660,541 3587,531 3561,518 3549,512 3538,502 3530,493", _draw_="c 5 -black B 7 3714 546 3660 541 3587 531 3561 518 3549 512 3538 502 3530 493 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3532 490 3523 485 3527 495 "]; "UV add_envopt (23)" -> "UV xmalloc (26)" [pos="e,3635,485 3727,541 3709,535 3690,528 3673,518 3662,511 3651,501 3642,492", _draw_="c 5 -black B 7 3727 541 3709 535 3690 528 3673 518 3662 511 3651 501 3642 492 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3645 490 3635 485 3640 495 "]; "UV add_envopt (23)" -> "UV strspn (28)" [pos="e,3737,485 3764,535 3757,523 3748,508 3741,494", _draw_="c 5 -black B 4 3764 535 3757 523 3748 508 3741 494 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3744 493 3737 485 3738 496 "]; "UV add_envopt (23)" -> "UV calloc (31)" [pos="e,3813,484 3784,534 3790,522 3799,506 3807,493", _draw_="c 5 -black B 4 3784 534 3790 522 3799 506 3807 493 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3810 494 3813 484 3805 490 "]; "UV getenv (24)" -> "UV add_envopt (23)" [style=invis, minlen=0, pos="e,3716,545 3537,483 3548,495 3563,510 3579,518 3601,529 3659,538 3706,544"]; "UV xmalloc (26)" -> "UV add_envopt (23)" [style=invis, minlen=0, pos="e,3737,538 3648,483 3661,494 3676,508 3691,518 3702,524 3715,530 3727,535"]; "UV strspn (28)" -> "UV add_envopt (23)" [style=invis, minlen=0, pos="e,3775,534 3747,484 3755,495 3764,511 3770,525"]; "UV calloc (31)" -> "UV add_envopt (23)" [style=invis, minlen=0, pos="e,3794,535 3823,485 3817,497 3808,513 3800,526"]; } subgraph cluster_4 { graph [label="S 4", color="#800000", style=bold, lp="6919,591", bb="6409,186,7429,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6919 586 0 23 3 -S 4 ", _draw_="S 4 -bold c 7 -#800000 p 4 6409 186 6409 603 7429 603 7429 186 ", xdotversion=""]; "UV treat_file (99)" [label=treat_file, width="1.53", height="0.49", style=bold, color="#800000", pos="6776,552", _draw_="S 4 -bold c 7 -#800000 e 6776 552 55 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6776 547 0 62 10 -treat_file "]; "UV get_istat (106)" [label=get_istat, width="1.47", height="0.50", style=bold, color="#800000", pos="7196,467", _draw_="S 4 -bold c 7 -#800000 e 7196 467 53 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7196 462 0 61 9 -get_istat "]; "UV make_ofname (107)" [label=make_ofname, width="2.14", height="0.50", style=bold, color="#800000", pos="7344,467", _draw_="S 4 -bold c 7 -#800000 e 7344 467 77 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7344 462 0 95 11 -make_ofname "]; "UV open (108)" [label=open, width="0.94", height="0.50", style=dotted, color="#800000", pos="6491,382", _draw_="S 6 -dotted c 7 -#800000 e 6491 382 34 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6491 377 0 34 4 -open "]; "UV create_outfile (110)" [label=create_outfile, width="2.14", height="0.50", style=bold, color="#800000", pos="6660,467", _draw_="S 4 -bold c 7 -#800000 e 6660 467 77 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6660 462 0 95 14 -create_outfile "]; "UV copy_stat (112)" [label=copy_stat, width="1.58", height="0.50", style=bold, color="#800000", pos="7008,467", _draw_="S 4 -bold c 7 -#800000 e 7008 467 57 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7008 462 0 66 9 -copy_stat "]; "UV check_ofname (113)" [label=check_ofname, width="2.19", height="0.50", style=bold, color="#800000", pos="6722,382", _draw_="S 4 -bold c 7 -#800000 e 6722 382 79 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6722 377 0 98 12 -check_ofname "]; "UV name_too_long (114)" [label=name_too_long, width="2.33", height="0.50", style=bold, color="#800000", pos="6521,297", _draw_="S 4 -bold c 7 -#800000 e 6521 297 84 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6521 292 0 105 13 -name_too_long "]; "UV shorten_name (115)" [label=shorten_name, width="2.22", height="0.50", style=bold, color="#800000", pos="6703,297", _draw_="S 4 -bold c 7 -#800000 e 6703 297 80 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6703 292 0 99 12 -shorten_name "]; "UV do_stat (116)" [label=do_stat, width="1.28", height="0.50", style=bold, color="#800000", pos="6885,382", _draw_="S 4 -bold c 7 -#800000 e 6885 382 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6885 377 0 51 7 -do_stat "]; "UV lstat (117)" [label=lstat, width="0.89", height="0.50", style=dotted, color="#800000", pos="7173,297", _draw_="S 6 -dotted c 7 -#800000 e 7173 297 32 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7173 292 0 31 5 -lstat "]; "UV stat (118)" [label=stat, width="0.83", height="0.50", style=dotted, color="#800000", pos="6848,212", _draw_="S 6 -dotted c 7 -#800000 e 6848 212 30 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6848 207 0 27 4 -stat "]; "UV get_suffix (119)" [label=get_suffix, width="1.61", height="0.50", style=bold, color="#800000", pos="7361,212", _draw_="S 4 -bold c 7 -#800000 e 7361 212 58 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7361 207 0 68 10 -get_suffix "]; "UV strcat (120)" [label=strcat, width="1.08", height="0.50", style=dotted, color="#800000", pos="7342,382", _draw_="S 6 -dotted c 7 -#800000 e 7342 382 39 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7342 377 0 40 6 -strcat "]; "UV same_file (125)" [label=same_file, width="1.53", height="0.50", style=bold, color="#800000", pos="7000,212", _draw_="S 4 -bold c 7 -#800000 e 7000 212 55 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7000 207 0 64 9 -same_file "]; "UV fflush (126)" [label=fflush, width="1.03", height="0.50", style=dotted, color="#800000", pos="6838,297", _draw_="S 6 -dotted c 7 -#800000 e 6838 297 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6838 292 0 38 6 -fflush "]; "UV fgets (127)" [label=fgets, width="0.94", height="0.50", style=dotted, color="#800000", pos="6927,297", _draw_="S 6 -dotted c 7 -#800000 e 6927 297 34 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6927 292 0 34 5 -fgets "]; "UV chmod (128)" [label=chmod, width="1.17", height="0.50", style=dotted, color="#800000", pos="7061,297", _draw_="S 6 -dotted c 7 -#800000 e 7061 297 42 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7061 292 0 45 5 -chmod "]; "UV reset_times (129)" [label=reset_times, width="1.83", height="0.50", style=bold, color="#800000", pos="7199,382", _draw_="S 4 -bold c 7 -#800000 e 7199 382 66 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7199 377 0 80 11 -reset_times "]; "UV utime (130)" [label=utime, width="1.08", height="0.50", style=dotted, color="#800000", pos="7282,297", _draw_="S 6 -dotted c 7 -#800000 e 7282 297 39 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7282 292 0 40 5 -utime "]; "UV chown (131)" [label=chown, width="1.19", height="0.50", style=dotted, color="#800000", pos="7052,382", _draw_="S 6 -dotted c 7 -#800000 e 7052 382 43 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7052 377 0 46 5 -chown "]; "UV treat_file (99)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6808,538 6808,566 6829,570 6849,566 6849,552 6849,540 6835,536 6818,537"]; "UV treat_file (99)" -> "UV get_istat (106)" [pos="e,7173,483 6831,550 6914,547 7069,538 7120,518 7137,511 7152,500 7165,489", _draw_="c 5 -black B 7 6831 550 6914 547 7069 538 7120 518 7137 511 7152 500 7165 489 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7167 492 7173 483 7163 486 "]; "UV treat_file (99)" -> "UV make_ofname (107)" [pos="e,7315,484 6831,551 6939,549 7172,542 7249,518 7269,511 7289,500 7306,489", _draw_="c 5 -black B 7 6831 551 6939 549 7172 542 7249 518 7269 511 7289 500 7306 489 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7308 492 7315 484 7305 486 "]; "UV treat_file (99)" -> "UV open (108)" [pos="e,6486,400 6721,551 6657,548 6559,540 6530,518 6498,491 6487,442 6486,410", _draw_="c 5 -black B 7 6721 551 6657 548 6559 540 6530 518 6498 491 6487 442 6486 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6490 410 6486 400 6483 410 "]; "UV treat_file (99)" -> "UV create_outfile (110)" [pos="e,6678,485 6750,537 6731,524 6706,506 6686,491", _draw_="c 5 -black B 4 6750 537 6731 524 6706 506 6686 491 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6688 488 6678 485 6684 494 "]; "UV treat_file (99)" -> "UV copy_stat (112)" [pos="e,6982,483 6827,545 6858,540 6896,532 6928,518 6945,511 6960,500 6974,489", _draw_="c 5 -black B 7 6827 545 6858 540 6896 532 6928 518 6945 511 6960 500 6974 489 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6976 492 6982 483 6972 486 "]; "UV get_istat (106)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6831,550 7186,485 7175,496 7157,510 7138,518 7086,538 6930,546 6841,550"]; "UV get_istat (106)" -> "UV do_stat (116)" [pos="e,6912,397 7153,456 7130,451 7101,445 7074,441 7042,435 7032,441 7000,433 6973,425 6943,412 6921,401", _draw_="c 5 -black B 10 7153 456 7130 451 7101 445 7074 441 7042 435 7032 441 7000 433 6973 425 6943 412 6921 401 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6923 398 6912 397 6920 404 "]; "UV get_istat (106)" -> "UV get_suffix (119)" [pos="e,7367,230 7225,452 7235,448 7247,443 7258,441 7273,437 7380,443 7390,433 7415,405 7386,293 7370,240", _draw_="c 5 -black B 10 7225 452 7235 448 7247 443 7258 441 7273 437 7380 443 7390 433 7415 405 7386 293 7370 240 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7373 239 7367 230 7367 241 "]; "UV get_istat (106)" -> "UV strcat (120)" [pos="e,7329,399 7228,453 7237,448 7248,444 7258,441 7272,436 7277,439 7289,433 7301,426 7313,416 7322,407", _draw_="c 5 -black B 10 7228 453 7237 448 7248 444 7258 441 7272 436 7277 439 7289 433 7301 426 7313 416 7322 407 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7325 409 7329 399 7320 404 "]; "UV make_ofname (107)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6831,551 7328,485 7313,496 7290,510 7267,518 7190,542 6956,550 6841,551"]; "UV make_ofname (107)" -> "UV get_suffix (119)" [pos="e,7378,229 7385,452 7393,447 7401,441 7405,433 7409,427 7404,272 7403,271 7399,259 7392,247 7384,237", _draw_="c 5 -black B 10 7385 452 7393 447 7401 441 7405 433 7409 427 7404 272 7403 271 7399 259 7392 247 7384 237 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7387 235 7378 229 7381 239 "]; "UV make_ofname (107)" -> "UV strcat (120)" [pos="e,7342,400 7344,449 7343,438 7343,423 7343,410", _draw_="c 5 -black B 4 7344 449 7343 438 7343 423 7343 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7346 410 7342 400 7340 410 "]; "UV open (108)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6721,550 6497,400 6503,429 6512,488 6548,518 6573,538 6652,546 6711,549"]; "UV create_outfile (110)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6759,535 6689,484 6708,497 6732,515 6751,529"]; "UV create_outfile (110)" -> "UV open (108)" [pos="e,6514,396 6620,451 6607,446 6592,439 6579,433 6560,423 6539,411 6523,401", _draw_="c 5 -black B 7 6620 451 6607 446 6592 439 6579 433 6560 423 6539 411 6523 401 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6524 398 6514 396 6521 404 "]; "UV create_outfile (110)" -> "UV check_ofname (113)" [pos="e,6709,400 6673,449 6681,438 6693,421 6703,408", _draw_="c 5 -black B 4 6673 449 6681 438 6693 421 6703 408 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6706 410 6709 400 6700 406 "]; "UV create_outfile (110)" -> "UV name_too_long (114)" [pos="e,6529,315 6628,450 6620,445 6612,440 6605,433 6573,401 6548,354 6533,324", _draw_="c 5 -black B 7 6628 450 6620 445 6612 440 6605 433 6573 401 6548 354 6533 324 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6536 323 6529 315 6530 326 "]; "UV create_outfile (110)" -> "UV shorten_name (115)" [pos="e,6666,313 6633,450 6627,445 6622,439 6619,433 6605,402 6604,386 6619,356 6627,340 6642,328 6657,318", _draw_="c 5 -black B 10 6633 450 6627 445 6622 439 6619 433 6605 402 6604 386 6619 356 6627 340 6642 328 6657 318 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6659 321 6666 313 6656 315 "]; "UV copy_stat (112)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6829,547 6996,485 6984,496 6965,510 6946,518 6912,533 6872,541 6839,546"]; "UV copy_stat (112)" -> "UV chmod (128)" [pos="e,7078,314 7044,453 7056,449 7068,445 7079,441 7091,437 7098,442 7104,433 7125,405 7115,388 7104,356 7100,344 7093,332 7085,322", _draw_="c 5 -black B 13 7044 453 7056 449 7068 445 7079 441 7091 437 7098 442 7104 433 7125 405 7115 388 7104 356 7100 344 7093 332 7085\ 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7087 319 7078 314 7082 324 "]; "UV copy_stat (112)" -> "UV reset_times (129)" [pos="e,7177,399 7044,453 7055,449 7067,444 7079,441 7097,436 7103,439 7119,433 7137,426 7155,415 7169,405", _draw_="c 5 -black B 10 7044 453 7055 449 7067 444 7079 441 7097 436 7103 439 7119 433 7137 426 7155 415 7169 405 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7171 408 7177 399 7167 402 "]; "UV copy_stat (112)" -> "UV chown (131)" [pos="e,7043,400 7017,449 7023,437 7031,422 7038,409", _draw_="c 5 -black B 4 7017 449 7023 437 7031 422 7038 409 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7041 410 7043 400 7035 407 "]; "UV check_ofname (113)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6776,534 6737,400 6745,411 6755,426 6761,441 6771,468 6775,501 6776,524"]; "UV check_ofname (113)" -> "UV name_too_long (114)" [pos="e,6549,314 6672,368 6653,362 6633,356 6614,348 6595,340 6575,329 6558,319", _draw_="c 5 -black B 7 6672 368 6653 362 6633 356 6614 348 6595 340 6575 329 6558 319 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6559 316 6549 314 6556 322 "]; "UV check_ofname (113)" -> "UV shorten_name (115)" [pos="e,6707,315 6718,364 6716,353 6712,338 6709,325", _draw_="c 5 -black B 4 6718 364 6716 353 6712 338 6709 325 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6712 324 6707 315 6706 325 "]; "UV check_ofname (113)" -> "UV stat (118)" [pos="e,6868,226 6767,367 6782,363 6799,358 6815,356 6833,353 6959,360 6970,348 6994,323 6992,297 6970,271 6961,258 6951,268 6936,263 \ 6915,255 6893,242 6877,231", _draw_="c 5 -black B 16 6767 367 6782 363 6799 358 6815 356 6833 353 6959 360 6970 348 6994 323 6992 297 6970 271 6961 258 6951 268 6936\ 263 6915 255 6893 242 6877 231 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6878 228 6868 226 6875 234 "]; "UV check_ofname (113)" -> "UV same_file (125)" [pos="e,7004,230 6767,367 6782,363 6799,358 6815,356 6834,353 6970,360 6983,348 7013,320 7011,271 7006,240", _draw_="c 5 -black B 10 6767 367 6782 363 6799 358 6815 356 6834 353 6970 360 6983 348 7013 320 7011 271 7006 240 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7009 239 7004 230 7003 240 "]; "UV check_ofname (113)" -> "UV fflush (126)" [pos="e,6825,314 6761,366 6772,361 6783,355 6792,348 6802,340 6811,331 6819,322", _draw_="c 5 -black B 7 6761 366 6772 361 6783 355 6792 348 6802 340 6811 331 6819 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6822 324 6825 314 6816 320 "]; "UV check_ofname (113)" -> "UV fgets (127)" [pos="e,6917,314 6769,367 6783,363 6800,359 6815,356 6846,350 6857,362 6884,348 6895,342 6905,332 6911,323", _draw_="c 5 -black B 10 6769 367 6783 363 6800 359 6815 356 6846 350 6857 362 6884 348 6895 342 6905 332 6911 323 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6914 324 6917 314 6909 320 "]; "UV check_ofname (113)" -> "UV chmod (128)" [pos="e,7048,314 6767,367 6782,363 6799,358 6815,356 6857,349 6966,364 7005,348 7019,342 7032,332 7041,322", _draw_="c 5 -black B 10 6767 367 6782 363 6799 358 6815 356 6857 349 6966 364 7005 348 7019 342 7032 332 7041 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7044 324 7048 314 7039 319 "]; "UV name_too_long (114)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6721,550 6476,312 6456,321 6435,336 6423,356 6388,418 6378,465 6427,518 6446,538 6615,546 6711,550"]; "UV name_too_long (114)" -> "UV stat (118)" [pos="e,6820,219 6572,283 6586,279 6600,275 6614,271 6683,252 6764,232 6810,221", _draw_="c 5 -black B 7 6572 283 6586 279 6600 275 6614 271 6683 252 6764 232 6810 221 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6811 224 6820 219 6810 218 "]; "UV name_too_long (114)" -> "UV same_file (125)" [pos="e,6973,228 6567,282 6582,277 6598,273 6614,271 6675,261 6828,276 6887,263 6914,257 6943,244 6964,233", _draw_="c 5 -black B 10 6567 282 6582 277 6598 273 6614 271 6675 261 6828 276 6887 263 6914 257 6943 244 6964 233 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6966 236 6973 228 6963 230 "]; "UV shorten_name (115)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6724,547 6673,314 6646,329 6611,350 6605,356 6559,412 6527,462 6574,518 6583,528 6658,539 6714,546"]; "UV shorten_name (115)" -> "UV get_suffix (119)" [pos="e,7313,222 6747,282 6761,277 6777,273 6792,271 6912,252 6944,275 7064,263 7148,254 7244,236 7303,224", _draw_="c 5 -black B 10 6747 282 6761 277 6777 273 6792 271 6912 252 6944 275 7064 263 7148 254 7244 236 7303 224 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7304 227 7313 222 7303 221 "]; "UV do_stat (116)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6804,537 6879,400 6867,432 6841,499 6825,518 6821,522 6816,527 6812,530"]; "UV do_stat (116)" -> "UV lstat (117)" [pos="e,7163,314 6913,367 6923,363 6934,358 6945,356 6985,346 7091,365 7127,348 7139,342 7149,332 7157,322", _draw_="c 5 -black B 10 6913 367 6923 363 6934 358 6945 356 6985 346 7091 365 7127 348 7139 342 7149 332 7157 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7160 324 7163 314 7154 320 "]; "UV do_stat (116)" -> "UV stat (118)" [pos="e,6867,226 6913,367 6923,363 6934,358 6945,356 6964,351 7100,361 7112,348 7136,323 7136,295 7112,271 7099,256 6955,268 6936,263 \ 6914,256 6892,244 6875,232", _draw_="c 5 -black B 16 6913 367 6923 363 6934 358 6945 356 6964 351 7100 361 7112 348 7136 323 7136 295 7112 271 7099 256 6955 268 6936\ 263 6914 256 6892 244 6875 232 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6877 229 6867 226 6873 235 "]; "UV lstat (117)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6815,540 7162,314 7154,326 7141,340 7126,348 7110,355 6980,345 6965,356 6937,377 6968,409 6940,433 6922,448 6907,426 6887,441 \ 6857,463 6877,491 6849,518 6842,525 6833,530 6824,535"]; "UV stat (118)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6723,547 6818,214 6726,220 6454,241 6428,271 6406,296 6405,322 6428,348 6445,365 6518,339 6534,356 6586,406 6500,465 6549,518 \ 6560,529 6650,540 6713,546"]; "UV get_suffix (119)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6831,549 7363,230 7364,259 7362,316 7330,348 7319,359 7306,344 7294,356 7269,380 7302,410 7274,433 7246,456 7138,417 7109,441 \ 7082,463 7117,494 7090,518 7072,534 6928,544 6841,549"]; "UV strcat (120)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6831,550 7330,399 7320,411 7306,426 7289,433 7274,439 7148,430 7134,441 7106,462 7137,495 7109,518 7090,534 6932,544 6841,549"]; "UV same_file (125)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6825,544 7051,219 7108,227 7195,245 7214,271 7235,298 7238,323 7214,348 7196,367 6996,339 6975,356 6948,378 6984,409 6957,433 \ 6938,451 6918,423 6897,441 6870,464 6898,492 6873,518 6862,529 6849,536 6835,541"]; "UV fflush (126)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6722,548 6828,315 6820,326 6807,341 6792,348 6775,355 6462,342 6448,356 6396,409 6434,476 6496,518 6514,529 6635,541 6712,547"]; "UV fgets (127)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6768,535 6918,315 6910,326 6899,341 6884,348 6872,354 6644,346 6634,356 6623,368 6623,420 6634,433 6652,451 6728,424 6746,441 \ 6773,464 6751,484 6761,518 6762,520 6763,523 6764,526"]; "UV chmod (128)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6781,534 7046,314 7035,326 7018,341 7000,348 6983,354 6845,344 6830,356 6803,378 6820,398 6810,433 6801,464 6791,500 6784,524"]; "UV reset_times (129)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6830,549 7174,399 7158,409 7136,422 7116,433 7109,436 7105,434 7099,441 7076,467 7102,495 7074,518 7057,532 6922,543 6840,548"]; "UV reset_times (129)" -> "UV utime (130)" [pos="e,7266,314 7216,364 7229,351 7245,335 7259,321", _draw_="c 5 -black B 4 7216 364 7229 351 7245 335 7259 321 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7261 324 7266 314 7256 319 "]; "UV utime (130)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6824,543 7270,314 7260,326 7246,341 7229,348 7206,357 7021,340 7000,356 6972,377 7003,409 6975,433 6956,449 6937,423 6917,441 \ 6891,464 6922,492 6897,518 6888,527 6860,535 6834,541"]; "UV chown (131)" -> "UV treat_file (99)" [style=invis, minlen=0, pos="e,6826,545 7037,399 7027,411 7012,425 6995,433 6974,443 6961,425 6942,441 6915,464 6944,493 6917,518 6905,529 6869,537 6836,543"]; } subgraph cluster_49 { graph [label="S 49", color="#404080", style=bold, lp="8361,251", bb="8309,186,8413,263", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8361 246 0 32 4 -S 49 ", _draw_="S 4 -bold c 7 -#404080 p 4 8309 186 8309 263 8413 263 8413 186 ", xdotversion=""]; "UV close (109)" [label=close, width="0.97", height="0.49", style=dotted, color="#404080", pos="8352,212", _draw_="S 6 -dotted c 7 -#404080 e 8352 212 35 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8352 207 0 34 5 -close "]; "UV close (109)" -> "UV close (109)" [style=invis, minlen=0, pos="e,8373,198 8373,226 8389,231 8405,226 8405,212 8405,201 8395,196 8383,196"]; } subgraph cluster_14 { graph [label="S 14", color="#808040", style=bold, lp="7456,166", bb="7398,101,7514,178", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7456 161 0 32 4 -S 14 ", _draw_="S 4 -bold c 7 -#808040 p 4 7398 101 7398 178 7514 178 7514 101 ", xdotversion=""]; "UV strcpy (27)" [label=strcpy, width="1.14", height="0.49", style=dotted, color="#808040", pos="7447,127", _draw_="S 6 -dotted c 7 -#808040 e 7447 127 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 7447 122 0 42 6 -strcpy "]; "UV strcpy (27)" -> "UV strcpy (27)" [style=invis, minlen=0, pos="e,7471,113 7471,141 7489,146 7506,141 7506,127 7506,116 7495,110 7481,111"]; } subgraph cluster_5 { graph [label="S 5", color="#800080", style=bold, lp="6712,166", bb="6656,101,6768,178", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6712 161 0 23 3 -S 5 ", _draw_="S 4 -bold c 7 -#800080 p 4 6656 101 6656 178 6768 178 6768 101 ", xdotversion=""]; "UV strlen (25)" [label=strlen, width="1.08", height="0.49", style=dotted, color="#800080", pos="6703,127", _draw_="S 6 -dotted c 7 -#800080 e 6703 127 39 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6703 122 0 40 6 -strlen "]; "UV strlen (25)" -> "UV strlen (25)" [style=invis, minlen=0, pos="e,6726,113 6726,141 6743,146 6760,141 6760,127 6760,116 6749,110 6736,111"]; } subgraph cluster_15 { graph [label="S 15", color="#8080C0", style=bold, lp="6017,591", bb="5949,526,6085,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6017 586 0 32 4 -S 15 ", _draw_="S 4 -bold c 7 -#8080C0 p 4 5949 526 5949 603 6085 603 6085 526 ", xdotversion=""]; "UV strncmp (94)" [label=strncmp, width="1.42", height="0.49", style=dotted, color="#8080C0", pos="6008,552", _draw_="S 6 -dotted c 7 -#8080C0 e 6008 552 51 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6008 547 0 56 7 -strncmp "]; "UV strncmp (94)" -> "UV strncmp (94)" [style=invis, minlen=0, pos="e,6038,538 6038,566 6058,570 6077,566 6077,552 6077,540 6064,536 6048,537"]; } subgraph cluster_6 { graph [label="S 6", color="#808000", style=bold, lp="4812,591", bb="4730,526,4894,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4812 586 0 23 3 -S 6 ", _draw_="S 4 -bold c 7 -#808000 p 4 4730 526 4730 603 4894 603 4894 526 ", xdotversion=""]; "UV treat_stdin (100)" [label=treat_stdin, width="1.81", height="0.49", style=bold, color="#808000", pos="4803,552", _draw_="S 4 -bold c 7 -#808000 e 4803 552 65 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 4803 547 0 76 11 -treat_stdin "]; "UV treat_stdin (100)" -> "UV treat_stdin (100)" [style=invis, minlen=0, pos="e,4839,537 4839,567 4863,570 4886,565 4886,552 4886,541 4869,536 4849,536"]; } subgraph cluster_16 { graph [label="S 16", color="#004000", style=bold, lp="5605,336", bb="5547,271,5663,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5605 331 0 32 4 -S 16 ", _draw_="S 4 -bold c 7 -#004000 p 4 5547 271 5547 348 5663 348 5663 271 ", xdotversion=""]; "UV fprintf (33)" [label=fprintf, width="1.14", height="0.49", style=dotted, color="#004000", pos="5596,297", _draw_="S 6 -dotted c 7 -#004000 e 5596 297 41 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5596 292 0 42 7 -fprintf "]; "UV fprintf (33)" -> "UV fprintf (33)" [style=invis, minlen=0, pos="e,5620,283 5620,311 5638,316 5655,311 5655,297 5655,286 5644,280 5630,281"]; } subgraph cluster_7 { graph [label="S 7", color="#808080", style=bold, lp="3411,591", bb="3365,526,3457,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3411 586 0 23 3 -S 7 ", _draw_="S 4 -bold c 7 -#808080 p 4 3365 526 3365 603 3457 603 3457 526 ", xdotversion=""]; "UV atoi (97)" [label=atoi, width="0.81", height="0.49", style=dotted, color="#808080", pos="3402,552", _draw_="S 6 -dotted c 7 -#808080 e 3402 552 29 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3402 547 0 26 4 -atoi "]; "UV atoi (97)" -> "UV atoi (97)" [style=invis, minlen=0, pos="e,3420,538 3420,566 3434,571 3449,566 3449,552 3449,541 3440,536 3430,536"]; } subgraph cluster_17 { graph [label="S 17", color="#004080", style=bold, lp="5518,676", bb="5466,611,5570,688", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5518 671 0 32 4 -S 17 ", _draw_="S 4 -bold c 7 -#004080 p 4 5466 611 5466 688 5570 688 5570 611 ", xdotversion=""]; "UV main (91)" [label=main, width="0.97", height="0.49", style=bold, color="#004080", pos="5509,637", _draw_="S 4 -bold c 7 -#004080 e 5509 637 35 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5509 632 0 34 4 -main "]; "UV main (91)" -> "UV main (91)" [style=invis, minlen=0, pos="e,5532,624 5532,650 5547,653 5562,649 5562,637 5562,628 5553,623 5542,623"]; } subgraph cluster_8 { graph [label="S 8", color="#000040", style=bold, lp="8984,825", bb="8665,441,9303,837", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8984 820 0 23 3 -S 8 ", _draw_="S 4 -bold c 7 -#000040 p 4 8665 441 8665 837 9303 837 9303 441 ", xdotversion=""]; "UV fillbuf (49)" [label=fillbuf, width="1.03", height="0.50", style=bold, color="#000040", pos="8714,786", _draw_="S 4 -bold c 7 -#000040 e 8714 786 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8714 781 0 38 7 -fillbuf "]; "UV getbits (50)" [label=getbits, width="1.22", height="0.50", style=bold, color="#000040", pos="8930,467", _draw_="S 4 -bold c 7 -#000040 e 8930 467 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8930 462 0 47 7 -getbits "]; "UV init_getbits (51)" [label=init_getbits, width="1.78", height="0.50", style=bold, color="#000040", pos="8837,552", _draw_="S 4 -bold c 7 -#000040 e 8837 552 64 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8837 547 0 77 12 -init_getbits "]; "UV make_table (52)" [label=make_table, width="1.83", height="0.50", style=bold, color="#000040", pos="9058,467", _draw_="S 4 -bold c 7 -#000040 e 9058 467 66 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9058 462 0 79 10 -make_table "]; "UV read_pt_len (53)" [label=read_pt_len, width="1.86", height="0.50", style=bold, color="#000040", pos="9026,552", _draw_="S 4 -bold c 7 -#000040 e 9026 552 67 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9026 547 0 81 11 -read_pt_len "]; "UV read_c_len (54)" [label=read_c_len, width="1.72", height="0.50", style=bold, color="#000040", pos="9173,552", _draw_="S 4 -bold c 7 -#000040 e 9173 552 62 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9173 547 0 74 10 -read_c_len "]; "UV decode_c (55)" [label=decode_c, width="1.50", height="0.50", style=bold, color="#000040", pos="9181,637", _draw_="S 4 -bold c 7 -#000040 e 9181 637 54 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9181 632 0 62 8 -decode_c "]; "UV decode_p (56)" [label=decode_p, width="1.53", height="0.50", style=bold, color="#000040", pos="9054,637", _draw_="S 4 -bold c 7 -#000040 e 9054 637 55 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9054 632 0 64 8 -decode_p "]; "UV huf_decode_start (57)" [label=huf_decode_start, width="2.61", height="0.50", style=bold, color="#000040", pos="8887,637", _draw_="S 4 -bold c 7 -#000040 e 8887 637 94 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8887 632 0 119 16 -huf_decode_start "]; "UV decode_start (58)" [label=decode_start, width="2.03", height="0.50", style=bold, color="#000040", pos="8924,714", _draw_="S 4 -bold c 7 -#000040 e 8924 714 73 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 8924 709 0 89 12 -decode_start "]; "UV decode (59)" [label=decode, width="1.22", height="0.50", style=bold, color="#000040", pos="9099,714", _draw_="S 4 -bold c 7 -#000040 e 9099 714 44 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9099 709 0 48 6 -decode "]; "UV unlzh (60)" [label=unlzh, width="1.08", height="0.49", style=bold, color="#000040", pos="9036,786", _draw_="S 4 -bold c 7 -#000040 e 9036 786 39 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 9036 781 0 39 5 -unlzh "]; "UV fillbuf (49)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,8997,786 8751,786 8831,786 8908,786 8987,786"]; "UV getbits (50)" -> "UV fillbuf (49)" [pos="e,8708,768 8889,474 8836,484 8748,503 8725,526 8663,587 8688,705 8705,758", _draw_="c 5 -black B 7 8889 474 8836 484 8748 503 8725 526 8663 587 8688 705 8705 758 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8702 759 8708 768 8708 757 "]; "UV getbits (50)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9074,781 8942,484 8952,496 8966,511 8983,518 8997,523 9234,515 9244,526 9295,577 9281,625 9244,688 9211,745 9134,769 9084,779"]; "UV init_getbits (51)" -> "UV fillbuf (49)" [pos="e,8708,768 8784,562 8757,570 8726,585 8709,611 8681,656 8694,721 8705,758", _draw_="c 5 -black B 7 8784 562 8757 570 8726 585 8709 611 8681 656 8694 721 8705 758 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8702 759 8708 768 8708 757 "]; "UV init_getbits (51)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,8999,780 8815,569 8804,580 8790,595 8784,611 8772,642 8767,658 8784,688 8788,694 8793,691 8799,696 8820,709 8820,720 8842,732 \ 8889,756 8949,771 8989,778"]; "UV make_table (52)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,8998,781 9039,484 9025,496 9004,511 8983,518 8972,521 8773,517 8764,526 8700,592 8723,679 8799,732 8829,753 8928,770 8988,779"]; "UV read_pt_len (53)" -> "UV fillbuf (49)" [pos="e,8709,768 8997,568 8974,580 8941,596 8910,603 8891,607 8744,597 8729,611 8690,649 8698,719 8707,758", _draw_="c 5 -black B 10 8997 568 8974 580 8941 596 8910 603 8891 607 8744 597 8729 611 8690 649 8698 719 8707 758 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8704 759 8709 768 8710 758 "]; "UV read_pt_len (53)" -> "UV getbits (50)" [pos="e,8947,484 9004,535 8997,529 8990,524 8983,518 8974,509 8963,500 8954,491", _draw_="c 5 -black B 7 9004 535 8997 529 8990 524 8983 518 8974 509 8963 500 8954 491 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8957 489 8947 484 8952 494 "]; "UV read_pt_len (53)" -> "UV make_table (52)" [pos="e,9051,485 9033,534 9037,523 9043,508 9047,495", _draw_="c 5 -black B 4 9033 534 9037 523 9043 508 9047 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9051 496 9051 485 9044 493 "]; "UV read_pt_len (53)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9074,781 9046,569 9060,581 9081,596 9102,603 9117,608 9234,599 9244,611 9268,635 9262,658 9244,688 9211,745 9134,769 9084,779"]; "UV read_c_len (54)" -> "UV fillbuf (49)" [pos="e,8715,768 9155,569 9142,581 9122,596 9102,603 9069,614 8815,592 8784,611 8733,642 8719,717 8716,758", _draw_="c 5 -black B 10 9155 569 9142 581 9122 596 9102 603 9069 614 8815 592 8784 611 8733 642 8719 717 8716 758 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8713 758 8715 768 8719 758 "]; "UV read_c_len (54)" -> "UV getbits (50)" [pos="e,8943,484 9139,537 9127,532 9114,528 9102,526 9077,520 9008,528 8983,518 8970,512 8959,502 8950,492", _draw_="c 5 -black B 10 9139 537 9127 532 9114 528 9102 526 9077 520 9008 528 8983 518 8970 512 8959 502 8950 492 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8952 489 8943 484 8947 494 "]; "UV read_c_len (54)" -> "UV make_table (52)" [pos="e,9081,484 9150,535 9133,522 9108,504 9089,490", _draw_="c 5 -black B 4 9150 535 9133 522 9108 504 9089 490 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9091 487 9081 484 9087 493 "]; "UV read_c_len (54)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9074,781 9203,568 9219,578 9236,592 9244,611 9259,641 9262,658 9244,688 9211,745 9134,769 9084,779"]; "UV decode_c (55)" -> "UV fillbuf (49)" [pos="e,8730,770 9166,654 9154,666 9137,681 9118,688 9061,709 8901,676 8842,696 8801,710 8762,741 8737,763", _draw_="c 5 -black B 10 9166 654 9154 666 9137 681 9118 688 9061 709 8901 676 8842 696 8801 710 8762 741 8737 763 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8735 760 8730 770 8740 765 "]; "UV decode_c (55)" -> "UV getbits (50)" [pos="e,8931,485 9151,622 9141,617 9129,613 9118,611 9100,606 8964,615 8950,603 8943,596 8935,533 8932,495", _draw_="c 5 -black B 10 9151 622 9141 617 9129 613 9118 611 9100 606 8964 615 8950 603 8943 596 8935 533 8932 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8935 495 8931 485 8929 495 "]; "UV decode_c (55)" -> "UV read_pt_len (53)" [pos="e,9050,569 9147,623 9129,616 9110,607 9102,603 9087,595 9071,584 9058,575", _draw_="c 5 -black B 7 9147 623 9129 616 9110 607 9102 603 9087 595 9071 584 9058 575 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9060 572 9050 569 9056 578 "]; "UV decode_c (55)" -> "UV read_c_len (54)" [pos="e,9175,570 9179,619 9178,608 9177,593 9176,580", _draw_="c 5 -black B 4 9179 619 9178 608 9177 593 9176 580 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9179 580 9175 570 9173 580 "]; "UV decode_c (55)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9071,778 9180,655 9178,676 9171,710 9152,732 9134,753 9105,766 9081,775"]; "UV decode_p (56)" -> "UV fillbuf (49)" [pos="e,8722,768 9039,654 9027,666 9009,681 8990,688 8967,696 8791,683 8769,696 8757,703 8739,735 8727,759", _draw_="c 5 -black B 10 9039 654 9027 666 9009 681 8990 688 8967 696 8791 683 8769 696 8757 703 8739 735 8727 759 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8724 758 8722 768 8730 761 "]; "UV decode_p (56)" -> "UV getbits (50)" [pos="e,8924,485 9022,622 9012,618 9001,614 8990,611 8979,607 8944,612 8935,603 8909,573 8914,526 8921,495", _draw_="c 5 -black B 10 9022 622 9012 618 9001 614 8990 611 8979 607 8944 612 8935 603 8909 573 8914 526 8921 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8924 496 8924 485 8918 494 "]; "UV decode_p (56)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9038,768 9052,655 9050,667 9048,682 9046,696 9044,717 9041,740 9039,758"]; "UV huf_decode_start (57)" -> "UV init_getbits (51)" [pos="e,8848,570 8876,619 8870,608 8861,592 8853,579", _draw_="c 5 -black B 4 8876 619 8870 608 8861 592 8853 579 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8856 577 8848 570 8850 580 "]; "UV huf_decode_start (57)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9034,768 8921,654 8957,671 9006,695 9006,696 9021,713 9029,739 9032,758"]; "UV decode_start (58)" -> "UV huf_decode_start (57)" [pos="e,8896,655 8915,696 8910,687 8905,675 8900,664", _draw_="c 5 -black B 4 8915 696 8910 687 8905 675 8900 664 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8903 663 8896 655 8897 666 "]; "UV decode_start (58)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9018,771 8955,730 8972,740 8993,754 9009,765"]; "UV decode (59)" -> "UV decode_c (55)" [pos="e,9163,654 9117,697 9129,687 9143,673 9155,661", _draw_="c 5 -black B 4 9117 697 9129 687 9143 673 9155 661 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9158 663 9163 654 9153 658 "]; "UV decode (59)" -> "UV decode_p (56)" [pos="e,9064,655 9089,696 9083,687 9076,674 9069,663", _draw_="c 5 -black B 4 9089 696 9083 687 9076 674 9069 663 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9072 662 9064 655 9066 665 "]; "UV decode (59)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9055,770 9089,732 9082,742 9071,753 9062,763"]; "UV unlzh (60)" -> "UV decode_start (58)" [pos="e,8945,731 9010,773 8993,763 8971,749 8953,737", _draw_="c 5 -black B 4 9010 773 8993 763 8971 749 8953 737 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8955 734 8945 731 8951 740 "]; "UV unlzh (60)" -> "UV decode (59)" [pos="e,9079,731 9045,769 9052,760 9062,748 9072,738", _draw_="c 5 -black B 4 9045 769 9052 760 9062 748 9072 738 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 9074 741 9079 731 9069 736 "]; "UV unlzh (60)" -> "UV unlzh (60)" [style=invis, minlen=0, pos="e,9063,773 9063,799 9079,801 9093,797 9093,786 9093,777 9084,773 9073,773"]; } subgraph cluster_30 { graph [label="S 30", color="#80C040", style=bold, lp="3884,251", bb="3821,101,3947,263", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3884 246 0 32 4 -S 30 ", _draw_="S 4 -bold c 7 -#80C040 p 4 3821 101 3821 263 3947 263 3947 101 ", xdotversion=""]; "UV do_exit (98)" [label=do_exit, width="1.28", height="0.49", style=bold, color="#80C040", pos="3875,212", _draw_="S 4 -bold c 7 -#80C040 e 3875 212 46 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3875 207 0 50 7 -do_exit "]; "UV exit (132)" [label=exit, width="0.81", height="0.50", style=dotted, color="#80C040", pos="3875,127", _draw_="S 6 -dotted c 7 -#80C040 e 3875 127 29 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 3875 122 0 26 4 -exit "]; "UV do_exit (98)" -> "UV do_exit (98)" [style=invis, minlen=0, pos="e,3902,198 3902,226 3921,230 3939,226 3939,212 3939,201 3927,196 3912,197"]; "UV do_exit (98)" -> "UV exit (132)" [pos="e,3870,145 3869,194 3868,182 3868,168 3869,155", _draw_="c 5 -black B 4 3869 194 3868 182 3868 168 3869 155 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3872 155 3870 145 3866 155 "]; "UV exit (132)" -> "UV do_exit (98)" [style=invis, minlen=0, pos="e,3881,194 3880,145 3882,156 3882,171 3881,184"]; } subgraph cluster_18 { graph [label="S 18", color="#00C000", style=bold, lp="6157,591", bb="6093,526,6221,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6157 586 0 32 4 -S 18 ", _draw_="S 4 -bold c 7 -#00C000 p 4 6093 526 6093 603 6221 603 6221 526 ", xdotversion=""]; "UV strncpy (95)" [label=strncpy, width="1.31", height="0.49", style=dotted, color="#00C000", pos="6148,552", _draw_="S 6 -dotted c 7 -#00C000 e 6148 552 47 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6148 547 0 51 7 -strncpy "]; "UV strncpy (95)" -> "UV strncpy (95)" [style=invis, minlen=0, pos="e,6175,538 6175,566 6194,570 6213,566 6213,552 6213,541 6200,536 6185,537"]; } subgraph cluster_9 { graph [label="S 9", color="#0000C0", style=bold, lp="5885,591", bb="5829,526,5941,603", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5885 586 0 23 3 -S 9 ", _draw_="S 4 -bold c 7 -#0000C0 p 4 5829 526 5829 603 5941 603 5941 526 ", xdotversion=""]; "UV signal (93)" [label=signal, width="1.08", height="0.49", style=dotted, color="#0000C0", pos="5876,552", _draw_="S 6 -dotted c 7 -#0000C0 e 5876 552 39 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5876 547 0 40 6 -signal "]; "UV signal (93)" -> "UV signal (93)" [style=invis, minlen=0, pos="e,5899,538 5899,566 5916,571 5933,566 5933,552 5933,541 5922,535 5909,536"]; } subgraph cluster_31 { graph [label="S 31", color="#80C0C0", style=bold, lp="2868,336", bb="2818,271,2918,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2868 331 0 32 4 -S 31 ", _draw_="S 4 -bold c 7 -#80C0C0 p 4 2818 271 2818 348 2918 348 2918 271 ", xdotversion=""]; "UV read (9)" [label=read, width="0.92", height="0.49", style=dotted, color="#80C0C0", pos="2859,297", _draw_="S 6 -dotted c 7 -#80C0C0 e 2859 297 33 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2859 292 0 31 4 -read "]; "UV read (9)" -> "UV read (9)" [style=invis, minlen=0, pos="e,2879,283 2879,311 2895,316 2910,311 2910,297 2910,286 2901,281 2889,281"]; } subgraph cluster_32 { graph [label="S 32", color="#400000", style=bold, lp="2593,336", bb="2518,186,2668,348", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2593 331 0 32 4 -S 32 ", _draw_="S 4 -bold c 7 -#400000 p 4 2518 186 2518 348 2668 348 2668 186 ", xdotversion=""]; "UV write_buf (12)" [label=write_buf, width="1.61", height="0.49", style=bold, color="#400000", pos="2584,297", _draw_="S 4 -bold c 7 -#400000 e 2584 297 58 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2584 292 0 66 9 -write_buf "]; "UV write (17)" [label=write, width="1.03", height="0.50", style=dotted, color="#400000", pos="2584,212", _draw_="S 6 -dotted c 7 -#400000 e 2584 212 37 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2584 207 0 37 5 -write "]; "UV write_buf (12)" -> "UV write_buf (12)" [style=invis, minlen=0, pos="e,2617,283 2617,311 2639,315 2660,311 2660,297 2660,285 2645,280 2627,282"]; "UV write_buf (12)" -> "UV write (17)" [pos="e,2579,230 2578,279 2577,268 2577,253 2578,240", _draw_="c 5 -black B 4 2578 279 2577 268 2577 253 2578 240 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2581 240 2579 230 2575 240 "]; "UV write (17)" -> "UV write_buf (12)" [style=invis, minlen=0, pos="e,2590,279 2589,230 2591,241 2591,256 2591,269"]; } subgraph cluster_19 { graph [label="S 19", color="#00C080", style=bold, lp="6253,421", bb="6175,356,6331,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6253 416 0 32 4 -S 19 ", _draw_="S 4 -bold c 7 -#00C080 p 4 6175 356 6175 433 6331 433 6331 356 ", xdotversion=""]; "UV basename (6)" [label=basename, width="1.69", height="0.49", style=bold, color="#00C080", pos="6244,382", _draw_="S 4 -bold c 7 -#00C080 e 6244 382 61 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 6244 377 0 70 8 -basename "]; "UV basename (6)" -> "UV basename (6)" [style=invis, minlen=0, pos="e,6279,367 6279,397 6301,400 6323,395 6323,382 6323,371 6307,366 6289,366"]; } subgraph cluster_33 { graph [label="S 33", color="#400080", style=bold, lp="2997,421", bb="2917,356,3077,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2997 416 0 32 4 -S 33 ", _draw_="S 4 -bold c 7 -#400080 p 4 2917 356 2917 433 3077 433 3077 356 ", xdotversion=""]; "UV read_error (13)" [label=read_error, width="1.75", height="0.49", style=bold, color="#400080", pos="2988,382", _draw_="S 4 -bold c 7 -#400080 e 2988 382 63 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2988 377 0 73 10 -read_error "]; "UV read_error (13)" -> "UV read_error (13)" [style=invis, minlen=0, pos="e,3024,367 3024,397 3047,400 3069,395 3069,382 3069,371 3053,366 3034,366"]; } subgraph cluster_34 { graph [label="S 34", color="#408000", style=bold, lp="5117,506", bb="4975,356,5259,518", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5117 501 0 32 4 -S 34 ", _draw_="S 4 -bold c 7 -#408000 p 4 4975 356 4975 518 5259 518 5259 356 ", xdotversion=""]; "UV get_method (105)" [label=get_method, width="1.94", height="0.49", style=bold, color="#408000", pos="5108,467", _draw_="S 4 -bold c 7 -#408000 e 5108 467 70 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5108 462 0 83 10 -get_method "]; "UV memcmp (121)" [label=memcmp, width="1.50", height="0.50", style=dotted, color="#408000", pos="5037,382", _draw_="S 6 -dotted c 7 -#408000 e 5037 382 54 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5037 377 0 62 6 -memcmp "]; "UV check_zipfile (40)" [label=check_zipfile, width="1.97", height="0.50", style=bold, color="#408000", pos="5180,382", _draw_="S 4 -bold c 7 -#408000 e 5180 382 71 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 5180 377 0 87 13 -check_zipfile "]; "UV get_method (105)" -> "UV check_zipfile (40)" [pos="e,5160,399 5117,449 5126,436 5141,420 5153,406", _draw_="c 5 -black B 4 5117 449 5126 436 5141 420 5153 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5155 409 5160 399 5150 404 "]; "UV get_method (105)" -> "UV get_method (105)" [style=invis, minlen=0, pos="e,5147,452 5147,482 5172,485 5196,480 5196,467 5196,456 5178,451 5157,451"]; "UV get_method (105)" -> "UV memcmp (121)" [pos="e,5047,400 5088,450 5077,438 5063,422 5053,409", _draw_="c 5 -black B 4 5088 450 5077 438 5063 422 5053 409 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5055 406 5047 400 5050 410 "]; "UV memcmp (121)" -> "UV get_method (105)" [style=invis, minlen=0, pos="e,5099,449 5057,399 5069,411 5082,427 5093,441"]; "UV check_zipfile (40)" -> "UV get_method (105)" [style=invis, minlen=0, pos="e,5128,450 5170,400 5161,413 5147,429 5135,442"]; } subgraph cluster_35 { graph [label="S 35", color="#408080", style=bold, lp="2732,421", bb="2663,356,2801,433", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2732 416 0 32 4 -S 35 ", _draw_="S 4 -bold c 7 -#408080 p 4 2663 356 2663 433 2801 433 2801 356 ", xdotversion=""]; "UV fill_inbuf (15)" [label=fill_inbuf, width="1.44", height="0.49", style=bold, color="#408080", pos="2723,382", _draw_="S 4 -bold c 7 -#408080 e 2723 382 52 18 ", _ldraw_="F 14.000000 11 -Times-Roman c 5 -black T 2723 377 0 58 10 -fill_inbuf "]; "UV fill_inbuf (15)" -> "UV fill_inbuf (15)" [style=invis, minlen=0, pos="e,2753,368 2753,396 2773,400 2793,396 2793,382 2793,370 2779,366 2763,367"]; } "UV zip (0)" -> "UV updcrc (2)" [style=dotted, pos="e,1316,297 615,934 506,932 75,919 30,881 -2,852 9,829 9,786 9,786 9,786 9,467 9,416 -9,389 28,356 77,313 1062,300 1306,297", _draw_="S 6 -dotted c 5 -black B 16 615 934 506 932 75 919 30 881 -2 852 9 829 9 786 9 786 9 786 9 467 9 416 -9 389 28 356 77 313 1062 3\ 00 1306 297 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1306 301 1316 297 1306 294 "]; "UV zip (0)" -> "UV basename (6)" [style=dotted, pos="e,6279,396 665,935 1176,933 9214,906 9307,837 9327,822 9323,809 9323,786 9323,786 9323,786 9323,552 9323,502 9345,473 9307,441 9\ 292,427 6425,436 6405,433 6364,427 6320,412 6288,400", _draw_="S 6 -dotted c 5 -black B 19 665 935 1176 933 9214 906 9307 837 9327 822 9323 809 9323 786 9323 786 9323 786 9323 552 9323 502 93\ 45 473 9307 441 9292 427 6425 436 6405 433 6364 427 6320 412 6288 400 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6290 397 6279 396 6287 403 "]; "UV flush_outbuf (1)" -> "UV write_buf (12)" [style=dotted, pos="e,2526,299 1115,375 1170,369 1251,361 1321,356 1778,324 2327,305 2516,299", _draw_="S 6 -dotted c 5 -black B 7 1115 375 1170 369 1251 361 1321 356 1778 324 2327 305 2516 299 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2516 303 2526 299 2516 296 "]; "UV do_exit (98)" -> "UV free (30)" [style=dotted, pos="e,3773,142 3849,198 3839,192 3827,185 3817,178 3805,169 3792,158 3781,149", _draw_="S 6 -dotted c 5 -black B 7 3849 198 3839 192 3827 185 3817 178 3805 169 3792 158 3781 149 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3783 146 3773 142 3778 151 "]; "UV treat_file (99)" -> "UV clear_bufs (14)" [style=dotted, pos="e,5626,480 6723,547 6651,541 6519,530 6405,526 6337,523 5853,527 5784,518 5732,511 5676,495 5636,483", _draw_="S 6 -dotted c 5 -black B 10 6723 547 6651 541 6519 530 6405 526 6337 523 5853 527 5784 518 5732 511 5676 495 5636 483 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5637 480 5626 480 5635 486 "]; "UV treat_file (99)" -> "UV write_error (18)" [style=dotted, pos="e,5366,399 6723,547 6651,541 6519,531 6405,526 6338,522 6170,527 6103,518 5971,498 5945,459 5812,441 5771,435 5480,443 5439,433 \ 5417,427 5393,414 5375,404", _draw_="S 6 -dotted c 5 -black B 16 6723 547 6651 541 6519 531 6405 526 6338 522 6170 527 6103 518 5971 498 5945 459 5812 441 5771 435 5\ 480 443 5439 433 5417 427 5393 414 5375 404 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5376 401 5366 399 5373 407 "]; "UV treat_file (99)" -> "UV strlen (25)" [style=dotted, pos="e,6742,130 6722,548 6606,540 6343,521 6339,518 6314,490 6345,376 6375,356 6391,345 7742,361 7755,348 7856,246 7634,186 7631,186 \ 7606,177 7421,179 7394,178 7153,164 6864,141 6752,131", _draw_="S 6 -dotted c 5 -black B 19 6722 548 6606 540 6343 521 6339 518 6314 490 6345 376 6375 356 6391 345 7742 361 7755 348 7856 246 7\ 634 186 7631 186 7606 177 7421 179 7394 178 7153 164 6864 141 6752 131 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6752 128 6742 130 6752 134 "]; "UV treat_file (99)" -> "UV strcpy (27)" [style=dotted, pos="e,7487,132 6722,548 6646,542 6515,530 6496,518 6434,476 6396,409 6448,356 6461,342 7760,361 7772,348 7826,293 7779,229 7716,186 \ 7681,161 7564,143 7497,133", _draw_="S 6 -dotted c 5 -black B 16 6722 548 6646 542 6515 530 6496 518 6434 476 6396 409 6448 356 6461 342 7760 361 7772 348 7826 293 7\ 779 229 7716 186 7681 161 7564 143 7497 133 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7497 130 7487 132 7497 136 "]; "UV treat_file (99)" -> "UV fprintf (33)" [style=dotted, pos="e,5637,299 6722,548 6599,540 6307,519 6301,518 6172,494 6120,515 6017,433 5987,408 6007,378 5974,356 5923,319 5737,304 5647,299", _draw_="S 6 -dotted c 5 -black B 13 6722 548 6599 540 6307 519 6301 518 6172 494 6120 515 6017 433 5987 408 6007 378 5974 356 5923 319 5\ 737 304 5647 299 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5647 296 5637 299 5647 303 "]; "UV treat_file (99)" -> "UV perror (36)" [style=dotted, pos="e,8160,312 6831,552 6988,550 7431,543 7573,518 7817,474 7881,455 8103,348 8120,340 8138,328 8152,318", _draw_="S 6 -dotted c 5 -black B 10 6831 552 6988 550 7431 543 7573 518 7817 474 7881 455 8103 348 8120 340 8138 328 8152 318 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8154 321 8160 312 8150 315 "]; "UV treat_file (99)" -> "UV display_ratio (37)" [style=dotted, pos="e,4738,394 6723,547 6651,541 6519,530 6405,526 6373,524 5844,526 5812,518 5745,499 5744,459 5676,441 5639,430 5010,436 4971,433 \ 4894,425 4806,408 4748,396", _draw_="S 6 -dotted c 5 -black B 16 6723 547 6651 541 6519 530 6405 526 6373 524 5844 526 5812 518 5745 499 5744 459 5676 441 5639 430 5\ 010 436 4971 433 4894 425 4806 408 4748 396 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4748 393 4738 394 4747 399 "]; "UV treat_file (99)" -> "UV (86)" [style=dotted, pos="e,2931,484 6723,547 6651,540 6519,529 6405,526 6358,524 3049,529 3003,518 2981,512 2958,500 2940,490", _draw_="S 6 -dotted c 5 -black B 10 6723 547 6651 540 6519 529 6405 526 6358 524 3049 529 3003 518 2981 512 2958 500 2940 490 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2941 487 2931 484 2937 492 "]; "UV treat_file (99)" -> "UV strcmp (92)" [style=dotted, pos="e,8294,130 6831,551 7068,548 7997,533 8127,518 8306,496 8359,506 8522,433 8636,382 8735,280 8653,186 8631,159 8409,139 8304,131", _draw_="S 6 -dotted c 5 -black B 13 6831 551 7068 548 7997 533 8127 518 8306 496 8359 506 8522 433 8636 382 8735 280 8653 186 8631 159 8\ 409 139 8304 131 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8304 128 8294 130 8304 134 "]; "UV treat_file (99)" -> "UV treat_stdin (100)" [style=dotted, pos="e,4861,560 6729,561 6657,574 6517,598 6396,607 6337,611 5386,610 5326,607 5163,598 4971,575 4871,561", _draw_="S 6 -dotted c 5 -black B 10 6729 561 6657 574 6517 598 6396 607 6337 611 5386 610 5326 607 5163 598 4971 575 4871 561 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4871 558 4861 560 4871 564 "]; "UV treat_file (99)" -> "UV do_list (101)" [style=dotted, pos="e,4353,471 6723,547 6651,541 6519,530 6405,526 6087,513 5290,531 4971,518 4744,508 4474,483 4363,472", _draw_="S 6 -dotted c 5 -black B 10 6723 547 6651 541 6519 530 6405 526 6087 513 5290 531 4971 518 4744 508 4474 483 4363 472 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4363 469 4353 471 4363 475 "]; "UV treat_file (99)" -> "UV fileno (102)" [style=dotted, pos="e,7933,313 6831,551 6967,549 7317,541 7430,518 7641,474 7695,451 7883,348 7898,340 7913,329 7925,319", _draw_="S 6 -dotted c 5 -black B 10 6831 551 6967 549 7317 541 7430 518 7641 474 7695 451 7883 348 7898 340 7913 329 7925 319 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7927 322 7933 313 7923 316 "]; "UV treat_file (99)" -> "UV get_method (105)" [style=dotted, pos="e,5155,480 6723,547 6651,541 6519,530 6405,526 6287,521 5457,531 5339,518 5278,511 5211,495 5165,483", _draw_="S 6 -dotted c 5 -black B 10 6723 547 6651 541 6519 530 6405 526 6287 521 5457 531 5339 518 5278 511 5211 495 5165 483 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5166 480 5155 480 5164 486 "]; "UV treat_file (99)" -> "UV close (109)" [style=dotted, pos="e,8354,230 6831,552 7009,551 7562,546 7737,518 8005,475 8137,545 8322,348 8350,318 8354,271 8354,240", _draw_="S 6 -dotted c 5 -black B 10 6831 552 7009 551 7562 546 7737 518 8005 475 8137 545 8322 348 8350 318 8354 271 8354 240 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8358 240 8354 230 8351 240 "]; "UV treat_file (99)" -> "UV unlink (111)" [style=dotted, pos="e,8460,229 6831,551 7052,548 7865,535 7979,518 8117,496 8164,508 8281,433 8362,381 8427,284 8455,238", _draw_="S 6 -dotted c 5 -black B 10 6831 551 7052 548 7865 535 7979 518 8117 496 8164 508 8281 433 8362 381 8427 284 8455 238 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8458 239 8460 229 8452 236 "]; "UV treat_stdin (100)" -> "UV clear_bufs (14)" [style=dotted, pos="e,5556,482 4867,549 5030,541 5447,520 5461,518 5491,511 5523,498 5547,487", _draw_="S 6 -dotted c 5 -black B 7 4867 549 5030 541 5447 520 5461 518 5491 511 5523 498 5547 487 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5549 490 5556 482 5546 484 "]; "UV treat_stdin (100)" -> "UV strcpy (27)" [style=dotted, pos="e,7407,131 4803,534 4803,503 4803,437 4803,382 4803,382 4803,382 4803,297 4803,187 6663,183 6772,178 7007,166 7285,142 7397,132", _draw_="S 6 -dotted c 5 -black B 13 4803 534 4803 503 4803 437 4803 382 4803 382 4803 382 4803 297 4803 187 6663 183 6772 178 7007 166 7\ 285 142 7397 132 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7397 135 7407 131 7397 129 "]; "UV treat_stdin (100)" -> "UV error (32)" [style=dotted, pos="e,3870,396 4738,550 4584,545 4202,532 4145,518 4042,493 3931,432 3879,401", _draw_="S 6 -dotted c 5 -black B 7 4738 550 4584 545 4202 532 4145 518 4042 493 3931 432 3879 401 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3880 398 3870 396 3877 404 "]; "UV treat_stdin (100)" -> "UV fprintf (33)" [style=dotted, pos="e,5559,305 4811,534 4813,529 4815,523 4817,518 4842,447 4806,401 4865,356 4875,348 5283,349 5294,348 5386,340 5490,319 5549,307", _draw_="S 6 -dotted c 5 -black B 13 4811 534 4813 529 4815 523 4817 518 4842 447 4806 401 4865 356 4875 348 5283 349 5294 348 5386 340 5\ 490 319 5549 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5550 310 5559 305 5549 304 "]; "UV treat_stdin (100)" -> "UV display_ratio (37)" [style=dotted, pos="e,4696,399 4791,535 4770,506 4726,443 4702,407", _draw_="S 6 -dotted c 5 -black B 4 4791 535 4770 506 4726 443 4702 407 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4705 405 4696 399 4699 409 "]; "UV treat_stdin (100)" -> "UV (86)" [style=dotted, pos="e,2931,484 4738,550 4588,544 4201,532 3877,526 3853,525 3027,524 3003,518 2981,512 2958,500 2940,490", _draw_="S 6 -dotted c 5 -black B 10 4738 550 4588 544 4201 532 3877 526 3853 525 3027 524 3003 518 2981 512 2958 500 2940 490 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2941 487 2931 484 2937 492 "]; "UV treat_stdin (100)" -> "UV do_exit (98)" [style=dotted, pos="e,3898,227 4738,550 4582,546 4197,533 4173,518 4142,496 4159,471 4135,441 4067,351 3959,270 3906,233", _draw_="S 6 -dotted c 5 -black B 10 4738 550 4582 546 4197 533 4173 518 4142 496 4159 471 4135 441 4067 351 3959 270 3906 233 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3908 230 3898 227 3904 236 "]; "UV treat_stdin (100)" -> "UV do_list (101)" [style=dotted, pos="e,4351,474 4748,542 4652,526 4453,492 4361,476", _draw_="S 6 -dotted c 5 -black B 4 4748 542 4652 526 4453 492 4361 476 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4361 473 4351 474 4360 479 "]; "UV treat_stdin (100)" -> "UV fileno (102)" [style=dotted, pos="e,7920,307 4840,538 4851,532 4862,526 4871,518 4905,488 4902,471 4925,433 4946,399 4937,375 4971,356 4988,346 7736,350 7755,348 \ 7810,341 7871,323 7910,310", _draw_="S 6 -dotted c 5 -black B 16 4840 538 4851 532 4862 526 4871 518 4905 488 4902 471 4925 433 4946 399 4937 375 4971 356 4988 346 7\ 736 350 7755 348 7810 341 7871 323 7910 310 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7911 313 7920 307 7909 307 "]; "UV treat_stdin (100)" -> "UV isatty (103)" [style=dotted, pos="e,5991,304 4821,535 4827,530 4832,524 4837,518 4891,451 4867,397 4941,356 4959,346 5647,349 5667,348 5781,338 5912,317 5981,306", _draw_="S 6 -dotted c 5 -black B 13 4821 535 4827 530 4832 524 4837 518 4891 451 4867 397 4941 356 4959 346 5647 349 5667 348 5781 338 5\ 912 317 5981 306 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5982 309 5991 304 5981 303 "]; "UV treat_stdin (100)" -> "UV fstat (104)" [style=dotted, pos="e,5718,398 4867,550 4986,545 5228,534 5263,518 5307,497 5295,460 5339,441 5373,426 5634,445 5668,433 5684,427 5699,416 5711,405", _draw_="S 6 -dotted c 5 -black B 13 4867 550 4986 545 5228 534 5263 518 5307 497 5295 460 5339 441 5373 426 5634 445 5668 433 5684 427 5\ 699 416 5711 405 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5713 408 5718 398 5708 403 "]; "UV treat_stdin (100)" -> "UV get_method (105)" [style=dotted, pos="e,5072,482 4858,543 4891,537 4933,528 4969,518 5001,509 5036,496 5062,486", _draw_="S 6 -dotted c 5 -black B 7 4858 543 4891 537 4933 528 4969 518 5001 509 5036 496 5062 486 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5064 489 5072 482 5061 482 "]; "UV do_list (101)" -> "UV read (9)" [style=dotted, pos="e,2892,298 4276,458 4248,451 4210,442 4176,433 4059,401 4034,376 3913,356 3714,322 3075,303 2902,298", _draw_="S 6 -dotted c 5 -black B 10 4276 458 4248 451 4210 442 4176 433 4059 401 4034 376 3913 356 3714 322 3075 303 2902 298 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2902 295 2892 298 2902 302 "]; "UV do_list (101)" -> "UV read_error (13)" [style=dotted, pos="e,3018,398 4271,464 4194,458 4022,445 3877,441 3835,439 3155,441 3113,433 3083,427 3051,414 3027,403", _draw_="S 6 -dotted c 5 -black B 10 4271 464 4194 458 4022 445 3877 441 3835 439 3155 441 3113 433 3083 427 3051 414 3027 403 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3028 400 3018 398 3025 406 "]; "UV do_list (101)" -> "UV display_ratio (37)" [style=dotted, pos="e,4662,399 4353,464 4422,459 4555,448 4599,433 4618,426 4637,415 4653,405", _draw_="S 6 -dotted c 5 -black B 7 4353 464 4422 459 4555 448 4599 433 4618 426 4637 415 4653 405 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4656 407 4662 399 4652 402 "]; "UV lm_init (5)" -> "UV error (32)" [style=dotted, pos="e,3812,386 1278,863 1438,861 1984,856 2157,837 2396,810 2452,778 2687,732 2728,724 2777,754 2777,714 2777,714 2777,714 2777,552 \ 2777,497 2785,470 2831,441 2841,434 3244,433 3255,433 3460,422 3703,398 3802,387", _draw_="S 6 -dotted c 5 -black B 22 1278 863 1438 861 1984 856 2157 837 2396 810 2452 778 2687 732 2728 724 2777 754 2777 714 2777 714 2\ 777 714 2777 552 2777 497 2785 470 2831 441 2841 434 3244 433 3255 433 3460 422 3703 398 3802 387 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3802 390 3812 386 3802 384 "]; "UV lm_init (5)" -> "UV memset (47)" [style=dotted, pos="e,2342,400 1278,863 1451,862 2072,859 2107,837 2267,737 2325,492 2340,410", _draw_="S 6 -dotted c 5 -black B 7 1278 863 1451 862 2072 859 2107 837 2267 737 2325 492 2340 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2343 410 2342 400 2337 409 "]; "UV lm_init (5)" -> "UV (86)" [style=dotted, pos="e,2891,484 1278,863 1530,860 2777,849 2791,837 2834,801 2815,769 2815,714 2815,714 2815,714 2815,637 2815,579 2856,523 2884,492", _draw_="S 6 -dotted c 5 -black B 13 1278 863 1530 860 2777 849 2791 837 2834 801 2815 769 2815 714 2815 714 2815 714 2815 637 2815 579 2\ 856 523 2884 492 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2887 494 2891 484 2882 489 "]; "UV basename (6)" -> "UV strlwr (19)" [style=dotted, pos="e,7875,145 6290,370 6315,365 6346,358 6375,356 6395,354 7739,357 7755,348 7828,305 7861,203 7873,155", _draw_="S 6 -dotted c 5 -black B 10 6290 370 6315 365 6346 358 6375 356 6395 354 7739 357 7755 348 7828 305 7861 203 7873 155 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7876 155 7875 145 7870 154 "]; "UV basename (6)" -> "UV strrchr (21)" [style=dotted, pos="e,7539,228 6283,368 6299,363 6319,358 6337,356 6353,353 7448,356 7461,348 7494,327 7479,302 7501,271 7510,258 7521,245 7532,235", _draw_="S 6 -dotted c 5 -black B 13 6283 368 6299 363 6319 358 6337 356 6353 353 7448 356 7461 348 7494 327 7479 302 7501 271 7510 258 7\ 521 245 7532 235 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7534 238 7539 228 7529 233 "]; "UV get_method (105)" -> "UV basename (6)" [style=dotted, pos="e,6189,390 5169,458 5216,452 5281,444 5339,441 5543,427 5594,446 5797,433 5934,423 6092,403 6179,391", _draw_="S 6 -dotted c 5 -black B 10 5169 458 5216 452 5281 444 5339 441 5543 427 5594 446 5797 433 5934 423 6092 403 6179 391 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6179 394 6189 390 6179 388 "]; "UV get_method (105)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2759,395 5039,463 4920,457 4666,445 4451,441 4366,439 2998,444 2913,433 2863,426 2807,410 2769,398", _draw_="S 6 -dotted c 5 -black B 10 5039 463 4920 457 4666 445 4451 441 4366 439 2998 444 2913 433 2863 426 2807 410 2769 398 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2770 395 2759 395 2768 401 "]; "UV get_method (105)" -> "UV error (32)" [style=dotted, pos="e,3881,389 5039,464 4920,459 4666,448 4451,441 4328,436 4297,444 4173,433 4071,424 3953,402 3891,391", _draw_="S 6 -dotted c 5 -black B 10 5039 464 4920 459 4666 448 4451 441 4328 436 4297 444 4173 433 4071 424 3953 402 3891 391 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3891 388 3881 389 3890 394 "]; "UV get_method (105)" -> "UV fprintf (33)" [style=dotted, pos="e,5618,312 5165,457 5200,451 5246,444 5286,441 5297,440 5648,440 5655,433 5679,408 5669,387 5655,356 5649,341 5638,328 5626,318", _draw_="S 6 -dotted c 5 -black B 13 5165 457 5200 451 5246 444 5286 441 5297 440 5648 440 5655 433 5679 408 5669 387 5655 356 5649 341 5\ 638 328 5626 318 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5628 315 5618 312 5624 321 "]; "UV file_read (8)" -> "UV updcrc (2)" [style=dotted, pos="e,1402,299 4487,367 4476,363 4463,358 4451,356 4399,345 2568,349 2514,348 2089,337 1576,309 1412,300", _draw_="S 6 -dotted c 5 -black B 10 4487 367 4476 363 4463 358 4451 356 4399 345 2568 349 2514 348 2089 337 1576 309 1412 300 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1412 297 1402 299 1412 303 "]; "UV file_read (8)" -> "UV read (9)" [style=dotted, pos="e,2892,298 4486,367 4476,363 4463,358 4451,356 4419,349 4187,349 4154,348 3663,331 3065,306 2902,298", _draw_="S 6 -dotted c 5 -black B 10 4486 367 4476 363 4463 358 4451 356 4419 349 4187 349 4154 348 3663 331 3065 306 2902 298 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2902 295 2892 298 2902 302 "]; "UV get_istat (106)" -> "UV __errno_location (11)" [style=dotted, pos="e,5241,309 7154,456 7131,450 7101,444 7074,441 6971,429 6241,445 6137,433 5984,415 5951,375 5797,356 5685,341 5656,357 5543,348 \ 5443,339 5326,323 5251,311", _draw_="S 6 -dotted c 5 -black B 16 7154 456 7131 450 7101 444 7074 441 6971 429 6241 445 6137 433 5984 415 5951 375 5797 356 5685 341 5\ 656 357 5543 348 5443 339 5326 323 5251 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5251 308 5241 309 5250 314 "]; "UV get_istat (106)" -> "UV strlen (25)" [style=dotted, pos="e,6742,131 7225,452 7235,448 7247,443 7258,441 7303,431 7623,436 7668,433 7799,422 8166,447 8251,348 8274,322 8275,295 8251,271 \ 8238,257 7918,268 7899,263 7841,244 7844,204 7785,186 7765,179 7416,179 7394,178 7153,166 6864,142 6752,132", _draw_="S 6 -dotted c 5 -black B 25 7225 452 7235 448 7247 443 7258 441 7303 431 7623 436 7668 433 7799 422 8166 447 8251 348 8274 322 8\ 275 295 8251 271 8238 257 7918 268 7899 263 7841 244 7844 204 7785 186 7765 179 7416 179 7394 178 7153 166 6864 142 6752 132 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6752 129 6742 131 6752 135 "]; "UV get_istat (106)" -> "UV strcpy (27)" [style=dotted, pos="e,7486,132 7225,452 7235,448 7247,443 7258,441 7273,438 8309,443 8319,433 8370,381 8365,326 8319,271 8304,252 7918,189 7894,186 \ 7865,181 7857,181 7827,178 7708,163 7569,144 7496,133", _draw_="S 6 -dotted c 5 -black B 19 7225 452 7235 448 7247 443 7258 441 7273 438 8309 443 8319 433 8370 381 8365 326 8319 271 8304 252 7\ 918 189 7894 186 7865 181 7857 181 7827 178 7708 163 7569 144 7496 133 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7496 130 7486 132 7496 136 "]; "UV get_istat (106)" -> "UV perror (36)" [style=dotted, pos="e,8167,314 7225,452 7235,448 7247,443 7258,441 7333,425 7524,441 7599,433 7772,413 7811,378 7983,356 8015,351 8096,360 8125,348 \ 8138,342 8151,331 8160,321", _draw_="S 6 -dotted c 5 -black B 16 7225 452 7235 448 7247 443 7258 441 7333 425 7524 441 7599 433 7772 413 7811 378 7983 356 8015 351 8\ 096 360 8125 348 8138 342 8151 331 8160 321 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8162 324 8167 314 8157 319 "]; "UV get_istat (106)" -> "UV strcmp (92)" [style=dotted, pos="e,8294,131 7225,452 7235,447 7247,443 7258,441 7291,434 8424,445 8454,433 8577,381 8711,287 8624,186 8604,162 8402,141 8304,132", _draw_="S 6 -dotted c 5 -black B 13 7225 452 7235 447 7247 443 7258 441 7291 434 8424 445 8454 433 8577 381 8711 287 8624 186 8604 162 8\ 402 141 8304 132 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8304 129 8294 131 8304 135 "]; "UV make_ofname (107)" -> "UV strlwr (19)" [style=dotted, pos="e,7915,135 7421,467 7673,466 8454,461 8499,433 8536,410 8532,388 8546,348 8571,280 8614,237 8563,186 8556,178 8206,178 8195,178 \ 8099,169 7987,148 7925,137", _draw_="S 6 -dotted c 5 -black B 16 7421 467 7673 466 8454 461 8499 433 8536 410 8532 388 8546 348 8571 280 8614 237 8563 186 8556 178 8\ 206 178 8195 178 8099 169 7987 148 7925 137 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7925 134 7915 135 7924 140 "]; "UV make_ofname (107)" -> "UV strcpy (27)" [style=dotted, pos="e,7485,134 7421,467 7666,466 8411,460 8454,433 8526,387 8522,345 8541,263 8550,229 8566,210 8541,186 8535,178 7837,178 7827,178 \ 7708,168 7568,147 7495,136", _draw_="S 6 -dotted c 5 -black B 16 7421 467 7666 466 8411 460 8454 433 8526 387 8522 345 8541 263 8550 229 8566 210 8541 186 8535 178 7\ 837 178 7827 178 7708 168 7568 147 7495 136 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7495 133 7485 134 7494 139 "]; "UV make_ofname (107)" -> "UV fprintf (33)" [style=dotted, pos="e,5635,303 7303,452 7289,447 7273,443 7258,441 7244,438 6184,441 6171,433 6141,412 6171,377 6141,356 6127,345 5995,349 5976,348 \ 5857,337 5717,316 5645,305", _draw_="S 6 -dotted c 5 -black B 16 7303 452 7289 447 7273 443 7258 441 7244 438 6184 441 6171 433 6141 412 6171 377 6141 356 6127 345 5\ 995 349 5976 348 5857 337 5717 316 5645 305 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5645 302 5635 303 5644 308 "]; "UV make_ofname (107)" -> "UV strcmp (92)" [style=dotted, pos="e,8295,128 7421,466 7681,462 8511,447 8534,433 8630,372 8663,272 8590,186 8554,143 8391,132 8305,128", _draw_="S 6 -dotted c 5 -black B 10 7421 466 7681 462 8511 447 8534 433 8630 372 8663 272 8590 186 8554 143 8391 132 8305 128 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8305 125 8295 128 8305 132 "]; "UV copy (10)" -> "UV read (9)" [style=dotted, pos="e,2856,315 3029,453 3021,448 3012,443 3003,441 2991,437 2893,441 2883,433 2853,406 2852,356 2855,325", _draw_="S 6 -dotted c 5 -black B 10 3029 453 3021 448 3012 443 3003 441 2991 437 2893 441 2883 433 2853 406 2852 356 2855 325 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2858 325 2856 315 2852 325 "]; "UV copy (10)" -> "UV __errno_location (11)" [style=dotted, pos="e,5104,309 3029,453 3021,448 3012,443 3003,441 2984,435 2927,447 2913,433 2890,407 2889,380 2913,356 2923,346 4775,348 4787,348 \ 4894,340 5016,323 5094,311", _draw_="S 6 -dotted c 5 -black B 16 3029 453 3021 448 3012 443 3003 441 2984 435 2927 447 2913 433 2890 407 2889 380 2913 356 2923 346 4\ 775 348 4787 348 4894 340 5016 323 5094 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5095 314 5104 309 5094 308 "]; "UV copy (10)" -> "UV write_buf (12)" [style=dotted, pos="e,2634,306 3029,453 3021,448 3012,443 3003,441 2971,431 2881,450 2852,433 2818,412 2838,380 2805,356 2780,337 2701,318 2644,308", _draw_="S 6 -dotted c 5 -black B 13 3029 453 3021 448 3012 443 3003 441 2971 431 2881 450 2852 433 2818 412 2838 380 2805 356 2780 337 2\ 701 318 2644 308 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2644 305 2634 306 2643 311 "]; "UV copy (10)" -> "UV read_error (13)" [style=dotted, pos="e,3000,399 3037,450 3028,438 3016,421 3006,407", _draw_="S 6 -dotted c 5 -black B 4 3037 450 3028 438 3016 421 3006 407 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3009 405 3000 399 3003 409 "]; "UV write_buf (12)" -> "UV write_error (18)" [style=dotted, pos="e,5306,367 2626,309 2672,322 2748,340 2814,348 2882,355 5196,345 5263,356 5274,358 5286,360 5297,364", _draw_="S 6 -dotted c 5 -black B 10 2626 309 2672 322 2748 340 2814 348 2882 355 5196 345 5263 356 5274 358 5286 360 5297 364 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5295 367 5306 367 5298 361 "]; "UV read_error (13)" -> "UV __errno_location (11)" [style=dotted, pos="e,5104,309 3028,368 3045,363 3065,358 3083,356 3177,343 4693,354 4787,348 4894,340 5016,323 5094,311", _draw_="S 6 -dotted c 5 -black B 10 3028 368 3045 363 3065 358 3083 356 3177 343 4693 354 4787 348 4894 340 5016 323 5094 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5095 314 5104 309 5094 308 "]; "UV read_error (13)" -> "UV fprintf (33)" [style=dotted, pos="e,5560,305 3028,368 3045,363 3065,358 3083,356 3205,339 5172,358 5294,348 5386,339 5491,319 5550,307", _draw_="S 6 -dotted c 5 -black B 10 3028 368 3045 363 3065 358 3083 356 3205 339 5172 358 5294 348 5386 339 5491 319 5550 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5551 310 5560 305 5550 304 "]; "UV read_error (13)" -> "UV abort_gzip (34)" [style=dotted, pos="e,4166,298 3028,369 3045,364 3065,359 3083,356 3292,323 3937,304 4156,298", _draw_="S 6 -dotted c 5 -black B 7 3028 369 3045 364 3065 359 3083 356 3292 323 3937 304 4156 298 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4156 302 4166 298 4156 295 "]; "UV read_error (13)" -> "UV perror (36)" [style=dotted, pos="e,8151,309 3034,370 3057,364 3087,358 3113,356 3181,348 7952,358 8019,348 8062,341 8109,325 8141,313", _draw_="S 6 -dotted c 5 -black B 10 3034 370 3057 364 3087 358 3113 356 3181 348 7952 358 8019 348 8062 341 8109 325 8141 313 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8143 316 8151 309 8140 309 "]; "UV create_outfile (110)" -> "UV fprintf (33)" [style=dotted, pos="e,5635,302 6583,465 6441,461 6147,450 6103,433 6056,413 6064,377 6017,356 6009,352 5756,318 5645,303", _draw_="S 6 -dotted c 5 -black B 10 6583 465 6441 461 6147 450 6103 433 6056 413 6064 377 6017 356 6009 352 5756 318 5645 303 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5645 300 5635 302 5645 306 "]; "UV create_outfile (110)" -> "UV perror (36)" [style=dotted, pos="e,8167,314 6729,459 6786,453 6869,444 6942,441 6967,439 7367,442 7390,433 7438,414 7427,374 7474,356 7508,342 8092,361 8125,348 \ 8139,342 8151,332 8160,322", _draw_="S 6 -dotted c 5 -black B 16 6729 459 6786 453 6869 444 6942 441 6967 439 7367 442 7390 433 7438 414 7427 374 7474 356 7508 342 8\ 092 361 8125 348 8139 342 8151 332 8160 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8163 324 8167 314 8158 319 "]; "UV create_outfile (110)" -> "UV fstat (104)" [style=dotted, pos="e,5755,396 6584,464 6381,456 5842,434 5837,433 5811,426 5784,412 5764,401", _draw_="S 6 -dotted c 5 -black B 7 6584 464 6381 456 5842 434 5837 433 5811 426 5784 412 5764 401 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5765 398 5755 396 5762 404 "]; "UV create_outfile (110)" -> "UV close (109)" [style=dotted, pos="e,8348,229 6729,459 6786,453 6869,444 6942,441 7107,432 7518,445 7681,433 7816,422 8172,425 8281,348 8318,322 8337,271 8345,239", _draw_="S 6 -dotted c 5 -black B 13 6729 459 6786 453 6869 444 6942 441 7107 432 7518 445 7681 433 7816 422 8172 425 8281 348 8318 322 8\ 337 271 8345 239 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8348 240 8348 229 8342 238 "]; "UV create_outfile (110)" -> "UV unlink (111)" [style=dotted, pos="e,8457,229 6729,459 6786,453 6869,444 6942,441 7057,435 7857,446 7970,433 8130,413 8180,422 8322,348 8376,320 8425,268 8450,237", _draw_="S 6 -dotted c 5 -black B 13 6729 459 6786 453 6869 444 6942 441 7057 435 7857 446 7970 433 8130 413 8180 422 8322 348 8376 320 8\ 425 268 8450 237 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8453 239 8457 229 8448 234 "]; "UV copy_stat (112)" -> "UV fprintf (33)" [style=dotted, pos="e,5635,303 6955,460 6902,454 6819,445 6746,441 6730,440 6157,440 6141,433 6102,413 6118,376 6079,356 6059,345 5999,350 5976,348 \ 5857,336 5718,315 5645,304", _draw_="S 6 -dotted c 5 -black B 16 6955 460 6902 454 6819 445 6746 441 6730 440 6157 440 6141 433 6102 413 6118 376 6079 356 6059 345 5\ 999 350 5976 348 5857 336 5718 315 5645 304 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5645 301 5635 303 5645 307 "]; "UV copy_stat (112)" -> "UV perror (36)" [style=dotted, pos="e,8167,314 7053,456 7077,450 7107,444 7134,441 7172,436 7438,443 7474,433 7537,414 7537,374 7599,356 7628,347 8098,358 8125,348 \ 8139,342 8151,332 8160,322", _draw_="S 6 -dotted c 5 -black B 16 7053 456 7077 450 7107 444 7134 441 7172 436 7438 443 7474 433 7537 414 7537 374 7599 356 7628 347 8\ 098 358 8125 348 8139 342 8151 332 8160 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8163 324 8167 314 8158 319 "]; "UV copy_stat (112)" -> "UV unlink (111)" [style=dotted, pos="e,8474,230 7052,455 7076,450 7107,443 7134,441 7152,439 8420,444 8433,433 8489,385 8482,287 8476,240", _draw_="S 6 -dotted c 5 -black B 10 7052 455 7076 450 7107 443 7134 441 7152 439 8420 444 8433 433 8489 385 8482 287 8476 240 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8479 239 8474 230 8473 240 "]; "UV fill_inbuf (15)" -> "UV read (9)" [style=dotted, pos="e,2837,311 2748,366 2770,352 2804,331 2828,316", _draw_="S 6 -dotted c 5 -black B 4 2748 366 2770 352 2804 331 2828 316 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2830 319 2837 311 2827 313 "]; "UV fill_inbuf (15)" -> "UV __errno_location (11)" [style=dotted, pos="e,5104,309 2767,373 2799,366 2844,359 2883,356 3094,338 4576,362 4787,348 4894,340 5016,323 5094,311", _draw_="S 6 -dotted c 5 -black B 10 2767 373 2799 366 2844 359 2883 356 3094 338 4576 362 4787 348 4894 340 5016 323 5094 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5095 314 5104 309 5094 308 "]; "UV fill_inbuf (15)" -> "UV read_error (13)" [style=dotted, pos="e,2925,382 2775,382 2822,382 2868,382 2915,382", _draw_="S 6 -dotted c 5 -black B 4 2775 382 2822 382 2868 382 2915 382 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2915 386 2925 382 2915 379 "]; "UV check_ofname (113)" -> "UV __errno_location (11)" [style=dotted, pos="e,5240,309 6659,371 6623,365 6576,359 6534,356 6315,339 5763,363 5543,348 5442,340 5325,323 5250,311", _draw_="S 6 -dotted c 5 -black B 10 6659 371 6623 365 6576 359 6534 356 6315 339 5763 363 5543 348 5442 340 5325 323 5250 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5250 308 5240 309 5249 314 "]; "UV check_ofname (113)" -> "UV isupper (20)" [style=dotted, pos="e,7964,59 6770,368 6788,363 6810,358 6830,356 6847,353 8008,359 8019,348 8058,308 7995,136 7968,69", _draw_="S 6 -dotted c 5 -black B 10 6770 368 6788 363 6810 358 6830 356 6847 353 8008 359 8019 348 8058 308 7995 136 7968 69 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7971 67 7964 59 7964 70 "]; "UV check_ofname (113)" -> "UV strcpy (27)" [style=dotted, pos="e,7486,132 6771,368 6789,363 6810,358 6830,356 6845,354 7851,358 7861,348 7912,296 7909,240 7861,186 7855,179 7605,147 7496,133", _draw_="S 6 -dotted c 5 -black B 13 6771 368 6789 363 6810 358 6830 356 6845 354 7851 358 7861 348 7912 296 7909 240 7861 186 7855 179 7\ 605 147 7496 133 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7496 130 7486 132 7496 136 "]; "UV check_ofname (113)" -> "UV fprintf (33)" [style=dotted, pos="e,5634,304 6659,371 6623,365 6576,359 6534,356 6287,337 6224,366 5976,348 5857,338 5717,317 5644,306", _draw_="S 6 -dotted c 5 -black B 10 6659 371 6623 365 6576 359 6534 356 6287 337 6224 366 5976 348 5857 338 5717 317 5644 306 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5644 303 5634 304 5643 309 "]; "UV check_ofname (113)" -> "UV perror (36)" [style=dotted, pos="e,8167,314 6770,368 6788,363 6810,358 6830,356 6866,351 8092,361 8125,348 8139,342 8151,332 8160,322", _draw_="S 6 -dotted c 5 -black B 10 6770 368 6788 363 6810 358 6830 356 6866 351 8092 361 8125 348 8139 342 8151 332 8160 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8163 324 8167 314 8158 319 "]; "UV check_ofname (113)" -> "UV strcmp (92)" [style=dotted, pos="e,8229,142 6770,368 6788,363 6810,358 6830,356 6847,353 8035,356 8049,348 8082,327 8064,301 8087,271 8127,220 8185,174 8220,148", _draw_="S 6 -dotted c 5 -black B 13 6770 368 6788 363 6810 358 6830 356 6847 353 8035 356 8049 348 8082 327 8064 301 8087 271 8127 220 8\ 185 174 8220 148 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8223 150 8229 142 8219 145 "]; "UV check_ofname (113)" -> "UV fileno (102)" [style=dotted, pos="e,7939,314 6771,368 6789,363 6810,358 6830,356 6860,352 7872,359 7899,348 7912,342 7924,332 7933,322", _draw_="S 6 -dotted c 5 -black B 10 6771 368 6789 363 6810 358 6830 356 6860 352 7872 359 7899 348 7912 342 7924 332 7933 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7936 324 7939 314 7930 320 "]; "UV check_ofname (113)" -> "UV isatty (103)" [style=dotted, pos="e,6064,303 6657,372 6621,366 6575,360 6534,356 6477,350 6463,353 6405,348 6286,336 6146,315 6074,304", _draw_="S 6 -dotted c 5 -black B 10 6657 372 6621 366 6575 360 6534 356 6477 350 6463 353 6405 348 6286 336 6146 315 6074 304 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6074 301 6064 303 6074 307 "]; "UV check_ofname (113)" -> "UV unlink (111)" [style=dotted, pos="e,8458,229 6770,368 6788,363 6810,358 6830,356 6848,353 8073,357 8087,348 8120,327 8095,291 8127,271 8155,253 8388,275 8417,263 \ 8430,257 8443,247 8452,237", _draw_="S 6 -dotted c 5 -black B 16 6770 368 6788 363 6810 358 6830 356 6848 353 8073 357 8087 348 8120 327 8095 291 8127 271 8155 253 8\ 388 275 8417 263 8430 257 8443 247 8452 237 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8455 239 8458 229 8449 235 "]; "UV flush_window (16)" -> "UV updcrc (2)" [style=dotted, pos="e,1370,314 1401,364 1394,352 1384,336 1375,323", _draw_="S 6 -dotted c 5 -black B 4 1401 364 1394 352 1384 336 1375 323 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1378 321 1370 314 1372 324 "]; "UV flush_window (16)" -> "UV write_buf (12)" [style=dotted, pos="e,2526,299 1461,368 1480,364 1501,359 1521,356 1715,327 2313,306 2516,299", _draw_="S 6 -dotted c 5 -black B 7 1461 368 1480 364 1501 359 1521 356 1715 327 2313 306 2516 299 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2516 303 2526 299 2516 296 "]; "UV name_too_long (114)" -> "UV strlen (25)" [style=dotted, pos="e,6686,143 6540,279 6573,248 6642,184 6679,150", _draw_="S 6 -dotted c 5 -black B 4 6540 279 6573 248 6642 184 6679 150 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6681 153 6686 143 6676 148 "]; "UV shorten_name (115)" -> "UV strrchr (21)" [style=dotted, pos="e,7544,229 6747,282 6761,277 6777,273 6792,271 6831,265 7463,277 7499,263 7513,257 7527,247 7537,236", _draw_="S 6 -dotted c 5 -black B 10 6747 282 6761 277 6777 273 6792 271 6831 265 7463 277 7499 263 7513 257 7527 247 7537 236 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7539 239 7544 229 7534 234 "]; "UV shorten_name (115)" -> "UV strlen (25)" [style=dotted, pos="e,6703,145 6703,279 6703,249 6703,190 6703,155", _draw_="S 6 -dotted c 5 -black B 4 6703 279 6703 249 6703 190 6703 155 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6707 155 6703 145 6700 155 "]; "UV shorten_name (115)" -> "UV strcpy (27)" [style=dotted, pos="e,7406,129 6714,279 6731,253 6766,206 6809,186 6862,161 7254,137 7396,130", _draw_="S 6 -dotted c 5 -black B 7 6714 279 6731 253 6766 206 6809 186 6862 161 7254 137 7396 130 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7396 133 7406 129 7396 127 "]; "UV shorten_name (115)" -> "UV strcspn (29)" [style=dotted, pos="e,4561,213 6660,282 6645,277 6629,273 6614,271 6588,266 4904,222 4571,213", _draw_="S 6 -dotted c 5 -black B 7 6660 282 6645 277 6629 273 6614 271 6588 266 4904 222 4571 213 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4571 210 4561 213 4571 217 "]; "UV shorten_name (115)" -> "UV error (32)" [style=dotted, pos="e,3882,378 6681,314 6664,326 6639,341 6614,348 6582,356 4207,354 4173,356 4073,360 3955,371 3892,377", _draw_="S 6 -dotted c 5 -black B 10 6681 314 6664 326 6639 341 6614 348 6582 356 4207 354 4173 356 4073 360 3955 371 3892 377 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3892 374 3882 378 3892 380 "]; "UV shorten_name (115)" -> "UV strcmp (92)" [style=dotted, pos="e,8212,135 6747,282 6761,277 6777,273 6792,271 6827,265 7396,277 7428,263 7472,244 7458,205 7501,186 7524,175 7925,180 7949,178 \ 8040,169 8143,149 8202,137", _draw_="S 6 -dotted c 5 -black B 16 6747 282 6761 277 6777 273 6792 271 6827 265 7396 277 7428 263 7472 244 7458 205 7501 186 7524 175 7\ 925 180 7949 178 8040 169 8143 149 8202 137 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8203 140 8212 135 8202 134 "]; "UV write_error (18)" -> "UV fprintf (33)" [style=dotted, pos="e,5563,308 5383,368 5430,352 5506,327 5553,311", _draw_="S 6 -dotted c 5 -black B 4 5383 368 5430 352 5506 327 5553 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5554 314 5563 308 5552 308 "]; "UV write_error (18)" -> "UV abort_gzip (34)" [style=dotted, pos="e,4283,306 5305,367 5292,363 5277,358 5263,356 5191,343 4673,353 4599,348 4491,339 4366,320 4293,308", _draw_="S 6 -dotted c 5 -black B 10 5305 367 5292 363 5277 358 5263 356 5191 343 4673 353 4599 348 4491 339 4366 320 4293 308 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4293 305 4283 306 4292 311 "]; "UV write_error (18)" -> "UV perror (36)" [style=dotted, pos="e,8151,309 5383,368 5400,363 5420,358 5439,356 5582,337 7878,370 8019,348 8062,341 8109,325 8141,313", _draw_="S 6 -dotted c 5 -black B 10 5383 368 5400 363 5420 358 5439 356 5582 337 7878 370 8019 348 8062 341 8109 325 8141 313 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8143 316 8151 309 8140 309 "]; "UV strlwr (19)" -> "UV isupper (20)" [style=dotted, pos="e,7942,59 7894,111 7906,98 7922,81 7935,66", _draw_="S 6 -dotted c 5 -black B 4 7894 111 7906 98 7922 81 7935 66 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7937 69 7942 59 7932 64 "]; "UV do_stat (116)" -> "UV __errno_location (11)" [style=dotted, pos="e,5239,309 6854,368 6841,363 6825,358 6810,356 6741,344 5614,353 5543,348 5441,340 5324,323 5249,311", _draw_="S 6 -dotted c 5 -black B 10 6854 368 6841 363 6825 358 6810 356 6741 344 5614 353 5543 348 5441 340 5324 323 5249 311 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5249 308 5239 309 5248 314 "]; "UV make_simple_name (22)" -> "UV strrchr (21)" [style=dotted, pos="e,7569,229 7606,279 7597,267 7585,250 7575,237", _draw_="S 6 -dotted c 5 -black B 4 7606 279 7597 267 7585 250 7575 237 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7578 235 7569 229 7572 239 "]; "UV get_suffix (119)" -> "UV strlwr (19)" [style=dotted, pos="e,7841,132 7406,200 7426,195 7449,190 7471,186 7506,179 7730,147 7831,133", _draw_="S 6 -dotted c 5 -black B 7 7406 200 7426 195 7449 190 7471 186 7506 179 7730 147 7831 133 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7831 136 7841 132 7831 130 "]; "UV get_suffix (119)" -> "UV strlen (25)" [style=dotted, pos="e,6741,132 7307,205 7182,189 6870,148 6751,133", _draw_="S 6 -dotted c 5 -black B 4 7307 205 7182 189 6870 148 6751 133 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6751 130 6741 132 6751 136 "]; "UV get_suffix (119)" -> "UV strcpy (27)" [style=dotted, pos="e,7431,143 7378,195 7392,182 7410,164 7424,150", _draw_="S 6 -dotted c 5 -black B 4 7378 195 7392 182 7410 164 7424 150 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7426 153 7431 143 7421 148 "]; "UV get_suffix (119)" -> "UV strcmp (92)" [style=dotted, pos="e,8212,135 7404,200 7424,194 7449,189 7471,186 7577,172 7844,187 7949,178 8040,169 8143,149 8202,137", _draw_="S 6 -dotted c 5 -black B 10 7404 200 7424 194 7449 189 7471 186 7577 172 7844 187 7949 178 8040 169 8143 149 8202 137 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8203 140 8212 135 8202 134 "]; "UV add_envopt (23)" -> "UV strlen (25)" [style=dotted, pos="e,6664,127 3839,544 3875,538 3915,529 3928,518 4050,414 3934,274 4067,186 4123,148 6298,130 6654,127", _draw_="S 6 -dotted c 5 -black B 10 3839 544 3875 538 3915 529 3928 518 4050 414 3934 274 4067 186 4123 148 6298 130 6654 127 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6654 131 6664 127 6654 124 "]; "UV add_envopt (23)" -> "UV strcpy (27)" [style=dotted, pos="e,7407,131 3842,546 3889,540 3947,531 3967,518 4003,495 3997,474 4021,441 4079,363 4075,324 4154,271 4271,193 4319,205 4457,186 \ 4521,177 6708,180 6772,178 7007,168 7285,143 7397,132", _draw_="S 6 -dotted c 5 -black B 19 3842 546 3889 540 3947 531 3967 518 4003 495 3997 474 4021 441 4079 363 4075 324 4154 271 4271 193 4\ 319 205 4457 186 4521 177 6708 180 6772 178 7007 168 7285 143 7397 132 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7397 135 7407 131 7397 129 "]; "UV add_envopt (23)" -> "UV strcspn (29)" [style=dotted, pos="e,4498,229 3845,548 3906,543 3991,533 4021,518 4109,472 4084,397 4173,356 4204,342 4291,358 4322,348 4391,324 4457,268 4490,236", _draw_="S 6 -dotted c 5 -black B 13 3845 548 3906 543 3991 533 4021 518 4109 472 4084 397 4173 356 4204 342 4291 358 4322 348 4391 324 4\ 457 268 4490 236 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4493 238 4498 229 4488 233 "]; "UV add_envopt (23)" -> "UV free (30)" [style=dotted, pos="e,3762,144 3833,541 3859,535 3886,527 3895,518 3945,464 3942,422 3913,356 3890,301 3851,311 3817,263 3794,228 3775,182 3765,154", _draw_="S 6 -dotted c 5 -black B 13 3833 541 3859 535 3886 527 3895 518 3945 464 3942 422 3913 356 3890 301 3851 311 3817 263 3794 228 3\ 775 182 3765 154 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3768 153 3762 144 3762 155 "]; "UV add_envopt (23)" -> "UV error (32)" [style=dotted, pos="e,3858,399 3828,540 3849,534 3869,526 3874,518 3897,485 3879,437 3863,408", _draw_="S 6 -dotted c 5 -black B 7 3828 540 3849 534 3869 526 3874 518 3897 485 3879 437 3863 408 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3866 406 3858 399 3860 409 "]; "UV xmalloc (26)" -> "UV error (32)" [style=dotted, pos="e,3817,392 3655,453 3664,449 3673,445 3682,441 3725,424 3774,407 3807,395", _draw_="S 6 -dotted c 5 -black B 7 3655 453 3664 449 3673 445 3682 441 3725 424 3774 407 3807 395 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3808 398 3817 392 3806 392 "]; "UV xmalloc (26)" -> "UV malloc (39)" [style=dotted, pos="e,2604,398 3600,452 3591,448 3580,443 3570,441 3521,429 2708,448 2659,433 2642,427 2625,415 2612,405", _draw_="S 6 -dotted c 5 -black B 10 3600 452 3591 448 3580 443 3570 441 3521 429 2708 448 2659 433 2642 427 2625 415 2612 405 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2614 402 2604 398 2609 407 "]; "UV reset_times (129)" -> "UV fprintf (33)" [style=dotted, pos="e,5634,304 7158,368 7142,363 7122,358 7104,356 6980,338 6102,356 5976,348 5857,339 5716,317 5644,306", _draw_="S 6 -dotted c 5 -black B 10 7158 368 7142 363 7122 358 7104 356 6980 338 6102 356 5976 348 5857 339 5716 317 5644 306 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5644 303 5634 304 5643 309 "]; "UV reset_times (129)" -> "UV perror (36)" [style=dotted, pos="e,8167,314 7241,368 7258,363 7277,358 7294,356 7317,352 8104,356 8125,348 8139,342 8151,332 8160,322", _draw_="S 6 -dotted c 5 -black B 10 7241 368 7258 363 7277 358 7294 356 7317 352 8104 356 8125 348 8139 342 8151 332 8160 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8163 324 8167 314 8158 319 "]; "UV error (32)" -> "UV fprintf (33)" [style=dotted, pos="e,5560,305 3882,378 3942,372 4067,360 4173,356 4298,350 5170,358 5294,348 5386,339 5491,319 5550,307", _draw_="S 6 -dotted c 5 -black B 10 3882 378 3942 372 4067 360 4173 356 4298 350 5170 358 5294 348 5386 339 5491 319 5550 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5551 310 5560 305 5550 304 "]; "UV error (32)" -> "UV abort_gzip (34)" [style=dotted, pos="e,4180,308 3880,375 3944,361 4089,329 4170,310", _draw_="S 6 -dotted c 5 -black B 4 3880 375 3944 361 4089 329 4170 310 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4171 313 4180 308 4170 307 "]; "UV abort_gzip (34)" -> "UV do_exit (98)" [style=dotted, pos="e,3917,219 4191,283 4179,279 4165,274 4152,271 4075,249 3983,231 3927,221", _draw_="S 6 -dotted c 5 -black B 7 4191 283 4179 279 4165 274 4152 271 4075 249 3983 231 3927 221 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3927 218 3917 219 3926 224 "]; "UV abort_gzip (34)" -> "UV close (109)" [style=dotted, pos="e,8318,215 4289,291 4362,285 4490,274 4599,271 4936,258 7295,275 7631,263 7888,253 8195,227 8308,216", _draw_="S 6 -dotted c 5 -black B 10 4289 291 4362 285 4490 274 4599 271 4936 258 7295 275 7631 263 7888 253 8195 227 8308 216 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8308 219 8318 215 8308 213 "]; "UV abort_gzip (34)" -> "UV unlink (111)" [style=dotted, pos="e,8458,229 4289,291 4362,285 4490,274 4599,271 4626,270 8393,272 8417,263 8430,257 8443,247 8452,237", _draw_="S 6 -dotted c 5 -black B 10 4289 291 4362 285 4490 274 4599 271 4626 270 8393 272 8417 263 8430 257 8443 247 8452 237 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8455 239 8458 229 8449 235 "]; "UV warn (35)" -> "UV fprintf (33)" [style=dotted, pos="e,5576,313 5507,367 5524,354 5549,334 5568,319", _draw_="S 6 -dotted c 5 -black B 4 5507 367 5524 354 5549 334 5568 319 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5570 322 5576 313 5566 316 "]; "UV fill_window (133)" -> "UV memcpy (48)" [style=dotted, pos="e,2155,399 1258,701 1267,697 1276,693 1283,688 1411,604 1382,501 1521,441 1551,428 2077,444 2107,433 2122,427 2137,416 2148,406", _draw_="S 6 -dotted c 5 -black B 13 1258 701 1267 697 1276 693 1283 688 1411 604 1382 501 1521 441 1551 428 2077 444 2107 433 2122 427 2\ 137 416 2148 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2150 409 2155 399 2145 404 "]; "UV fill_window (133)" -> "UV (86)" [style=dotted, pos="e,2870,481 1277,709 1339,705 1437,698 1521,696 1587,693 2043,697 2107,688 2400,645 2738,529 2860,484", _draw_="S 6 -dotted c 5 -black B 10 1277 709 1339 705 1437 698 1521 696 1587 693 2043 697 2107 688 2400 645 2738 529 2860 484 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2861 487 2870 481 2859 481 "]; "UV display_ratio (37)" -> "UV fprintf (33)" [style=dotted, pos="e,5559,305 4737,370 4764,365 4797,359 4827,356 5034,335 5088,367 5294,348 5386,340 5490,319 5549,307", _draw_="S 6 -dotted c 5 -black B 10 4737 370 4764 365 4797 359 4827 356 5034 335 5088 367 5294 348 5386 340 5490 319 5549 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5550 310 5559 305 5549 304 "]; "UV check_zipfile (40)" -> "UV fprintf (33)" [style=dotted, pos="e,5557,302 5223,368 5236,363 5250,359 5263,356 5364,331 5481,313 5547,303", _draw_="S 6 -dotted c 5 -black B 7 5223 368 5236 363 5250 359 5263 356 5364 331 5481 313 5547 303 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5547 306 5557 302 5547 300 "]; "UV unzip (41)" -> "UV updcrc (2)" [style=dotted, pos="e,1345,314 1658,782 1608,776 1518,762 1447,732 1378,702 1307,712 1307,637 1307,637 1307,637 1307,552 1307,464 1294,438 1321,356 \ 1325,344 1332,332 1339,322", _draw_="S 6 -dotted c 5 -black B 16 1658 782 1608 776 1518 762 1447 732 1378 702 1307 712 1307 637 1307 637 1307 637 1307 552 1307 464 1\ 294 438 1321 356 1325 344 1332 332 1339 322 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1342 324 1345 314 1336 320 "]; "UV unzip (41)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2706,399 1731,780 1782,770 1877,752 1957,732 2238,659 2352,705 2572,518 2603,491 2587,464 2620,441 2635,430 2643,440 2659,433 \ 2673,426 2687,415 2698,406", _draw_="S 6 -dotted c 5 -black B 16 1731 780 1782 770 1877 752 1957 732 2238 659 2352 705 2572 518 2603 491 2587 464 2620 441 2635 430 2\ 643 440 2659 433 2673 426 2687 415 2698 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2701 408 2706 399 2696 403 "]; "UV unzip (41)" -> "UV flush_window (16)" [style=dotted, pos="e,1408,400 1662,777 1583,756 1391,697 1391,637 1391,637 1391,637 1391,552 1391,501 1400,443 1406,410", _draw_="S 6 -dotted c 5 -black B 10 1662 777 1583 756 1391 697 1391 637 1391 637 1391 637 1391 552 1391 501 1400 443 1406 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1409 410 1408 400 1403 409 "]; "UV unzip (41)" -> "UV error (32)" [style=dotted, pos="e,3812,386 1733,785 1899,782 2555,768 2639,732 2696,707 2739,698 2739,637 2739,637 2739,637 2739,552 2739,501 2724,473 2763,441 \ 2774,432 3242,433 3255,433 3460,422 3703,398 3802,387", _draw_="S 6 -dotted c 5 -black B 19 1733 785 1899 782 2555 768 2639 732 2696 707 2739 698 2739 637 2739 637 2739 637 2739 552 2739 501 2\ 724 473 2763 441 2774 432 3242 433 3255 433 3460 422 3703 398 3802 387 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3802 390 3812 386 3802 384 "]; "UV unzip (41)" -> "UV fprintf (33)" [style=dotted, pos="e,5560,305 1731,780 1795,771 1933,750 2049,732 2266,697 2335,712 2524,603 2626,544 2623,480 2733,441 2752,434 3066,443 3081,433 \ 3112,412 3083,376 3113,356 3126,347 5279,349 5294,348 5386,339 5491,319 5550,307", _draw_="S 6 -dotted c 5 -black B 22 1731 780 1795 771 1933 750 2049 732 2266 697 2335 712 2524 603 2626 544 2623 480 2733 441 2752 434 3\ 066 443 3081 433 3112 412 3083 376 3113 356 3126 347 5279 349 5294 348 5386 339 5491 319 5550 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5551 310 5560 305 5550 304 "]; "UV inflate (42)" -> "UV flush_window (16)" [style=dotted, pos="e,1419,400 1560,697 1558,694 1556,691 1554,688 1496,589 1444,463 1423,409", _draw_="S 6 -dotted c 5 -black B 7 1560 697 1558 694 1556 691 1554 688 1496 589 1444 463 1423 409 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1426 408 1419 400 1420 411 "]; "UV read_tree (43)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2731,399 3126,549 3033,543 2857,531 2831,518 2786,493 2753,441 2736,408", _draw_="S 6 -dotted c 5 -black B 7 3126 549 3033 543 2857 531 2831 518 2786 493 2753 441 2736 408 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2739 406 2731 399 2733 409 "]; "UV read_tree (43)" -> "UV error (32)" [style=dotted, pos="e,3811,385 3213,537 3264,513 3368,466 3461,441 3582,408 3729,392 3801,386", _draw_="S 6 -dotted c 5 -black B 7 3213 537 3264 513 3368 466 3461 441 3582 408 3729 392 3801 386 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3801 389 3811 385 3801 383 "]; "UV unpack (45)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2760,394 3150,453 3139,448 3126,443 3113,441 3026,422 3001,446 2913,433 2863,425 2808,409 2770,397", _draw_="S 6 -dotted c 5 -black B 10 3150 453 3139 448 3126 443 3113 441 3026 422 3001 446 2913 433 2863 425 2808 409 2770 397 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2771 394 2760 394 2769 400 "]; "UV unpack (45)" -> "UV flush_window (16)" [style=dotted, pos="e,1439,399 3151,453 3140,448 3126,443 3113,441 3027,424 1608,452 1521,433 1496,427 1468,415 1448,404", _draw_="S 6 -dotted c 5 -black B 10 3151 453 3140 448 3126 443 3113 441 3027 424 1608 452 1521 433 1496 427 1468 415 1448 404 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1449 401 1439 399 1446 407 "]; "UV unpack (45)" -> "UV error (32)" [style=dotted, pos="e,3812,386 3223,461 3343,446 3680,404 3802,387", _draw_="S 6 -dotted c 5 -black B 4 3223 461 3343 446 3680 404 3802 387 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3802 390 3812 386 3802 384 "]; "UV unlzw (46)" -> "UV read (9)" [style=dotted, pos="e,2831,307 2425,455 2437,450 2449,442 2459,433 2488,405 2470,376 2503,356 2520,346 2654,350 2672,348 2725,340 2784,322 2821,310", _draw_="S 6 -dotted c 5 -black B 13 2425 455 2437 450 2449 442 2459 433 2488 405 2470 376 2503 356 2520 346 2654 350 2672 348 2725 340 2\ 784 322 2821 310 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2822 313 2831 307 2820 307 "]; "UV unlzw (46)" -> "UV write_buf (12)" [style=dotted, pos="e,2543,310 2411,451 2416,445 2421,439 2425,433 2447,401 2438,383 2465,356 2484,337 2511,323 2534,314", _draw_="S 6 -dotted c 5 -black B 10 2411 451 2416 445 2421 439 2425 433 2447 401 2438 383 2465 356 2484 337 2511 323 2534 314 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2535 317 2543 310 2532 311 "]; "UV unlzw (46)" -> "UV read_error (13)" [style=dotted, pos="e,2948,396 2435,463 2488,457 2585,447 2668,441 2729,436 2745,443 2805,433 2852,426 2902,411 2938,399", _draw_="S 6 -dotted c 5 -black B 10 2435 463 2488 457 2585 447 2668 441 2729 436 2745 443 2805 433 2852 426 2902 411 2938 399 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2939 402 2948 396 2937 396 "]; "UV unlzw (46)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2708,399 2424,454 2437,449 2453,444 2468,441 2510,432 2620,447 2659,433 2675,427 2690,416 2701,406", _draw_="S 6 -dotted c 5 -black B 10 2424 454 2437 449 2453 444 2468 441 2510 432 2620 447 2659 433 2675 427 2690 416 2701 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2703 409 2708 399 2698 404 "]; "UV unlzw (46)" -> "UV error (32)" [style=dotted, pos="e,3812,386 2435,463 2497,457 2621,445 2725,441 2961,429 3020,444 3255,433 3460,422 3703,398 3802,387", _draw_="S 6 -dotted c 5 -black B 10 2435 463 2497 457 2621 445 2725 441 2961 429 3020 444 3255 433 3460 422 3703 398 3802 387 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3802 390 3812 386 3802 384 "]; "UV unlzw (46)" -> "UV fprintf (33)" [style=dotted, pos="e,5560,305 2419,453 2427,448 2436,444 2445,441 2467,433 2477,446 2495,433 2526,410 2501,376 2533,356 2550,345 5275,349 5294,348 \ 5386,339 5491,319 5550,307", _draw_="S 6 -dotted c 5 -black B 16 2419 453 2427 448 2436 444 2445 441 2467 433 2477 446 2495 433 2526 410 2501 376 2533 356 2550 345 5\ 275 349 5294 348 5386 339 5491 319 5550 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5551 310 5560 305 5550 304 "]; "UV unlzw (46)" -> "UV memset (47)" [style=dotted, pos="e,2355,399 2385,450 2378,438 2368,421 2360,408", _draw_="S 6 -dotted c 5 -black B 4 2385 450 2378 438 2368 421 2360 408 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2363 406 2355 399 2357 409 "]; "UV unlzw (46)" -> "UV memcpy (48)" [style=dotted, pos="e,2199,396 2360,457 2338,451 2308,442 2283,433 2258,423 2230,411 2208,400", _draw_="S 6 -dotted c 5 -black B 7 2360 457 2338 451 2308 442 2283 433 2258 423 2230 411 2208 400 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2210 397 2199 396 2207 403 "]; "UV fillbuf (49)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2719,400 8677,786 8205,784 3397,761 3255,732 3010,682 2881,720 2733,518 2711,486 2713,440 2717,410", _draw_="S 6 -dotted c 5 -black B 10 8677 786 8205 784 3397 761 3255 732 3010 682 2881 720 2733 518 2711 486 2713 440 2717 410 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2720 410 2719 400 2714 409 "]; "UV make_table (52)" -> "UV error (32)" [style=dotted, pos="e,3880,389 9023,452 9011,447 8996,443 8983,441 8918,429 4240,438 4173,433 4071,424 3952,403 3890,391", _draw_="S 6 -dotted c 5 -black B 10 9023 452 9011 447 8996 443 8983 441 8918 429 4240 438 4173 433 4071 424 3952 403 3890 391 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3890 388 3880 389 3889 394 "]; "UV unlzh (60)" -> "UV write_buf (12)" [style=dotted, pos="e,2627,309 8997,783 8944,779 8845,771 8760,768 8457,754 3530,801 3300,603 3216,529 3341,428 3255,356 3246,348 2827,349 2814,348 \ 2753,341 2683,324 2637,312", _draw_="S 6 -dotted c 5 -black B 16 8997 783 8944 779 8845 771 8760 768 8457 754 3530 801 3300 603 3216 529 3341 428 3255 356 3246 348 2\ 827 349 2814 348 2753 341 2683 324 2637 312 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2638 309 2627 309 2636 315 "]; "UV lzw (78)" -> "UV fprintf (33)" [style=dotted, pos="e,5596,315 5596,364 5596,352 5596,338 5596,325", _draw_="S 6 -dotted c 5 -black B 4 5596 364 5596 352 5596 338 5596 325 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5600 325 5596 315 5593 325 "]; "UV huft_build (79)" -> "UV malloc (39)" [style=dotted, pos="e,2556,394 2093,462 2199,453 2417,435 2425,433 2468,425 2514,409 2546,398", _draw_="S 6 -dotted c 5 -black B 7 2093 462 2199 453 2417 435 2425 433 2468 425 2514 409 2546 398 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2548 401 2556 394 2545 394 "]; "UV huft_build (79)" -> "UV memset (47)" [style=dotted, pos="e,2322,398 2094,463 2138,459 2200,450 2251,433 2273,425 2295,413 2313,403", _draw_="S 6 -dotted c 5 -black B 7 2094 463 2138 459 2200 450 2251 433 2273 425 2295 413 2313 403 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2315 406 2322 398 2312 400 "]; "UV huft_free (80)" -> "UV free (30)" [style=dotted, pos="e,3727,127 1990,367 2073,329 2307,226 2514,186 2752,139 3531,129 3717,127", _draw_="S 6 -dotted c 5 -black B 7 1990 367 2073 329 2307 226 2514 186 2752 139 3531 129 3717 127 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3717 131 3727 127 3717 124 "]; "UV inflate_codes (81)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2708,399 1858,456 1890,450 1931,444 1968,441 2007,437 2623,445 2659,433 2675,427 2690,416 2701,406", _draw_="S 6 -dotted c 5 -black B 10 1858 456 1890 450 1931 444 1968 441 2007 437 2623 445 2659 433 2675 427 2690 416 2701 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2703 409 2708 399 2698 404 "]; "UV inflate_codes (81)" -> "UV flush_window (16)" [style=dotted, pos="e,1441,398 1731,461 1662,455 1560,444 1521,433 1497,426 1470,414 1450,403", _draw_="S 6 -dotted c 5 -black B 7 1731 461 1662 455 1560 444 1521 433 1497 426 1470 414 1450 403 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1451 400 1441 398 1448 406 "]; "UV inflate_codes (81)" -> "UV memcpy (48)" [style=dotted, pos="e,2155,399 1859,456 1891,451 1932,444 1968,441 1999,437 2079,444 2107,433 2122,427 2137,416 2148,406", _draw_="S 6 -dotted c 5 -black B 10 1859 456 1891 451 1932 444 1968 441 1999 437 2079 444 2107 433 2122 427 2137 416 2148 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2150 409 2155 399 2145 404 "]; "UV inflate_stored (82)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2708,399 1848,537 1862,532 1878,528 1892,526 1908,523 2453,527 2466,518 2497,497 2467,462 2496,441 2511,430 2643,439 2659,433 \ 2675,427 2690,416 2701,406", _draw_="S 6 -dotted c 5 -black B 16 1848 537 1862 532 1878 528 1892 526 1908 523 2453 527 2466 518 2497 497 2467 462 2496 441 2511 430 2\ 643 439 2659 433 2675 427 2690 416 2701 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2703 409 2708 399 2698 404 "]; "UV inflate_stored (82)" -> "UV flush_window (16)" [style=dotted, pos="e,1446,398 1766,537 1751,531 1734,524 1718,518 1630,481 1608,472 1521,433 1500,423 1475,412 1455,402", _draw_="S 6 -dotted c 5 -black B 10 1766 537 1751 531 1734 524 1718 518 1630 481 1608 472 1521 433 1500 423 1475 412 1455 402 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 1457 399 1446 398 1454 405 "]; "UV inflate_dynamic (84)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2707,399 2075,550 2210,547 2461,539 2496,518 2531,497 2510,461 2544,441 2566,427 2636,442 2659,433 2674,427 2688,416 2699,406", _draw_="S 6 -dotted c 5 -black B 13 2075 550 2210 547 2461 539 2496 518 2531 497 2510 461 2544 441 2566 427 2636 442 2659 433 2674 427 2\ 688 416 2699 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2702 408 2707 399 2697 403 "]; "UV inflate_dynamic (84)" -> "UV fprintf (33)" [style=dotted, pos="e,5560,305 2045,538 2064,533 2085,526 2104,518 2174,488 2202,489 2251,433 2276,405 2253,376 2283,356 2301,344 5274,349 5294,348 \ 5386,339 5491,319 5550,307", _draw_="S 6 -dotted c 5 -black B 16 2045 538 2064 533 2085 526 2104 518 2174 488 2202 489 2251 433 2276 405 2253 376 2283 356 2301 344 5\ 274 349 5294 348 5386 339 5491 319 5550 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5551 310 5560 305 5550 304 "]; "UV inflate_block (85)" -> "UV fill_inbuf (15)" [style=dotted, pos="e,2707,399 1872,633 2033,623 2426,591 2533,518 2567,495 2548,462 2582,441 2612,422 2628,446 2659,433 2674,427 2688,416 2699,406", _draw_="S 6 -dotted c 5 -black B 13 1872 633 2033 623 2426 591 2533 518 2567 495 2548 462 2582 441 2612 422 2628 446 2659 433 2674 427 2\ 688 416 2699 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 2702 408 2707 399 2697 403 "]; "UV usage (87)" -> "UV fprintf (33)" [style=dotted, pos="e,5635,303 5425,458 5450,452 5484,444 5514,441 5530,439 5787,444 5797,433 5821,408 5818,383 5797,356 5779,332 5699,313 5645,305", _draw_="S 6 -dotted c 5 -black B 13 5425 458 5450 452 5484 444 5514 441 5530 439 5787 444 5797 433 5821 408 5818 383 5797 356 5779 332 5\ 699 313 5645 305 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5645 302 5635 303 5644 308 "]; "UV help (88)" -> "UV fprintf (33)" [style=dotted, pos="e,5636,302 5414,540 5426,534 5440,529 5453,526 5502,515 5629,532 5676,518 5747,497 5782,496 5818,433 5835,403 5839,383 5818,356 \ 5797,329 5705,311 5646,303", _draw_="S 6 -dotted c 5 -black B 16 5414 540 5426 534 5440 529 5453 526 5502 515 5629 532 5676 518 5747 497 5782 496 5818 433 5835 403 5\ 839 383 5818 356 5797 329 5705 311 5646 303 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5646 300 5636 302 5646 306 "]; "UV help (88)" -> "UV usage (87)" [style=dotted, pos="e,5391,485 5391,534 5391,522 5391,508 5391,495", _draw_="S 6 -dotted c 5 -black B 4 5391 534 5391 522 5391 508 5391 495 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5395 495 5391 485 5388 495 "]; "UV license (89)" -> "UV fprintf (33)" [style=dotted, pos="e,5637,299 5539,539 5552,534 5568,529 5583,526 5601,522 5891,530 5903,518 5954,466 5949,411 5903,356 5871,317 5726,303 5647,299", _draw_="S 6 -dotted c 5 -black B 13 5539 539 5552 534 5568 529 5583 526 5601 522 5891 530 5903 518 5954 466 5949 411 5903 356 5871 317 5\ 726 303 5647 299 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5647 296 5637 299 5647 303 "]; "UV version (90)" -> "UV fprintf (33)" [style=dotted, pos="e,5636,301 5673,539 5687,534 5704,529 5719,526 5732,523 5933,526 5941,518 5991,466 5988,411 5941,356 5923,334 5738,312 5646,302", _draw_="S 6 -dotted c 5 -black B 13 5673 539 5687 534 5704 529 5719 526 5732 523 5933 526 5941 518 5991 466 5988 411 5941 356 5923 334 5\ 738 312 5646 302 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5646 299 5636 301 5646 305 "]; "UV main (91)" -> "UV basename (6)" [style=dotted, pos="e,6228,399 5544,636 5602,633 5715,624 5747,603 5781,580 5761,546 5795,526 5821,511 6028,527 6055,518 6123,495 6187,438 6220,406", _draw_="S 6 -dotted c 5 -black B 13 5544 636 5602 633 5715 624 5747 603 5781 580 5761 546 5795 526 5821 511 6028 527 6055 518 6123 495 6\ 187 438 6220 406 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6223 408 6228 399 6218 403 "]; "UV main (91)" -> "UV add_envopt (23)" [style=dotted, pos="e,3834,562 5474,637 5285,635 4385,627 4107,603 4016,594 3910,576 3844,564", _draw_="S 6 -dotted c 5 -black B 7 5474 637 5285 635 4385 627 4107 603 4016 594 3910 576 3844 564 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3844 561 3834 562 3843 567 "]; "UV main (91)" -> "UV strlen (25)" [style=dotted, pos="e,6664,127 5474,637 5268,635 4226,622 4135,518 4103,479 4110,322 4154,271 4245,164 4319,206 4457,186 4680,151 6345,131 6654,127", _draw_="S 6 -dotted c 5 -black B 13 5474 637 5268 635 4226 622 4135 518 4103 479 4110 322 4154 271 4245 164 4319 206 4457 186 4680 151 6\ 345 131 6654 127 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6654 131 6664 127 6654 124 "]; "UV main (91)" -> "UV strcpy (27)" [style=dotted, pos="e,7449,145 5544,635 5597,632 5691,624 5717,603 5746,579 5718,547 5747,526 5768,511 5948,527 5970,518 6018,498 6016,473 6055,441 \ 6105,400 6111,376 6171,356 6188,350 7421,360 7433,348 7460,322 7454,208 7450,155", _draw_="S 6 -dotted c 5 -black B 22 5544 635 5597 632 5691 624 5717 603 5746 579 5718 547 5747 526 5768 511 5948 527 5970 518 6018 498 6\ 016 473 6055 441 6105 400 6111 376 6171 356 6188 350 7421 360 7433 348 7460 322 7454 208 7450 155 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 7453 155 7449 145 7447 155 "]; "UV main (91)" -> "UV fprintf (33)" [style=dotted, pos="e,5559,305 5474,635 5365,627 5035,597 4971,518 4927,461 4921,407 4971,356 4978,349 5286,348 5294,348 5386,339 5490,318 5549,307", _draw_="S 6 -dotted c 5 -black B 13 5474 635 5365 627 5035 597 4971 518 4927 461 4921 407 4971 356 4978 349 5286 348 5294 348 5386 339 5\ 490 318 5549 307 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5550 310 5559 305 5549 304 "]; "UV main (91)" -> "UV usage (87)" [style=dotted, pos="e,5374,483 5474,635 5431,631 5363,622 5347,603 5326,576 5337,558 5347,526 5352,513 5360,501 5368,491", _draw_="S 6 -dotted c 5 -black B 10 5474 635 5431 631 5363 622 5347 603 5326 576 5337 558 5347 526 5352 513 5360 501 5368 491 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5371 493 5374 483 5365 489 "]; "UV main (91)" -> "UV help (88)" [style=dotted, pos="e,5408,567 5486,624 5476,618 5464,610 5453,603 5440,594 5427,583 5416,574", _draw_="S 6 -dotted c 5 -black B 7 5486 624 5476 618 5464 610 5453 603 5440 594 5427 583 5416 574 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5418 571 5408 567 5413 576 "]; "UV main (91)" -> "UV license (89)" [style=dotted, pos="e,5509,570 5509,619 5509,607 5509,593 5509,580", _draw_="S 6 -dotted c 5 -black B 4 5509 619 5509 607 5509 593 5509 580 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5513 580 5509 570 5506 580 "]; "UV main (91)" -> "UV version (90)" [style=dotted, pos="e,5625,568 5537,626 5551,620 5569,612 5583,603 5595,595 5608,585 5618,575", _draw_="S 6 -dotted c 5 -black B 7 5537 626 5551 620 5569 612 5583 603 5595 595 5608 585 5618 575 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5620 578 5625 568 5615 573 "]; "UV main (91)" -> "UV strcmp (92)" [style=dotted, pos="e,8258,144 5544,634 5613,629 5765,616 5784,603 5816,581 5793,546 5825,526 5845,513 6008,520 6030,518 6199,497 6236,458 6405,441 \ 6519,429 7319,439 7433,433 7616,422 8129,483 8251,348 8299,294 8277,200 8261,154", _draw_="S 6 -dotted c 5 -black B 22 5544 634 5613 629 5765 616 5784 603 5816 581 5793 546 5825 526 5845 513 6008 520 6030 518 6199 497 6\ 236 458 6405 441 6519 429 7319 439 7433 433 7616 422 8129 483 8251 348 8299 294 8277 200 8261 154 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 8264 153 8258 144 8258 155 "]; "UV main (91)" -> "UV signal (93)" [style=dotted, pos="e,5864,569 5544,636 5616,633 5775,625 5823,603 5836,597 5848,586 5857,576", _draw_="S 6 -dotted c 5 -black B 7 5544 636 5616 633 5775 625 5823 603 5836 597 5848 586 5857 576 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5859 579 5864 569 5854 574 "]; "UV main (91)" -> "UV strncmp (94)" [style=dotted, pos="e,5993,569 5544,635 5641,631 5908,617 5945,603 5960,597 5974,586 5985,576", _draw_="S 6 -dotted c 5 -black B 7 5544 635 5641 631 5908 617 5945 603 5960 597 5974 586 5985 576 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 5988 578 5993 569 5983 573 "]; "UV main (91)" -> "UV strncpy (95)" [style=dotted, pos="e,6134,569 5544,636 5662,633 6039,623 6089,603 6103,597 6117,586 6127,576", _draw_="S 6 -dotted c 5 -black B 7 5544 636 5662 633 6039 623 6089 603 6103 597 6117 586 6127 576 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6129 579 6134 569 6124 574 "]; "UV main (91)" -> "UV getopt_long (96)" [style=dotted, pos="e,6286,569 5544,636 5679,634 6161,623 6225,603 6244,597 6263,586 6278,575", _draw_="S 6 -dotted c 5 -black B 7 5544 636 5679 634 6161 623 6225 603 6244 597 6263 586 6278 575 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6280 578 6286 569 6276 572 "]; "UV main (91)" -> "UV atoi (97)" [style=dotted, pos="e,3415,568 5474,637 5207,635 3511,621 3461,603 3447,597 3433,586 3422,575", _draw_="S 6 -dotted c 5 -black B 7 5474 637 5207 635 3511 621 3461 603 3447 597 3433 586 3422 575 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3425 573 3415 568 3420 578 "]; "UV main (91)" -> "UV do_exit (98)" [style=dotted, pos="e,3837,222 5474,637 5196,635 3359,622 3339,603 3165,425 3666,269 3827,225", _draw_="S 6 -dotted c 5 -black B 7 5474 637 5196 635 3359 622 3339 603 3165 425 3666 269 3827 225 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 3828 228 3837 222 3826 222 "]; "UV main (91)" -> "UV treat_file (99)" [style=dotted, pos="e,6727,560 5544,636 5688,632 6234,618 6405,603 6516,593 6644,574 6717,562", _draw_="S 6 -dotted c 5 -black B 7 5544 636 5688 632 6234 618 6405 603 6516 593 6644 574 6717 562 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 6718 565 6727 560 6717 559 "]; "UV main (91)" -> "UV treat_stdin (100)" [style=dotted, pos="e,4827,568 5474,636 5353,632 4956,618 4900,603 4878,597 4854,584 4836,573", _draw_="S 6 -dotted c 5 -black B 7 5474 636 5353 632 4956 618 4900 603 4878 597 4854 584 4836 573 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4837 570 4827 568 4834 576 "]; "UV main (91)" -> "UV do_list (101)" [style=dotted, pos="e,4272,473 5474,637 5197,635 3380,622 3361,603 3337,578 3337,550 3361,526 3372,515 3863,518 3877,518 4018,508 4181,486 4262,474", _draw_="S 6 -dotted c 5 -black B 13 5474 637 5197 635 3380 622 3361 603 3337 578 3337 550 3361 526 3372 515 3863 518 3877 518 4018 508 4\ 181 486 4262 474 ", _hdraw_="S 5 -solid S 15 -setlinewidth(1) c 5 -black C 5 -black P 3 4262 477 4272 473 4262 471 "]; } ocamlgraph-2.0.0/dgraph/examples/crazy.dot0000755000175000001440000001270413735627615017143 0ustar rtusersdigraph "unix" { graph [ fontname = "Helvetica-Oblique", fontsize = 36, label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93", size = "6,6" ]; node [ shape = polygon, sides = 4, distortion = "0.0", orientation = "0.0", skew = "0.0", color = white, style = filled, fontname = "Helvetica-Outline" ]; "5th Edition" [sides=9, distortion="0.936354", orientation=28, skew="-0.126818", color=salmon2]; "6th Edition" [sides=5, distortion="0.238792", orientation=11, skew="0.995935", color=deepskyblue]; "PWB 1.0" [sides=8, distortion="0.019636", orientation=79, skew="-0.440424", color=goldenrod2]; LSX [sides=9, distortion="-0.698271", orientation=22, skew="-0.195492", color=burlywood2]; "1 BSD" [sides=7, distortion="0.265084", orientation=26, skew="0.403659", color=gold1]; "Mini Unix" [distortion="0.039386", orientation=2, skew="-0.461120", color=greenyellow]; Wollongong [sides=5, distortion="0.228564", orientation=63, skew="-0.062846", color=darkseagreen]; Interdata [distortion="0.624013", orientation=56, skew="0.101396", color=dodgerblue1]; "Unix/TS 3.0" [sides=8, distortion="0.731383", orientation=43, skew="-0.824612", color=thistle2]; "PWB 2.0" [sides=6, distortion="0.592100", orientation=34, skew="-0.719269", color=darkolivegreen3]; "7th Edition" [sides=10, distortion="0.298417", orientation=65, skew="0.310367", color=chocolate]; "8th Edition" [distortion="-0.997093", orientation=50, skew="-0.061117", color=turquoise3]; "32V" [sides=7, distortion="0.878516", orientation=19, skew="0.592905", color=steelblue3]; V7M [sides=10, distortion="-0.960249", orientation=32, skew="0.460424", color=navy]; "Ultrix-11" [sides=10, distortion="-0.633186", orientation=10, skew="0.333125", color=darkseagreen4]; Xenix [sides=8, distortion="-0.337997", orientation=52, skew="-0.760726", color=coral]; "UniPlus+" [sides=7, distortion="0.788483", orientation=39, skew="-0.526284", color=darkolivegreen3]; "9th Edition" [sides=7, distortion="0.138690", orientation=55, skew="0.554049", color=coral3]; "2 BSD" [sides=7, distortion="-0.010661", orientation=84, skew="0.179249", color=blanchedalmond]; "2.8 BSD" [distortion="-0.239422", orientation=44, skew="0.053841", color=lightskyblue1]; "2.9 BSD" [distortion="-0.843381", orientation=70, skew="-0.601395", color=aquamarine2]; "3 BSD" [sides=10, distortion="0.251820", orientation=18, skew="-0.530618", color=lemonchiffon]; "4 BSD" [sides=5, distortion="-0.772300", orientation=24, skew="-0.028475", color=darkorange1]; "4.1 BSD" [distortion="-0.226170", orientation=38, skew="0.504053", color=lightyellow1]; "4.2 BSD" [sides=10, distortion="-0.807349", orientation=50, skew="-0.908842", color=darkorchid4]; "4.3 BSD" [sides=10, distortion="-0.030619", orientation=76, skew="0.985021", color=lemonchiffon2]; "Ultrix-32" [distortion="-0.644209", orientation=21, skew="0.307836", color=goldenrod3]; "PWB 1.2" [sides=7, distortion="0.640971", orientation=84, skew="-0.768455", color=cyan]; "USG 1.0" [distortion="0.758942", orientation=42, skew="0.039886", color=blue]; "CB Unix 1" [sides=9, distortion="-0.348692", orientation=42, skew="0.767058", color=firebrick]; "USG 2.0" [distortion="0.748625", orientation=74, skew="-0.647656", color=chartreuse4]; "CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow]; "CB Unix 3" [sides=10, distortion="0.992237", orientation=29, skew="0.256102", color=bisque4]; "Unix/TS++" [sides=6, distortion="0.545461", orientation=16, skew="0.313589", color=mistyrose2]; "PDP-11 Sys V" [sides=9, distortion="-0.267769", orientation=40, skew="0.271226", color=cadetblue1]; "USG 3.0" [distortion="-0.848455", orientation=44, skew="0.267152", color=bisque2]; "Unix/TS 1.0" [distortion="0.305594", orientation=75, skew="0.070516", color=orangered]; "TS 4.0" [sides=10, distortion="-0.641701", orientation=50, skew="-0.952502", color=crimson]; "System V.0" [sides=9, distortion="0.021556", orientation=26, skew="-0.729938", color=darkorange1]; "System V.2" [sides=6, distortion="0.985153", orientation=33, skew="-0.399752", color=darkolivegreen4]; "System V.3" [sides=7, distortion="-0.687574", orientation=58, skew="-0.180116", color=lightsteelblue1]; "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-2.0.0/dgraph/examples/unix2.gv0000755000175000001440000000326713735627615016712 0ustar rtusers/* Courtesy of Ian Darwin * and Geoff Collyer * Mildly updated by Ian Darwin in 2000. */ digraph unix { size="6,6"; node [color=lightblue2, style=filled]; "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"; "9th Edition" -> "10th 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"; "4.3 BSD" -> "4.4 BSD"; "4.4 BSD" -> "FreeBSD"; "4.4 BSD" -> "NetBSD"; "4.4 BSD" -> "OpenBSD"; "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"; "System V.3" -> "System V.4"; } ocamlgraph-2.0.0/dgraph/examples/dep.dot0000755000175000001440000005423413735627615016567 0ustar rtusersdigraph G { ""; "-slice-loop-var is set"; "-inout is set"; "-sparecode-verbose is set"; "message_table"; "-copy is set"; "contextfree_only_globals"; " is set"; "Components.compute"; "-scg-help"; "-security-analysis"; "-continue-annot-error"; "-orig-name"; "-dominators-verbose is set"; "pdg_node lattice_set offsetmap_bitwise G[base] ptmap hashconsing_table 9"; "-dominators-help is set"; "-cg-init-func"; "(bool lattice_base, bool lattice_base) lattice_product offsetmap_bitwise G[base] ptmap hashconsing_table 10"; "Cluster_info offsetmaphashconsing_table"; "(bool lattice_base, bool lattice_base) lattice_product offsetmap_bitwise G[base] ptmap hashconsing_table 12"; "-overflow is set"; "-journal-enable"; "-occurrence-verbose is set"; "-slicing-verbose"; "-unicode"; "-debug is set"; "message_counter"; "-slicing-keep-annotations"; "-security-help is set"; "Users"; "-cg-help is set"; "big_int lattice_mod G[base] ptmap hashconsing_table 3"; "-slice-undef-functions is set"; "-value-debug is set"; "-sparecode-analysis"; "-simplify-cfg is set"; "-no-type"; "V_Or_Uninitialized offsetmap G[base] ptmap hashconsing_table 6"; "postdominator"; "-obfuscate"; "FileIndex"; "-slicing-level is set"; "int lattice_set offsetmap_bitwise G[base] ptmap hashconsing_table 13"; "-impact-pragma is set"; "Components.Nodes"; "-pdg is set"; "Dynamic_Alloc_Table"; "-sparecode-debug is set"; "-scope-help is set"; "-security-debug"; "-input is set"; "-slice-pragma"; "Annotations"; "Components"; "-quiet is set"; "-slice-loop-inv is set"; "-security-verbose is set"; "-metrics-debug"; "-dump-dependencies"; "-slice-assert is set"; "-value-verbose"; "-wp-help is set"; "-cast-from-constant"; "-inout-debug is set"; "-cpp-extra-args"; "FileIndex.compute"; "-lib-entry"; "-unspecified-access"; "-security-annotation"; "Globals.Vars"; "-users-verbose"; "builtin logic functions table"; "-slice-return"; "-sparecode-help"; "-security-analysis is set"; "-no-obj"; "-float-digits"; "-annot"; "-cg is set"; "-impact-help is set"; "-ocode is set"; "-impact-verbose is set"; "-users-debug is set"; "-wp-cfg"; "-wp-help"; "-slice-calls"; "-security-annotation is set"; "-print"; "alarms"; "-constfold is set"; "-slice-rd"; "-deps is set"; "-machdep is set"; "logic types table"; "-val is set"; "UseRelations"; "-sparecode-help is set"; "-slice-loop-var"; "-semantic-const-fold"; "-main is set"; "AST"; "FormalsDecl"; "-out-external"; "-wp-cfg is set"; "-value-help is set"; "external_inputs"; "-scope-debug is set"; "-from-help is set"; "internal_inouts"; "-security-lattice is set"; "-inout-help is set"; "metrics"; "-memory-footprint is set"; "-impact-slicing"; "-print-path"; "-scf-help"; "-metrics-verbose"; "!Db.Value.compute"; "-overflow"; "-semantic-const-fold is set"; "callwise_from"; "vid"; "-verbose"; "-security-slicing"; "-input-with-formals is set"; "-slevel is set"; "-value-debug"; "Leaf_Table"; "-dominators-verbose"; "-dominators-debug"; "-semantic-const-folding"; "-cpp-command"; "-add-path is set"; "-val"; "-slice-calls is set"; "-unicode is set"; "-pdg-help"; "-wp-proof"; "-slice-value"; "-help is set"; "-users-help is set"; "-scf-help is set"; "-occurrence-debug is set"; "-verbose is set"; "called_functions"; "-deref"; "-version is set"; "Location_Bytes offsetmaphashconsing_table"; "-cg-verbose"; "-debug"; "-ulevel"; "-context-valid-pointers is set"; "-keep-switch"; "-pdg-debug"; "File.t"; "Functions"; "value_table"; "-load-module is set"; "-time is set"; "-security-help"; "-slicing-debug"; "-input-with-formals"; "Buckx.MemoryFootprint"; "-dump-dependencies is set"; "-slice-wr is set"; "-wp-bot is set"; "-slicing-help"; "-scg-verbose is set"; "-occurrence"; "-cast-from-constant is set"; "-security-slicing is set"; "-propagate-top"; "-ulevel is set"; "-scg-init-func is set"; "unit G[base] ptmap hashconsing_table 2"; "-metrics-debug is set"; "-journal-name"; "Pdg.State"; "internal_outs"; "-keep-switch is set"; "-wp-dot is set"; "((bool lattice_base, bool lattice_base) lattice_product, (bool lattice_base, bool lattice_base) lattice_product) lattice_product offsetmap_bitwise G[base] ptmap hashconsing_table 11"; "-typecheck is set"; "-load-script"; "builtin logic contructors table"; "-slicing-debug is set"; "-wp-builtin-why-file"; "-pp-annot is set"; "-no-obj is set"; "-memory-footprint"; "-from-debug is set"; "BuiltinFunctions"; "CurrentLoc"; "SCQueue"; "Binary_cache.MemoryFootprint"; "-save"; "-copy"; "-scf-debug is set"; "-journal-name is set"; "-slice-print is set"; "vglobals"; "-impact-slicing is set"; "reachable_stmts"; "unit G[varinfo] ptmap hashconsing_table 1"; "-slice-wr"; "-occurrence-verbose"; "external_derefs"; "-slice-value is set"; "Callers"; "Mem_Exec"; "-metrics-dump"; "-slicing-level"; "sid"; "-slicing-help is set"; "-journal-enable is set"; "base"; "Int_Intervals G[base] ptmap hashconsing_table 4"; "-dominators-debug is set"; "VarInfos"; "-safe-arrays"; "Slicing.Project"; "Untyped AST"; "-keep-comments"; "-metrics-dump is set"; "-klr is set"; "-constfold"; "-sparecode-annot"; "-mem-exec-all is set"; "-access-path is set"; "-inout-verbose is set"; "SemanticsServicestate"; "-dot-postdom"; "-occurrence-debug"; "external_outs"; "-context-valid-pointers"; "logic functions table"; "-slicing-verbose is set"; "-load"; "-metrics-help is set"; "-wp-dot"; "-timeout"; "-context-width is set"; "-security-lattice"; "eid"; "-plevel is set"; "-inout-debug"; "!Db.From.compute_all"; "Sparecode"; "Widen.Hints"; "-cg"; "-main"; "logic contructors table"; "-no-type is set"; "-cpp-command is set"; "LoopStmts"; "-slice-assert"; "-rm-unused-globals"; "-check"; "-wp-proof is set"; "Location_Bytes offsetmap G[base] ptmap hashconsing_table 7"; "-orig-name is set"; "-pdg-help is set"; "-scf-verbose"; "-rm-unused-globals is set"; "-slicing-keep-annotations is set"; "-impact-print"; "-scg-init-func"; "-scg"; "-fct-pdg is set"; "-mem-exec is set"; "-load is set"; "natural_loops"; "-scf-verbose is set"; "Components.Annotations"; "-absolute-valid-range"; "-context-depth is set"; "-cg-help"; "-dot-pdg"; "-pdg-debug is set"; "-slice-print"; "-impact-help"; "MinValidAbsoluteAddress"; "-slice-callers"; "Occurrence.compute"; "-context-width"; "-from-help"; "-from-debug"; "-slice-return is set"; "-typecheck"; "-impact-print is set"; "-deref is set"; "is_called"; "-quiet"; "-cg-init-func is set"; "-users-debug"; "Cluster_info offsetmap G[base] ptmap hashconsing_table 8"; "external_inouts"; "-klr"; "-scg-debug"; "-wp-verbose"; "-add-path"; "-plevel"; "SGState"; "-continue-annot-error is set"; "-save is set"; "-occurrence is set"; "-input"; "-pdg-verbose is set"; "-help"; "-wp-bot"; "-sparecode-debug"; "-load-script is set"; "-fct-pdg"; "-codpds is set"; "-wp-debug is set"; "-security-propagate-assertions"; "-pp-annot"; "internal derefs"; "-machdep"; "-users"; "-propagate-top is set"; "-slice-undef-functions"; "-print-libpath is set"; "-scf-debug"; "-deps"; "-metrics"; "-scg is set"; "-occurrence-help"; "V_Or_Uninitialized offsetmaphashconsing_table"; "-wp-mm"; "-users-verbose is set"; "-timeout is set"; "-ocode"; "-print is set"; "-wlevel is set"; "-semantic-const-folding is set"; "-unspecified-access is set"; "-version"; "-obfuscate is set"; "-metrics-verbose is set"; "-from-verbose"; "-impact-debug"; "KF"; "-cpp-extra-args is set"; "dominator"; "internal_inputs"; "-inout"; "MaxValidAbsoluteAddress"; "Occurrences.LastResult"; "-float-digits is set"; "Sparecode.Globs.Result"; "syntactic callgraph"; "-mem-exec"; "-out is set"; "-dot-postdom is set"; "-check is set"; "Eval.Got_Imprecise_Value"; "-value-verbose is set"; "with_formals_inputs"; "-print-path is set"; "-out"; "-wp-fct"; "Never_Terminates"; "-occurrence-help is set"; "-context-depth"; "-wp-behav is set"; "GlobalAnnotations"; "-wlevel"; "-calldeps is set"; "-pdg-verbose"; "-metrics-help"; "-slice-threat"; "-scope-verbose"; "-annot is set"; "Non linear assignments"; "-scg-verbose"; "-wp-builtin-why-file is set"; "-keep-comments is set"; "-simplify-cfg"; "-slice-loop-inv"; "-absolute-valid-range is set"; "-wp-verbose is set"; "-wp-fct is set"; "-access-path"; "-warn-unspecified-order"; "-users is set"; "-inout-help"; "-scope-debug"; "-out-external is set"; "-inout-verbose"; "-pdg"; "-sparecode-analysis is set"; "-slevel"; "-print-plugin-path"; "-cg-verbose is set"; "theMachine"; "-load-module"; "-users-help"; "-security-propagate-assertions is set"; "-metrics is set"; "-impact-verbose"; "-slice-rd is set"; "-scg-help is set"; "-sparecode-annot is set"; "-slice-callers is set"; "builtin logic types table"; "-security-debug is set"; "-wp-mm is set"; "-print-libpath"; "-security-verbose"; "Int_Intervals map_lattice offsetmap_bitwise G[base] ptmap hashconsing_table 5"; "-cg-debug is set"; "-scg-debug is set"; "-warn-unspecified-order is set"; "-impact-debug is set"; "-wp-debug"; "-scope-verbose is set"; "-wp-behav"; "-value-help"; "-time"; "-print-plugin-path is set"; "-slice-threat is set"; "-dot-pdg is set"; "-mem-exec-all"; "-lib-entry is set"; "-sparecode-verbose"; "Occurrences.State"; "-safe-arrays is set"; "-codpds"; "-dominators-help"; "-scope-help"; "-slice-pragma is set"; "-calldeps"; "-from-verbose is set"; "Constant_Propagation"; "-cg-debug"; "functionwise_from"; "compinfokey"; "-impact-pragma"; "" -> " is set"; "" -> "File.t"; "Components.compute" -> "Components"; "Components.compute" -> "Components.Nodes"; "-scg-help" -> "-scg-help is set"; "-security-analysis" -> "-security-analysis is set"; "-continue-annot-error" -> "-continue-annot-error is set"; "-orig-name" -> "-orig-name is set"; "-cg-init-func" -> "-cg-init-func is set"; "-journal-enable" -> "-journal-enable is set"; "-slicing-verbose" -> "-slicing-verbose is set"; "-unicode" -> "-unicode is set"; "-slicing-keep-annotations" -> "-slicing-keep-annotations is set"; "-sparecode-analysis" -> "-sparecode-analysis is set"; "-no-type" -> "-no-type is set"; "-obfuscate" -> "-obfuscate is set"; "FileIndex" -> "FileIndex.compute"; "-security-debug" -> "-security-debug is set"; "-slice-pragma" -> "-slice-pragma is set"; "-metrics-debug" -> "-metrics-debug is set"; "-dump-dependencies" -> "-dump-dependencies is set"; "-value-verbose" -> "-value-verbose is set"; "-cast-from-constant" -> "-cast-from-constant is set"; "-cpp-extra-args" -> "-cpp-extra-args is set"; "-cpp-extra-args" -> "File.t"; "-lib-entry" -> "-lib-entry is set"; "-lib-entry" -> "contextfree_only_globals"; "-lib-entry" -> "value_table"; "-unspecified-access" -> "-unspecified-access is set"; "-security-annotation" -> "-security-annotation is set"; "-users-verbose" -> "-users-verbose is set"; "builtin logic functions table" -> "logic functions table"; "-slice-return" -> "-slice-return is set"; "-sparecode-help" -> "-sparecode-help is set"; "-no-obj" -> "-no-obj is set"; "-float-digits" -> "-float-digits is set"; "-annot" -> "-annot is set"; "-annot" -> "AST"; "-wp-cfg" -> "-wp-cfg is set"; "-wp-help" -> "-wp-help is set"; "-slice-calls" -> "-slice-calls is set"; "-print" -> "-print is set"; "-slice-rd" -> "-slice-rd is set"; "UseRelations" -> "value_table"; "-slice-loop-var" -> "-slice-loop-var is set"; "-semantic-const-fold" -> "-semantic-const-fold is set"; "AST" -> "((bool lattice_base, bool lattice_base) lattice_product, (bool lattice_base, bool lattice_base) lattice_product) lattice_product offsetmap_bitwise G[base] ptmap hashconsing_table 11"; "AST" -> "(bool lattice_base, bool lattice_base) lattice_product offsetmap_bitwise G[base] ptmap hashconsing_table 10"; "AST" -> "(bool lattice_base, bool lattice_base) lattice_product offsetmap_bitwise G[base] ptmap hashconsing_table 12"; "AST" -> "Annotations"; "AST" -> "Cluster_info offsetmap G[base] ptmap hashconsing_table 8"; "AST" -> "Cluster_info offsetmaphashconsing_table"; "AST" -> "Components.Annotations"; "AST" -> "FileIndex"; "AST" -> "FormalsDecl"; "AST" -> "Functions"; "AST" -> "GlobalAnnotations"; "AST" -> "Globals.Vars"; "AST" -> "Int_Intervals G[base] ptmap hashconsing_table 4"; "AST" -> "Int_Intervals map_lattice offsetmap_bitwise G[base] ptmap hashconsing_table 5"; "AST" -> "KF"; "AST" -> "Location_Bytes offsetmap G[base] ptmap hashconsing_table 7"; "AST" -> "Location_Bytes offsetmaphashconsing_table"; "AST" -> "LoopStmts"; "AST" -> "Non linear assignments"; "AST" -> "Occurrences.LastResult"; "AST" -> "V_Or_Uninitialized offsetmap G[base] ptmap hashconsing_table 6"; "AST" -> "V_Or_Uninitialized offsetmaphashconsing_table"; "AST" -> "VarInfos"; "AST" -> "Widen.Hints"; "AST" -> "big_int lattice_mod G[base] ptmap hashconsing_table 3"; "AST" -> "contextfree_only_globals"; "AST" -> "dominator"; "AST" -> "int lattice_set offsetmap_bitwise G[base] ptmap hashconsing_table 13"; "AST" -> "logic contructors table"; "AST" -> "logic functions table"; "AST" -> "logic types table"; "AST" -> "message_counter"; "AST" -> "message_table"; "AST" -> "metrics"; "AST" -> "natural_loops"; "AST" -> "pdg_node lattice_set offsetmap_bitwise G[base] ptmap hashconsing_table 9"; "AST" -> "postdominator"; "AST" -> "reachable_stmts"; "AST" -> "syntactic callgraph"; "AST" -> "unit G[base] ptmap hashconsing_table 2"; "AST" -> "unit G[varinfo] ptmap hashconsing_table 1"; "AST" -> "value_table"; "-out-external" -> "-out-external is set"; "external_inputs" -> "Slicing.Project"; "internal_inouts" -> "external_inouts"; "-impact-slicing" -> "-impact-slicing is set"; "-print-path" -> "-print-path is set"; "-scf-help" -> "-scf-help is set"; "-metrics-verbose" -> "-metrics-verbose is set"; "-overflow" -> "-overflow is set"; "-overflow" -> "value_table"; "-verbose" -> "-verbose is set"; "-security-slicing" -> "-security-slicing is set"; "-value-debug" -> "-value-debug is set"; "-dominators-verbose" -> "-dominators-verbose is set"; "-dominators-debug" -> "-dominators-debug is set"; "-semantic-const-folding" -> "-semantic-const-folding is set"; "-cpp-command" -> "-cpp-command is set"; "-cpp-command" -> "File.t"; "-val" -> "-val is set"; "-pdg-help" -> "-pdg-help is set"; "-wp-proof" -> "-wp-proof is set"; "-slice-value" -> "-slice-value is set"; "-deref" -> "-deref is set"; "-cg-verbose" -> "-cg-verbose is set"; "-debug" -> "-debug is set"; "-ulevel" -> "-ulevel is set"; "-ulevel" -> "AST"; "-keep-switch" -> "-keep-switch is set"; "-keep-switch" -> "AST"; "-pdg-debug" -> "-pdg-debug is set"; "File.t" -> "AST"; "File.t" -> "Untyped AST"; "value_table" -> "!Db.Value.compute"; "value_table" -> "Callers"; "value_table" -> "Constant_Propagation"; "value_table" -> "Dynamic_Alloc_Table"; "value_table" -> "Eval.Got_Imprecise_Value"; "value_table" -> "Leaf_Table"; "value_table" -> "Mem_Exec"; "value_table" -> "Never_Terminates"; "value_table" -> "Occurrences.State"; "value_table" -> "SGState"; "value_table" -> "Users"; "value_table" -> "alarms"; "value_table" -> "called_functions"; "value_table" -> "callwise_from"; "value_table" -> "functionwise_from"; "value_table" -> "internal derefs"; "value_table" -> "internal_inouts"; "value_table" -> "internal_inputs"; "value_table" -> "internal_outs"; "value_table" -> "is_called"; "value_table" -> "vglobals"; "-security-help" -> "-security-help is set"; "-slicing-debug" -> "-slicing-debug is set"; "-input-with-formals" -> "-input-with-formals is set"; "-slicing-help" -> "-slicing-help is set"; "-occurrence" -> "-occurrence is set"; "-propagate-top" -> "-propagate-top is set"; "-propagate-top" -> "value_table"; "-journal-name" -> "-journal-name is set"; "Pdg.State" -> "Components.compute"; "Pdg.State" -> "Slicing.Project"; "internal_outs" -> "external_outs"; "-load-script" -> "-load-script is set"; "builtin logic contructors table" -> "logic contructors table"; "-wp-builtin-why-file" -> "-wp-builtin-why-file is set"; "-memory-footprint" -> "-memory-footprint is set"; "-memory-footprint" -> "Binary_cache.MemoryFootprint"; "-memory-footprint" -> "Buckx.MemoryFootprint"; "-save" -> "-save is set"; "-copy" -> "-copy is set"; "-slice-wr" -> "-slice-wr is set"; "-occurrence-verbose" -> "-occurrence-verbose is set"; "-metrics-dump" -> "-metrics-dump is set"; "-slicing-level" -> "-slicing-level is set"; "-safe-arrays" -> "-safe-arrays is set"; "-safe-arrays" -> "value_table"; "-keep-comments" -> "-keep-comments is set"; "-constfold" -> "-constfold is set"; "-constfold" -> "AST"; "-sparecode-annot" -> "-sparecode-annot is set"; "-dot-postdom" -> "-dot-postdom is set"; "-occurrence-debug" -> "-occurrence-debug is set"; "external_outs" -> "Slicing.Project"; "-context-valid-pointers" -> "-context-valid-pointers is set"; "-context-valid-pointers" -> "value_table"; "-load" -> "-load is set"; "-wp-dot" -> "-wp-dot is set"; "-timeout" -> "-timeout is set"; "-security-lattice" -> "-security-lattice is set"; "-inout-debug" -> "-inout-debug is set"; "-cg" -> "-cg is set"; "-main" -> "-main is set"; "-main" -> "SemanticsServicestate"; "-main" -> "contextfree_only_globals"; "-main" -> "value_table"; "-slice-assert" -> "-slice-assert is set"; "-rm-unused-globals" -> "-rm-unused-globals is set"; "-check" -> "-check is set"; "-scf-verbose" -> "-scf-verbose is set"; "-impact-print" -> "-impact-print is set"; "-scg-init-func" -> "-scg-init-func is set"; "-scg-init-func" -> "SemanticsServicestate"; "-scg" -> "-scg is set"; "Components.Annotations" -> "Components.Nodes"; "Components.Annotations" -> "Components.compute"; "-absolute-valid-range" -> "-absolute-valid-range is set"; "-absolute-valid-range" -> "value_table"; "-cg-help" -> "-cg-help is set"; "-dot-pdg" -> "-dot-pdg is set"; "-slice-print" -> "-slice-print is set"; "-impact-help" -> "-impact-help is set"; "-slice-callers" -> "-slice-callers is set"; "-context-width" -> "-context-width is set"; "-context-width" -> "value_table"; "-from-help" -> "-from-help is set"; "-from-debug" -> "-from-debug is set"; "-typecheck" -> "-typecheck is set"; "-quiet" -> "-quiet is set"; "-users-debug" -> "-users-debug is set"; "-klr" -> "-klr is set"; "-klr" -> "value_table"; "-scg-debug" -> "-scg-debug is set"; "-wp-verbose" -> "-wp-verbose is set"; "-add-path" -> "-add-path is set"; "-plevel" -> "-plevel is set"; "-plevel" -> "value_table"; "SGState" -> "SCQueue"; "SGState" -> "SemanticsServicestate"; "-input" -> "-input is set"; "-help" -> "-help is set"; "-wp-bot" -> "-wp-bot is set"; "-sparecode-debug" -> "-sparecode-debug is set"; "-fct-pdg" -> "-fct-pdg is set"; "-security-propagate-assertions" -> "-security-propagate-assertions is set"; "-pp-annot" -> "-pp-annot is set"; "-pp-annot" -> "AST"; "internal derefs" -> "external_derefs"; "-machdep" -> "-machdep is set"; "-machdep" -> "theMachine"; "-users" -> "-users is set"; "-users" -> "Users"; "-slice-undef-functions" -> "-slice-undef-functions is set"; "-scf-debug" -> "-scf-debug is set"; "-deps" -> "-deps is set"; "-metrics" -> "-metrics is set"; "-occurrence-help" -> "-occurrence-help is set"; "-wp-mm" -> "-wp-mm is set"; "-ocode" -> "-ocode is set"; "-version" -> "-version is set"; "-from-verbose" -> "-from-verbose is set"; "-impact-debug" -> "-impact-debug is set"; "internal_inputs" -> "external_inputs"; "internal_inputs" -> "with_formals_inputs"; "-inout" -> "-inout is set"; "-mem-exec" -> "-mem-exec is set"; "-mem-exec" -> "value_table"; "-out" -> "-out is set"; "-wp-fct" -> "-wp-fct is set"; "-context-depth" -> "-context-depth is set"; "-context-depth" -> "value_table"; "-wlevel" -> "-wlevel is set"; "-wlevel" -> "value_table"; "-pdg-verbose" -> "-pdg-verbose is set"; "-metrics-help" -> "-metrics-help is set"; "-slice-threat" -> "-slice-threat is set"; "-scope-verbose" -> "-scope-verbose is set"; "-scg-verbose" -> "-scg-verbose is set"; "-simplify-cfg" -> "-simplify-cfg is set"; "-simplify-cfg" -> "AST"; "-slice-loop-inv" -> "-slice-loop-inv is set"; "-access-path" -> "-access-path is set"; "-warn-unspecified-order" -> "-warn-unspecified-order is set"; "-inout-help" -> "-inout-help is set"; "-scope-debug" -> "-scope-debug is set"; "-inout-verbose" -> "-inout-verbose is set"; "-pdg" -> "-pdg is set"; "-slevel" -> "-slevel is set"; "-slevel" -> "value_table"; "-print-plugin-path" -> "-print-plugin-path is set"; "theMachine" -> "AST"; "theMachine" -> "BuiltinFunctions"; "theMachine" -> "Untyped AST"; "theMachine" -> "builtin logic contructors table"; "theMachine" -> "builtin logic functions table"; "theMachine" -> "builtin logic types table"; "-load-module" -> "-load-module is set"; "-users-help" -> "-users-help is set"; "-impact-verbose" -> "-impact-verbose is set"; "builtin logic types table" -> "logic types table"; "-print-libpath" -> "-print-libpath is set"; "-security-verbose" -> "-security-verbose is set"; "-wp-debug" -> "-wp-debug is set"; "-wp-behav" -> "-wp-behav is set"; "-value-help" -> "-value-help is set"; "-time" -> "-time is set"; "-mem-exec-all" -> "-mem-exec-all is set"; "-mem-exec-all" -> "value_table"; "-sparecode-verbose" -> "-sparecode-verbose is set"; "Occurrences.State" -> "Occurrence.compute"; "Occurrences.State" -> "Occurrences.LastResult"; "-codpds" -> "-codpds is set"; "-dominators-help" -> "-dominators-help is set"; "-scope-help" -> "-scope-help is set"; "-calldeps" -> "-calldeps is set"; "-cg-debug" -> "-cg-debug is set"; "functionwise_from" -> "!Db.From.compute_all"; "functionwise_from" -> "Pdg.State"; "-impact-pragma" -> "-impact-pragma is set"; }ocamlgraph-2.0.0/dgraph/examples/jsort.dot0000755000175000001440000001405513735627615017155 0ustar rtusersdigraph prof { size="6,4"; ratio = fill; node [style=filled]; start -> main [color="0.002 0.999 0.999"]; start -> on_exit [color="0.649 0.701 0.701"]; main -> sort [color="0.348 0.839 0.839"]; main -> merge [color="0.515 0.762 0.762"]; main -> term [color="0.647 0.702 0.702"]; main -> signal [color="0.650 0.700 0.700"]; main -> sbrk [color="0.650 0.700 0.700"]; main -> unlink [color="0.650 0.700 0.700"]; main -> newfile [color="0.650 0.700 0.700"]; main -> fclose [color="0.650 0.700 0.700"]; main -> close [color="0.650 0.700 0.700"]; main -> brk [color="0.650 0.700 0.700"]; main -> setbuf [color="0.650 0.700 0.700"]; main -> copyproto [color="0.650 0.700 0.700"]; main -> initree [color="0.650 0.700 0.700"]; main -> safeoutfil [color="0.650 0.700 0.700"]; main -> getpid [color="0.650 0.700 0.700"]; main -> sprintf [color="0.650 0.700 0.700"]; main -> creat [color="0.650 0.700 0.700"]; main -> rem [color="0.650 0.700 0.700"]; main -> oldfile [color="0.650 0.700 0.700"]; sort -> msort [color="0.619 0.714 0.714"]; sort -> filbuf [color="0.650 0.700 0.700"]; sort -> newfile [color="0.650 0.700 0.700"]; sort -> fclose [color="0.650 0.700 0.700"]; sort -> setbuf [color="0.650 0.700 0.700"]; sort -> setfil [color="0.650 0.700 0.700"]; msort -> qsort [color="0.650 0.700 0.700"]; msort -> insert [color="0.650 0.700 0.700"]; msort -> wline [color="0.650 0.700 0.700"]; msort -> div [color="0.650 0.700 0.700"]; msort -> cmpsave [color="0.650 0.700 0.700"]; merge -> insert [color="0.650 0.700 0.700"]; merge -> rline [color="0.650 0.700 0.700"]; merge -> wline [color="0.650 0.700 0.700"]; merge -> unlink [color="0.650 0.700 0.700"]; merge -> fopen [color="0.650 0.700 0.700"]; merge -> fclose [color="0.650 0.700 0.700"]; merge -> setfil [color="0.650 0.700 0.700"]; merge -> mul [color="0.650 0.700 0.700"]; merge -> setbuf [color="0.650 0.700 0.700"]; merge -> cmpsave [color="0.650 0.700 0.700"]; insert -> cmpa [color="0.650 0.700 0.700"]; wline -> flsbuf [color="0.649 0.700 0.700"]; qsort -> cmpa [color="0.650 0.700 0.700"]; rline -> filbuf [color="0.649 0.700 0.700"]; xflsbuf -> write [color="0.650 0.700 0.700"]; flsbuf -> xflsbuf [color="0.649 0.700 0.700"]; filbuf -> read [color="0.650 0.700 0.700"]; term -> unlink [color="0.650 0.700 0.700"]; term -> signal [color="0.650 0.700 0.700"]; term -> setfil [color="0.650 0.700 0.700"]; term -> exit [color="0.650 0.700 0.700"]; endopen -> open [color="0.650 0.700 0.700"]; fopen -> endopen [color="0.639 0.705 0.705"]; fopen -> findiop [color="0.650 0.700 0.700"]; newfile -> fopen [color="0.634 0.707 0.707"]; newfile -> setfil [color="0.650 0.700 0.700"]; fclose -> fflush [color="0.642 0.704 0.704"]; fclose -> close [color="0.650 0.700 0.700"]; fflush -> xflsbuf [color="0.635 0.707 0.707"]; malloc -> morecore [color="0.325 0.850 0.850"]; malloc -> demote [color="0.650 0.700 0.700"]; morecore -> sbrk [color="0.650 0.700 0.700"]; morecore -> getfreehdr [color="0.650 0.700 0.700"]; morecore -> free [color="0.650 0.700 0.700"]; morecore -> getpagesize [color="0.650 0.700 0.700"]; morecore -> putfreehdr [color="0.650 0.700 0.700"]; morecore -> udiv [color="0.650 0.700 0.700"]; morecore -> umul [color="0.650 0.700 0.700"]; on_exit -> malloc [color="0.325 0.850 0.850"]; signal -> sigvec [color="0.650 0.700 0.700"]; moncontrol -> profil [color="0.650 0.700 0.700"]; getfreehdr -> sbrk [color="0.650 0.700 0.700"]; free -> insert [color="0.650 0.700 0.700"]; insert -> getfreehdr [color="0.650 0.700 0.700"]; setfil -> div [color="0.650 0.700 0.700"]; setfil -> rem [color="0.650 0.700 0.700"]; sigvec -> sigblock [color="0.650 0.700 0.700"]; sigvec -> sigsetmask [color="0.650 0.700 0.700"]; doprnt -> urem [color="0.650 0.700 0.700"]; doprnt -> udiv [color="0.650 0.700 0.700"]; doprnt -> strlen [color="0.650 0.700 0.700"]; doprnt -> localeconv [color="0.650 0.700 0.700"]; sprintf -> doprnt [color="0.650 0.700 0.700"]; cmpa [color="0.000 1.000 1.000"]; wline [color="0.201 0.753 1.000"]; insert [color="0.305 0.625 1.000"]; rline [color="0.355 0.563 1.000"]; sort [color="0.408 0.498 1.000"]; qsort [color="0.449 0.447 1.000"]; write [color="0.499 0.386 1.000"]; read [color="0.578 0.289 1.000"]; msort [color="0.590 0.273 1.000"]; merge [color="0.603 0.258 1.000"]; unlink [color="0.628 0.227 1.000"]; filbuf [color="0.641 0.212 1.000"]; open [color="0.641 0.212 1.000"]; sbrk [color="0.647 0.204 1.000"]; signal [color="0.647 0.204 1.000"]; moncontrol [color="0.647 0.204 1.000"]; xflsbuf [color="0.650 0.200 1.000"]; flsbuf [color="0.650 0.200 1.000"]; div [color="0.650 0.200 1.000"]; cmpsave [color="0.650 0.200 1.000"]; rem [color="0.650 0.200 1.000"]; setfil [color="0.650 0.200 1.000"]; close [color="0.650 0.200 1.000"]; fclose [color="0.650 0.200 1.000"]; fflush [color="0.650 0.200 1.000"]; setbuf [color="0.650 0.200 1.000"]; endopen [color="0.650 0.200 1.000"]; findiop [color="0.650 0.200 1.000"]; fopen [color="0.650 0.200 1.000"]; mul [color="0.650 0.200 1.000"]; newfile [color="0.650 0.200 1.000"]; sigblock [color="0.650 0.200 1.000"]; sigsetmask [color="0.650 0.200 1.000"]; sigvec [color="0.650 0.200 1.000"]; udiv [color="0.650 0.200 1.000"]; urem [color="0.650 0.200 1.000"]; brk [color="0.650 0.200 1.000"]; getfreehdr [color="0.650 0.200 1.000"]; strlen [color="0.650 0.200 1.000"]; umul [color="0.650 0.200 1.000"]; doprnt [color="0.650 0.200 1.000"]; copyproto [color="0.650 0.200 1.000"]; creat [color="0.650 0.200 1.000"]; demote [color="0.650 0.200 1.000"]; exit [color="0.650 0.200 1.000"]; free [color="0.650 0.200 1.000"]; getpagesize [color="0.650 0.200 1.000"]; getpid [color="0.650 0.200 1.000"]; initree [color="0.650 0.200 1.000"]; insert [color="0.650 0.200 1.000"]; localeconv [color="0.650 0.200 1.000"]; main [color="0.650 0.200 1.000"]; malloc [color="0.650 0.200 1.000"]; morecore [color="0.650 0.200 1.000"]; oldfile [color="0.650 0.200 1.000"]; on_exit [color="0.650 0.200 1.000"]; profil [color="0.650 0.200 1.000"]; putfreehdr [color="0.650 0.200 1.000"]; safeoutfil [color="0.650 0.200 1.000"]; sprintf [color="0.650 0.200 1.000"]; term [color="0.650 0.200 1.000"]; } ocamlgraph-2.0.0/dgraph/examples/services.dot0000755000175000001440000002554713735627615017647 0ustar rtusersdigraph G { "unlzw (1)" [height=0.200000, width=0.200000, shape=box, color="#000080", style=bold]; "unzip (9)" [height=1.800000, width=1.800000, shape=box, color="#008000", style=bold]; "make_simple_name (1)" [height=0.200000, width=0.200000, shape=box, color="#008080", style=bold]; "treat_file (21)" [height=4.200000, width=4.200000, shape=box, color="#800000", style=bold]; "strlen (1)" [height=0.200000, width=0.200000, shape=box, color="#800080", style=dotted]; "treat_stdin (1)" [height=0.200000, width=0.200000, shape=box, color="#808000", style=bold]; "atoi (1)" [height=0.200000, width=0.200000, shape=box, color="#808080", style=dotted]; "unlzh (12)" [height=2.400000, width=2.400000, shape=box, color="#000040", style=bold]; "signal (1)" [height=0.200000, width=0.200000, shape=box, color="#0000C0", style=dotted]; "strcmp (1)" [height=0.200000, width=0.200000, shape=box, color="#008040", style=dotted]; "do_list (4)" [height=0.800000, width=0.800000, shape=box, color="#0080C0", style=bold]; "version (1)" [height=0.200000, width=0.200000, shape=box, color="#800040", style=bold]; "add_envopt (5)" [height=1.000000, width=1.000000, shape=box, color="#8000C0", style=bold]; "strcpy (1)" [height=0.200000, width=0.200000, shape=box, color="#808040", style=dotted]; "strncmp (1)" [height=0.200000, width=0.200000, shape=box, color="#8080C0", style=dotted]; "fprintf (1)" [height=0.200000, width=0.200000, shape=box, color="#004000", style=dotted]; "main (1)" [height=0.200000, width=0.200000, shape=box, color="#004080", style=bold]; "strncpy (1)" [height=0.200000, width=0.200000, shape=box, color="#00C000", style=dotted]; "basename (1)" [height=0.200000, width=0.200000, shape=box, color="#00C080", style=bold]; "lzw (1)" [height=0.200000, width=0.200000, shape=box, color="#804000", style=bold]; "zip (26)" [height=5.200000, width=5.200000, shape=box, color="#804080", style=bold]; "getopt_long (1)" [height=0.200000, width=0.200000, shape=box, color="#80C000", style=dotted]; "usage (1)" [height=0.200000, width=0.200000, shape=box, color="#80C080", style=bold]; "warn (1)" [height=0.200000, width=0.200000, shape=box, color="#004040", style=bold]; "copy (1)" [height=0.200000, width=0.200000, shape=box, color="#0040C0", style=bold]; "help (1)" [height=0.200000, width=0.200000, shape=box, color="#00C040", style=bold]; "unpack (3)" [height=0.600000, width=0.600000, shape=box, color="#00C0C0", style=bold]; "license (1)" [height=0.200000, width=0.200000, shape=box, color="#804040", style=bold]; "file_read (1)" [height=0.200000, width=0.200000, shape=box, color="#8040C0", style=bold]; "do_exit (2)" [height=0.400000, width=0.400000, shape=box, color="#80C040", style=bold]; "read (1)" [height=0.200000, width=0.200000, shape=box, color="#80C0C0", style=dotted]; "write_buf (2)" [height=0.400000, width=0.400000, shape=box, color="#400000", style=bold]; "read_error (1)" [height=0.200000, width=0.200000, shape=box, color="#400080", style=bold]; "get_method (3)" [height=0.600000, width=0.600000, shape=box, color="#408000", style=bold]; "fill_inbuf (1)" [height=0.200000, width=0.200000, shape=box, color="#408080", style=bold]; "error (1)" [height=0.200000, width=0.200000, shape=box, color="#C00000", style=bold]; "memset (1)" [height=0.200000, width=0.200000, shape=box, color="#C00080", style=dotted]; "memcpy (1)" [height=0.200000, width=0.200000, shape=box, color="#C08000", style=dotted]; "updcrc (1)" [height=0.200000, width=0.200000, shape=box, color="#C08080", style=bold]; "flush_window (1)" [height=0.200000, width=0.200000, shape=box, color="#400040", style=bold]; "strrchr (1)" [height=0.200000, width=0.200000, shape=box, color="#4000C0", style=dotted]; "clear_bufs (1)" [height=0.200000, width=0.200000, shape=box, color="#408040", style=bold]; "write_error (1)" [height=0.200000, width=0.200000, shape=box, color="#4080C0", style=bold]; "perror (1)" [height=0.200000, width=0.200000, shape=box, color="#C00040", style=dotted]; "display_ratio (2)" [height=0.400000, width=0.400000, shape=box, color="#C000C0", style=bold]; " (1)" [height=0.200000, width=0.200000, shape=box, color="#C08040", style=bold]; "fileno (1)" [height=0.200000, width=0.200000, shape=box, color="#C080C0", style=dotted]; "abort_gzip (1)" [height=0.200000, width=0.200000, shape=box, color="#404000", style=bold]; "close (1)" [height=0.200000, width=0.200000, shape=box, color="#404080", style=dotted]; "unlink (1)" [height=0.200000, width=0.200000, shape=box, color="#40C000", style=dotted]; "isatty (1)" [height=0.200000, width=0.200000, shape=box, color="#40C080", style=dotted]; "fstat (1)" [height=0.200000, width=0.200000, shape=box, color="#C04000", style=dotted]; "strcspn (1)" [height=0.200000, width=0.200000, shape=box, color="#C04080", style=dotted]; "free (1)" [height=0.200000, width=0.200000, shape=box, color="#C0C000", style=dotted]; "strlwr (1)" [height=0.200000, width=0.200000, shape=box, color="#C0C080", style=bold]; "__errno_location (1)" [height=0.200000, width=0.200000, shape=box, color="#404040", style=dotted]; "malloc (1)" [height=0.200000, width=0.200000, shape=box, color="#4040C0", style=dotted]; "__ctype_b_loc (1)" [height=0.200000, width=0.200000, shape=box, color="#40C040", style=dotted]; "unlzw (1)" -> "fprintf (1)"; "unlzw (1)" -> "read (1)"; "unlzw (1)" -> "write_buf (2)"; "unlzw (1)" -> "read_error (1)"; "unlzw (1)" -> "fill_inbuf (1)"; "unlzw (1)" -> "error (1)"; "unlzw (1)" -> "memset (1)"; "unlzw (1)" -> "memcpy (1)"; "unzip (9)" -> "fprintf (1)"; "unzip (9)" -> "fill_inbuf (1)"; "unzip (9)" -> "error (1)"; "unzip (9)" -> "memset (1)"; "unzip (9)" -> "memcpy (1)"; "unzip (9)" -> "updcrc (1)"; "unzip (9)" -> "flush_window (1)"; "unzip (9)" -> "free (1)"; "unzip (9)" -> "malloc (1)"; "make_simple_name (1)" -> "strrchr (1)"; "treat_file (21)" -> "strlen (1)"; "treat_file (21)" -> "treat_stdin (1)"; "treat_file (21)" -> "strcmp (1)"; "treat_file (21)" -> "do_list (4)"; "treat_file (21)" -> "strcpy (1)"; "treat_file (21)" -> "fprintf (1)"; "treat_file (21)" -> "get_method (3)"; "treat_file (21)" -> "error (1)"; "treat_file (21)" -> "strrchr (1)"; "treat_file (21)" -> "clear_bufs (1)"; "treat_file (21)" -> "write_error (1)"; "treat_file (21)" -> "perror (1)"; "treat_file (21)" -> "display_ratio (2)"; "treat_file (21)" -> " (1)"; "treat_file (21)" -> "fileno (1)"; "treat_file (21)" -> "close (1)"; "treat_file (21)" -> "unlink (1)"; "treat_file (21)" -> "isatty (1)"; "treat_file (21)" -> "fstat (1)"; "treat_file (21)" -> "strcspn (1)"; "treat_file (21)" -> "strlwr (1)"; "treat_file (21)" -> "__errno_location (1)"; "treat_file (21)" -> "__ctype_b_loc (1)"; "treat_stdin (1)" -> "do_list (4)"; "treat_stdin (1)" -> "strcpy (1)"; "treat_stdin (1)" -> "fprintf (1)"; "treat_stdin (1)" -> "do_exit (2)"; "treat_stdin (1)" -> "get_method (3)"; "treat_stdin (1)" -> "error (1)"; "treat_stdin (1)" -> "clear_bufs (1)"; "treat_stdin (1)" -> "display_ratio (2)"; "treat_stdin (1)" -> " (1)"; "treat_stdin (1)" -> "fileno (1)"; "treat_stdin (1)" -> "isatty (1)"; "treat_stdin (1)" -> "fstat (1)"; "unlzh (12)" -> "write_buf (2)"; "unlzh (12)" -> "fill_inbuf (1)"; "unlzh (12)" -> "error (1)"; "do_list (4)" -> "read (1)"; "do_list (4)" -> "read_error (1)"; "do_list (4)" -> "display_ratio (2)"; "version (1)" -> "fprintf (1)"; "add_envopt (5)" -> "strlen (1)"; "add_envopt (5)" -> "strcpy (1)"; "add_envopt (5)" -> "error (1)"; "add_envopt (5)" -> "strcspn (1)"; "add_envopt (5)" -> "free (1)"; "add_envopt (5)" -> "malloc (1)"; "main (1)" -> "treat_file (21)"; "main (1)" -> "strlen (1)"; "main (1)" -> "treat_stdin (1)"; "main (1)" -> "atoi (1)"; "main (1)" -> "signal (1)"; "main (1)" -> "strcmp (1)"; "main (1)" -> "do_list (4)"; "main (1)" -> "version (1)"; "main (1)" -> "add_envopt (5)"; "main (1)" -> "strcpy (1)"; "main (1)" -> "strncmp (1)"; "main (1)" -> "fprintf (1)"; "main (1)" -> "strncpy (1)"; "main (1)" -> "basename (1)"; "main (1)" -> "getopt_long (1)"; "main (1)" -> "usage (1)"; "main (1)" -> "help (1)"; "main (1)" -> "license (1)"; "main (1)" -> "do_exit (2)"; "basename (1)" -> "strrchr (1)"; "basename (1)" -> "strlwr (1)"; "lzw (1)" -> "fprintf (1)"; "zip (26)" -> "basename (1)"; "zip (26)" -> "write_buf (2)"; "zip (26)" -> "error (1)"; "zip (26)" -> "memset (1)"; "zip (26)" -> "memcpy (1)"; "zip (26)" -> "updcrc (1)"; "zip (26)" -> " (1)"; "usage (1)" -> "fprintf (1)"; "warn (1)" -> "fprintf (1)"; "copy (1)" -> "read (1)"; "copy (1)" -> "write_buf (2)"; "copy (1)" -> "read_error (1)"; "copy (1)" -> "__errno_location (1)"; "help (1)" -> "fprintf (1)"; "help (1)" -> "usage (1)"; "unpack (3)" -> "fill_inbuf (1)"; "unpack (3)" -> "error (1)"; "unpack (3)" -> "flush_window (1)"; "license (1)" -> "fprintf (1)"; "file_read (1)" -> "read (1)"; "file_read (1)" -> "updcrc (1)"; "do_exit (2)" -> "free (1)"; "write_buf (2)" -> "write_error (1)"; "read_error (1)" -> "fprintf (1)"; "read_error (1)" -> "perror (1)"; "read_error (1)" -> "abort_gzip (1)"; "read_error (1)" -> "__errno_location (1)"; "get_method (3)" -> "fprintf (1)"; "get_method (3)" -> "basename (1)"; "get_method (3)" -> "fill_inbuf (1)"; "get_method (3)" -> "error (1)"; "fill_inbuf (1)" -> "read (1)"; "fill_inbuf (1)" -> "read_error (1)"; "fill_inbuf (1)" -> "__errno_location (1)"; "error (1)" -> "fprintf (1)"; "error (1)" -> "abort_gzip (1)"; "flush_window (1)" -> "write_buf (2)"; "flush_window (1)" -> "updcrc (1)"; "write_error (1)" -> "fprintf (1)"; "write_error (1)" -> "perror (1)"; "write_error (1)" -> "abort_gzip (1)"; "display_ratio (2)" -> "fprintf (1)"; "abort_gzip (1)" -> "do_exit (2)"; "abort_gzip (1)" -> "close (1)"; "abort_gzip (1)" -> "unlink (1)"; "strlwr (1)" -> "__ctype_b_loc (1)"; }ocamlgraph-2.0.0/dgraph/examples/fancy.dot0000644000175000001440000000076613735627615017115 0ustar rtusers digraph G { size ="4,4"; main [shape=box]; /* this is a comment */ main -> parse [weight=8]; parse -> execute; main -> init [style=dotted, comment="youhou"]; main -> cleanup; execute -> { make_string; printf} init -> make_string; edge [color=red]; // so is this main -> printf [style=bold,label="100 times"]; make_string [label="make a\nstring"]; node [shape=box,style=filled,color=".7 .3 1.0"]; execute -> compare; } ocamlgraph-2.0.0/dgraph/examples/viewfile.gv0000755000175000001440000000334713735627615017456 0ustar rtusersdigraph Viewfile { node [ style = filled ]; atoi [color=green]; chkmalloc [color=green]; close [color=green]; error [color=blue]; exit [color=blue]; fclose [color=green]; fgets [color=red]; fopen [color=green]; fprintf [color=blue]; free [color=blue]; free_list [color=blue]; fstat [color=green]; getopt [color=green]; init_list [color=green]; insert_list [color=green]; main [color=green]; makeargs [color=blue]; makepairs [color=green]; malloc [color=green]; open [color=green]; printf [color=red]; read [color=green]; rewind [color=green]; viewline [color=green]; viewlines [color=green]; walk_list [color=green]; write [color=green]; fclose -> close [color=green]; fgets -> fstat [color=green]; fgets -> read [color=green]; fopen -> open [color=green]; printf -> write [color=green]; main -> fgets [color=blue]; main -> getopt [color=green]; main -> makeargs [color=blue]; main -> makepairs [color=green]; main -> chkmalloc [color=green]; main -> error [color=blue]; main -> viewlines [color=green]; makeargs -> chkmalloc [color=blue]; makepairs -> atoi [color=green]; makepairs -> init_list [color=green]; makepairs -> insert_list [color=green]; makepairs -> chkmalloc [color=green]; free_list -> free [color=blue]; init_list -> chkmalloc [color=green]; insert_list -> chkmalloc [color=green]; walk_list -> error [color=blue]; walk_list -> viewline [color=green]; chkmalloc -> malloc [color=green]; chkmalloc -> error [color=blue]; error -> exit [color=blue]; error -> fprintf [color=blue]; error -> error [color=blue]; viewline -> fgets [color=red]; viewline -> printf [color=red]; viewline -> rewind [color=green]; viewlines -> fclose [color=green]; viewlines -> fopen [color=green]; viewlines -> walk_list [color=green]; viewlines -> viewline [color=blue]; } ocamlgraph-2.0.0/dgraph/examples/polypoly.gv0000755000175000001440000001204313735627615017524 0ustar rtusersdigraph polypoly { size="7,9.5"; page="8.5,11"; ratio=fill; node [shape=polygon]; { rank=same; node [sides=0]; node [peripheries=1]; 0000 [label="M"]; 0001 [label="MMMMMMMMMM"]; 0002 [label="M\nM\nM\nM\nM\nM"]; 0003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; 0010 [label="M"]; 0011 [label="MMMMMMMMMM"]; 0012 [label="M\nM\nM\nM\nM\nM"]; 0013 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [distortion=-.3]; 0110 [label="M"]; 0111 [label="MMMMMMMMMM"]; 0112 [label="M\nM\nM\nM\nM\nM"]; 0113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } { rank=same; node [sides=3]; node [peripheries=1]; node [orientation=0]; 3000 [label="M"]; 3001 [label="MMMMMMMMMM"]; 3002 [label="M\nM\nM\nM\nM\nM"]; 3003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; node [orientation=60]; 3110 [label="M"]; 3111 [label="MMMMMMMMMM"]; 3112 [label="M\nM\nM\nM\nM\nM"]; 3113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } 3000->0000; { rank=same; node [sides=4]; node [peripheries=1]; node [orientation=0]; 4000 [label="M"]; 4001 [label="MMMMMMMMMM"]; 4002 [label="M\nM\nM\nM\nM\nM"]; 4003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; node [orientation=45]; 4110 [label="M"]; 4111 [label="MMMMMMMMMM"]; 4112 [label="M\nM\nM\nM\nM\nM"]; 4113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } 4000->3000; { rank=same; node [sides=5]; node [peripheries=1]; node [orientation=0]; 5000 [label="M"]; 5001 [label="MMMMMMMMMM"]; 5002 [label="M\nM\nM\nM\nM\nM"]; 5003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; node [orientation=36]; 5110 [label="M"]; 5111 [label="MMMMMMMMMM"]; 5112 [label="M\nM\nM\nM\nM\nM"]; 5113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } 5000->4000; { rank=same; node [sides=6]; node [peripheries=1]; node [orientation=0]; 6000 [label="M"]; 6001 [label="MMMMMMMMMM"]; 6002 [label="M\nM\nM\nM\nM\nM"]; 6003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; node [orientation=30]; 6110 [label="M"]; 6111 [label="MMMMMMMMMM"]; 6112 [label="M\nM\nM\nM\nM\nM"]; 6113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } 6000->5000; { rank=same; node [sides=7]; node [peripheries=1]; node [orientation=0]; 7000 [label="M"]; 7001 [label="MMMMMMMMMM"]; 7002 [label="M\nM\nM\nM\nM\nM"]; 7003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; node [orientation=25.7]; 7110 [label="M"]; 7111 [label="MMMMMMMMMM"]; 7112 [label="M\nM\nM\nM\nM\nM"]; 7113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } 7000->6000; { rank=same; node [sides=8]; node [peripheries=1]; node [orientation=0]; 8000 [label="M"]; 8001 [label="MMMMMMMMMM"]; 8002 [label="M\nM\nM\nM\nM\nM"]; 8003 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; node [peripheries=2]; node [orientation=22.5]; 8110 [label="M"]; 8111 [label="MMMMMMMMMM"]; 8112 [label="M\nM\nM\nM\nM\nM"]; 8113 [label="MMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM\nMMMMMMMMMM"]; } 8000->7000; { rank=same; node [sides=4]; node [peripheries=1]; node [regular=1]; node [distortion=.5]; node [orientation=0]; 9000 [label="M"]; node [orientation=45.]; 9001 [label="M"]; node [orientation=90.]; 9002 [label="M"]; node [orientation=135.]; 9003 [label="M"]; node [orientation=180.]; 9004 [label="M"]; node [orientation=225.]; 9005 [label="M"]; node [orientation=270.]; 9006 [label="M"]; node [orientation=315.]; 9007 [label="M"]; node [peripheries=2]; node [orientation=0]; 9010 [label="M"]; node [orientation=45.]; 9011 [label="M"]; node [orientation=90.]; 9012 [label="M"]; node [orientation=135.]; 9013 [label="M"]; node [orientation=180.]; 9014 [label="M"]; node [orientation=225.]; 9015 [label="M"]; node [orientation=270.]; 9016 [label="M"]; node [orientation=315.]; 9017 [label="M"]; } 9000->8000; } ocamlgraph-2.0.0/dgraph/examples/dfa.gv0000755000175000001440000000167713735627615016402 0ustar rtusersdigraph g { "start" [ label = "MWGC-" ]; "n1" [ label = "WC-MG" ]; "n2" [ label = "MWC-G" ]; "n3" [ label = "C-MWG" ]; "n4" [ label = "W-MGC" ]; "n5" [ label = "MGC-W" ]; "n6" [ label = "MWG-C" ]; "n7" [ label = "G-MWC" ]; "n8" [ label = "MG-WC" ]; "n9" [ label = "-MWGC" ]; "start" -> "n1" [ label = "g" ]; "n1" -> "start" [ label = "g" ]; subgraph l { rank = same; "n3" "n4" } subgraph r { rank = same; "n5" "n6" } "n1" -> "n2" [ label = "m" ]; "n2" -> "n1" [ label = "m" ]; "n2" -> "n3" [ label = "w" ]; "n3" -> "n2" [ label = "w" ]; "n2" -> "n4" [ label = "c" ]; "n4" -> "n2" [ label = "c" ]; "n3" -> "n5" [ label = "g" ]; "n5" -> "n3" [ label = "g" ]; "n4" -> "n6" [ label = "g" ]; "n6" -> "n4" [ label = "g" ]; "n5" -> "n7" [ label = "c" ]; "n7" -> "n5" [ label = "c" ]; "n6" -> "n7" [ label = "w" ]; "n7" -> "n6" [ label = "w" ]; "n7" -> "n8" [ label = "m" ]; "n8" -> "n7" [ label = "m" ]; "n8" -> "n9" [ label = "g" ]; "n9" -> "n8" [ label = "g" ]; } ocamlgraph-2.0.0/dgraph/examples/crazy2.dot0000755000175000001440000000066113735627615017224 0ustar rtusersdigraph "unix" { graph [ fontname = "Helvetica-Oblique", fontsize = 36, label = "\n\n\n\nObject Oriented Graphs\nStephen North, 3/19/93", size = "6,6" ]; node [ shape = polygon, sides = 4, distortion = "0.0", orientation = "0.0", skew = "0.0", color = blue, style = filled, fontname = "Helvetica-Outline" ]; "CB Unix 2" [sides=10, distortion="0.851818", orientation=32, skew="-0.020120", color=greenyellow]; } ocamlgraph-2.0.0/dgraph/examples/gzip.dot0000755000175000001440000011466413735627615016774 0ustar rtusersdigraph G { "UV atoi (97)" [shape=diamond, label="atoi", color="#4000A0", style=dotted]; "UV zip (0)" [shape=diamond, label="zip", color="#000000", style=bold]; "UV do_exit (98)" [shape=diamond, label="do_exit", color="#408020", style=bold]; "UV flush_outbuf (1)" [label="flush_outbuf", color="#000000", style=bold]; "UV updcrc (2)" [shape=diamond, label="updcrc", color="#008000", style=bold]; "UV treat_file (99)" [shape=diamond, label="treat_file", color="#4080A0", style=bold]; "UV treat_stdin (100)" [shape=diamond, label="treat_stdin", color="#C00020", style=bold]; "UV bi_init (3)" [label="bi_init", color="#000000", style=bold]; "UV do_list (101)" [shape=diamond, label="do_list", color="#C000A0", style=bold]; "UV ct_init (4)" [label="ct_init", color="#000000", style=bold]; "UV fileno (102)" [shape=diamond, label="fileno", color="#C08020", style=dotted]; "UV lm_init (5)" [label="lm_init", color="#000000", style=bold]; "UV basename (6)" [shape=diamond, label="basename", color="#808000", style=bold]; "UV isatty (103)" [shape=diamond, label="isatty", color="#C080A0", style=dotted]; "UV fstat (104)" [shape=diamond, label="fstat", color="#400060", style=dotted]; "UV deflate (7)" [label="deflate", color="#000000", style=bold]; "UV get_method (105)" [shape=diamond, label="get_method", color="#4000E0", style=bold]; "UV file_read (8)" [shape=diamond, label="file_read", color="#000040", style=bold]; "UV read (9)" [shape=diamond, label="read", color="#0000C0", style=dotted]; "UV get_istat (106)" [label="get_istat", color="#4080A0", style=bold]; "UV make_ofname (107)" [label="make_ofname", color="#4080A0", style=bold]; "UV copy (10)" [shape=diamond, label="copy", color="#008040", style=bold]; "UV __errno_location (11)" [shape=diamond, label="__errno_location", color="#0080C0", style=dotted]; "UV open (108)" [label="open", color="#4080A0", style=dotted]; "UV close (109)" [shape=diamond, label="close", color="#C000E0", style=dotted]; "UV write_buf (12)" [shape=diamond, label="write_buf", color="#800040", style=bold]; "UV read_error (13)" [shape=diamond, label="read_error", color="#8000C0", style=bold]; "UV create_outfile (110)" [label="create_outfile", color="#4080A0", style=bold]; "UV unlink (111)" [shape=diamond, label="unlink", color="#C080E0", style=dotted]; "UV clear_bufs (14)" [shape=diamond, label="clear_bufs", color="#808040", style=bold]; "UV fill_inbuf (15)" [shape=diamond, label="fill_inbuf", color="#8080C0", style=bold]; "UV copy_stat (112)" [label="copy_stat", color="#4080A0", style=bold]; "UV flush_window (16)" [shape=diamond, label="flush_window", color="#004000", style=bold]; "UV check_ofname (113)" [label="check_ofname", color="#4080A0", style=bold]; "UV write (17)" [label="write", color="#800040", style=dotted]; "UV name_too_long (114)" [label="name_too_long", color="#4080A0", style=bold]; "UV write_error (18)" [shape=diamond, label="write_error", color="#00C000", style=bold]; "UV shorten_name (115)" [label="shorten_name", color="#4080A0", style=bold]; "UV strlwr (19)" [shape=diamond, label="strlwr", color="#00C080", style=bold]; "UV do_stat (116)" [label="do_stat", color="#4080A0", style=bold]; "UV isupper (20)" [shape=diamond, label="isupper", color="#804000", style=dotted]; "UV lstat (117)" [label="lstat", color="#4080A0", style=dotted]; "UV strrchr (21)" [shape=diamond, label="strrchr", color="#804080", style=dotted]; "UV stat (118)" [label="stat", color="#4080A0", style=dotted]; "UV get_suffix (119)" [label="get_suffix", color="#4080A0", style=bold]; "UV make_simple_name (22)" [shape=diamond, label="make_simple_name", color="#80C000", style=bold]; "UV strcat (120)" [label="strcat", color="#4080A0", style=dotted]; "UV add_envopt (23)" [shape=diamond, label="add_envopt", color="#80C080", style=bold]; "UV memcmp (121)" [label="memcmp", color="#4000E0", style=dotted]; "UV getenv (24)" [label="getenv", color="#80C080", style=dotted]; "UV strlen (25)" [shape=diamond, label="strlen", color="#0040C0", style=dotted]; "UV printf (122)" [label="printf", color="#C000A0", style=dotted]; "UV lseek (123)" [label="lseek", color="#C000A0", style=dotted]; "UV xmalloc (26)" [label="xmalloc", color="#80C080", style=bold]; "UV strcpy (27)" [shape=diamond, label="strcpy", color="#00C0C0", style=dotted]; "UV ctime (124)" [label="ctime", color="#C000A0", style=dotted]; "UV same_file (125)" [label="same_file", color="#4080A0", style=bold]; "UV strspn (28)" [label="strspn", color="#80C080", style=dotted]; "UV strcspn (29)" [shape=diamond, label="strcspn", color="#8040C0", style=dotted]; "UV fflush (126)" [label="fflush", color="#4080A0", style=dotted]; "UV free (30)" [shape=diamond, label="free", color="#80C040", style=dotted]; "UV fgets (127)" [label="fgets", color="#4080A0", style=dotted]; "UV chmod (128)" [label="chmod", color="#4080A0", style=dotted]; "UV calloc (31)" [label="calloc", color="#80C080", style=dotted]; "UV error (32)" [shape=diamond, label="error", color="#400000", style=bold]; "UV reset_times (129)" [label="reset_times", color="#4080A0", style=bold]; "UV fprintf (33)" [shape=diamond, label="fprintf", color="#400080", style=dotted]; "UV utime (130)" [label="utime", color="#4080A0", style=dotted]; "UV abort_gzip (34)" [shape=diamond, label="abort_gzip", color="#408000", style=bold]; "UV chown (131)" [label="chown", color="#4080A0", style=dotted]; "UV exit (132)" [label="exit", color="#408020", style=dotted]; "UV warn (35)" [shape=diamond, label="warn", color="#408080", style=bold]; "UV perror (36)" [shape=diamond, label="perror", color="#C00000", style=dotted]; "UV fill_window (133)" [label="fill_window", color="#000000", style=bold]; "UV display_ratio (37)" [shape=diamond, label="display_ratio", color="#C00080", style=bold]; "UV longest_match (134)" [label="longest_match", color="#000000", style=bold]; "UV _IO_putc (38)" [label="_IO_putc", color="#C00080", style=dotted]; "UV deflate_fast (135)" [label="deflate_fast", color="#000000", style=bold]; "UV malloc (39)" [shape=diamond, label="malloc", color="#C08080", style=dotted]; "UV check_zipfile (40)" [label="check_zipfile", color="#4000E0", style=bold]; "UV unzip (41)" [shape=diamond, label="unzip", color="#4000C0", style=bold]; "UV inflate (42)" [label="inflate", color="#4000C0", style=bold]; "UV read_tree (43)" [label="read_tree", color="#C000C0", style=bold]; "UV build_tree (44)" [label="build_tree", color="#C000C0", style=bold]; "UV unpack (45)" [shape=diamond, label="unpack", color="#C000C0", style=bold]; "UV unlzw (46)" [shape=diamond, label="unlzw", color="#C08040", style=bold]; "UV memset (47)" [shape=diamond, label="memset", color="#C080C0", style=dotted]; "UV memcpy (48)" [shape=diamond, label="memcpy", color="#404000", style=dotted]; "UV fillbuf (49)" [label="fillbuf", color="#C04040", style=bold]; "UV getbits (50)" [label="getbits", color="#C04040", style=bold]; "UV init_getbits (51)" [label="init_getbits", color="#C04040", style=bold]; "UV make_table (52)" [label="make_table", color="#C04040", style=bold]; "UV read_pt_len (53)" [label="read_pt_len", color="#C04040", style=bold]; "UV read_c_len (54)" [label="read_c_len", color="#C04040", style=bold]; "UV decode_c (55)" [label="decode_c", color="#C04040", style=bold]; "UV decode_p (56)" [label="decode_p", color="#C04040", style=bold]; "UV huf_decode_start (57)" [label="huf_decode_start", color="#C04040", style=bold]; "UV decode_start (58)" [label="decode_start", color="#C04040", style=bold]; "UV decode (59)" [label="decode", color="#C04040", style=bold]; "UV unlzh (60)" [shape=diamond, label="unlzh", color="#C04040", style=bold]; "UV gen_codes (61)" [label="gen_codes", color="#000000", style=bold]; "UV bi_reverse (62)" [label="bi_reverse", color="#000000", style=bold]; "UV init_block (63)" [label="init_block", color="#000000", style=bold]; "UV pqdownheap (64)" [label="pqdownheap", color="#000000", style=bold]; "UV gen_bitlen (65)" [label="gen_bitlen", color="#000000", style=bold]; "UV build_tree_0 (66)" [label="build_tree_0", color="#000000", style=bold]; "UV scan_tree (67)" [label="scan_tree", color="#000000", style=bold]; "UV send_tree (68)" [label="send_tree", color="#000000", style=bold]; "UV send_bits (69)" [label="send_bits", color="#000000", style=bold]; "UV build_bl_tree (70)" [label="build_bl_tree", color="#000000", style=bold]; "UV send_all_trees (71)" [label="send_all_trees", color="#000000", style=bold]; "UV flush_block (72)" [label="flush_block", color="#000000", style=bold]; "UV set_file_type (73)" [label="set_file_type", color="#000000", style=bold]; "UV copy_block (74)" [label="copy_block", color="#000000", style=bold]; "UV compress_block (75)" [label="compress_block", color="#000000", style=bold]; "UV bi_windup (76)" [label="bi_windup", color="#000000", style=bold]; "UV ct_tally (77)" [label="ct_tally", color="#000000", style=bold]; "UV lzw (78)" [shape=diamond, label="lzw", color="#808060", style=bold]; "UV huft_build (79)" [label="huft_build", color="#4000C0", style=bold]; "UV huft_free (80)" [label="huft_free", color="#4000C0", style=bold]; "UV inflate_codes (81)" [label="inflate_codes", color="#4000C0", style=bold]; "UV inflate_stored (82)" [label="inflate_stored", color="#4000C0", style=bold]; "UV inflate_fixed (83)" [label="inflate_fixed", color="#4000C0", style=bold]; "UV inflate_dynamic (84)" [label="inflate_dynamic", color="#4000C0", style=bold]; "UV inflate_block (85)" [label="inflate_block", color="#4000C0", style=bold]; "UV (86)" [shape=diamond, label="", color="#80C020", style=bold]; "UV usage (87)" [shape=diamond, label="usage", color="#80C0A0", style=bold]; "UV help (88)" [shape=diamond, label="help", color="#004060", style=bold]; "UV license (89)" [shape=diamond, label="license", color="#0040E0", style=bold]; "UV version (90)" [shape=diamond, label="version", color="#00C060", style=bold]; "UV main (91)" [shape=diamond, label="main", color="#00C0E0", style=bold]; "UV strcmp (92)" [shape=diamond, label="strcmp", color="#804060", style=dotted]; "UV signal (93)" [shape=diamond, label="signal", color="#8040E0", style=dotted]; "UV strncmp (94)" [shape=diamond, label="strncmp", color="#80C060", style=dotted]; "UV strncpy (95)" [shape=diamond, label="strncpy", color="#80C0E0", style=dotted]; "UV getopt_long (96)" [shape=diamond, label="getopt_long", color="#400020", style=dotted]; subgraph cluster_36 { label="S 36"; color="#C00000"; style=bold; "UV perror (36)"; }; subgraph cluster_37 { label="S 37"; color="#C00080"; style=bold; "UV _IO_putc (38)";"UV display_ratio (37)"; }; subgraph cluster_86 { label="S 86"; color="#80C020"; style=bold; "UV (86)"; }; subgraph cluster_87 { label="S 87"; color="#80C0A0"; style=bold; "UV usage (87)"; }; subgraph cluster_39 { label="S 39"; color="#C08080"; style=bold; "UV malloc (39)"; }; subgraph cluster_88 { label="S 88"; color="#004060"; style=bold; "UV help (88)"; }; subgraph cluster_89 { label="S 89"; color="#0040E0"; style=bold; "UV license (89)"; }; subgraph cluster_20 { label="S 20"; color="#804000"; style=bold; "UV isupper (20)"; }; subgraph cluster_21 { label="S 21"; color="#804080"; style=bold; "UV strrchr (21)"; }; subgraph cluster_111 { label="S 111"; color="#C080E0"; style=bold; "UV unlink (111)"; }; subgraph cluster_22 { label="S 22"; color="#80C000"; style=bold; "UV make_simple_name (22)"; }; subgraph cluster_23 { label="S 23"; color="#80C080"; style=bold; "UV calloc (31)";"UV strspn (28)";"UV xmalloc (26)";"UV getenv (24)";"UV add_envopt (23)"; }; subgraph cluster_25 { label="S 25"; color="#0040C0"; style=bold; "UV strlen (25)"; }; subgraph cluster_27 { label="S 27"; color="#00C0C0"; style=bold; "UV strcpy (27)"; }; subgraph cluster_41 { label="S 41"; color="#4000C0"; style=bold; "UV inflate_block (85)";"UV inflate_dynamic (84)";"UV inflate_fixed (83)";"UV inflate_stored (82)";"UV inflate_codes (81)";"UV huft_free (80)";"UV huft_build (79)";"UV inflate (42)";"UV unzip (41)"; }; subgraph cluster_90 { label="S 90"; color="#00C060"; style=bold; "UV version (90)"; }; subgraph cluster_29 { label="S 29"; color="#8040C0"; style=bold; "UV strcspn (29)"; }; subgraph cluster_91 { label="S 91"; color="#00C0E0"; style=bold; "UV main (91)"; }; subgraph cluster_78 { label="S 78"; color="#808060"; style=bold; "UV lzw (78)"; }; subgraph cluster_92 { label="S 92"; color="#804060"; style=bold; "UV strcmp (92)"; }; subgraph cluster_0 { label="S 0"; color="#000000"; style=bold; "UV ct_tally (77)";"UV bi_windup (76)";"UV compress_block (75)";"UV copy_block (74)";"UV set_file_type (73)";"UV flush_block (72)";"UV send_all_trees (71)";"UV build_bl_tree (70)";"UV send_bits (69)";"UV send_tree (68)";"UV scan_tree (67)";"UV build_tree_0 (66)";"UV gen_bitlen (65)";"UV pqdownheap (64)";"UV init_block (63)";"UV bi_reverse (62)";"UV gen_codes (61)";"UV deflate_fast (135)";"UV longest_match (134)";"UV fill_window (133)";"UV deflate (7)";"UV lm_init (5)";"UV ct_init (4)";"UV bi_init (3)";"UV flush_outbuf (1)";"UV zip (0)"; }; subgraph cluster_93 { label="S 93"; color="#8040E0"; style=bold; "UV signal (93)"; }; subgraph cluster_45 { label="S 45"; color="#C000C0"; style=bold; "UV unpack (45)";"UV build_tree (44)";"UV read_tree (43)"; }; subgraph cluster_10 { label="S 10"; color="#008040"; style=bold; "UV copy (10)"; }; subgraph cluster_100 { label="S 100"; color="#C00020"; style=bold; "UV treat_stdin (100)"; }; subgraph cluster_94 { label="S 94"; color="#80C060"; style=bold; "UV strncmp (94)"; }; subgraph cluster_46 { label="S 46"; color="#C08040"; style=bold; "UV unlzw (46)"; }; subgraph cluster_11 { label="S 11"; color="#0080C0"; style=bold; "UV __errno_location (11)"; }; subgraph cluster_101 { label="S 101"; color="#C000A0"; style=bold; "UV ctime (124)";"UV lseek (123)";"UV printf (122)";"UV do_list (101)"; }; subgraph cluster_2 { label="S 2"; color="#008000"; style=bold; "UV updcrc (2)"; }; subgraph cluster_95 { label="S 95"; color="#80C0E0"; style=bold; "UV strncpy (95)"; }; subgraph cluster_60 { label="S 60"; color="#C04040"; style=bold; "UV unlzh (60)";"UV decode (59)";"UV decode_start (58)";"UV huf_decode_start (57)";"UV decode_p (56)";"UV decode_c (55)";"UV read_c_len (54)";"UV read_pt_len (53)";"UV make_table (52)";"UV init_getbits (51)";"UV getbits (50)";"UV fillbuf (49)"; }; subgraph cluster_47 { label="S 47"; color="#C080C0"; style=bold; "UV memset (47)"; }; subgraph cluster_12 { label="S 12"; color="#800040"; style=bold; "UV write (17)";"UV write_buf (12)"; }; subgraph cluster_102 { label="S 102"; color="#C08020"; style=bold; "UV fileno (102)"; }; subgraph cluster_96 { label="S 96"; color="#400020"; style=bold; "UV getopt_long (96)"; }; subgraph cluster_48 { label="S 48"; color="#404000"; style=bold; "UV memcpy (48)"; }; subgraph cluster_13 { label="S 13"; color="#8000C0"; style=bold; "UV read_error (13)"; }; subgraph cluster_103 { label="S 103"; color="#C080A0"; style=bold; "UV isatty (103)"; }; subgraph cluster_97 { label="S 97"; color="#4000A0"; style=bold; "UV atoi (97)"; }; subgraph cluster_14 { label="S 14"; color="#808040"; style=bold; "UV clear_bufs (14)"; }; subgraph cluster_104 { label="S 104"; color="#400060"; style=bold; "UV fstat (104)"; }; subgraph cluster_98 { label="S 98"; color="#408020"; style=bold; "UV exit (132)";"UV do_exit (98)"; }; subgraph cluster_15 { label="S 15"; color="#8080C0"; style=bold; "UV fill_inbuf (15)"; }; subgraph cluster_105 { label="S 105"; color="#4000E0"; style=bold; "UV check_zipfile (40)";"UV memcmp (121)";"UV get_method (105)"; }; subgraph cluster_6 { label="S 6"; color="#808000"; style=bold; "UV basename (6)"; }; subgraph cluster_16 { label="S 16"; color="#004000"; style=bold; "UV flush_window (16)"; }; subgraph cluster_99 { label="S 99"; color="#4080A0"; style=bold; "UV chown (131)";"UV utime (130)";"UV reset_times (129)";"UV chmod (128)";"UV fgets (127)";"UV fflush (126)";"UV same_file (125)";"UV strcat (120)";"UV get_suffix (119)";"UV stat (118)";"UV lstat (117)";"UV do_stat (116)";"UV shorten_name (115)";"UV name_too_long (114)";"UV check_ofname (113)";"UV copy_stat (112)";"UV create_outfile (110)";"UV open (108)";"UV make_ofname (107)";"UV get_istat (106)";"UV treat_file (99)"; }; subgraph cluster_30 { label="S 30"; color="#80C040"; style=bold; "UV free (30)"; }; subgraph cluster_8 { label="S 8"; color="#000040"; style=bold; "UV file_read (8)"; }; subgraph cluster_18 { label="S 18"; color="#00C000"; style=bold; "UV write_error (18)"; }; subgraph cluster_9 { label="S 9"; color="#0000C0"; style=bold; "UV read (9)"; }; subgraph cluster_32 { label="S 32"; color="#400000"; style=bold; "UV error (32)"; }; subgraph cluster_19 { label="S 19"; color="#00C080"; style=bold; "UV strlwr (19)"; }; subgraph cluster_109 { label="S 109"; color="#C000E0"; style=bold; "UV close (109)"; }; subgraph cluster_33 { label="S 33"; color="#400080"; style=bold; "UV fprintf (33)"; }; subgraph cluster_34 { label="S 34"; color="#408000"; style=bold; "UV abort_gzip (34)"; }; subgraph cluster_35 { label="S 35"; color="#408080"; style=bold; "UV warn (35)"; }; "UV zip (0)" -> "UV flush_outbuf (1)" [color="#000000"]; "UV zip (0)" -> "UV updcrc (2)" [color="#000000"]; "UV zip (0)" -> "UV bi_init (3)" [color="#000000"]; "UV zip (0)" -> "UV ct_init (4)" [color="#000000"]; "UV zip (0)" -> "UV lm_init (5)" [color="#000000"]; "UV zip (0)" -> "UV basename (6)" [color="#000000"]; "UV zip (0)" -> "UV deflate (7)" [color="#000000"]; "UV zip (0)" -> "UV write_buf (12)" [color="#000000"]; "UV zip (0)" -> "UV error (32)" [color="#000000"]; "UV zip (0)" -> "UV memset (47)" [color="#000000"]; "UV zip (0)" -> "UV memcpy (48)" [color="#000000"]; "UV zip (0)" -> "UV (86)" [color="#000000"]; "UV do_exit (98)" -> "UV free (30)" [color="#408020"]; "UV do_exit (98)" -> "UV exit (132)" [color="#408020"]; "UV flush_outbuf (1)" -> "UV write_buf (12)" [color="#000000"]; "UV treat_file (99)" -> "UV __errno_location (11)" [color="#4080A0"]; "UV treat_file (99)" -> "UV clear_bufs (14)" [color="#4080A0"]; "UV treat_file (99)" -> "UV write_error (18)" [color="#4080A0"]; "UV treat_file (99)" -> "UV strlwr (19)" [color="#4080A0"]; "UV treat_file (99)" -> "UV isupper (20)" [color="#4080A0"]; "UV treat_file (99)" -> "UV strrchr (21)" [color="#4080A0"]; "UV treat_file (99)" -> "UV strlen (25)" [color="#4080A0"]; "UV treat_file (99)" -> "UV strcpy (27)" [color="#4080A0"]; "UV treat_file (99)" -> "UV strcspn (29)" [color="#4080A0"]; "UV treat_file (99)" -> "UV error (32)" [color="#4080A0"]; "UV treat_file (99)" -> "UV fprintf (33)" [color="#4080A0"]; "UV treat_file (99)" -> "UV perror (36)" [color="#4080A0"]; "UV treat_file (99)" -> "UV display_ratio (37)" [color="#4080A0"]; "UV treat_file (99)" -> "UV (86)" [color="#4080A0"]; "UV treat_file (99)" -> "UV strcmp (92)" [color="#4080A0"]; "UV treat_file (99)" -> "UV treat_stdin (100)" [color="#4080A0"]; "UV treat_file (99)" -> "UV do_list (101)" [color="#4080A0"]; "UV treat_file (99)" -> "UV fileno (102)" [color="#4080A0"]; "UV treat_file (99)" -> "UV isatty (103)" [color="#4080A0"]; "UV treat_file (99)" -> "UV fstat (104)" [color="#4080A0"]; "UV treat_file (99)" -> "UV get_method (105)" [color="#4080A0"]; "UV treat_file (99)" -> "UV get_istat (106)" [color="#4080A0"]; "UV treat_file (99)" -> "UV make_ofname (107)" [color="#4080A0"]; "UV treat_file (99)" -> "UV open (108)" [color="#4080A0"]; "UV treat_file (99)" -> "UV close (109)" [color="#4080A0"]; "UV treat_file (99)" -> "UV create_outfile (110)" [color="#4080A0"]; "UV treat_file (99)" -> "UV unlink (111)" [color="#4080A0"]; "UV treat_file (99)" -> "UV copy_stat (112)" [color="#4080A0"]; "UV treat_stdin (100)" -> "UV clear_bufs (14)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV strcpy (27)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV error (32)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV fprintf (33)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV display_ratio (37)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV (86)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV do_exit (98)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV do_list (101)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV fileno (102)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV isatty (103)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV fstat (104)" [color="#C00020"]; "UV treat_stdin (100)" -> "UV get_method (105)" [color="#C00020"]; "UV do_list (101)" -> "UV read (9)" [color="#C000A0"]; "UV do_list (101)" -> "UV read_error (13)" [color="#C000A0"]; "UV do_list (101)" -> "UV display_ratio (37)" [color="#C000A0"]; "UV do_list (101)" -> "UV printf (122)" [color="#C000A0"]; "UV do_list (101)" -> "UV lseek (123)" [color="#C000A0"]; "UV do_list (101)" -> "UV ctime (124)" [color="#C000A0"]; "UV ct_init (4)" -> "UV gen_codes (61)" [color="#000000"]; "UV ct_init (4)" -> "UV bi_reverse (62)" [color="#000000"]; "UV ct_init (4)" -> "UV init_block (63)" [color="#000000"]; "UV lm_init (5)" -> "UV error (32)" [color="#000000"]; "UV lm_init (5)" -> "UV memset (47)" [color="#000000"]; "UV lm_init (5)" -> "UV (86)" [color="#000000"]; "UV lm_init (5)" -> "UV fill_window (133)" [color="#000000"]; "UV basename (6)" -> "UV strlwr (19)" [color="#808000"]; "UV basename (6)" -> "UV strrchr (21)" [color="#808000"]; "UV deflate (7)" -> "UV flush_block (72)" [color="#000000"]; "UV deflate (7)" -> "UV ct_tally (77)" [color="#000000"]; "UV deflate (7)" -> "UV fill_window (133)" [color="#000000"]; "UV deflate (7)" -> "UV longest_match (134)" [color="#000000"]; "UV deflate (7)" -> "UV deflate_fast (135)" [color="#000000"]; "UV get_method (105)" -> "UV basename (6)" [color="#4000E0"]; "UV get_method (105)" -> "UV fill_inbuf (15)" [color="#4000E0"]; "UV get_method (105)" -> "UV error (32)" [color="#4000E0"]; "UV get_method (105)" -> "UV fprintf (33)" [color="#4000E0"]; "UV get_method (105)" -> "UV check_zipfile (40)" [color="#4000E0"]; "UV get_method (105)" -> "UV memcmp (121)" [color="#4000E0"]; "UV file_read (8)" -> "UV updcrc (2)" [color="#000040"]; "UV file_read (8)" -> "UV read (9)" [color="#000040"]; "UV get_istat (106)" -> "UV __errno_location (11)" [color="#4080A0"]; "UV get_istat (106)" -> "UV strlen (25)" [color="#4080A0"]; "UV get_istat (106)" -> "UV strcpy (27)" [color="#4080A0"]; "UV get_istat (106)" -> "UV perror (36)" [color="#4080A0"]; "UV get_istat (106)" -> "UV strcmp (92)" [color="#4080A0"]; "UV get_istat (106)" -> "UV do_stat (116)" [color="#4080A0"]; "UV get_istat (106)" -> "UV get_suffix (119)" [color="#4080A0"]; "UV get_istat (106)" -> "UV strcat (120)" [color="#4080A0"]; "UV make_ofname (107)" -> "UV strlwr (19)" [color="#4080A0"]; "UV make_ofname (107)" -> "UV strcpy (27)" [color="#4080A0"]; "UV make_ofname (107)" -> "UV fprintf (33)" [color="#4080A0"]; "UV make_ofname (107)" -> "UV strcmp (92)" [color="#4080A0"]; "UV make_ofname (107)" -> "UV get_suffix (119)" [color="#4080A0"]; "UV make_ofname (107)" -> "UV strcat (120)" [color="#4080A0"]; "UV copy (10)" -> "UV read (9)" [color="#008040"]; "UV copy (10)" -> "UV __errno_location (11)" [color="#008040"]; "UV copy (10)" -> "UV write_buf (12)" [color="#008040"]; "UV copy (10)" -> "UV read_error (13)" [color="#008040"]; "UV write_buf (12)" -> "UV write (17)" [color="#800040"]; "UV write_buf (12)" -> "UV write_error (18)" [color="#800040"]; "UV read_error (13)" -> "UV __errno_location (11)" [color="#8000C0"]; "UV read_error (13)" -> "UV fprintf (33)" [color="#8000C0"]; "UV read_error (13)" -> "UV abort_gzip (34)" [color="#8000C0"]; "UV read_error (13)" -> "UV perror (36)" [color="#8000C0"]; "UV create_outfile (110)" -> "UV fprintf (33)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV perror (36)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV fstat (104)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV open (108)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV close (109)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV unlink (111)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV check_ofname (113)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV name_too_long (114)" [color="#4080A0"]; "UV create_outfile (110)" -> "UV shorten_name (115)" [color="#4080A0"]; "UV fill_inbuf (15)" -> "UV read (9)" [color="#8080C0"]; "UV fill_inbuf (15)" -> "UV __errno_location (11)" [color="#8080C0"]; "UV fill_inbuf (15)" -> "UV read_error (13)" [color="#8080C0"]; "UV copy_stat (112)" -> "UV fprintf (33)" [color="#4080A0"]; "UV copy_stat (112)" -> "UV perror (36)" [color="#4080A0"]; "UV copy_stat (112)" -> "UV unlink (111)" [color="#4080A0"]; "UV copy_stat (112)" -> "UV chmod (128)" [color="#4080A0"]; "UV copy_stat (112)" -> "UV reset_times (129)" [color="#4080A0"]; "UV copy_stat (112)" -> "UV chown (131)" [color="#4080A0"]; "UV flush_window (16)" -> "UV updcrc (2)" [color="#004000"]; "UV flush_window (16)" -> "UV write_buf (12)" [color="#004000"]; "UV check_ofname (113)" -> "UV __errno_location (11)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV isupper (20)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV strcpy (27)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV fprintf (33)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV perror (36)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV strcmp (92)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV fileno (102)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV isatty (103)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV unlink (111)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV name_too_long (114)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV shorten_name (115)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV stat (118)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV same_file (125)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV fflush (126)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV fgets (127)" [color="#4080A0"]; "UV check_ofname (113)" -> "UV chmod (128)" [color="#4080A0"]; "UV name_too_long (114)" -> "UV strlen (25)" [color="#4080A0"]; "UV name_too_long (114)" -> "UV stat (118)" [color="#4080A0"]; "UV name_too_long (114)" -> "UV same_file (125)" [color="#4080A0"]; "UV write_error (18)" -> "UV fprintf (33)" [color="#00C000"]; "UV write_error (18)" -> "UV abort_gzip (34)" [color="#00C000"]; "UV write_error (18)" -> "UV perror (36)" [color="#00C000"]; "UV shorten_name (115)" -> "UV strrchr (21)" [color="#4080A0"]; "UV shorten_name (115)" -> "UV strlen (25)" [color="#4080A0"]; "UV shorten_name (115)" -> "UV strcpy (27)" [color="#4080A0"]; "UV shorten_name (115)" -> "UV strcspn (29)" [color="#4080A0"]; "UV shorten_name (115)" -> "UV error (32)" [color="#4080A0"]; "UV shorten_name (115)" -> "UV strcmp (92)" [color="#4080A0"]; "UV shorten_name (115)" -> "UV get_suffix (119)" [color="#4080A0"]; "UV strlwr (19)" -> "UV isupper (20)" [color="#00C080"]; "UV do_stat (116)" -> "UV __errno_location (11)" [color="#4080A0"]; "UV do_stat (116)" -> "UV lstat (117)" [color="#4080A0"]; "UV do_stat (116)" -> "UV stat (118)" [color="#4080A0"]; "UV get_suffix (119)" -> "UV strlwr (19)" [color="#4080A0"]; "UV get_suffix (119)" -> "UV strlen (25)" [color="#4080A0"]; "UV get_suffix (119)" -> "UV strcpy (27)" [color="#4080A0"]; "UV get_suffix (119)" -> "UV strcmp (92)" [color="#4080A0"]; "UV make_simple_name (22)" -> "UV strrchr (21)" [color="#80C000"]; "UV add_envopt (23)" -> "UV getenv (24)" [color="#80C080"]; "UV add_envopt (23)" -> "UV strlen (25)" [color="#80C080"]; "UV add_envopt (23)" -> "UV xmalloc (26)" [color="#80C080"]; "UV add_envopt (23)" -> "UV strcpy (27)" [color="#80C080"]; "UV add_envopt (23)" -> "UV strspn (28)" [color="#80C080"]; "UV add_envopt (23)" -> "UV strcspn (29)" [color="#80C080"]; "UV add_envopt (23)" -> "UV free (30)" [color="#80C080"]; "UV add_envopt (23)" -> "UV calloc (31)" [color="#80C080"]; "UV add_envopt (23)" -> "UV error (32)" [color="#80C080"]; "UV add_envopt (23)" -> "UV malloc (39)" [color="#80C080"]; "UV xmalloc (26)" -> "UV error (32)" [color="#80C080"]; "UV xmalloc (26)" -> "UV malloc (39)" [color="#80C080"]; "UV error (32)" -> "UV fprintf (33)" [color="#400000"]; "UV error (32)" -> "UV abort_gzip (34)" [color="#400000"]; "UV reset_times (129)" -> "UV fprintf (33)" [color="#4080A0"]; "UV reset_times (129)" -> "UV perror (36)" [color="#4080A0"]; "UV reset_times (129)" -> "UV utime (130)" [color="#4080A0"]; "UV abort_gzip (34)" -> "UV do_exit (98)" [color="#408000"]; "UV abort_gzip (34)" -> "UV close (109)" [color="#408000"]; "UV abort_gzip (34)" -> "UV unlink (111)" [color="#408000"]; "UV warn (35)" -> "UV fprintf (33)" [color="#408080"]; "UV fill_window (133)" -> "UV memcpy (48)" [color="#000000"]; "UV fill_window (133)" -> "UV (86)" [color="#000000"]; "UV display_ratio (37)" -> "UV fprintf (33)" [color="#C00080"]; "UV display_ratio (37)" -> "UV _IO_putc (38)" [color="#C00080"]; "UV deflate_fast (135)" -> "UV flush_block (72)" [color="#000000"]; "UV deflate_fast (135)" -> "UV ct_tally (77)" [color="#000000"]; "UV deflate_fast (135)" -> "UV fill_window (133)" [color="#000000"]; "UV deflate_fast (135)" -> "UV longest_match (134)" [color="#000000"]; "UV check_zipfile (40)" -> "UV fprintf (33)" [color="#4000E0"]; "UV unzip (41)" -> "UV updcrc (2)" [color="#4000C0"]; "UV unzip (41)" -> "UV fill_inbuf (15)" [color="#4000C0"]; "UV unzip (41)" -> "UV flush_window (16)" [color="#4000C0"]; "UV unzip (41)" -> "UV free (30)" [color="#4000C0"]; "UV unzip (41)" -> "UV error (32)" [color="#4000C0"]; "UV unzip (41)" -> "UV fprintf (33)" [color="#4000C0"]; "UV unzip (41)" -> "UV malloc (39)" [color="#4000C0"]; "UV unzip (41)" -> "UV inflate (42)" [color="#4000C0"]; "UV unzip (41)" -> "UV memset (47)" [color="#4000C0"]; "UV unzip (41)" -> "UV memcpy (48)" [color="#4000C0"]; "UV inflate (42)" -> "UV flush_window (16)" [color="#4000C0"]; "UV inflate (42)" -> "UV inflate_block (85)" [color="#4000C0"]; "UV read_tree (43)" -> "UV fill_inbuf (15)" [color="#C000C0"]; "UV read_tree (43)" -> "UV error (32)" [color="#C000C0"]; "UV unpack (45)" -> "UV fill_inbuf (15)" [color="#C000C0"]; "UV unpack (45)" -> "UV flush_window (16)" [color="#C000C0"]; "UV unpack (45)" -> "UV error (32)" [color="#C000C0"]; "UV unpack (45)" -> "UV read_tree (43)" [color="#C000C0"]; "UV unpack (45)" -> "UV build_tree (44)" [color="#C000C0"]; "UV unlzw (46)" -> "UV read (9)" [color="#C08040"]; "UV unlzw (46)" -> "UV write_buf (12)" [color="#C08040"]; "UV unlzw (46)" -> "UV read_error (13)" [color="#C08040"]; "UV unlzw (46)" -> "UV fill_inbuf (15)" [color="#C08040"]; "UV unlzw (46)" -> "UV error (32)" [color="#C08040"]; "UV unlzw (46)" -> "UV fprintf (33)" [color="#C08040"]; "UV unlzw (46)" -> "UV memset (47)" [color="#C08040"]; "UV unlzw (46)" -> "UV memcpy (48)" [color="#C08040"]; "UV fillbuf (49)" -> "UV fill_inbuf (15)" [color="#C04040"]; "UV getbits (50)" -> "UV fillbuf (49)" [color="#C04040"]; "UV init_getbits (51)" -> "UV fillbuf (49)" [color="#C04040"]; "UV make_table (52)" -> "UV error (32)" [color="#C04040"]; "UV read_pt_len (53)" -> "UV fillbuf (49)" [color="#C04040"]; "UV read_pt_len (53)" -> "UV getbits (50)" [color="#C04040"]; "UV read_pt_len (53)" -> "UV make_table (52)" [color="#C04040"]; "UV read_c_len (54)" -> "UV fillbuf (49)" [color="#C04040"]; "UV read_c_len (54)" -> "UV getbits (50)" [color="#C04040"]; "UV read_c_len (54)" -> "UV make_table (52)" [color="#C04040"]; "UV decode_c (55)" -> "UV fillbuf (49)" [color="#C04040"]; "UV decode_c (55)" -> "UV getbits (50)" [color="#C04040"]; "UV decode_c (55)" -> "UV read_pt_len (53)" [color="#C04040"]; "UV decode_c (55)" -> "UV read_c_len (54)" [color="#C04040"]; "UV decode_p (56)" -> "UV fillbuf (49)" [color="#C04040"]; "UV decode_p (56)" -> "UV getbits (50)" [color="#C04040"]; "UV huf_decode_start (57)" -> "UV init_getbits (51)" [color="#C04040"]; "UV decode_start (58)" -> "UV huf_decode_start (57)" [color="#C04040"]; "UV decode (59)" -> "UV decode_c (55)" [color="#C04040"]; "UV decode (59)" -> "UV decode_p (56)" [color="#C04040"]; "UV unlzh (60)" -> "UV write_buf (12)" [color="#C04040"]; "UV unlzh (60)" -> "UV fill_inbuf (15)" [color="#C04040"]; "UV unlzh (60)" -> "UV error (32)" [color="#C04040"]; "UV unlzh (60)" -> "UV decode_start (58)" [color="#C04040"]; "UV unlzh (60)" -> "UV decode (59)" [color="#C04040"]; "UV gen_codes (61)" -> "UV bi_reverse (62)" [color="#000000"]; "UV build_tree_0 (66)" -> "UV gen_codes (61)" [color="#000000"]; "UV build_tree_0 (66)" -> "UV pqdownheap (64)" [color="#000000"]; "UV build_tree_0 (66)" -> "UV gen_bitlen (65)" [color="#000000"]; "UV send_tree (68)" -> "UV send_bits (69)" [color="#000000"]; "UV send_bits (69)" -> "UV flush_outbuf (1)" [color="#000000"]; "UV build_bl_tree (70)" -> "UV build_tree_0 (66)" [color="#000000"]; "UV build_bl_tree (70)" -> "UV scan_tree (67)" [color="#000000"]; "UV send_all_trees (71)" -> "UV send_tree (68)" [color="#000000"]; "UV send_all_trees (71)" -> "UV send_bits (69)" [color="#000000"]; "UV flush_block (72)" -> "UV init_block (63)" [color="#000000"]; "UV flush_block (72)" -> "UV build_tree_0 (66)" [color="#000000"]; "UV flush_block (72)" -> "UV send_bits (69)" [color="#000000"]; "UV flush_block (72)" -> "UV build_bl_tree (70)" [color="#000000"]; "UV flush_block (72)" -> "UV send_all_trees (71)" [color="#000000"]; "UV flush_block (72)" -> "UV set_file_type (73)" [color="#000000"]; "UV flush_block (72)" -> "UV copy_block (74)" [color="#000000"]; "UV flush_block (72)" -> "UV compress_block (75)" [color="#000000"]; "UV flush_block (72)" -> "UV bi_windup (76)" [color="#000000"]; "UV copy_block (74)" -> "UV flush_outbuf (1)" [color="#000000"]; "UV copy_block (74)" -> "UV bi_windup (76)" [color="#000000"]; "UV compress_block (75)" -> "UV send_bits (69)" [color="#000000"]; "UV bi_windup (76)" -> "UV flush_outbuf (1)" [color="#000000"]; "UV lzw (78)" -> "UV fprintf (33)" [color="#808060"]; "UV huft_build (79)" -> "UV malloc (39)" [color="#4000C0"]; "UV huft_build (79)" -> "UV memset (47)" [color="#4000C0"]; "UV huft_build (79)" -> "UV huft_free (80)" [color="#4000C0"]; "UV huft_free (80)" -> "UV free (30)" [color="#4000C0"]; "UV inflate_codes (81)" -> "UV fill_inbuf (15)" [color="#4000C0"]; "UV inflate_codes (81)" -> "UV flush_window (16)" [color="#4000C0"]; "UV inflate_codes (81)" -> "UV memcpy (48)" [color="#4000C0"]; "UV inflate_stored (82)" -> "UV fill_inbuf (15)" [color="#4000C0"]; "UV inflate_stored (82)" -> "UV flush_window (16)" [color="#4000C0"]; "UV inflate_fixed (83)" -> "UV huft_build (79)" [color="#4000C0"]; "UV inflate_fixed (83)" -> "UV huft_free (80)" [color="#4000C0"]; "UV inflate_fixed (83)" -> "UV inflate_codes (81)" [color="#4000C0"]; "UV inflate_dynamic (84)" -> "UV fill_inbuf (15)" [color="#4000C0"]; "UV inflate_dynamic (84)" -> "UV fprintf (33)" [color="#4000C0"]; "UV inflate_dynamic (84)" -> "UV huft_build (79)" [color="#4000C0"]; "UV inflate_dynamic (84)" -> "UV huft_free (80)" [color="#4000C0"]; "UV inflate_dynamic (84)" -> "UV inflate_codes (81)" [color="#4000C0"]; "UV inflate_block (85)" -> "UV fill_inbuf (15)" [color="#4000C0"]; "UV inflate_block (85)" -> "UV inflate_stored (82)" [color="#4000C0"]; "UV inflate_block (85)" -> "UV inflate_fixed (83)" [color="#4000C0"]; "UV inflate_block (85)" -> "UV inflate_dynamic (84)" [color="#4000C0"]; "UV usage (87)" -> "UV fprintf (33)" [color="#80C0A0"]; "UV help (88)" -> "UV fprintf (33)" [color="#004060"]; "UV help (88)" -> "UV usage (87)" [color="#004060"]; "UV license (89)" -> "UV fprintf (33)" [color="#0040E0"]; "UV version (90)" -> "UV fprintf (33)" [color="#00C060"]; "UV main (91)" -> "UV basename (6)" [color="#00C0E0"]; "UV main (91)" -> "UV add_envopt (23)" [color="#00C0E0"]; "UV main (91)" -> "UV strlen (25)" [color="#00C0E0"]; "UV main (91)" -> "UV strcpy (27)" [color="#00C0E0"]; "UV main (91)" -> "UV fprintf (33)" [color="#00C0E0"]; "UV main (91)" -> "UV usage (87)" [color="#00C0E0"]; "UV main (91)" -> "UV help (88)" [color="#00C0E0"]; "UV main (91)" -> "UV license (89)" [color="#00C0E0"]; "UV main (91)" -> "UV version (90)" [color="#00C0E0"]; "UV main (91)" -> "UV strcmp (92)" [color="#00C0E0"]; "UV main (91)" -> "UV signal (93)" [color="#00C0E0"]; "UV main (91)" -> "UV strncmp (94)" [color="#00C0E0"]; "UV main (91)" -> "UV strncpy (95)" [color="#00C0E0"]; "UV main (91)" -> "UV getopt_long (96)" [color="#00C0E0"]; "UV main (91)" -> "UV atoi (97)" [color="#00C0E0"]; "UV main (91)" -> "UV do_exit (98)" [color="#00C0E0"]; "UV main (91)" -> "UV treat_file (99)" [color="#00C0E0"]; "UV main (91)" -> "UV treat_stdin (100)" [color="#00C0E0"]; "UV main (91)" -> "UV do_list (101)" [color="#00C0E0"]; }ocamlgraph-2.0.0/editor/0000755000175000001440000000000013735627615013477 5ustar rtusersocamlgraph-2.0.0/editor/dirTree.mli0000644000175000001440000000260213735627615015600 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) type t val id : t -> int type label val children : t -> t list ;; val label : t -> label ;; val string_of_label : label -> string ;; val from_dir : string -> string -> t ;; ocamlgraph-2.0.0/editor/ed_graph.ml0000644000175000001440000002106513735627615015606 0ustar rtusers(**************************************************************************) (* *) (* 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 = Stdlib.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 (_: 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-2.0.0/editor/outils_tort.ml0000644000175000001440000000760613735627615016431 0ustar rtusers(**************************************************************************) (* *) (* 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 Outils_math let debug_outil_tort = ref false let (w,h)= (600.,600.) (*** Tortue Hyperbolique ***) 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 advance turt step = { pos = gamma turt.pos turt.dir step ; dir = delta turt.pos turt.dir step } 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 to_tortue(x,y)= ((float x*.(2./.w) -. 1.),(1. -. float y *.(2./.h))) (* ((float x*.(2./.w) ),(float y *.(2./.h) ))*) let from_tortue (x,y) = let xzoom = (w/.2.) and yzoom = (h/.2.) in (truncate (x*.xzoom +. xzoom), truncate(yzoom -. y*.yzoom)) let depart = to_tortue (truncate(w/.2.), truncate(h/.2.)) let origine =ref depart (* GTK *) let point_courant = ref (0,0) (*let canvas = graphEdGTK.root *) let moveto_gtk x y = point_courant := (x,y) let tmoveto_gtk tor = let (x,y)= from_tortue tor.pos in point_courant := (x,y) let tlineto_gtk tor line = let (x',y')= from_tortue tor.pos in point_courant := (x',y'); List.append line [(float x'); (float y') ] let tdraw_string_gtk tor (ellipse : GnoCanvas.ellipse) = let (x,y) = from_tortue tor.pos in (* debug *) if !debug_outil_tort then Format.eprintf "tdraw_string_gtk x=%d y=%d@." x y; (* /debug *) moveto_gtk x y; ellipse#parent#move ~x:(float x) ~y:(float y); ellipse#parent#set [`X (float x); `Y (float y)] (* avance la tortue en tra�ant, d'une distance d, en un certain nombre d'etapes, et retourne la nouvelle position de la tortue *) let tdraw_edge_gtk tor d etapes line = let d = d /. (float etapes) in let rec list_points t liste = function | 0 -> (t,liste) | n ->let t = advance t d in list_points t (tlineto_gtk t liste) (n-1) in let l = let (x,y) =from_tortue tor.pos in [(float x); (float y)] in let t,lpoints = list_points tor l etapes in (* debug *) if (!debug_outil_tort) then (let ltext= let rec chaine = function |[]->"" |e::l->(string_of_float e)^" "^chaine l in chaine lpoints in Format.eprintf "taille %d %s @." (List.length lpoints) ltext); (* /debug *) let p = Array.of_list lpoints in line#set [`POINTS p]; t ocamlgraph-2.0.0/editor/dirTree.ml0000644000175000001440000000506413735627615015434 0ustar rtusers(**************************************************************************) (* *) (* 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 Unix ;; type t = { id : int; name : string ; children : t list Lazy.t } ;; let id t = t.id let newid = let r = ref 0 in fun () -> incr r; !r type label = string ;; let children t = Lazy.force t.children ;; let label t = t.name ;; let string_of_label s = s ;; let is_dir path = try (lstat path).st_kind = S_DIR with Unix_error _ -> false ;; let less t1 t2 = t1.name <= t2.name ;; let rec tree_list_from_path path = let opt_handle = try Some(opendir path) with Unix_error _ -> None in match opt_handle with | None -> [] | Some handle -> let list = Sort.list less (tree_list_from_handle path handle) in closedir handle ; list and tree_list_from_handle path handle = let opt_name = try Some(readdir handle) with End_of_file -> None in match opt_name with | None -> [] | Some name -> let path' = path ^ "/" ^ name in if name <> "." && name <> ".." && is_dir path' then { id = newid(); name = name ; children = lazy (tree_list_from_path path') } :: tree_list_from_handle path handle else tree_list_from_handle path handle ;; let from_dir path name = try let path' = path ^ "/" ^ name in if is_dir path' then { id = newid(); name = name ; children = lazy (tree_list_from_path path') } else invalid_arg "DirTree.from_dir" with _ -> failwith "DirTree.from_dir" ;; ocamlgraph-2.0.0/editor/gtree.mli0000644000175000001440000000257513735627615015321 0ustar rtusers(**************************************************************************) (* *) (* 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 T : sig type t = DirTree.t val root : t end *) module T : sig type t val root : t end val show_tree : #GnoCanvas.group -> T.t -> int -> int -> unit ocamlgraph-2.0.0/editor/graphEdGTK.ml0000644000175000001440000006007013735627615015754 0ustar rtusers(**************************************************************************) (* *) (* 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 Format open Outils_tort open Outils_math open Graph (* graph data structure *) module Gr = struct module G = Imperative.Graph.Abstract(String) module B = Builder.I(G) module GmlParser = Gml.Parse (B) (struct let node l = try match List.assoc "id" l with Gml.Int n -> string_of_int n | _ -> "" with Not_found -> "" let edge _ = () 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 -> s let edge _ = () end) let parse_file f = if Filename.check_suffix f ".gml" then GmlParser.parse f else DotParser.parse f module Components = Components.Make(G) module Dfs = Traverse.Dfs(G) end open Gr open Gr.G let debug_graphEdGTK = ref false let trace f x = try f x with e -> eprintf "TRACE: %s@." (Printexc.to_string e); raise e let _ = GMain.Main.init () let graph = ref (Gr.parse_file Sys.argv.(1)) exception Choose of V.t type t = V.t type label = V.t let label x = x let string_of_label x = V.label x let label_of_string x = x (* [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 0.0 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 zx*.zx +. zy*.zy end end ;; let edge v w = mem_edge !graph v w || mem_edge !graph w v let make_subgraph l = let gl = create () in List.iter (fun v -> add_vertex gl v) l; List.iter (fun v -> List.iter (fun w -> if edge v w then 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 let v = match c with | v :: l -> List.fold_left (fun m v -> if out_degree gc v < 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 let rlimit = 0.90 let rlimit_sqr = rlimit *. rlimit 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 = Hashtbl.create 97 let add_vertex v = let row = model#append () in model#set ~row ~column:name (V.label v); model#set ~row ~column:vertex v; Hashtbl.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 (V.label w) let reset () = Hashtbl.clear rows; model#clear (); iter_vertex (fun v -> let row = add_vertex v in iter_succ (add_edge_1 row) !graph v) !graph let add_edge v w = let row_v = Hashtbl.find rows v in add_edge_1 row_v w; if not is_directed then let row_w = Hashtbl.find rows w in add_edge_1 row_w v end let () = Model.reset () let model = ref Model.model open GtkTree (* Ouverture fenetre GTK *) let window = GWindow.window ~border_width: 10 ~title:"GraphEd" ~position: `CENTER () (* une Verticale Box pour contenir le menu de la fenetre principale *) let v_box = GPack.vbox ~homogeneous:false ~spacing:30 ~packing:window#add () (* la barre de Menu ajoutée dans la V_box *) let menu_bar = GMenu.menu_bar ~packing:v_box#pack () 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:true ~width:(truncate w) ~height:(truncate h) ~packing:h_box#add () let canvas_root = canvas#root let choose_root () = try iter_vertex (fun v -> raise (Choose v)) !graph; Format.eprintf "empty graph@."; exit 0 with Choose v -> v let root = ref (choose_root ()) let load_graph f = graph := parse_file f; Model.reset (); root := choose_root () module Vset = Set.Make(V) let vset_of_list = List.fold_left (fun s x -> Vset.add x s) Vset.empty module H = Hashtbl.Make(V) (* table donnant pour chaque noeud sa profondeur et sa tortue *) let pos = H.create 97 (* table des ellipses existantes *) let ellipses = H.create 97 let tdraw_string_gtk v tor canvas = let ellipse = try let item = H.find ellipses v in item#parent#show(); item with Not_found -> let s = string_of_label v in let (w,h) = (40,20) in let noeud = GnoCanvas.group ~x:0.0 ~y:0.0 canvas in let ellipse = GnoCanvas.ellipse ~props:[ `X1 ( float_of_int (-w/2)); `Y1 (float_of_int (-h/2)); `X2 (float_of_int (w/2)) ; `Y2 ( float_of_int (h/2)) ; `FILL_COLOR "grey" ; `OUTLINE_COLOR "black" ; `WIDTH_PIXELS 0 ] noeud in let texte = GnoCanvas.text ~props:[`X 0.0; `Y 0.0 ; `TEXT s; `FILL_COLOR "blue"] noeud in let w2 = texte#text_width in if w2 > float_of_int w then ellipse#set [ `X1 (-.( w2+.6.)/.2.); `X2 ((w2+.6.)/.2.)]; H.add ellipses v ellipse; ellipse in tdraw_string_gtk tor ellipse; ellipse module H2 = Hashtbl.Make (struct type t = V.t * V.t let hash (v,w) = Hashtbl.hash (V.hash v, V.hash w) let equal (v1,w1) (v2,w2) = V.equal v1 v2 && V.equal w1 w2 end) let grey_edges = H2.create 97 let black_edges = H2.create 97 let draw_grey_edge vw tv tw canvas = (* debug *) if !debug_graphEdGTK then ( let (v,w)= let (v,w) = vw in (string_of_label v, string_of_label w) in eprintf "tortue %s \t tortue %s@." v w ); (* /debug *) let p,l = try let _,l as pl = H2.find grey_edges vw in l#show(); pl with Not_found -> let p = GnomeCanvas.PathDef.new_path () in let l = GnoCanvas.bpath canvas ~props:[ `BPATH p ; `OUTLINE_COLOR "SlateGrey" ; `WIDTH_PIXELS 1 ] in l#lower_to_bottom (); H2.add grey_edges vw (p,l); p,l in let (x,y) = let (x ,y ) = from_tortue tv.pos in ((float_of_int x),(float_of_int y)) in let (x',y') = let (x',y') = from_tortue tw.pos in ((float_of_int x'),(float_of_int y')) in let rapport = 1.95 in GnomeCanvas.PathDef.reset p; GnomeCanvas.PathDef.moveto p x y ; GnomeCanvas.PathDef.curveto p ((x+. x')/.rapport) ((y +. y')/.rapport) ((x +.x')/.rapport) ((y +. y')/.rapport) x' y'; l#set [`BPATH p] let tdraw_edge_gtk vw t distance etapes canvas = let line = try let l = H2.find black_edges vw in l#show (); l with Not_found -> let color = "black" in let l = GnoCanvas.line canvas ~props:[ `FILL_COLOR color ; `WIDTH_PIXELS 1; `SMOOTH true] in H2.add black_edges vw l; l in tdraw_edge_gtk t distance etapes line let color_change_intern_edge color node = iter_edges (fun _ w -> try let _,n = H2.find grey_edges (node,w) in n#set [`OUTLINE_COLOR color] with Not_found -> try let _,n = H2.find grey_edges (w,node) in n#set [`OUTLINE_COLOR color] with Not_found -> () ) !graph let color_change_direct_edge color node = iter_succ (fun w -> try let n = H2.find black_edges (node,w) in n#set [`FILL_COLOR color] with Not_found -> try let n = H2.find black_edges (w,node) in n#set [`FILL_COLOR color] with Not_found -> () ) !graph node let select = ref None let is_selected_node v = match !select with | None -> false | Some (w,_) -> V.equal v w let step = ref 0 let rec draw_graph depth noeud tortue canvas = if !debug_graphEdGTK then (let (x,y) = tortue.pos in Format.eprintf " hspace : %f\t pos : %f %f \tnoeud : %s@." ( hspace_dist_sqr tortue )x y(string_of_label noeud); ); if hspace_dist_sqr tortue <= rlimit_sqr then begin H.replace pos noeud (depth, Some tortue); tmoveto_gtk tortue; (* draw label *) let ellipse = tdraw_string_gtk noeud tortue canvas in let sigs = ellipse#parent#connect in let _ = sigs#event (drag_label noeud ellipse) in let l = succ !graph noeud in let l = List.filter (fun x -> not (H.mem pos x) ) l in List.iter (fun w -> H.add pos w (depth+1, None)) l; let l = order_children l in let n = List.length l in if n > 0 then begin let distance = step_from (max 3 n) and angle = (if depth = 0 then 2. else 1.) *. pi /. (float_of_int n) in let tortue = if depth = 0 then tortue else turn_right tortue ((pi -. angle) /. 2.) in let _ = draw_edges noeud (depth+1) tortue distance angle canvas l in () end; ellipse#parent#raise_to_top(); end else if noeud <> !root then try let ellipse = tdraw_string_gtk noeud tortue canvas in ellipse#parent#hide(); iter_succ (fun w -> try ignore (H.find pos w) with Not_found -> try let n = H2.find black_edges (noeud,w) in n#hide() with Not_found -> try let n = H2.find black_edges (w,noeud) in n#hide() with Not_found -> () ) !graph noeud (* H.remove pos noeud*) with Not_found -> Format.eprintf"je devrai pas etre la@." and draw_edges noeud depth t distance angle canvas= function | [] -> [] | v :: l -> let etapes = 10 in let tv = tdraw_edge_gtk (noeud,v) t distance etapes canvas in (*if hspace_dist_sqr t <= rlimit_sqr then H.add pos v (depth,tv);*) let t = turn_left t angle in let l = (v,tv) :: draw_edges noeud depth t distance angle canvas l in draw_graph depth v tv canvas; l and drag_label noeud item ev = begin match ev with | `ENTER_NOTIFY _ -> if not (is_selected_node noeud) then begin item#set [ `FILL_COLOR "steelblue" ]; color_change_intern_edge "blue" noeud ; color_change_direct_edge "blue" noeud end; | `LEAVE_NOTIFY ev -> if not (is_selected_node noeud) then begin let state = GdkEvent.Crossing.state ev in if not (Gdk.Convert.test_modifier `BUTTON1 state) then item#set [ `FILL_COLOR "grey" ; ]; color_change_intern_edge "SlateGrey" noeud ; color_change_direct_edge "black" noeud; begin match !select with | None -> () | Some (n,i) -> begin color_change_intern_edge "red" n ; color_change_direct_edge "red" n end end; end | `BUTTON_RELEASE ev -> item#parent#ungrab (GdkEvent.Button.time ev) | `MOTION_NOTIFY ev -> incr step; let state = GdkEvent.Motion.state ev in if Gdk.Convert.test_modifier `BUTTON1 state && !step mod 10 = 0 then begin let curs = Gdk.Cursor.create `FLEUR in item#parent#grab [`POINTER_MOTION; `BUTTON_RELEASE] curs (GdkEvent.Button.time ev); let ibounds = item#parent#get_bounds in let z1 = to_tortue(truncate((ibounds.(0)+.ibounds.(2))/.2.), truncate((ibounds.(1)+. ibounds.(3))/.2.)) in let mx = GdkEvent.Motion.x ev in let my = GdkEvent.Motion.y ev in let z2 = to_tortue (truncate mx, truncate my) in let tmp = !origine in let (x,y) = drag_origin !origine z1 z2 in origine := (x,y); let tor = make_turtle !origine 0.0 in if hspace_dist_sqr tor <= rlimit_sqr then begin draw tor canvas_root; if !step mod 15 = 0 then canvas_root#canvas#update_now () end else origine := tmp end | `TWO_BUTTON_PRESS ev-> if (GdkEvent.Button.button ev) = 1 then selectionner_noeud noeud item; | `BUTTON_PRESS ev -> if (GdkEvent.Button.button ev) = 1 then deselectionner_noeud noeud item ; if (GdkEvent.Button.button ev) = 3 then begin let loc_menu = GMenu.menu () in let factory = new GMenu.factory loc_menu in ignore (factory#add_item " Ajouter un successeur" ~callback: (ajout_successeur noeud)); begin match !select with | None -> () | Some (n,_) -> if not(V.equal n noeud) then begin ignore (factory#add_item " Ajouter une arrête" ~callback: (ajout_arrete n noeud)); end end; loc_menu#popup ~button:3 ~time:(GdkEvent.Button.time ev); end | _ -> () end; true and ajout_successeur noeud () = let window = GWindow.window ~title: "Choix du nom du label" ~width: 300 ~height: 50 () 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 (); let _ = entry#connect#activate ~callback: (fun () -> let text = entry#text in let label = label_of_string text in let vertex = V.create label in add_vertex !graph vertex; add_edge !graph noeud vertex; window#destroy (); ignore (Model.add_vertex vertex); Model.add_edge noeud vertex; let tor = make_turtle !origine 0.0 in draw tor canvas_root) in () and ajout_arrete n1 n2 () = if not( edge n1 n2) then begin add_edge !graph n1 n2; Model.add_edge n1 n2; let tor = make_turtle !origine 0.0 in draw tor canvas_root end and selectionner_noeud noeud item= begin begin match !select with | None -> () | Some (n,i) -> begin i#set [ `FILL_COLOR "grey" ; ]; color_change_intern_edge "SlateGrey" n ; color_change_direct_edge "black" n end end; select := Some (noeud, item); item#set [ `FILL_COLOR "red" ]; color_change_intern_edge "red" noeud ; color_change_direct_edge "red" noeud end and deselectionner_noeud noeud item = begin if is_selected_node noeud then begin item#set [ `FILL_COLOR "steelblue" ]; color_change_intern_edge "blue" noeud ; color_change_direct_edge "blue" noeud end else match !select with | None -> () | Some (n,i) -> begin i#set [ `FILL_COLOR "grey" ; ]; color_change_intern_edge "SlateGrey" n ; color_change_direct_edge "black" n; (* color_change_intern_edge "red" n ; color_change_direct_edge "red" n *) end; end; select := None; and draw tortue canvas = H.clear pos; canvas#hide(); draw_graph 0 !root tortue canvas; (* H.iter (fun v ev -> if not (H.mem pos v) then ev#parent#hide ()) ellipses; *) (* draw intern edges *) iter_edges (fun v w -> try begin match H.find pos v, H.find pos w with | (lv, Some tv), (lw, Some tw) -> if abs (lw - lv) <> 1 && (lv <> 0 || lw <> 0) then begin (* debug *) if !debug_graphEdGTK then (Format.eprintf "tortue : %s\t\t\t tortue : %s@." (string_of_label v) (string_of_label w); let (x ,y ) = from_tortue tv.pos and (x',y') = from_tortue tw.pos in Format.eprintf "pos x:%d y:%d \t pos x:%d y:%d@." x y x' y'; ); (* /debug *) ignore(draw_grey_edge (v,w) tv tw canvas) end else raise Not_found | (_, None), _ | _, (_, None) -> raise Not_found end with Not_found -> begin (* debug *) if !debug_graphEdGTK then Format.eprintf"Je vais tenter de détruire un edge@."; (* /debug *) try let _,l = H2.find grey_edges (w,v) in l#hide(); (* debug *) if !debug_graphEdGTK then Format.eprintf"J'ai effacé un grey edge@."; (* /debug *) with Not_found -> (); try let _,l = H2.find grey_edges (v,w) in l#hide(); (* debug *) if !debug_graphEdGTK then Format.eprintf"J'ai effacé un grey edge@."; (* /debug *) with Not_found -> (); end ) !graph; canvas#show() let ajout_noeud () = let window = GWindow.window ~title: "Choix du nom du label" ~width: 300 ~height: 50 () 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 (); let _ = entry#connect#activate ~callback: (fun () -> let text = entry#text in let label = label_of_string text in let vertex = V.create label in add_vertex !graph vertex; window#destroy (); ignore (Model.add_vertex vertex); let tor = make_turtle !origine 0.0 in draw tor canvas_root) in () let canvas_event ev = (* Format.eprintf "toto suis-je empty ? : %b@." (is_empty !graph); *) begin match ev with | `BUTTON_PRESS ev -> if (GdkEvent.Button.button ev) = 1 then begin match !select with | None -> () | Some(noeud,item) -> deselectionner_noeud noeud item ; end; if (GdkEvent.Button.button ev) = 3 (* && (is_empty !graph)*) then begin let loc_menu = GMenu.menu () in let factory = new GMenu.factory loc_menu in ignore (factory#add_item " Ajouter un noeud" ~callback: ajout_noeud); loc_menu#popup ~button:3 ~time:(GdkEvent.Button.time ev); end | _ -> () end; true let _ = canvas#root#connect#event (canvas_event) let node_selection ~(model : GTree.tree_store) path = let row = model#get_iter path in let v = model#get ~row ~column: Model.vertex in root := v; let tortue = origine := depart; let (x,y) = from_tortue !origine in moveto_gtk x y; make_turtle !origine 0.0; in let l = canvas_root#get_items in Format.eprintf "il y a %d elements dans le canvas @." (List.length l); List.iter (fun v -> v#hide()) l; draw tortue canvas_root 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 `GROW_ONLY; 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 ~packing:sw#add () let () = treeview#set_rules_hint true let () = treeview#selection#set_mode `MULTIPLE let _ = add_columns ~view:treeview ~model:!model (*let _ = treeview#misc#connect#realize ~callback:treeview#expand_all*) let reset_table_and_canvas () = let l = canvas_root#get_items in List.iter (fun v -> trace v#destroy ()) l; H2.clear grey_edges; H2.clear black_edges; H.clear ellipses; H.clear pos; origine := depart let open_graph() = let default 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 ask_for_file parent = let dialog = GWindow.file_chooser_dialog ~action:`OPEN ~title:"Ouvrir un fichier" ~parent () in dialog#add_button_stock `CANCEL `CANCEL ; dialog#add_select_button_stock `OPEN `OPEN ; dialog#add_filter (graph_filter ()) ; dialog#add_filter (all_files ()) ; let f = match dialog#run () with | `OPEN ->default "" dialog#filename | `DELETE_EVENT | `CANCEL -> "" in dialog#destroy (); f in let fichier = ask_for_file window in if fichier <> "" then begin load_graph fichier; reset_table_and_canvas (); let tortue = let (x,y) = from_tortue !origine in moveto_gtk x y; make_turtle !origine 0.0 in draw tortue canvas_root end let new_graph () = graph := create (); model := Model.model; Model.reset(); reset_table_and_canvas () let create_menu label menubar = let item = GMenu.menu_item ~label ~packing:menubar#append () in GMenu.menu ~packing:item#set_submenu () let print msg () = print_endline msg; flush stdout (* le menu file : la description puis l'ajout au menu_bar *) let menu_files = [ `I ("_New Graph", new_graph); `I ("_Open Graph", open_graph); `I ("_Save Graph", print "todo save graph"); `I ("Save Graph _As ...", print "todo save graph as..."); `S; `I ("_Quit", GMain.Main.quit ) ] let menu = create_menu "File" menu_bar let _ = GToolbox.build_menu menu ~entries:menu_files (* la zone d'affichage du graph, le canvas *) let tortue = let (x,y) = from_tortue !origine in moveto_gtk x y; make_turtle !origine 0.0 let () = canvas#set_scroll_region 0. 0. w h (* l'affichage de la fenetre principale *) let () = window#show () let _ = draw tortue canvas_root let () = GMain.Main.main () ocamlgraph-2.0.0/editor/tests/0000755000175000001440000000000013735627615014641 5ustar rtusersocamlgraph-2.0.0/editor/tests/ring_100.gml0000644000175000001440000002125513735627615016666 0ustar rtusersgraph [ 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-2.0.0/editor/tests/de_bruijn4.gml0000644000175000001440000000420013735627615017363 0ustar rtusersgraph [ 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-2.0.0/editor/tests/full20.gml0000644000175000001440000002660613735627615016460 0ustar rtusersgraph [ 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-2.0.0/editor/tests/softmaint.dot0000644000175000001440000003515213735627615017363 0ustar rtusersdigraph 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-2.0.0/editor/tests/full50.gml0000644000175000001440000020645513735627615016465 0ustar rtusersgraph [ 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-2.0.0/editor/tests/rand_10_40.gml0000644000175000001440000000454013735627615017074 0ustar rtusersgraph [ 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-2.0.0/editor/tests/twopi2.dot0000644000175000001440000043271313735627615016607 0ustar rtusersdigraph 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-2.0.0/editor/tests/test2_2.gml0000644000175000001440000000071013735627615016622 0ustar rtusersgraph [ 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-2.0.0/editor/tests/test2,1_2.gml0000644000175000001440000000100713735627615016757 0ustar rtusersgraph [ 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-2.0.0/editor/tests/rand_100_300.gml0000644000175000001440000004576713735627615017253 0ustar rtusersgraph [ 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-2.0.0/editor/tests/rand_10_10.gml0000644000175000001440000000154113735627615017067 0ustar rtusersgraph [ 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-2.0.0/editor/tests/fsm.dot0000644000175000001440000000100413735627615016131 0ustar rtusersdigraph 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-2.0.0/editor/tests/parcours.dot0000644000175000001440000000041713735627615017211 0ustar rtusersdigraph 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-2.0.0/editor/tests/transparency.dot0000644000175000001440000000345413735627615020070 0ustar rtusersgraph 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-2.0.0/editor/tests/test2,1_3.gml0000644000175000001440000000114713735627615016765 0ustar rtusersgraph [ 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-2.0.0/editor/tests/dep_why.dot0000644000175000001440000000502313735627615017010 0ustar rtusersdigraph 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-2.0.0/editor/tests/rand_50_300.gml0000644000175000001440000004224313735627615017161 0ustar rtusersgraph [ 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-2.0.0/editor/tests/unix.dot0000644000175000001440000000261613735627615016341 0ustar rtusers/* 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-2.0.0/editor/tests/rand_100_10.gml0000644000175000001440000001003213735627615017142 0ustar rtusersgraph [ 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-2.0.0/editor/tests/test.gml0000644000175000001440000000165313735627615016326 0ustar rtusersgraph [ 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-2.0.0/editor/tests/test2,1_3tot.gml0000644000175000001440000000120613735627615017510 0ustar rtusersgraph [ 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-2.0.0/editor/tests/divisors12.gml0000644000175000001440000000163113735627615017350 0ustar rtusersgraph [ 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-2.0.0/editor/tests/full10.gml0000644000175000001440000000614113735627615016447 0ustar rtusersgraph [ 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-2.0.0/editor/tests/full30.gml0000644000175000001440000006153713735627615016463 0ustar rtusersgraph [ 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-2.0.0/editor/tests/world.dot0000644000175000001440000000172413735627615016504 0ustar rtusersdigraph 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-2.0.0/editor/tests/dep_ed.dot0000644000175000001440000000030213735627615016564 0ustar rtusersdigraph 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-2.0.0/editor/ed_icon.xpm0000644000175000001440000014073213735627615015634 0ustar rtusers/* XPM */ static char * ed_icon_xpm[] = { "128 128 1018 2", " c None", ". c #CDCAC4", "+ c #B4B1AD", "@ c #9E9C98", "# c #94928E", "$ c #908E8B", "% c #8E8C89", "& c #8C8A87", "* c #8B8986", "= c #CFCBC6", "- c #A3A09C", "; c #8B8987", "> c #8B8A88", ", c #8D8C8B", "' c #9A9A9A", ") c #B2B2B2", "! c #CCCCCC", "~ c #E4E4E4", "{ c #F0F0F0", "] c #F4F4F4", "^ c #F8F8F8", "/ c #FAFAFA", "( c #FCFCFC", "_ c #D1CDC8", ": c #969390", "< c #888785", "[ c #90908F", "} c #B0AFAF", "| c #DEDEDE", "1 c #F9F9F9", "2 c #C2BFBA", "3 c #8A8A89", "4 c #AAAAAA", "5 c #EBEBEB", "6 c #D4D1CB", "7 c #918F8C", "8 c #8A8988", "9 c #B8B8B8", "0 c #F5F5F5", "a c #B7B4AF", "b c #848280", "c c #A3A3A2", "d c #ECECEC", "e c #A5A29E", "f c #848382", "g c #C2C2C2", "h c #FBFBFB", "i c #A7A4A0", "j c #858483", "k c #D1D1D1", "l c #B9B6B1", "m c #82817F", "n c #CECECE", "o c #D7D3CE", "p c #817F7D", "q c #B9B9B9", "r c #9B9995", "s c #959494", "t c #F6F6F6", "u c #D0CCC7", "v c #7F7E7C", "w c #D5D5D5", "x c #989797", "y c #F7F7F7", "z c #C5C5C5", "A c #D2CFCA", "B c #7E7D7B", "C c #E8E8E8", "D c #BDBAB5", "E c #8C8C8B", "F c #ABA8A4", "G c #A0A09F", "H c #9F9C99", "I c #9A9794", "J c #BBBBBB", "K c #EFEFEF", "L c #C9C9C9", "M c #E0E0E0", "N c #BFBFBF", "O c #C4C4C4", "P c #A6A6A6", "Q c #ADADAD", "R c #9F9D99", "S c #BCBCBC", "T c #DDDDDD", "U c #D8D8D8", "V c #ABAAAA", "W c #A5A5A5", "X c #A0A1A6", "Y c #CCCDE4", "Z c #F3F3F3", "` c #DCDCDC", " . c #DBDBDB", ".. c #D6D3D3", "+. c #BD8383", "@. c #807F7F", "#. c #B9B9BA", "$. c #BEBFD3", "%. c #A9ABD5", "&. c #DADAEC", "*. c #BEBAB6", "=. c #A0A0A0", "-. c #E6E6E6", ";. c #D9D9D9", ">. c #D39A9A", ",. c #D8CACA", "'. c #717171", "). c #E8E8E9", "!. c #CACBE4", "~. c #ABADD5", "{. c #E4E5F1", "]. c #D3CFCA", "^. c #8B8B8A", "/. c #E2E2E2", "(. c #F2F2F2", "_. c #E5E5E5", ":. c #E0B8B8", "<. c #E6C7C7", "[. c #C0C0C0", "}. c #8C8C8C", "|. c #F9F9FB", "1. c #BFC1DF", "2. c #AEB0D7", "3. c #ECEDF5", "4. c #BEBEBE", "5. c #AEAEAE", "6. c #C1C1C1", "7. c #DFDFDF", "8. c #EEDADA", "9. c #D8A5A5", "0. c #949494", "a. c #DADADA", "b. c #F5F5F9", "c. c #B7B9DB", "d. c #B5B6DA", "e. c #F3F3F8", "f. c #B7B7B7", "g. c #7E7E7E", "h. c #9FA0A9", "i. c #9D9FC4", "j. c #B9BBD7", "k. c #DDDDEB", "l. c #F5F6F9", "m. c #E1E1E1", "n. c #F8F2F2", "o. c #CF8F8F", "p. c #FBFAFA", "q. c #888888", "r. c #E3E3E3", "s. c #EFEFF6", "t. c #B0B2D8", "u. c #BEC0DF", "v. c #F8F8FA", "w. c #A4A19D", "x. c #B9B0B0", "y. c #ABA5A5", "z. c #DADAE4", "A. c #CCCDE5", "B. c #B6B8DB", "C. c #B1B2D8", "D. c #D6D6EA", "E. c #F4F4F8", "F. c #D7D7D7", "G. c #FCFBFB", "H. c #D19292", "I. c #F6EEEE", "J. c #8F8F8F", "K. c #D6D6D6", "L. c #E5E5F1", "M. c #ABADD6", "N. c #CBCCE5", "O. c #979696", "P. c #C89292", "Q. c #D5D0D0", "R. c #8E8E8E", "S. c #ABABAB", "T. c #D7D8EA", "U. c #B8BADC", "V. c #E8E9F3", "W. c #DBADAD", "X. c #EBD2D2", "Y. c #919191", "Z. c #D8D9EB", "`. c #DCDCED", " + c #F1F1F1", ".+ c #DFDEDE", "++ c #D39898", "@+ c #787878", "#+ c #F6F6F9", "$+ c #E2E2EF", "%+ c #C4C5E1", "&+ c #A3A5CA", "*+ c #A0A1C8", "=+ c #ABADD2", "-+ c #C2C4E1", ";+ c #DFE0EE", ">+ c #E9CFCF", ",+ c #DDB0B0", "'+ c #E7E7E7", ")+ c #9E9E9E", "!+ c #FAFAFB", "~+ c #C7C8E3", "{+ c #EDEEF5", "]+ c #9A9894", "^+ c #F1E2E2", "/+ c #B3B3B3", "(+ c #A2A2A2", "_+ c #EAEAF3", ":+ c #CECFE6", "<+ c #ABA5CB", "[+ c #98769C", "}+ c #D0D1E7", "|+ c #EEEEF5", "1+ c #EEEEEE", "2+ c #E9E9E9", "3+ c #B4B6DA", "4+ c #BCBEDE", "5+ c #D8A6A6", "6+ c #F6EDED", "7+ c #878787", "8+ c #EDEDED", "9+ c #FBF9F9", "0+ c #CE8D8D", "a+ c #F9F5F5", "b+ c #F7F7FA", "c+ c #DDDDED", "d+ c #BDBFDD", "e+ c #9FA1C6", "f+ c #6D6E86", "g+ c #A8AACD", "h+ c #B5B6D6", "i+ c #C8C9DB", "j+ c #F1F1F7", "k+ c #A9AAD4", "l+ c #EAEAEA", "m+ c #D39797", "n+ c #D2D2D2", "o+ c #A4A4A4", "p+ c #D7A1A1", "q+ c #EFDDDD", "r+ c #E9E9EF", "s+ c #C1C2D5", "t+ c #BCBDDE", "u+ c #AFB0D6", "v+ c #A2A3C8", "w+ c #C0C1DF", "x+ c #EEEFF6", "y+ c #FBFBFC", "z+ c #EFF0F6", "A+ c #B8B5B1", "B+ c #F4E8E8", "C+ c #DBABAB", "D+ c #909090", "E+ c #E4C1C1", "F+ c #E2BDBD", "G+ c #DADADB", "H+ c #EAEAF2", "I+ c #D5D6E9", "J+ c #B2B4D9", "K+ c #A7A9C6", "L+ c #C7C8DA", "M+ c #D1D2E8", "N+ c #EBECF4", "O+ c #B1B3D9", "P+ c #C4C6E2", "Q+ c #FAFBFB", "R+ c #DCAFAF", "S+ c #F2E4E4", "T+ c #929292", "U+ c #F1E1E1", "V+ c #D59D9D", "W+ c #A3A3A3", "X+ c #D8D8DA", "Y+ c #D0D1E1", "Z+ c #C1C3E0", "`+ c #B1B3D8", " @ c #B4B5DA", ".@ c #C6C7E2", "+@ c #E1E1EF", "@@ c #F7F8FA", "#@ c #DCDDED", "$@ c #A8AAD4", "%@ c #D7D7E4", "&@ c #6B6B6D", "*@ c #676769", "=@ c #D3D3D3", "-@ c #F9F4F4", ";@ c #C7C7C7", ">@ c #E7E7F2", ",@ c #B5B7DA", "'@ c #4E4F6D", ")@ c #363977", "!@ c #32356E", "~@ c #7F7F80", "{@ c #E2E1E1", "]@ c #C29E9E", "^@ c #EFE4E4", "/@ c #A7A7A7", "(@ c #E0E0EF", "_@ c #BFC0DF", ":@ c #ADAFD6", "<@ c #55485D", "[@ c #3C3F83", "}@ c #363876", "|@ c #757576", "1@ c #DEB4B4", "2@ c #F0DFDF", "3@ c #CBCBCB", "4@ c #A8A8A8", "5@ c #DEB2B2", "6@ c #E4C8C8", "7@ c #959595", "8@ c #C7C9E3", "9@ c #ECE2EA", "0@ c #EE888A", "a@ c #7D4879", "b@ c #303145", "c@ c #272840", "d@ c #D4D5D9", "e@ c #EBD3D3", "f@ c #DBACAC", "g@ c #F2F2F7", "h@ c #D3D4E9", "i@ c #B7B9DC", "j@ c #ADAFD3", "k@ c #AEAFC4", "l@ c #FBFCFC", "m@ c #F7B9B9", "n@ c #E67C82", "o@ c #8E82B9", "p@ c #D69F9F", "q@ c #EDEDF0", "r@ c #C8C9D8", "s@ c #BABCDD", "t@ c #D9D9EB", "u@ c #FAE7E7", "v@ c #F38888", "w@ c #DDA6B3", "x@ c #A4A6D2", "y@ c #A0A2D0", "z@ c #F0F1F6", "A@ c #848381", "B@ c #E0B9B9", "C@ c #FBF8F8", "D@ c #CF8E8E", "E@ c #F8F3F3", "F@ c #CACACA", "G@ c #F9FAFB", "H@ c #C3C5E1", "I@ c #B5B6CD", "J@ c #E4E3E3", "K@ c #F6ACAC", "L@ c #F49292", "M@ c #CCC3DB", "N@ c #ECECF4", "O@ c #F0F0F6", "P@ c #CC9999", "Q@ c #D49D9D", "R@ c #A7A7A8", "S@ c #E5E6F1", "T@ c #B3B4D9", "U@ c #9E9FC6", "V@ c #E9E9F3", "W@ c #FADDDD", "X@ c #DC9393", "Y@ c #E6BFC0", "Z@ c #CDCEE6", "`@ c #D2D3E8", " # c #AFB0D7", ".# c #B3B5D9", "+# c #D7D4D4", "@# c #CFB1B1", "## c #B5B5B5", "$# c #C8C8C8", "%# c #DCB5B5", "&# c #CEACAC", "*# c #C7C7D6", "=# c #BEC0DD", "-# c #757690", ";# c #ACADC2", "># c #BBBCCA", ",# c #D8D8E3", "'# c #FCF7F7", ")# c #F5A0A0", "!# c #F49C9C", "~# c #EFEBF1", "{# c #9597C2", "]# c #DBDBE7", "^# c #B6B7DB", "/# c #888786", "(# c #E1BEBE", "_# c #858585", ":# c #D8A4A4", "<# c #B4B5CD", "[# c #EBEBF4", "}# c #939393", "|# c #F9D1D1", "1# c #F28383", "2# c #F9D9D9", "3# c #AAACD5", "4# c #D7D7D8", "5# c #ABACD2", "6# c #F9F9FA", "7# c #C3C4E1", "8# c #E7E8F2", "9# c #F1F2F7", "0# c #A8A5AA", "a# c #AC768A", "b# c #B7B8DA", "c# c #A6A7CD", "d# c #A4A6CA", "e# c #C0C2E0", "f# c #CDCDCD", "g# c #FBF4F4", "h# c #F5A8A8", "i# c #FCFAFA", "j# c #C8CAE4", "k# c #BABBDD", "l# c #B3B5D8", "m# c #D2D3D5", "n# c #AFB1D7", "o# c #E2E3F0", "p# c #C8C9E3", "q# c #A6A8CA", "r# c #ADAFD5", "s# c #B0B0D5", "t# c #563B4B", "u# c #D3D3E4", "v# c #F7BFBF", "w# c #F38585", "x# c #E3BFBF", "y# c #EAEBF4", "z# c #B2B4D3", "A# c #A9ABD1", "B# c #B8B9DC", "C# c #CACCE4", "D# c #F0F0F4", "E# c #DEDEDF", "F# c #D6A1A1", "G# c #CEBBBB", "H# c #A1A1A1", "I# c #9D9D9D", "J# c #FBEAEA", "K# c #E87E7E", "L# c #EEB0B0", "M# c #DEDFEE", "N# c #E6E7F2", "O# c #BFC0D1", "P# c #C1C2E0", "Q# c #EDEDF5", "R# c #BBBCDD", "S# c #D8D8EB", "T# c #A582A1", "U# c #B0B0D6", "V# c #DBDCEC", "W# c #DFDFE6", "X# c #E0BABA", "Y# c #E4C2C2", "Z# c #C6C6C6", "`# c #DAD9D9", " $ c #F0B2B2", ".$ c #F38F8F", "+$ c #F9EEEE", "@$ c #A6A8D3", "#$ c #E9EAF3", "$$ c #BBBCD0", "%$ c #E1E2EF", "&$ c #BABABA", "*$ c #E7E7EE", "=$ c #DADBEC", "-$ c #C2C3E0", ";$ c #B5B7DB", ">$ c #B2B3D9", ",$ c #D3D1E4", "'$ c #CA979F", ")$ c #DFC8C8", "!$ c #D2A0A0", "~$ c #FADEDE", "{$ c #F08787", "]$ c #DCCFCF", "^$ c #CDCDD8", "/$ c #D9DAEC", "($ c #D4D5E9", "_$ c #E3E4F0", ":$ c #9F9F9F", "<$ c #898AA8", "[$ c #ADAFD4", "}$ c #BEBFDE", "|$ c #D3D3E8", "1$ c #E2BCBC", "2$ c #ECD6D6", "3$ c #D19494", "4$ c #F49B9B", "5$ c #FCF6F6", "6$ c #B9B9CD", "7$ c #E2E2E4", "8$ c #C9CAE4", "9$ c #ACAED6", "0$ c #A9A9A9", "a$ c #7A7A7A", "b$ c #747474", "c$ c #8A8A8A", "d$ c #F8CDCD", "e$ c #F28484", "f$ c #BDBEDE", "g$ c #C9CBE4", "h$ c #DFDFEE", "i$ c #AFAFAF", "j$ c #D4BABA", "k$ c #BDABAB", "l$ c #D4D4D4", "m$ c #898989", "n$ c #DEDCDC", "o$ c #D0A6A6", "p$ c #D19393", "q$ c #F4E9E9", "r$ c #E1D6D6", "s$ c #F18C8C", "t$ c #F6ADAD", "u$ c #ABADD3", "v$ c #DADADD", "w$ c #E7C9C9", "x$ c #D4B9B9", "y$ c #8B8B8B", "z$ c #979797", "A$ c #DBB3B3", "B$ c #E2D7D7", "C$ c #D7A2A2", "D$ c #EDD8D8", "E$ c #BDBDBD", "F$ c #F6B4B4", "G$ c #E37B7B", "H$ c #F7E7E7", "I$ c #A7A9D3", "J$ c #E8E8F2", "K$ c #B1B2D6", "L$ c #D7D7DA", "M$ c #BABCD4", "N$ c #EAD0D0", "O$ c #E4C5C5", "P$ c #734F4F", "Q$ c #989898", "R$ c #F38484", "S$ c #F8C6C6", "T$ c #B2B3CE", "U$ c #AFB0C6", "V$ c #D6D7EA", "W$ c #E3C0C0", "X$ c #F3E6E6", "Y$ c #DAAAAA", "Z$ c #ACACAC", "`$ c #CDB5B5", " % c #CCB6B6", ".% c #7B7B7B", "+% c #F49797", "@% c #F59D9D", "#% c #A9ABCD", "$% c #B3B5DA", "%% c #8D8D8C", "&% c #C18F8F", "*% c #E6DCDC", "=% c #D59C9C", "-% c #848484", ";% c #DEA4A4", ">% c #F28585", ",% c #FAE4E4", "'% c #A7A9D4", ")% c #E0E0E1", "!% c #B0B1C7", "~% c #AFB1D8", "{% c #F3E5E5", "]% c #DEB3B3", "^% c #D29696", "/% c #C3BABA", "(% c #CF9191", "_% c #F9DFDF", ":% c #8B5050", "<% c #EEB5B5", "[% c #E4E4E6", "}% c #A9ABD0", "|% c #C7C8E1", "1% c #E4DFDF", "2% c #835757", "3% c #8A8787", "4% c #9B9B9B", "5% c #797979", "6% c #DBD9D9", "7% c #DFB6B6", "8% c #D57F7F", "9% c #A2A1A1", "0% c #9EA0CA", "a% c #DEDEEA", "b% c #D7D8EB", "c% c #F6ECEC", "d% c #D49A9A", "e% c #FAF7F7", "f% c #FAF8F8", "g% c #CC8B8B", "h% c #DED5D5", "i% c #F3E2E2", "j% c #E3E3EC", "k% c #A5A7D3", "l% c #DEDEE4", "m% c #DDDEED", "n% c #F7F0F0", "o% c #DAA8A8", "p% c #E6E2E2", "q% c #CC9494", "r% c #F5F4F4", "s% c #EEDFDF", "t% c #E4BDBD", "u% c #A05959", "v% c #D2A5A5", "w% c #BBBCCD", "x% c #A0A2C9", "y% c #BBBDDD", "z% c #ADAFC6", "A% c #D4C2C2", "B% c #C38E8E", "C% c #D4BDBD", "D% c #E67F7F", "E% c #F5ABAB", "F% c #F9F6F6", "G% c #D6D6D7", "H% c #ACADC5", "I% c #D4D4D8", "J% c #BCBEDB", "K% c #D5D5D8", "L% c #D8A3A3", "M% c #D29595", "N% c #E6C8C8", "O% c #7D7D7D", "P% c #A6A5A5", "Q% c #EC9A9A", "R% c #F29393", "S% c #DBD0D0", "T% c #B9BADC", "U% c #EEDBDB", "V% c #E3BEBE", "W% c #FCF9F9", "X% c #F3ABAB", "Y% c #C36F6F", "Z% c #928E8E", "`% c #CFCFCF", " & c #DCDCE0", ".& c #B5B6C9", "+& c #E6E6ED", "@& c #F9F3F3", "#& c #E8CDCD", "$& c #F7C1C1", "%& c #F8D0D0", "&& c #8D8D8D", "*& c #C3C3C3", "=& c #A1A2BD", "-& c #BBBCCC", ";& c #D4D5DA", ">& c #A3A4B8", ",& c #D59E9E", "'& c #D8D4D4", ")& c #D49B9B", "!& c #F9D3D3", "~& c #F7BDBD", "{& c #999999", "]& c #9C9C9C", "^& c #B0B0B0", "/& c #C5C5C6", "(& c #8081A5", "_& c #C4C4C5", ":& c #8A8BAA", "<& c #9B9CB2", "[& c #B4B4BC", "}& c #CEA5A5", "|& c #EDD9D9", "1& c #DECECE", "2& c #C98C8C", "3& c #DDC2C2", "4& c #F18888", "5& c #F6ABAB", "6& c #F1E0E0", "7& c #D9A6A6", "8& c #B09D9D", "9& c #ADADAE", "0& c #7C7EA1", "a& c #C2C2C4", "b& c #B5B5B8", "c& c #8A8CA8", "d& c #9C9DB2", "e& c #B6B6BF", "f& c #BEB2B2", "g& c #AC8686", "h& c #A06969", "i& c #9D6464", "j& c #9A8989", "k& c #F5EAEA", "l& c #D09090", "m& c #DCDADA", "n& c #FAE8E8", "o& c #F39090", "p& c #F49F9F", "q& c #DFD7D7", "r& c #B1B1B1", "s& c #C0C1D1", "t& c #C4C5D6", "u& c #C4AFC3", "v& c #CC9DA5", "w& c #D39999", "x& c #DCAEAE", "y& c #EDEAEA", "z& c #DFB5B5", "A& c #F8F1F1", "B& c #CE8C8C", "C& c #FBF1F1", "D& c #F49595", "E& c #F49696", "F& c #FBEEEE", "G& c #DBB1B1", "H& c #C08484", "I& c #CA9D9D", "J& c #C0C1D6", "K& c #C6C8E3", "L& c #D8D8D9", "M& c #D6A0A0", "N& c #B795AB", "O& c #E4D9E2", "P& c #F7EFEF", "Q& c #DED7D7", "R& c #F59F9F", "S& c #F38E8E", "T& c #D6BCBC", "U& c #C18787", "V& c #CD9696", "W& c #D1BFBF", "X& c #969696", "Y& c #DCDCE8", "Z& c #ADAED3", "`& c #E6E4E4", " * c #E1CACA", ".* c #DAA9A9", "+* c #D9A7A7", "@* c #D69E9E", "#* c #D09292", "$* c #F3E7E7", "%* c #F4A7A7", "&* c #E47C7C", "** c #FAE0E0", "=* c #F5EBEB", "-* c #868686", ";* c #9D9EC9", ">* c #EAEAEB", ",* c #E1BCBC", "'* c #C08A95", ")* c #BF8690", "!* c #CDAAAA", "~* c #EBECF3", "{* c #F0DEDE", "]* c #E4A0A0", "^* c #F6D3D3", "/* c #808081", "(* c #A2A4CF", "_* c #E3E3E8", ":* c #EDECEC", "<* c #E8CCCC", "[* c #DDAFAF", "}* c #ADACD2", "|* c #C4C5DC", "1* c #D0D0D4", "2* c #CB9696", "3* c #E4CCCC", "4* c #F7BABA", "5* c #F38787", "6* c #E6BBBB", "7* c #E5C5C5", "8* c #ECD4D4", "9* c #AEB0D6", "0* c #878893", "a* c #D9A8A8", "b* c #C18888", "c* c #D09C9C", "d* c #E7CACA", "e* c #F7F1F1", "f* c #F7F7F9", "g* c #ADAEC8", "h* c #F4F5F8", "i* c #E5C7C7", "j* c #F8C4C4", "k* c #F8C5C5", "l* c #DDBFBF", "m* c #C48B8B", "n* c #E9CDCD", "o* c #6F6F6F", "p* c #D2CBDE", "q* c #916060", "r* c #B98080", "s* c #E5C3C3", "t* c #DFB7B7", "u* c #F38686", "v* c #F7BBBB", "w* c #ECD5D5", "x* c #CBAEAE", "y* c #DEDBDB", "z* c #907F7F", "A* c #BB828F", "B* c #BD848F", "C* c #E3DADA", "D* c #ADAFD7", "E* c #D7A3A3", "F* c #E9C6C6", "G* c #F6B2B2", "H* c #E1BBBB", "I* c #858383", "J* c #D3BFBF", "K* c #E0B7B7", "L* c #CB9191", "M* c #C59090", "N* c #956C6C", "O* c #DCD9E8", "P* c #B9BBDC", "Q* c #E1BABA", "R* c #F9DBDB", "S* c #F28989", "T* c #E19595", "U* c #FBF7F7", "V* c #D49C9C", "W* c #E4D3D3", "X* c #D4B2B2", "Y* c #985F5F", "Z* c #CF9898", "`* c #DAB4B4", " = c #DDCCCC", ".= c #DEDEE7", "+= c #808080", "@= c #BEBFDF", "#= c #EDD7D7", "$= c #FAE1E1", "%= c #F38D8D", "&= c #F4A1A1", "*= c #E9CACA", "== c #C28A8A", "-= c #D19797", ";= c #ECEBEB", ">= c #DDD4D4", ",= c #C79F9F", "'= c #ACADB2", ")= c #8C8EB9", "!= c #838383", "~= c #EEEFEF", "{= c #DDB1B1", "]= c #FAE6E6", "^= c #E88181", "/= c #D59595", "(= c #EEEAEA", "_= c #F2E3E3", ":= c #E6C6C6", "<= c #D09797", "[= c #C68D8D", "}= c #D0A0A0", "|= c #D1AEAE", "1= c #B5B5BA", "2= c #C5C6D4", "3= c #C5C7E1", "4= c #A8AACE", "5= c #C09191", "6= c #A95252", "7= c #CE8080", "8= c #F08B8B", "9= c #D75252", "0= c #D18989", "a= c #E8CBCB", "b= c #C18B8B", "c= c #EAD1D1", "d= c #E4E5ED", "e= c #D3D3D5", "f= c #BDBDCB", "g= c #D1B9B9", "h= c #921919", "i= c #8A1717", "j= c #AE2121", "k= c #B33F3F", "l= c #C67979", "m= c #DDB2B2", "n= c #F6F5F5", "o= c #DBDBDC", "p= c #B8B9D7", "q= c #CBACAC", "r= c #991919", "s= c #8E1717", "t= c #AD5A5A", "u= c #B6B8D8", "v= c #818181", "w= c #B4B5D0", "x= c #CFD0DD", "y= c #D9D9DF", "z= c #BDBFDE", "A= c #BA8585", "B= c #B47676", "C= c #C57878", "D= c #C3C4DF", "E= c #BDBFD6", "F= c #858696", "G= c #D09191", "H= c #E8CACA", "I= c #E3C1C1", "J= c #C69C9C", "K= c #E2CACA", "L= c #CFD0E7", "M= c #C5C6E2", "N= c #C3C4D0", "O= c #C6C7E0", "P= c #F7F5F5", "Q= c #CFBDBD", "R= c #EED9D9", "S= c #FAF6F6", "T= c #B6B6B6", "U= c #D29797", "V= c #E2BEBE", "W= c #CB9F9F", "X= c #CEA1A1", "Y= c #E0E1EF", "Z= c #D3D3D7", "`= c #AEB0D5", " - c #EEECEC", ".- c #EBD4D4", "+- c #DBCBCB", "@- c #C0C1E0", "#- c #D1D2DC", "$- c #F5ECEC", "%- c #CDBBBB", "&- c #D59F9F", "*- c #CE9595", "=- c #705151", "-- c #C4AAAA", ";- c #EFE2E2", ">- c #A9ABD4", ",- c #EFDCDC", "'- c #F0E7E7", ")- c #C4A7A7", "!- c #CA9398", "~- c #90729D", "{- c #DAAFB1", "]- c #CB9797", "^- c #D5D5D9", "/- c #D4CBCB", "(- c #B4B4B4", "_- c #C6AAAA", ":- c #A0A2CD", "<- c #D6BBBB", "[- c #C99696", "}- c #D29898", "|- c #827070", "1- c #D0C1C1", "2- c #D4C0C0", "3- c #F6F0F0", "4- c #DDB6B6", "5- c #EFE0E0", "6- c #C5A4A4", "7- c #B2B3D8", "8- c #E6E6F2", "9- c #D19FA3", "0- c #9D7FA4", "a- c #E7C8C8", "b- c #D8D9DA", "c- c #B2B4D8", "d- c #C39B9B", "e- c #EDDDDD", "f- c #EACFCF", "g- c #CD9595", "h- c #C4A8A8", "i- c #D39B9B", "j- c #F2E5E5", "k- c #F5F2F2", "l- c #AAAAAB", "m- c #A5A5AB", "n- c #D9A9A9", "o- c #AF9D9D", "p- c #E9CECE", "q- c #D09999", "r- c #D2BFBF", "s- c #E1B9B9", "t- c #C2A7A7", "u- c #865C5C", "v- c #C5C7E2", "w- c #CCCEE5", "x- c #F5F3F3", "y- c #B28EA6", "z- c #A9819D", "A- c #E3E3F0", "B- c #F6EDEE", "C- c #E6D5D5", "D- c #C19D9D", "E- c #C9A6A6", "F- c #AFB0BF", "G- c #A6A7CA", "H- c #D0D0D7", "I- c #CF9090", "J- c #F3E8E8", "K- c #6E6E7A", "L- c #E6C5C5", "M- c #F2F2F5", "N- c #D7CFCF", "O- c #707176", "P- c #9091BA", "Q- c #CD8E8E", "R- c #E8D4D4", "S- c #C4C5E2", "T- c #AD8E8E", "U- c #7D7E8D", "V- c #E1DFDF", "W- c #D8ACAC", "X- c #C58989", "Y- c #EAD7D7", "Z- c #727272", "`- c #E0E0EC", " ; c #E3E3E5", ".; c #D29A9A", "+; c #BEB4B4", "@; c #A1A2B4", "#; c #D8D1D1", "$; c #AB9999", " . + @ # $ % & * * & % $ # @ + . ", " = - ; > , ' ) ! ~ { ] ^ / ( ( / ^ ] { ~ ! ) ' , > ; - = ", " _ : < [ } | 1 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 1 | } [ < : _ ", " 2 * 3 4 5 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 5 4 3 * 2 ", " 6 7 8 9 0 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 0 9 8 7 6 ", " a b c d ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( d c b a ", " e f g h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h g f e ", " i j k ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( k j i ", " l m n ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n m l ", " o p q ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( q p o ", " r s t ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( t s r ", " u v w ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w v u ", " e x y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y x e ", " b z ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( z b ", " A B C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C B A ", " D E y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y E D ", " F G ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( G F ", " H ) ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) H ", " I J ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( K L M ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( J I ", " I N ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( O P Q / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( N I ", " R S ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y C T U V W X Y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( S R ", " F ) ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h Z ~ ` .M K C ..+.@.#.$.%.&.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) F ", " *.=.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / Z -.` .` ~ Z h ( y ;.C >.,.'.U M ).!.~.{.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( =.*. ", " ].^.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y | 1 ( ( ( ( ( ( ( 0 d /.T . .T ~ (.h ( ( ( ( ( _. .^ :.<.[.}.d _.| K |.1.2.3.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^.]. ", " B y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 4.5.6.K _.7.` . .` /.5 t h ( ( ( ( ( ( ( ( ( ] U d ( 8.9.y 0.4.y ;.( a.(.( b.c.d.e.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y B ", " b C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h f.g.h.i.j.k.l.( ( ( ( ( ( ( ( ( ( ( ( ( ( h m.| / ( n.o.p.~ q.7.0 r.(.h U t ( ( s.t.u.v.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C b ", " w.z ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( x.y.g.w z.A.B.t.C.c.D.E.( ( ( ( ( ( ( ( { F.{ ( ( G.H.I.( a.J._.(./ .( / K.1 ( ( ( L.M.N.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( z w. ", " u O.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( r.P.Q.R.S._.;.] ( ( b.T.U.t.t.B.N.V.h 1 T m.( ( ( ( W.X.( 1 .Y.C K ( ` 1 ( ^ F./ ( ( ( ( Z.%.`.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( O.u ", " v y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( +.+++` a.@+` 1 7.| 1 ( ( ( ( ( #+$+%+&+*+=+-+;+E.( >+,+( ( '+M )+5 d ( +~ ( ( ] ;.h ( ( ( ( !+~+2.{+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y v ", " ]+w ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / F.^+,+` { /+(+_.( ] a.-.( ( ( ( ( t ;.'+( !+_+:+U.<+[+d.}+|+a.z z 1+2+( ( ;.( ( ( { T ( ( ( ( ( ( E.3+4+|.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w ]+ ", " o s ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ` ] 5+6+` ( a.7+` d ( ( 8+U K ( ( r.` 1 ( ( ( ( ( 9+0+a+b+c+d+e+f+g+h+i+j+( -.K ( ( ( 5 m.( ( ( ( ( ( ( L.k+T.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( s o ", " p t ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( l+-.( m+( ` ( m.n+o+ .(.( ( h ~ K.w K ( ( ( ( ( ( ( p+q+( ( ( 2+8+R.!+r+s+t+C.u+v+w+Z.x+h '+-.( ( ( ( ( ( ( y+N.2.z+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( t p ", " A+9 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( t a.( B+C+( ` ( ^ T D+d F.y ( ^ ` /.T M / ( ( ( ( ( E+F+( ( ( ( ./ J.( 0 /.( ( ( G+H+I+u.J+C.K+L+M+N+v.( ( ( ( ( e.O+P+Q+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9 A+ ", " m h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h F.1 ( R+S+( ` ( ( a.l+T+1 F.r.a.y ( ( Z ;.C ( ( ( U+V+( ( ( ( h .C W+( y M ( ( ( Z /.( ( ( ( ( X+Y+Z+3+C.`+ @.@+@@@( #@$@%@&@*@8+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h m ", " i n ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 7. +( ( m+( ( T h ( l+5 o+L K.=@( ( ( ( ( ( 5 U +-@0+9+( ( ( ( d l+;@z ( 1 7.( ( ( ( a.( ( ( ( ( ( ;.] ( ( ( |.>@A.,@C.C.O+'@)@!@~@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n i ", " f ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( l+_.( ( I.9.( ( | / ( h K.U @+^ 1+7.( ( ( ( ( ( h {@]@^@( ( ( ( ( .h /@~ ( h T ( ( ( ( -.K ( ( ( ( ( / F.^ ( ( ( ( ( b+(@_@:@<@[@}@|@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( f ", " e k ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( Z .( ( ( 1@2@( ( | 1 / T 3@0 k 4@( '+-.( ( ( ( ( ( 5@6@` m.h ( ( h .( 7@t ( ( ` ( ( ( ( h .( ( ( ( ( ( ^ F./ 3.8@t.t.,@A.9@0@a@b@c@d@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( k e ", " j ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^ F.h ( ( ( ++G.( ( 7.M ;.t ] /.( T+l+( M 8+( ( ( ( e@f@( ( +U l+( 1+C ( D+( ( ( ` ( ( ( ( ( T ^ ( ( ( g@h@i@j@k@_@{.l@( ( m@n@o@$@2.$@,@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( j ", " a 6.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h F.y ( ( ( -@p@( h C L 8+( ( ( ;.( 8+Y.( ( .Z ( ( 6+H.h ( ( ( ( 2+;.K.1 ( J.( ( ( ` ( ( ( ( ( q@r@u.t.t.s@t@E.( { T ( ( u@v@w@x@y@Z.}+O+3+z@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 6.a ", " A@h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( a.Z ( ( ( ( B@8.d U d m.t ( ( ( _. +( (+` ( / F.^ C@D@E@( ( ( ( ( ( / F@` (.7@( ( ( ` G@L.H@t.t.B.I@|+( ( ( ( ( ( ( l+J@K@L@M@B.2.N@3+#+O+O@,@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h A@ ", " 6 (+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( | 1+( ( ( ( ( P@U '+( ( /.t ( ( ( / .( y 7+( ( ^ F.Q@2@( ( ( ( ( ( ( { -.y f.R@S@%+T@U@T@~+V@( ( ( '+1+( ( ( ( ( ( ( W@X@Y@3+Z@!.`@( #( O+( .#g@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (+6 ", " 7 d ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( m.5 ( ( ( ( (.+#@#h ( ( ( r.0 ( ( ( ( ./ ( ##$#( ( %#&#( ( ( ( ( ( ( b.*#=#T@-#;#>#,#|.` ( ( ( ( ( ( / .( ( ( ( ( '#)#!#~#{#]#S@^#( N@_@( O+( g@ @( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( d 7 ", " /#( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( r.C ( ( ( ] a./.(#e@( ( ( ( ~ Z ( ( ( ( K -.( h _#/ 8.:#8+M |.3.}+U.C.t.c.<#[#!+}#^ h '+;.K.( ( ( ( ( ( ( ` 1 ( ( ( |#1#2#;+3#e.4#5#6#( 7#8#( O+( ( @9#( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /# ", " 2 9 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( _.-.( ( y .7.1 ( ++h ( ( ( ( -.(.( ( ( ( ( ;.( ( L 0#a#b#O+c#d#e##@E.( ( Z r.( ( J.( ( ( / f#T / ( ( ( ( ( ] /.( g#L@h#i#j#k#h ( l#m#/ ( n#y+( d.6#( s.B.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9 2 ", " * 0 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( -._.( y T T ^ ( ( -@p@( ( ( ( ( C { ( ( b.o#p#q#r#C.s#t#u#b.y+( 7.1+( ( ( ( T 1 ( / Y.( ( ( ( ` 0 ;._.h ( ( ( ( a.v#w#u@h i@}+( ( !.M+] a.6#J+( ( s@e.( ( J+e.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 0 * ", " 8 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( '+~ 1 7.` t ( ( ( ( x#e@( ( b+y#`@z#A#C.`+B#C#L.D#E#( F#G#H#( ( ( ( a.] ( ( ( a.( ( 1+I#( ( ( ( ` ( ( 8+U 1+( ( J#K#L#G.v.:@M#( ( N#d.( ( 8+O#I+( ( P#Q#( ( [#R#( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 8 ", " _ 4 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C m.M .0 ( ( ( y+j+S#T#U#`+`+^#-+V#W#d ( ( ( ( ( ( a.X#Y#( }#C ( ( ( / F.1 ( Z r.( ( z Z#( ( ( ( ` ( ( ( h _.`# $.$+$` E.@$#$( ( @@@$|.( ( ( $$).( ( A.%$( ( ( 2.6#( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 4 _ ", " : l+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( K &$q Z#;.*$=$-$;$`+`+>$4+,$'$( ( ( ( ( ( 8+l+( ( ( ( ( ( )$!$( ( ] q.( ( ( ( y F.h 7.y ( ( )+1+( ( ( ( ` ( ( ( ( ~${$]$7./ ^$@$E.( ( ( t.[#( ( ( l@n#` Z ( /$($( ( ( _$%+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( l+: ", " < ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( k :$)+<$[$}$|$N+b+( ( ( ( 1$2$( ( ( ( ( ( K 2+( ( ( ( ( B+3$a.( ( ( ##Z#( ( ( ( (.` a.( ( ( J.( ( ( ( ( ` h ( '#)#4$5$( ] 6$i.7$( ( ( 8$`@( ( ( ( [#w+/ F.1 S@p#( ( ( ( 9$y+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( < ", " [ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 7./+0$a$b$c$k M 8+1 ( ( ( m+G.( ( ( ( ( ( +'+( ( ( ( a+0+a+T ^ ( ( h _#y ( ( ( ( -.K.( ( ( J.( ( ( ( ( | / d$e$2#( ( l@P#H@5 3@{ ( S@^#( ( ( ( ( f$|+( t ;.{+w+( ( ( ( g$h$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( [ ", " = i$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( j$k$l$` 6.Y.m$J T .` n$o$/ ( ( ( ( ( ( (.-.( ( ( G.p$q$( ] /.( ( ( U W+( ( ( ( 7.7.l+( +' ( ( ( ( ( r$s$t$G.( ( |.t.T.( ( /.a.a.u$!+( ( ( ( ( 2.( ( ( 1+v$B#( ( ( ( v.t.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( i$= ", " - | ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w$x$_.T +U '+q y$z$U A$B$T .` m.1+1 ( Z ~ ( ( ( C$D$( ( ( a.( ( ( ( T+l+( ( ( a.( T +f#E$( ( ( G.F$G$H$( ( ( j+I$J$( ( ( 1 ` K$L$M / ( ( ( E.B.( ( ( ( ~ M$( ( ( ( ( O+v.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( | - ", " * 1 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( N$O$` 2+_.( -.a.t K 5.P$Q$ .h ( t 2+| .K.=@1+1 :.Y#( ( ( ( _. +( ( ( +y$( ( Z r.( h U I#'+( ( W@R$S$/.0 ( ( {.$@E.( ( ( ( ( T$($( (.U 2+( ( :+#@( ( ( ( ( U$] ( ( ( ( ($V$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 1 * ", " > ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( D$W$ .h m.8+( 1 T m.X$Y$K Z$c$P 0 ( ( ( 0 | 2+`$ % .7.1+/ ( 1 T ( ( ( ( 5.n ( | ^ ( ( 1 .%1 5$+%@%'#( r.] ( h@.#!+( ( ( ( ( _$#%l+( ( ( l+U +C.!+( ( ( ( ( n#K.h ( ( ( b+$%( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( > ", " %%( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 2@B@8+2+( a.0 ( ( (.&%*%( ( ( | R.}# .( 0 /.q+=%( ( ^ l+T . .F@5 y ( ( h -%1 a.( ( ( ( c$;%>%,%( ( ( _.Z Z+H@( ( ( ( ( ( b.'%h a.( ( ( ( h )%!%y ( ( ( ( ( O+0 a.( ( ( ( ~%( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( %% ", " ' ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( {%]%( a.( h F.1 ( G.^%-.a.t ( ( ( +S.y$Q$/%(%p.( ( ( ( ( ( ( 5 ;.M . .| E$:$~ ( ( ( _%:%<%.+( ( ( ( [%}%D.( ( ( ( ( ( y+:@s.( | ^ ( ( ( ( h$|%` /.h ( ( ( >$( l+_.( ( ( 4+s.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ' ", ". ) ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( q$R+( | ^ ( t U h X.W$( 1 T m.h ( ( ( ( 1%2%3%4%~ ( ( ( ( ( ( h a.( ( ( 1 K 5%n .6%7%8%9%( C -.( ( E.0%a%( ( ( ( ( ( ( 7#b%( ( (.r.( ( ( ( c.e.( +U l+( ( >$( ( M K ( ( %$N.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) . ", "+ ! ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( c%f@( Z r.( ( { | d%e%( ( ( +U d ( ( f%g%h%( d (+y$W+2+( ( ( ( | y ( ( ( h 3@J.F$v@i%f.Q . .;@/.j%k%l%K ( ( ( ( ( ( m%f$( ( ( ( a.( ( ( ( 2.( ( ( ( 2+U (.O+( ( h U ^ ( v. @( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ! + ", "@ ~ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n%o%( ( a.( ( ( p%q%( ( ( ( ( ( -.a.r%^%s%M ( ( ( ( ~ I#y$S y ( t M ( ( ( 1+t%u%v%( ( W+2+( ( 1 w%x%G+k =@7.'+Z / ( j+3#y+( ( ( ( m.] ( ( s.y%( ( ( ( ( / M z%y ( ( ^ U h ( t.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ~ @ ", "# { ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n.5+( ( r.Z ( ( 1@A%K ( ( ( ( ( ( ^ B%C%y 7.( ( ( ( ( ( / L R.7@M a.( ( u@D%E%F%_#h ( 0.^ ( ( N.R#G%1 5 8+^ { _.| a.H%I%_.{ 1 ( ( y 7.( ( u.N@( ( ( ( ( ( ( J%K%r.h ( { 7.( J+!+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( { # ", "$ ] ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( a+L%( ( ^ | ( ( M%( ;.t ( ( ( ( ( ,+N% +K.;.( ( ( ( ( ( ( ( ( { W O%P%Q%R%S%( ( g J ( D+( ( t+A.( y F.5 d ( ( ( ( T%+@h Z C | ` .` F@l+] 2.( ( ( ( ( ( ( ( f$j+{ U 5 ( _.5 N.%$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ] $ ", "% ^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( e%p+( ( ( a.( U%7%( / F./ ( ( ( V%B@( ( ^ n a.t ( ( ( ( ( ( ( ( W%X%Y%Z%_#q 1 ( ( 7+T J.!+J+t@( ( ( +`%5 ( ( ( }+8$( ( ( ( ( ( ( h r.r. &.& . .| ~ 1+y ( ( e#Q#( ( '+;.Z .+&_@( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^ % ", "& / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9+p@( ( ( C 8+V+@&( ( 0 ;.( ( #&Y$( ( ( 1 7.1 ` /.h ( ( ( ( G.$&w#%& ./ F.N &&7@;.*&##9 =&o#( ( ( ( ( r.| ( ( J$J+( ( ( ( ( ( ( ( ( 1 T N.;+( ( / ] 2+m.` .-&;&'+(.1 / M .! >&m.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / & ", "* ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( p.,&( ( ( h '&)&( ( ( ( 1+M D$,&( ( ( ( 1 | ( ( +U d ( ( !&w#~&G.( 8+_.T ( ( +Q {&5.]&^&Z#Z#Z#Z#Z#Z#J =.N /&(&_&Z#Z#Z#Z#Z#Z#Z#Z#Z#Z#Z$:&Z#Z#Z#Z#Z#Z#Z#Z#Z#<&[&J ^&0$P P /@I#W+5./ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( * ", "* ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h V+( ( ( ( }&|&( ( ( ( ( 1&2&G.( ( ( ( / | ( ( ( ( -.3&4&5&G.( ( ( h $#] ( ( 6&7&8&/+c$i$Z#Z#Z#Z#Z#Z#J 9 9&0&a&Z#Z#Z#Z#Z#Z#Z#Z#Z#Z#Z#b&c&Z#Z#Z#Z#Z#Z#Z#Z#Z#d&e&Z#Z#f&g&h&i&j&4%i$/ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( * ", "& / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h V+( ( ( ( 2&-.( ( ( ( k&l&m&{ ( ( ( ( / | ( ( ( n&o&p&q&M / ( ( ( ( L s%:#m+]%6+[.r&r&&&;@( ( ( ( ( 1+l+R#s&^ ( ( ( ( ( ( ( ( ( ( ( }+t&( ( ( ( ( ( ( ( a+u&v&w&d%x&8.y&F.L q m.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / & ", "% ^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( p.,&( ( ( U%z&a.( ( ( A&B&a+h U y ( ( ( 1 | ( C&D&E&F&( ( (.U l+( -@G&H&I&I.( ( / -%7.R.h W 5.( ( ( ( 8+J&K&y U h ( ( ( ( ( ( ( ( ( ( t.L&( ( ( G.I.W$=%w&M&N&O&( ( h | /.-.2+` ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^ % ", "$ ] ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9+p@( ( ( ++f%7.t ( F%0+P&( ( 1 K./ ( ( 1 Q&R&S&n&( ( ( ( ( G.T&U&V&W&1 a.( ( ( r&3@( J.( ( N X&/ ( ( Y&Z&( ( (.` ( ( ( ( ( ( ( ( ( |.C.`& *.*)&)&+*2$9+( ( %+#$( { F.Z t . +-.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ] $ ", "# { ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( e%p+( ( n.@*( 0 m.9+#*$*( ( ( ( ] a.( '#%*&***( ( ( ( ( =*Y$^%Y#F%T 3@1 r.(.( (.c$( ( X&t ( ( K.-*Z 9#;*>*( ( ( l+~ ( ( ( ( ( h X$,*'*)*Q@!*6+h ( ( ( ( ( ( P#~*7.m.h ( ;.1 ~ Z ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( { # ", "@ ~ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( -@:#( ( ,+6&( ( ;.w&{*( ( ( ( ( ( y&]*v@^*7.( ( ( F%V%^%9.$*( ( ( C -.a.r.T ( 0.C ( ( 0$r.( ( ( C /*(*_*d ( ( ( ( m.:*n.<*9.d%)&[*8.}*!+( a.( ( ( ( ( ( ( ( |*1*(.( ( _.d ( ` h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ~ @ ", "+ ! ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( A&7&( G.M%( ( ( 2*3*( ( ( ( ( ( 4*5*6*2+^ 7.p.7*++V+8*G.( ( ( ( ( a.h ( d F@`%=.( ( ( `%S ( ( ( ( 9*0**&8+( e%X.a*)&b*c*d*e*( ( ( f*J+( ( -.{ ( ( ( ( ( h 7.g*h*( ( t .( ( .( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ! + ", ". ) ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( I.Y$( >+E+( ( f@i*` ( ( ( G.j*w#k*( ( m&l*m*w&n*p.( ( ( ( ( ( ( t 7.( ( ( C o*F.y ( ( 1+I#( ( ( _@p*<*q*r*)&p@s*I.G./ K.1 ( ( ( ( g$(@( ( / ` ( ( ( ( +F. +$%!+( ( U / ( ( ` ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) . ", " ' ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( k&x&( ++f%( t*x#( .h ( d$u*v*i#G.w*)&)&x*y*( ( ( ( ( ( ( ( ( ( | y ( ( ( q Z$y ` m./ a+z*1$F#A*B*+*w$C*P%(+h ( ( ( ( y U h ( ( ( D*( ( ( ( .h ( h M M h ( O+( ( ~ 8+( ( ^ 7.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ' ", " %%( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( {%5@6+E*( Y#]%( ( l+F*u*G*i#f%7%M%H*e%( 0 L / ( ( ( ( ( ( ( ( h a.( ( ( 0 I*J*K*V+L*m*M*N*U%O*c.( ( ( '+{ F@}.^ ( ( ( ( { | ( ( z+P*( ( ( ( _. + +F. +( ( ( O+( ] T ( ( ( d 5 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( %% ", " > ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( q+Q*9.=*n*.*( ( R*S*T*U*<*V*w&8.( ( ( ( t a.a.( ( ( ( ( ( ( F%W*X*+*V+)&Y*Z*`* =p.( ( l+g..=9$y+( ( ( -.(.( m.+=d ( ( ( ( C -.( @=[#( ( ( ( y 3@M h ( ( ( ( O+( F./ ( ( ( 7.^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( > ", " * 1 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w*W$m+#=p@G.$=%=&=*===-=<.e%( ( ( ( ( ( 0 /.;=>=#=Q*+*V*)&)&p+,=8*n%9+/.{&( h a.( ( ( ( '=)=X+y ( ( ( _.Z ( ( +!=;.( ( ( ( M ~=:@( ( ( ( { F.l$( ( ( ( ( ( O+m.{ ( ( ( ( .( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 1 * ", " - | ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( <*3${=^%]=.$^=/=w&Y#(=_.( ( h e%_=:=f@)&<=[=,&}=|=q+n%( ( ( t M ( ( ( 7+0 ( ( T ^ ( ( v.{#1=y ` m./ ( r.] ( ( ( 1 0.[.( ( ( ( 2=3=( ( h | m.h r.Z ( ( ( ( ( 4=7.( ( ( ( h ` ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( | - ", " = i$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h 5=6=7=8=9=0=5@e*{%a=R+b=V*)&=%M&1@c==*( ] ~ ( ( | { ( ( ( ( 7.t ( ( g q ( ( ( Z r.( y+%.d=X&( ( (.;.'+/.t ( ( ( ( ( Q o+( ( ( `+e=/ 1+U Z ( ( y 7.( ( ( ( / f=h ( ( ( ( { '+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( i$= ", " [ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( g=h=i=j=k=l=d%)&,&m=<*B+y*n=( ( ( ( ( ( ( Z _.( ( h U y ( ( h a.( ( t _#h ( ( ( ( a.y+O+_$( J.( ( ( ( d L 5 ( ( ( ( ( ( L }.t v.t.(.;@r.h ( ( ( ( a.( ( ( ( o=p=( ( ( ( ( | ^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( [ ", " < ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( q=r=s=t=#*B@$*p.( ( ( ( 0 M ( ( ( ( ( ( ( (.-.( ( ( 1 K./ ( 2+d ( ( :$` ( ( ( ( ( M u=Z.( ( J.( ( ( ( ( 7./.a.0 ( ( ( ( ( m.v=w=x=;.C M ( ( ( ( ( M 0 ( ( 5 y=z=( ( ( ( ( a.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( < ", " : l+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n=A=B=C=V+2$x&)&d%5+w*p.( a.( ( ( ( ( ( ( { C ( ( ( ( ] a.( a.( ( -.7@( ( ( ( ( ( D=E=( ( ( W -.( ( ( ( T / 1 | T 1 ( ( ( ( 8+F=z ( ( _.2+( ( ( ( t M ( ^ ;.8#.@( ( ( ( K '+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( l+: ", " _ 4 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( d%c=G=H=( ( n%I=V*w&J=K==*( ( ( ( ( 1+l+( ( ( ( ( 1+;.m.( h -*0 ( ( ( ( ( L=M=a.( ( ( n E$( ( ( ( ` ( ( ( t a.r.h h /.N=O=}#O ( ( T +( ( ( ( a.h U ^ =$h@( ( ( ( a.h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 4 _ ", " 8 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( e%D@F%,*++P&( ( ( ( P=Q=Y$d%d%x&R=S=d 5 ( ( ( ( ( ( w ~ ( ;@T=( ( ( ( ( Z.y%( r.(.( ( Z Q$( ( ( ( ` ( ( ( ( ( { k n { O+#+h P ^&( h U y ( ( ( 7.T 1+( A.%$( ( ( ] M ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 8 ", " * 0 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( U+,&( 6+U=V=( ( ( ( .h ( ( $*1$p@W=X=Y#n%G.( ( / .7.d _#h ( ( ( ( Y=T@( ( ^ | ( ( h D+( ( ( ( ` ( ( ( ( t a._.l+Z=`=( ( ( &${&h ^ F.h ( ( '+K.( ( w+|+( ( ( a./ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 0 * ", " 2 9 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( W$x#( ( N%#*B+( ( 2+d ( ( ( ( ( C -.-5+)&)&Y$+-y&( ]&z ( ( ( ( N#D*h ( ( ( a.( ( ( J.( ( ( ( ` ( ( / M ` 1 ( ( @-#-a.0 ( ( w -%{ ] .( y ;.a.( ( T%h*( ( { r.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9 2 ", " /#( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( V+^+( ( -@,&{=p./ .( ( ( ( ( -. +( ( ( h $-%-&-*-=---;-e%( 3.>-|.( ( ( ( -.{ ( ( 7@t ( ( ( ` ( '+;.Z ( ( ( ( 9$( 1 | | ^ ( d !=;.5 /.F.1 | 1 ( .#!+( ( U h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /# ", " 7 d ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9+0+F%( ( ( w*o.,-` / ( ( ( ( ~ Z ( ( ( ( +~ ( =.m&'-)-,&!-~-{-8.S=( ( ( / ` ( ( r&a.( ( ( l$U d ( ( ( ( ( V$M+( ( ( 0 ./.h ^ X&q n ~ ( K '+( O+( ( -.d ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( d 7 ", " 6 (+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( X$w&( ( ( ( 9+Y$]--.( ( ( ( r.0 ( ( ( ( ./ 8+D+( ( (.^-@$E._=1$M&)&V*C$Y#/-h ( ` ^&( (.;.`%( ( ( ( ( ( ( 9$y+( ( ( ( ( +U C ( (-4%U ] h .( O+( 1 ;.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (+6 ", " A@h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w$7%( ( ( ( ( S+_-<*( ( ( /.t ( ( ( 1 ` ( Y.d ( ( v.:-y=( ( ( ( ( G.-@8*<-[-)&}-|-1-2-3-` ( ( ( ( ( ( V._@( ( ( ( ( ( ( ( 5 k ;.a.v=L 1 ` h O+( .y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h A@ ", " a 6.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( a*#=( ( ( ( ( T 4-++6+( m.y ( ( ( /.Z T =.( ( |.%.N@~ 2+( ( ( ( ( ( ( / ` t .I#5-1$5+6-)&)&9.F+R=n%7-E.( ( ( ( ( ( ( ( K | ~ a.-.O%&$5 l+O+8+_.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 6.a ", " j ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( G.G=6+( ( ( ( ] m.P&>.7%M ^ ( ( h a.( -*0 ( y+2.8-( ( T { ( ( ( ( ( ( y L T ^ D+( ( ( ` ( ( A&8.V=9-0-)&)&V*Y$a-{%h ( (.a.( ( 1 7.;._###b-c-U ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( j ", " e k ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( E@0+f%( ( ( ( a.( ( c=d-e-( ( 8+C q 6.( ( T@Y=( ( ( ( U 0 ( ( ( y T T C l+( {&Z ( ( ` ( ( ( ( ( _@V.( ( G.6+f-m==%g-h-i-E*{=#&j-k-a..%l-m- .( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( k e ", " f ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( U+d%G.( ( ( /.Z ( ( T n-p+-@a. +q.h ( T%/$( ( ( ( ( / F.1 t T T y ( h .( Q 7.( ( ` ( ( ( ( h 9$( ( ( ( ( ( ( t F./ G.-@X$H=5@M&)&o-}#!=J ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( f ", " i n ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( p-f@( ( ( y | ( ( T h $*q-r-Y.2+( 1.h@( ( ( ( ( ( ( { Z#T y ( ( ( ( .h n E$( h T ( ( ( ( L=Z.( ( ( ( ( ( y K.1 ( ( ( ( 1 C . .9 S.^&L ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n i ", " m h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( s-V%( ( ( a.( ( ` ( ( 7.t-u-,-v-w-( ( ( ( ( ( 0 .| 1+` ( ( ( ( ( K '+1+I#( 1 7.( ( ( ( 9$y+( ( ( ( ( y K.1 ( ( { 7.a.T 1+( -./.M 7.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h m ", " A+9 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C+a=( ( '+1+( ` ( h ;.7+x-y-z-6+( ( ( ( ] .7.1 ( ( 5 /.( ( ( ( ( a.( J.( y m.( ( ( A-%+( ( ( ( ( y K.(.~ . .'+^ ( ( ( /.-.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 9 A+ ", " p t ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( G.M&#=( / ` ( ` ( '+##&$`@w+B-V+C+e%Z a.M 1 ( ( ( ( ( ~ 2+( ( ( ( T 1 J.( 0 r.( ( ( n#v.( ( ( ^ '+L U /.Z ( ( ( ( ( h | l+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( t p ", " o s ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( p.^%2@( .h ` ( ;.-%T.P*( ( ( C-D-E-1 ( ( ( ( ( ( ( ( | K ( ( ( +_.o+'+Z _.( ( s.c.t -.` .;.f#1 ( ( ( ( ( ( ( h ;.K ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( s o ", " ]+w ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( p.#*S+8+2+` (.Q$F-3+( ( K a.r./ c=G=:=G.( ( ( ( ( ( h ;.0 ( ( ( a.`%S { ~ 8+M G-H-M +h 0 F./ ( ( ( ( ( ( ( y F.] ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w ]+ ", " v y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( e%I-J-a.` K.K- #!+8+;._./ ( ( ( G.L-#*c=( ( ( ( ( ( / K.y y 8+`%k -*n+K.l+M-n#( ( ( ] F./ ( ( ( ( ( ( ( K U 1 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y v ", " u O.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( a+0+N-k O-P-l+U '+h ( ( ( ( ( ( ( p.Q*Q-R-2+m.` ` .U ;@M l+d /.D+2+1+( S-A-( ( Z U / ( ( ( ( ( ( ( m.M h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( O.u ", " w.z ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( -@T-^&U-G%'+t +d _.M | ` ` .` ` ` V-W-X-Y-( ( ( ( (. .( ( a.J.-.(.( M.( ( +;.h ( ( ( ( ( ( (.F.K ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( z w. ", " b C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h T=Z-S.=@T /.-.d (.y 1 h ( ( ( ( ( ( ( e%R+m+6&( ( ( d /.( M J.T 0 ($`@( K .h ( ( ( ( ( ] .m.h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C b ", " B y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( $#r&F@/.a.| (.( ( ( ( ( ( ( ( ( ( ( ( ( ( a+f@U=X$( ( _.2+0 H#/+y M.( 8+T ( ( ( ( ( K a.M ^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y B ", " ].^.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y ( ( ( ^ r.a.T 1+( ( ( ( ( ( ( ( ( ( ( ( ( a++*w&X$( | K L !=`-7#l+7.( ( ( t m.a.-.h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^.]. ", " *.=.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / 2+ . .'+^ ( ( ( ( ( ( ( ( ( ( ( E@7&)&X$;.a.'.r# ;m.( y r.a.7.0 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( =.*. ", " F ) ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h K 7. .` '+0 h ( ( ( ( ( ( ( ( e*5+.;+;T+@;| r.a.7.(.( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) F ", " R S ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h { /.T ` ` ` ` ` ` T T T T #;$;}#4@` Z ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( S R ", " I N ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h h h h h h h $#S.(-h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( N I ", " I J ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^ K.1+( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( J I ", " H ) ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) H ", " F G ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( G F ", " D E y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y E D ", " A B C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( C B A ", " b z ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( z b ", " e x y ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( y x e ", " u v w ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( w v u ", " r s t ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( t s r ", " o p q ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( q p o ", " l m n ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( n m l ", " i j k ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( k j i ", " e f g h ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( h g f e ", " a b c d ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( d c b a ", " 6 7 8 9 0 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 0 9 8 7 6 ", " 2 * 3 4 5 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 5 4 3 * 2 ", " _ : < [ } | 1 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 1 | } [ < : _ ", " = - ; > , ' ) ! ~ { ] ^ / ( ( / ^ ] { ~ ! ) ' , > ; - = ", " . + @ # $ % & * * & % $ # @ + . "}; ocamlgraph-2.0.0/editor/htree.ml0000644000175000001440000002200413735627615015136 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (*** Signatures ***) module type TREE = sig type t type label val children : t -> t list val label : t -> label end ;; module type HTREE = sig type t type label val children : t -> t list val label : t -> label type coord = float * float type driver = { rlimit : float ; moveto : coord -> unit ; lineto : coord -> unit ; curveto : coord -> coord -> coord -> unit ; draw_label : label -> coord -> float -> unit ; init_edge_pass : unit -> unit ; init_label_pass : unit -> unit ; finalize : unit -> unit ; } val shrink_factor : coord -> float val drag_origin : coord -> coord -> coord -> coord val draw_linear_tree : driver -> t -> coord -> float -> unit val draw_curved_tree : driver -> t -> coord -> float -> unit end ;; (*** Complex operators ***) 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 functions ***) 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 normalize ((u +& atht) /& (one +& (~&a) *& utht)) ;; (*** The 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 advance turt step = { pos = gamma turt.pos turt.dir step ; dir = delta turt.pos turt.dir step } ;; let turn turtle u = { pos = turtle.pos ; dir = turtle.dir *& u } ;; let turn_left turtle angle = turn turtle (expi angle) ;; let turn_right turtle angle = turn turtle (expi (-.angle)) ;; (*** Tree-independent functions ***) let shrink_factor (x, y) = 1.0 -. (x*.x +. y*.y) (* 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) (* [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 0.0 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 zx*.zx +. zy*.zy end end ;; (*** The functor ***) module Make(T : TREE) = struct type t = T.t type label = T.label let children = T.children let label = T.label type coord = float * float type driver = { rlimit : float ; moveto : coord -> unit ; lineto : coord -> unit ; curveto : coord -> coord -> coord -> unit ; draw_label : label -> coord -> float -> unit ; init_edge_pass : unit -> unit ; init_label_pass : unit -> unit ; finalize : unit -> unit ; } let shrink_factor = shrink_factor let drag_origin = drag_origin let draw_linear_edges drv tree turtle = let rlimit_sqr = drv.rlimit*.drv.rlimit in let rec do_tree tur t = if hspace_dist_sqr tur <= rlimit_sqr then begin let list = children t in let num = List.length list in if num > 0 then begin let step = step_from (2*(max 3 num)) and angle = pi/.float(num) in let tur' = turn_left tur (angle/.2.0 -. pi_over_2) in do_list tur' step (expi angle) list end end and do_list tur step u = function | [] -> () | t :: rest -> drv.moveto tur.pos ; let tur' = advance tur step in drv.lineto tur'.pos ; do_tree tur' t ; do_list (turn tur u) step u rest in do_tree turtle tree let draw_curved_edges drv tree turtle = let rlimit_sqr = drv.rlimit*.drv.rlimit in let rec do_tree tur t = if hspace_dist_sqr tur <= rlimit_sqr then begin let list = children t in let num = List.length list in if num > 0 then begin let step = step_from (2*(max 3 num)) and angle = pi/.float(num) in let tur' = turn_left tur (angle/.2.0 -. pi_over_2) in do_list tur' step (expi angle) list end end and do_list tur step u = function | [] -> () | t :: rest -> drv.moveto tur.pos ; let tur' = advance tur step in let (a0x, a0y) = tur.pos and (u0x, u0y) = tur.dir and (a3x, a3y) = tur'.pos and (u3x, u3y) = tur'.dir in let dx = a3x -. a0x and dy = a3y -. a0y in let k = sqrt(dx*.dx +. dy*.dy)/.3.0 in let a1 = (a0x +. k*.u0x, a0y +. k*.u0y) and a2 = (a3x -. k*.u3x, a3y -. k*.u3y) in drv.moveto tur.pos ; drv.curveto a1 a2 tur'.pos ; do_tree tur' t ; do_list (turn tur u) step u rest in do_tree turtle tree let draw_labels drv tree turtle = let rlimit_sqr = drv.rlimit*.drv.rlimit in let rec do_tree tur t = if hspace_dist_sqr tur <= rlimit_sqr then begin drv.draw_label (label t) tur.pos (shrink_factor tur.pos) ; let list = children t in let num = List.length list in if num > 0 then begin let step = step_from (2*(max 3 num)) and angle = pi/.float(num) in let tur' = turn_left tur (angle/.2.0 -. pi_over_2) in do_list tur' step (expi angle) list end end and do_list tur step u = function | [] -> () | t :: rest -> let tur' = advance tur step in do_tree tur' t ; do_list (turn tur u) step u rest in do_tree turtle tree let draw_linear_tree drv tree start angle = let turt = make_turtle start angle in drv.init_edge_pass () ; draw_linear_edges drv tree turt ; drv.init_label_pass () ; draw_labels drv tree turt ; drv.finalize () let draw_curved_tree drv tree start angle = let turt = make_turtle start angle in drv.init_edge_pass () ; draw_curved_edges drv tree turt ; drv.init_label_pass () ; draw_labels drv tree turt ; drv.finalize () end ocamlgraph-2.0.0/editor/dune0000644000175000001440000000240113735627615014352 0ustar rtusers(executable (name ed_main) (modules ed_main ed_display ed_graph ed_hyper ed_draw) (libraries graph lablgtk2 lablgtk2.gnomecanvas)) (executable (name editor) (modules editor gtree htree) (libraries graph lablgtk2 lablgtk2.gnomecanvas) (flags -w -32)) (executable (name graphEdGTK) (modules graphEdGTK outils_tort outils_math) (libraries graph lablgtk2 lablgtk2.gnomecanvas) (flags -w -32)) ;; FIXME: graphEd cannot be built because tmoveto / tlineto don't exist (anymore ?) ; (executable ; (name graphEd) ; (modules graphEd outils_math outils_tort) ; (libraries graph lablgtk2 lablgtk2.gnomecanvas)) ;; This was commented in the old makefile that was here before : ; # 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 .. ocamlgraph-2.0.0/editor/ed_hyper.ml0000644000175000001440000001317613735627615015640 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/editor/gtree.ml0000644000175000001440000002177513735627615015153 0ustar rtusers(**************************************************************************) (* *) (* 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 T = struct type t = DirTree.t type label = DirTree.t let id = DirTree.id let edges = Hashtbl.create 97 let children t = let l = DirTree.children t in List.iter (fun i -> Hashtbl.replace edges (DirTree.id t, DirTree.id i) ()) l; l let label x = x let string_of_label x = DirTree.string_of_label (DirTree.label x) let root = DirTree.from_dir "" Sys.argv.(1) end *) let debug = ref false type drag_box = { db_nom : string; db_noeud : GnoCanvas.ellipse; mutable db_x : float; mutable db_y : float; db_w : float; db_h : float; mutable db_viewable : bool; } let drag_boxes = Hashtbl.create 97 module T = struct open Graph.Pack.Graph let g = parse_gml_file Sys.argv.(1) exception Choose of V.t let root = try iter_vertex (fun v -> raise (Choose v)) g; Format.eprintf "empty graph@."; exit 0 with Choose v -> v type t = V.t type label = V.t module H = Hashtbl.Make(V) let ids = H.create 97 let id = let r = ref 0 in fun v -> try H.find ids v with Not_found -> incr r; H.add ids v !r; !r let edges = Hashtbl.create 97 let make_subgraph l = let edge v w = mem_edge g v w || mem_edge g w v in let gl = create () in List.iter (fun v -> add_vertex gl v) l; List.iter (fun v -> List.iter (fun w -> if edge v w then 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 let v = match c with | v :: l -> List.fold_left (fun m v -> if out_degree gc v < 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 let children v = let l = succ g v in List.iter (fun i -> Hashtbl.replace edges (id v, id i) ()) l; let l = List.filter (fun w -> try not (Hashtbl.find drag_boxes (id w)).db_viewable with Not_found -> true) l in let l = order_children l in if !debug then ( Format.printf "children %d: " (V.label v); List.iter (fun w -> Format.printf "%d " (V.label w)) l; Format.printf "@."; ); l let label x = x let string_of_label x = string_of_int (V.label x) end module HT = Htree.Make(T) let step = ref 0 let lines = Hashtbl.create 97 let show_tree canvas t width height = let rlimit = 0.98 in let xzoom = float(width)/.2.0 and yzoom = float(height)/.2.0 in let origin = ref (-0.5,0.0) in let xy2gtk x y = float x -. 300., float(height)/.2. -. float y +. 50. in let gtk2xy gx gy = truncate (gx +. 300.), truncate ((float height)/.2. +. 50. -. gy) in let xy2c (x, y) = let zx = (float(x) -. xzoom)/.xzoom and zy = (float(y) -. yzoom)/.yzoom in let zn = sqrt(zx*.zx +. zy*.zy) in if zn > rlimit then (rlimit*.zx/.zn, rlimit*.zy/.zn) else (zx, zy) in let draw_edges () = let draw_edge (i,j) () = try let dbi = Hashtbl.find drag_boxes i in let dbj = Hashtbl.find drag_boxes j in let l = try Hashtbl.find lines (i,j); (* if !debug then Format.printf "find edge %s ---- %s@." (dbi.db_nom)(dbj.db_nom) else (); *) with Not_found-> try Hashtbl.find lines (j,i); (* if !debug then Format.printf "find edge %s ---- %s@." (dbi.db_nom)(dbj.db_nom) else (); *) with Not_found -> let l = GnoCanvas.line canvas ~props:[ `FILL_COLOR "black" ;`WIDTH_PIXELS 1; `SMOOTH true] in Hashtbl.add lines (i,j) l; if !debug then Format.printf "draw_edge %s ---- %s@." (dbi.db_nom)(dbj.db_nom) else (); l in let p = [| dbi.db_x; dbi.db_y; dbj.db_x; dbj.db_y |] in l#set [`POINTS p]; l#lower_to_bottom () with Not_found -> try let l= Hashtbl.find lines (i,j) in l#destroy(); Hashtbl.remove lines (i,j) with Not_found -> () in Hashtbl.iter draw_edge T.edges in let rec draw_label lab (zx,zy) facteur_reduction = if !debug then Format.printf "draw_label %d@." (T.id lab); let x = truncate (zx*.xzoom +. xzoom) and y = truncate (zy*.yzoom +. yzoom) in let name = T.string_of_label lab in let (w,h) = (40,15) in let x0 = x - w/2 and y0 = y - h/2 in let fx,fy = xy2gtk x0 y0 in try let db = Hashtbl.find drag_boxes (T.id lab) in db.db_x <- fx; db.db_y <- fy; db.db_viewable <- true; db.db_noeud#parent#set [ `X fx; `Y fy; ]; db.db_noeud#parent#move ~x:zx ~y:zy; with Not_found -> let noeud = GnoCanvas.group ~x:fx ~y:fy canvas in let ellipse = GnoCanvas.ellipse ~props:[ `X1 ( float (-w/2)); `Y1 (float (-h/2)); `X2 (float (w/2)) ; `Y2 ( float (h/2)) ; `FILL_COLOR "grey" ; `OUTLINE_COLOR "black" ; `WIDTH_PIXELS 0 ] noeud in let _ = GnoCanvas.text ~props:[`X 0.0; `Y 0.0 ; `TEXT name; `FILL_COLOR "blue"] noeud in let sigs = noeud#connect in let db = { db_nom = name; db_noeud = ellipse; db_x = fx; db_y = fy; db_w = float w; db_h = float h; db_viewable = true } in let _ = sigs#event (drag_label db) in Hashtbl.add drag_boxes (T.id lab) db; and draw_drv = { HT.rlimit = rlimit ; HT.moveto = (fun _ -> ()); HT.lineto = (fun _ -> ()); HT.curveto = (fun _ _ _ -> ()); HT.draw_label = draw_label ; HT.init_edge_pass = (fun () -> ()); HT.init_label_pass = (fun () -> ()); HT.finalize = (fun () -> ()) } and draw_linear_tree t c f = (* mettre toutes les boites à faux *) Hashtbl.iter (fun _ db -> db.db_viewable <- false) drag_boxes; HT.draw_linear_tree draw_drv t c f; (* détruire toutes les boites restées à faux et les aretes correspondantes *) let l = Hashtbl.fold (fun i db acc -> if not db.db_viewable then begin db.db_noeud#parent#destroy (); db.db_noeud#destroy (); i::acc end else acc) drag_boxes [] in List.iter (fun i -> Hashtbl.remove drag_boxes i) l; draw_edges () and drag_label db ev = let item = db.db_noeud in begin match ev with | `ENTER_NOTIFY _ -> item#set [ `FILL_COLOR "steelblue" ] | `LEAVE_NOTIFY ev -> let state = GdkEvent.Crossing.state ev in if not (Gdk.Convert.test_modifier `BUTTON1 state) then item#set [ `FILL_COLOR "grey" ; ] | `BUTTON_RELEASE ev -> item#parent#ungrab (GdkEvent.Button.time ev) | `MOTION_NOTIFY ev -> incr step; let state = GdkEvent.Motion.state ev in if Gdk.Convert.test_modifier `BUTTON1 state && !step mod 10=0 then begin let curs = Gdk.Cursor.create `FLEUR in item#parent#grab [`POINTER_MOTION; `BUTTON_RELEASE] curs (GdkEvent.Button.time ev); let z1 = xy2c (gtk2xy db.db_x db.db_y) in let mx = GdkEvent.Motion.x ev in let my = GdkEvent.Motion.y ev in let z2 = xy2c (gtk2xy mx my) in item#parent#move ~x:mx ~y:my; item#parent#set [`X mx; `Y my]; (* inutil ? *) db.db_x <- mx; db.db_y <- my; origin := HT.drag_origin !origin z1 z2; draw_linear_tree t !origin 0.0; end | _ -> () end; true in draw_linear_tree t !origin 0.0 ocamlgraph-2.0.0/editor/outils_math.ml0000644000175000001440000000536513735627615016372 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (*** Operateurs Complex ***) 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) (*** Fonctions Hyperboliques ***) 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 normalize ((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) ocamlgraph-2.0.0/editor/editor.ml0000644000175000001440000000577413735627615015334 0ustar rtusers(**************************************************************************) (* *) (* 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 Format let _ = GMain.Main.init () let print _ () = () (* print_endline msg; flush stdout*) let create_menu label menubar = let item = GMenu.menu_item ~label ~packing:menubar#append () in GMenu.menu ~packing:item#set_submenu () let main () = (* Initialisation du fichier de graph *) if Sys.argv.(1) = "--help" then begin printf "usage: %s file.gml # browse graph of file.gml@." Sys.argv.(0) ; printf "@." ; exit 0 end ; (* if Array.length Sys.argv > 2 then eprintf "%s: ignoring trailing arguments@." Sys.argv.(0) ; *) (* la Fenetre principale *) let window = GWindow.window ~border_width: 10 ~title:"Edit'OcamlGraph" () in let _ = window#connect#destroy~callback:GMain.Main.quit in (* une Verticale Box pour contenir le menu de la fenetre principale *) let v_box = GPack.vbox ~homogeneous:false ~spacing:30 ~packing:window#add () in (* la barre de Menu ajout�e dans la V_box *) let menu_bar = GMenu.menu_bar ~packing:v_box#pack () in (* le menu file : la description puis l'ajout au menu_bar *) let menu_files = [ `I ("_New Graph", print "todo new graph"); `I ("_Open Graph", print "todo open graph"); `I ("_Save Graph", print "todo save graph"); `I ("Save Graph _As ...", print "todo save graph as..."); `S; `I ("_Quit", GMain.Main.quit ) ] and menu = create_menu "File" menu_bar in GToolbox.build_menu menu ~entries:menu_files ; (* la zone d'affichage du graph, le canvas *) let canvas = GnoCanvas.canvas ~aa:true ~width:800 ~height:600 ~packing:v_box#add () in let root = canvas#root in (* l'affichage de la fenetre principale *) window#show (); let _ = Gtree.show_tree root Gtree.T.root 640 480 in GMain.Main.main () let _ = main () ocamlgraph-2.0.0/editor/graphEd.ml0000644000175000001440000001522713735627615015412 0ustar rtusers(**************************************************************************) (* *) (* 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 Graph.Pack.Graph open Outils_math open Outils_tort open Format open Graphics let graph = parse_gml_file Sys.argv.(1) exception Choose of V.t let grey = rgb 128 128 128 let root = try iter_vertex (fun v -> raise (Choose v)) graph; Format.eprintf "empty graph@."; exit 0 with Choose v -> v (* [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 0.0 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 zx*.zx +. zy*.zy end end ;; let draw_label v = draw_string (string_of_int (V.label v)) let edge v w = mem_edge graph v w || mem_edge graph w v let make_subgraph l = let gl = create () in List.iter (fun v -> add_vertex gl v) l; List.iter (fun v -> List.iter (fun w -> if edge v w then 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 let v = match c with | v :: l -> List.fold_left (fun m v -> if out_degree gc v < 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 let rlimit = 0.90 let rlimit_sqr = rlimit *. rlimit module Vset = Set.Make(V) let vset_of_list = List.fold_left (fun s x -> Vset.add x s) Vset.empty module H = Hashtbl.Make(V) let pos = H.create 97 let rec draw_graph noeud tortue = if hspace_dist_sqr tortue <= rlimit_sqr then begin H.add pos noeud (0,tortue); tmoveto tortue; draw_label noeud; let l = succ graph noeud in let l = List.filter (fun x -> not (H.mem pos x) ) l in let l = order_children l in let n = List.length l in if n > 0 then begin let pas = step_from (max 3 n) and angle = 2. *. pi /. (float n) in let ll = draw_edges tortue pas angle l in List.iter (fun (v,tv) -> H.add pos v (1,tv)) ll; List.iter (fun (w,tw) -> let l = succ graph w in let l = List.filter (fun x -> not (H.mem pos x)) l in let n = List.length l in if n > 0 then begin let pas = step_from (max 3 n) and angle = pi /. (float n) in let tw = turn_right tw ((pi -. angle) /. 2.) in let l = draw_edges tw pas angle l in List.iter (fun (v,tv) -> H.add pos v (2,tv)) l end) ll; (* draw intern edges *) set_color grey; H.iter (fun v (lv,tv) -> List.iter (fun w -> try let lw,tw = H.find pos w in if abs (lw - lv) <> 1 then begin tmoveto tv; tlineto tw end with Not_found -> ()) (succ graph v)) pos; set_color black end end and draw_edges t pas angle= function | [] -> [] | v :: l -> let tv = tdraw_edge t pas 10 in if hspace_dist_sqr t <= rlimit_sqr then (draw_label v; H.add pos v (1,t)); let t = turn_left t angle in let list = (v,tv) :: draw_edges t pas angle l in draw_graph v tv ; list let draw origine tortue = H.clear pos; draw_graph root tortue let () = open_graph (sprintf " %dx%d" (truncate w) (truncate h)) let tortue = let (x,y) = from_tortue !origine in moveto x y; make_turtle !origine 0.0 let old_xy = ref None let flags = [Button_down; Button_up; Key_pressed; Mouse_motion] let rec boucle tortue = let st = wait_next_event flags in if st.button then begin match !old_xy with | None -> clear_graph (); draw origine tortue; old_xy := Some(st.mouse_x, st.mouse_y); boucle tortue | Some(x,y) -> let z1 = to_tortue(x,y) and z2 = to_tortue (st.mouse_x, st.mouse_y) in clear_graph (); origine := drag_origin !origine z1 z2 ; let tort = make_turtle_dir !origine tortue.dir in old_xy := Some(st.mouse_x, st.mouse_y); draw origine tortue; boucle tort end else begin match !old_xy with | None -> draw origine tortue; boucle tortue | Some(x,y) -> clear_graph (); draw origine tortue; old_xy := None; boucle tortue end let () = boucle tortue ocamlgraph-2.0.0/editor/ed_draw.ml0000644000175000001440000001236313735627615015443 0ustar rtusers(**************************************************************************) (* *) (* 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 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-2.0.0/editor/ed_main.ml0000644000175000001440000007744613735627615015447 0ustar rtusers(**************************************************************************) (* *) (* 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 open Ed_display 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 () 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 ~callback:(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 ~callback:(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 the developers. " ^"This application has only basic functionalities on graphs, so if you want a new functionality, send it too.\n"); buffer#insert ~iter ~tag_names:["subsection"] (ed_name^" represents a graph in hyperbolic geometry, and specifically 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 vertex 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 provides standard functionalities. You can create a new graph, open and save graphs from/to the 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"] "Vertex list\n"; buffer#insert ~iter ~tag_names:["subsection"] "\t You can change the root the of graph diagram by clicking on a vertex name. If you expand one, you can see its descendants.\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 vertex to move the whole graph around."); 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 the current 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 different menus, but the distinction is transparent for the user.\n" ^"The first is only composed by an 'adding node' menu, and appears when you click anywhere in the background of the disk.\n" ^"The second menu appears when you click on a vertex." ^" You can change root of the graph diagram, add a child node or remove the focused vertex." ^" The remainder of the menu depends on which nodes are selected. You can add or remove an edge with one of them 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 ~x1:0. ~y1:0. ~x2:w ~y2:h ; setup_ui window; ignore (window#show ()); GMain.Main.main () ocamlgraph-2.0.0/editor/htree.mli0000644000175000001440000000403613735627615015314 0ustar rtusers(**************************************************************************) (* *) (* 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 TREE = sig type t type label val children : t -> t list val label : t -> label end ;; module type HTREE = sig type t type label val children : t -> t list val label : t -> label type coord = float * float type driver = { rlimit : float ; moveto : coord -> unit ; lineto : coord -> unit ; curveto : coord -> coord -> coord -> unit ; draw_label : label -> coord -> float -> unit ; init_edge_pass : unit -> unit ; init_label_pass : unit -> unit ; finalize : unit -> unit ; } val shrink_factor : coord -> float val drag_origin : coord -> coord -> coord -> coord val draw_linear_tree : driver -> t -> coord -> float -> unit val draw_curved_tree : driver -> t -> coord -> float -> unit end ;; module Make(T : TREE) : HTREE with type t = T.t and type label = T.label ;; ocamlgraph-2.0.0/editor/ed_display.ml0000644000175000001440000003144713735627615016157 0ustar rtusers(**************************************************************************) (* *) (* 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 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 _,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 _,_ 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-2.0.0/.ocp-indent0000644000175000001440000000000713735627615014247 0ustar rtusersnormal ocamlgraph-2.0.0/Makefile0000644000175000001440000000012213735627615013644 0ustar rtusers all: dune build test: dune runtest doc: dune build @doc clean: dune clean ocamlgraph-2.0.0/view_graph/0000755000175000001440000000000013735627615014344 5ustar rtusersocamlgraph-2.0.0/view_graph/viewGraph.ml0000644000175000001440000000016613735627615016635 0ustar rtusersmodule ViewGraph = ViewGraph_core module ViewGraph_select = ViewGraph_select module ViewGraph_utils = ViewGraph_utilsocamlgraph-2.0.0/view_graph/viewGraph_test.ml0000644000175000001440000001524213735627615017675 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/view_graph/viewGraph_select.mli0000644000175000001440000000455313735627615020351 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/view_graph/README0000644000175000001440000000073013735627615015224 0ustar rtusers====================================================== 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-2.0.0/view_graph/viewGraph_utils.mli0000644000175000001440000000263613735627615020232 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/view_graph/viewGraph_select.ml0000644000175000001440000003112313735627615020171 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (** 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 ~wx:sx ~wy:sy in (* this is to handle zoom factor *) (* Format.printf "scroll to = %d x %d (canvas) @." sx sy; *) canvas#scroll_to ~x:sx ~y: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:(y-20) ; true | k when k = GdkKeysyms._Down -> canvas#scroll_to ~x ~y:(y+20) ; true | k when k = GdkKeysyms._Left -> canvas#scroll_to ~x:(x-10) ~y ; true | k when k = GdkKeysyms._Right -> canvas#scroll_to ~x:(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 ~callback:(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-2.0.0/view_graph/viewGraph_core.ml0000644000175000001440000002646013735627615017652 0ustar rtusers(**************************************************************************) (* *) (* 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 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 _), Some (Dot_ast.String _) -> (* 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 _ -> Cb.enter_node env node | `LEAVE_NOTIFY _ -> 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 ~callback:(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 ~x1:0. ~y1:0. ~x2:(float w) ~y2:(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 ~callback:(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-2.0.0/view_graph/doc/0000755000175000001440000000000013735627615015111 5ustar rtusersocamlgraph-2.0.0/view_graph/doc/style.css0000644000175000001440000000350113735627615016762 0ustar rtusers.typetable { border-style : hidden } .indextable { border-style : hidden } .paramstable { border-style : hidden ; padding: 5pt 5pt } body { background-color : white font-family: Lucida,Times,serif; margin-left: 2em; margin-right: 1em; } td.typefieldcomment { background-color : white font-size: smaller ; } pre { margin-bottom: 2px; } pre, code { font-family: terminal,"courier new",monospace; font-size: 10pt; } div.sig_block { margin-left: 2em } .keyword { font-weight : bold ; color : fuchsia; } .keywordsign { color : #C04600 } .superscript { font-size : 4 } .subscript { font-size : 4 } .comment { color : Green } .constructor { color : Blue } .type { color : #5C6585 } .string { color : Maroon } .warning { color : Red ; font-weight : bold } .info { margin-left : 3em; margin-right : 3em } .param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em } .code { color : #465F91 ; } a .code { color : #416DFF; } a:link { color : #416DFF; text-decoration : none; } a:visited { color : #416DFF; text-decoration : none; } a:hover { color : fuchsia; text-decoration : none; background-color: #CCE8FE; } a:active { color : fuchsia; text-decoration : underline; } h1 { font-size : 30 ; text-align: center; } h2 { background-color: #1E90FF ; font-size : 25 ; border: 1px solid #000000; margin-top: 2ex; margin-bottom: 1ex; margin-left: -1ex; margin-right: -1ex; text-align: center; padding: 2px; } h3 { background-color: #00CFFF ; font-size : 18 ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px; margin-left: 0; margin-right: 0; text-align: center; padding: 2px; } h4 { font-size : 18 ; margin-top: 1ex; margin-bottom: 1ex; } ul { margin:0; list-style-type: square; } ul ul { list-style-type: disc; } ocamlgraph-2.0.0/view_graph/doc/intro.txt0000644000175000001440000000515313735627615017011 0ustar rtusers{1 ViewGraph} {2 Presentation} ViewGraph is a small {{:http://caml.inria.fr/ocaml/}ocaml} library that helps to view a graph from a dot file in a Lablgtk canvas, and interact with it. It reads dot files and uses the dot tool for the layout of the nodes. You can have a look to {{:http://www.graphviz.org/}Graphviz} to know more about the dot tool and file format. It also uses the {{:http://caml.inria.fr/ocaml/}ocaml} graph library {{:http://ocamlgraph.lri.fr/}ocamlgraph}. It is composed of the {{:index_modules.html}modules}: - {!module:ViewGraph} : which is the main part and that can be used alone to parse a file, generate an image of the graph and add some user defined callbacks to interact with it, - {!module:ViewGraph_select} : which can be used to add selection features in addition to user callbacks, - {!module:ViewGraph_test} : which is not really part of the library but that creates a small gui to show how to use the 2 other modules. To know more about it, the best thing to do is to compile and test : - [make] - [./viewgraph file.dot] If you don't have any dot file, you can for instance use some examples from {{:http://www.graphviz.org/Gallery.php}graphviz gallery} but please remove the size attibutes (they are not handdled yet : see below) Notice also that if you are already using {{:http://ocamlgraph.lri.fr/}ocamlgraph} to build some graphs, it is quite easy to generate dot files by using {{:http://ocamlgraph.lri.fr/doc/Graphviz.html}Graph.Graphviz.Dot}. {2 Some more things TODO} - some of the dot format attributes are not handled (size and ratio for instance) - the zoom feature is very ugly at the moment ! - as we call 'dot' once for the image and another time for annotations, the layout is computed twice. That can be a problem for big graphs. - instead of using PNG images from dot, we could generate the GTK objects, and the zoom problem would be solved. This requires a lot of work, but we hope to do it soon ! - add something to find a node by its name - ... and more... {2 More links} - GTK : {ul {- all the {{:http://library.gnome.org/devel/gtk/stable/}widgets} Reference Manual} {- the {{:http://library.gnome.org/devel/libgnomecanvas/stable/}GnomeCanvas} Library Reference Manual} } - Lablgtk : {ul{- ocamldoc {{:http://plus.kaist.ac.kr/~shoh/ocaml/lablgtk2/lablgtk-2.4.0/doc/html/index.html} reference} with links on GTK reference,} {- an excellent {{:http://plus.kaist.ac.kr/~shoh/english/ocaml/lablgtk2/lablgtk2-tutorial/index.html}tutorial} fo those (like me) who don't know GTK.} } - Author : {{:http://www-sop.inria.fr/everest/personnel/Anne.Pacalet/}Anne Pacalet} ocamlgraph-2.0.0/view_graph/dune0000644000175000001440000000037013735627615015222 0ustar rtusers(library (name viewGraph) (wrapped false) (modules :standard \ viewGraph_test) (libraries ocamlgraph lablgtk2 lablgtk2.gnomecanvas)) (executable (name viewGraph_test) (modules viewGraph_test) (libraries viewGraph) (flags -open ViewGraph)) ocamlgraph-2.0.0/view_graph/viewGraph_utils.ml0000644000175000001440000000566613735627615020067 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/view_graph/viewGraph_core.mli0000644000175000001440000000601413735627615020014 0ustar rtusers(**************************************************************************) (* *) (* 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-2.0.0/ocamlgraph_gtk.opam0000644000175000001440000000152113735627615016050 0ustar rtusersopam-version: "2.0" synopsis: "Displaying graphs using OCamlGraph and GTK" description: "Displaying graphs using OCamlGraph and GTK" maintainer: ["filliatr@lri.fr"] authors: ["Sylvain Conchon" "Jean-Christophe Filliâtre" "Julien Signoles"] license: "LGPL-2.1-only" tags: [ "graph" "library" "algorithms" "directed graph" "vertice" "edge" "persistent" "imperative" ] homepage: "https://github.com/backtracking/ocamlgraph/" bug-reports: "https://github.com/backtracking/ocamlgraph/issues/new" depends: [ "ocaml" "stdlib-shims" "lablgtk" "conf-gnomecanvas" "ocamlgraph" "dune" {>= "2.0"} ] build: [ ["dune" "subst"] {pinned} [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} "@doc" {with-doc} ] ] dev-repo: "git+https://github.com/backtracking/ocamlgraph.git" ocamlgraph-2.0.0/README.md0000644000175000001440000000334213735627615013472 0ustar rtusers# OCamlgraph 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 (immutable) 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. ## Documentation https://backtracking.github.io/ocamlgraph/ ## Examples You'll find examples of OCamlgraph use in subdirectory examples/ (demo.ml, demo_planar.ml, color.ml, etc.). ## Bug reports https://github.com/backtracking/ocamlgraph/issues ocamlgraph-2.0.0/FAQ0000644000175000001440000001007713735627615012550 0ustar rtusers========================== FREQUENTLY ASKED QUESTIONS ========================== ========== Q: Is it possible to update imperative graph during traversal done by |fold_vertex| or |iter_vertex|? A: Imperative graphs being implemented with hash tables, the answer is no. Workarounds include - storing update information on the side, then apply it in a second step; - mutate a second graph instead. Regarding the latter, it is worth pointing out OCamlgraph also provides immutable graphs that could make it more efficient (free ``copy'' and possible sharing between the two graphs, at the extra cost of logarithmic operations instead of constant-time operations). ========== ========== 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-2.0.0/.gitignore0000644000175000001440000000012013735627615014172 0ustar rtusers.merlin /META /www/index.en.html /www/index.fr.html /www/version.prehtml _build ocamlgraph-2.0.0/tests/0000755000175000001440000000000013735627615013353 5ustar rtusersocamlgraph-2.0.0/tests/dot.expected0000644000175000001440000000073413735627615015670 0ustar rtusers========= BEGIN output graph ========= digraph G { "task_menu"; "task_ingredients"; "task_invitation"; "task_cook"; "task_table"; "task_eat"; "task_menu" -> "task_ingredients" [label=, ]; "task_ingredients" -> "task_cook" [label=, ]; "task_invitation" -> "task_cook" [label=, ]; "task_cook" -> "task_eat" [label=, ]; "task_table" -> "task_eat" [label=, ]; }========= END output graph =========ocamlgraph-2.0.0/tests/test_wto.expected0000644000175000001440000000004413735627615016744 0ustar rtusers(1 4 1' 4' ) 2' 3' 2 3 (6 5' 6' 5 ) ocamlgraph-2.0.0/tests/test_chaotic.ml0000644000175000001440000001167113735627615016364 0ustar rtusersopen Graph (* Analysis with ChaoticIteration of the following program : X:=0; while X<40 do X:=X+1 done The analyses uses the interval abstract domain, with widening, and the widening delay given as a parameter in the commande line (0 if no parameter is given). Executing this program should print: W = WTO, delay=40: 1 -> [-∞; +∞] 2 -> [0; +∞] 3 -> [0; 39] 4 -> [40; +∞] W = {3}, delay=39: 1 -> [-∞; +∞] 2 -> [0; +∞] 3 -> [0; +∞] 4 -> [40; +∞] W = WTO, delay=41: 1 -> [-∞; +∞] 2 -> [0; 40] 3 -> [0; 39] 4 -> [40; 40] *) (* Trivial language, only one variable *) module Operator = struct type expr = | Var | Int of int | Sum of expr * expr type test = | Le | Ge type t = | Affect of expr | Test of test * int let compare = compare let default = Affect Var end open Operator (* Basic interval domain *) module Interval = struct type num = | MinusInfinity | Int of int | PlusInfinity let print_num = function | MinusInfinity -> print_string "-∞" | Int n -> print_int n | PlusInfinity -> print_string "+∞" let ( <% ) n1 n2 = match n1, n2 with | MinusInfinity, MinusInfinity | PlusInfinity, PlusInfinity -> failwith "<%" | MinusInfinity, _ -> true | _, PlusInfinity -> true | Int a, Int b -> a < b | _, _ -> false let ( >=% ) n1 n2 = not (n1 <% n2) let ( <=% ) n1 n2 = n1 <% n2 || n1 = n2 let ( >% ) n1 n2 = n1 >=% n2 && n1 <> n2 let min_ n1 n2 = if n1 <=% n2 then n1 else n2 let max_ n1 n2 = if n1 >=% n2 then n1 else n2 type t = | Bottom | Bounded of num * num let top = Bounded (MinusInfinity, PlusInfinity) let equal = ( = ) let print = function | Bottom -> print_string "⊥" | Bounded (a, b) -> (* Printf is for the weak *) print_string "["; print_num a; print_string "; "; print_num b; print_string "]" let join i1 i2 = match i1, i2 with | Bottom, _ -> i2 | _, Bottom -> i1 | Bounded (a, b), Bounded (c, d) -> Bounded (min_ a c, max_ b d) let singleton n = Bounded (Int n, Int n) let ( +% ) x y = match x, y with | MinusInfinity, PlusInfinity | PlusInfinity, MinusInfinity -> failwith "+%" | MinusInfinity, _ | _, MinusInfinity -> MinusInfinity | PlusInfinity, _ | _, PlusInfinity -> PlusInfinity | Int a, Int b -> Int (a + b) let rec abstr_expr interval = function | Var -> interval | Int n -> singleton n | Sum (e1, e2) -> match abstr_expr interval e1, abstr_expr interval e2 with | Bottom, _ -> Bottom | _, Bottom -> Bottom | Bounded (a, b), Bounded (c, d) -> Bounded (a +% c, b +% d) let abstr_test interval test c = match interval with | Bottom -> Bottom | Bounded (a, b) -> match test with | Le -> if a >% c then Bottom else Bounded (a, min_ b c) | Ge -> if b <% c then Bottom else Bounded (max_ a c, b) let analyze (_, op, _) interval = match op with | Affect e -> abstr_expr interval e | Test (test, n) -> abstr_test interval test (Int n) let widening i1 i2 = match i1, i2 with | Bottom, _ -> i2 | Bounded _, Bottom -> failwith "widening" | Bounded (a, b), Bounded (c, d) -> Bounded ( (if a <=% c then a else MinusInfinity), (if b >=% d then b else PlusInfinity) ) end module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = ( = ) end module Data = struct include Interval type edge = int * Operator.t * int end module G = Persistent.Digraph.ConcreteLabeled (Int) (Operator) module Wto = WeakTopological.Make (G) module Chaotic = ChaoticIteration.Make (G) (Data) let edges = [ 1, 2, Affect (Int 0); 2, 3, Test (Le, 39); 3, 2, Affect (Sum (Var, Int 1)); 2, 4, Test (Ge, 40); ] let g = List.fold_left (fun acc (v, w, op) -> G.add_edge_e acc (G.E.create v op w)) G.empty edges let strategy = Wto.recursive_scc g 1 let print_vertex_data vertex interval = print_int vertex; print_string " -> "; Interval.print interval; print_newline () let init v = if v = 1 then Interval.top else Interval.Bottom let widening_delay1 = 40 let widening_set1 = ChaoticIteration.FromWto let widening_delay2 = 39 let widening_set2 = ChaoticIteration.Predicate (( = ) 3) let widening_delay3 = 41 let widening_set3 = ChaoticIteration.FromWto let result1 = Chaotic.recurse g strategy init widening_set1 widening_delay1 let result2 = Chaotic.recurse g strategy init widening_set2 widening_delay2 let result3 = Chaotic.recurse g strategy init widening_set3 widening_delay3 let () = print_endline "W = WTO, delay=40:"; Chaotic.M.iter print_vertex_data result1; print_newline (); print_endline "W = {3}, delay=39:"; Chaotic.M.iter print_vertex_data result2; print_newline (); print_endline "W = WTO, delay=41:"; Chaotic.M.iter print_vertex_data result3; print_newline (); ocamlgraph-2.0.0/tests/nonneg.ml0000644000175000001440000000474013735627615015176 0ustar rtusers (* 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-2.0.0/tests/dot.ml0000644000175000001440000000405313735627615014475 0ustar rtusers(**************************************************************************) (* *) (* 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 _ = [ `HtmlLabel "f$oo" ] let get_subgraph _ = None end module DotOutput = Graphviz.Dot(Display) let g = DotInput.parse Sys.argv.(1) let () = Printf.printf "========= BEGIN output graph =========\n"; DotOutput.output_graph stdout g; Printf.printf "========= END output graph ========="ocamlgraph-2.0.0/tests/bench.ml0000644000175000001440000000576613735627615015002 0ustar rtusers(**************************************************************************) (* *) (* 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 let () = Printf.printf "======== BEGIN bench1 =========\n"; bench1(); Printf.printf "======== END bench1 =========\n\n" (* 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 "i = %d v = %d e = %d d = %1.2f time = %2.2f@." i v e d t done (* r�sultats : voir results.bench2.txt *) let () = Printf.printf "======== BEGIN bench2 =========\n"; bench2(); Printf.printf "======== END bench2 =========\n\n" end module B1 = Bench(Pack.Digraph)(Builder.I(Pack.Digraph)) (* Local Variables: compile-command: "make -C .. bench" End: *) ocamlgraph-2.0.0/tests/strat.expected0000644000175000001440000000035513735627615016236 0ustar rtusers For 15 matches, is there a winning strategy for the first player ? true --- (15, 13) (14, 13) (12, 9) (11, 9) (10, 9) (8, 5) (7, 5) (6, 5) (4, 1) (3, 1) (2, 1) For 13 matches, is there a winning strategy for the first player ? false ocamlgraph-2.0.0/tests/test_fixpoint.ml0000644000175000001440000000216513735627615016610 0ustar rtusers (* Test file for Fixpoint *) let id x = x module IntOrdered = struct type t = int let compare: int -> int -> int = compare let hash: int -> int = id let equal: int -> int -> bool = (=) end module IntSet = Set.Make(IntOrdered) module G = Graph.Persistent.Digraph.Concrete(IntOrdered) module Divisors = Graph.Classic.P(G) module Analysis = struct type data = IntSet.t type edge = G.edge type vertex = G.vertex type g = G.t let direction = Graph.Fixpoint.Backward let join = IntSet.union let equal = IntSet.equal let analyze (_: edge): data -> data = id end module Fixpoint = Graph.Fixpoint.Make(G)(Analysis) let pp_int_set pp set = let first = ref true in Format.fprintf pp "@["; IntSet.iter (fun x -> if !first then first := false else Format.fprintf pp ",@ "; Format.pp_print_int pp x) set; Format.fprintf pp "@]" let () = let n = 15 in let labels = Fixpoint.analyze IntSet.singleton (Divisors.divisors n) in Format.open_vbox 0; for i = 2 to n do Format.printf "Labels for %d: %a@," i pp_int_set (labels i) done; Format.close_box (); Format.print_flush () ocamlgraph-2.0.0/tests/check.ml0000644000175000001440000005262013735627615014767 0ustar rtusers(**************************************************************************) (* *) (* 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 (* pair with equality which ignores the second component *) module Pair = struct type t = int * int let compare (x, _) (y, _) = Int.compare x y let hash (x, _) = Int.hash x let equal (x, _) (y, _) = x = y let default = 0, 0 end module W(E:sig type t type label val label: t -> label end) = struct type edge = E.t type t = int let weight = E.label 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 () (* Generic tests for imperative concrete graphs with custom equality *) module Make_pair (G : Sig.I with type V.label = int * 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, 0) in let v2 = G.V.create (2, 0) in let v3 = G.V.create (2, 1) in test_mirror g; G.add_edge g v1 v2; G.add_edge g v2 v1; G.add_edge g v1 v3; G.iter_vertex (fun v -> assert (snd (G.V.label v) = 0)) g; test_mirror g; assert (G.nb_vertex g = V.v && G.nb_edges g = V.e); G.remove_vertex g v3; 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_pair (Imperative.Digraph.ConcreteLabeled(Pair)(Pair)) (struct let v = 2 let e = 2 end) in let module A = Make_pair (Imperative.Graph.ConcreteLabeled(Pair)(Pair)) (struct let v = 2 let e = 1 end) in let module A = Make_pair (Imperative.Digraph.Concrete(Pair)) (struct let v = 2 let e = 2 end) in let module A = Make_pair (Imperative.Graph.Concrete(Pair)) (struct let v = 2 let e = 1 end) in let module A = Make_pair (Imperative.Digraph.ConcreteBidirectional(Pair)) (struct let v = 2 let e = 2 end) in let module A = Make_pair (Imperative.Digraph.ConcreteBidirectionalLabeled(Pair)(Pair)) (struct let v = 2 let e = 2 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(G.E)) 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_Tarjan(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_Tarjan(G2)(F2) let () = assert (snd (FF2.maxflow g 1 4) = 2); (* growth of the flow *) assert (snd (Gold2.maxflow g 1 4) = 3) (* max flow *) 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_tarjan : 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 module Test_clique = struct (* Test file for Brom-Kerbosch *) open Graph module G = Persistent.Graph.Concrete (struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) end) module BK = Clique.Bron_Kerbosch(G) let () = let vertices = [1;2;3;4;5;6;7] in let edges = [(1,2);(1,5);(2,5);(2,3);(4,5);(3,4);(4,6)] in let g = List.fold_left (fun graph v -> G.add_vertex graph v) G.empty vertices in let g = List.fold_left (fun graph (v1, v2) -> G.add_edge graph v1 v2) g edges in let cliques = BK.maximalcliques g in (* The cliques of this graph should be: [2, 3], [3, 4], [1, 2, 5], [4, 5], [4, 6], [7] *) assert (List.length cliques == 6); assert (List.exists (fun cl -> List.length cl == 2 && List.mem 2 cl && List.mem 3 cl) cliques); assert (List.exists (fun cl -> List.length cl == 2 && List.mem 3 cl && List.mem 4 cl) cliques); assert (List.exists (fun cl -> List.length cl == 3 && List.mem 1 cl && List.mem 2 cl && List.mem 5 cl) cliques); assert (List.exists (fun cl -> List.length cl == 2 && List.mem 4 cl && List.mem 5 cl) cliques); assert (List.exists (fun cl -> List.length cl == 2 && List.mem 4 cl && List.mem 6 cl) cliques); assert (List.exists (fun cl -> List.length cl == 1 && List.mem 7 cl) cliques) end module Test_reduction = struct open Graph module G = Imperative.Digraph.Concrete(struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) end) open G module R = Rand.I(G) module O = Oper.I(G) let check_included g1 g2 = iter_vertex (fun v -> assert (mem_vertex g2 v)) g1; iter_edges (fun u v -> assert (mem_edge g1 u v)) g1 let check_same_graph g1 g2 = check_included g1 g2; check_included g2 g1 let test v e = let g = R.graph ~loops:true ~v ~e () in let t = O.transitive_closure g in check_included g t; let r = O.transitive_reduction g in check_included r g; check_same_graph (O.transitive_closure r) t let () = for v = 1 to 10 do for e = 0 to v * (v-1) / 2 do test v e done done (* issue #91 *) let () = let g = create () in for v = 1 to 5 do add_vertex g v done; add_edge g 1 2; add_edge g 2 3; add_edge g 3 4; add_edge g 4 5; add_edge g 2 5; let r = O.transitive_reduction g in check_included r g; assert (nb_edges r = 4); assert (not (mem_edge r 2 5)); () end let () = Format.printf "check: all tests succeeded@." (* Local Variables: compile-command: "make -C .. check" End: *) ocamlgraph-2.0.0/tests/basic.ml0000644000175000001440000000462013735627615014770 0ustar rtusers(**************************************************************************) (* *) (* 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 end module G = Persistent.Digraph.ConcreteLabeled(Int)(Int) let g = G.empty let g = G.add_vertex g 1 let g = G.add_edge_e g (G.E.create 1 10 2) let g = G.add_edge_e g (G.E.create 2 50 3) let g = G.add_edge_e g (G.E.create 1 30 4) let g = G.add_edge_e g (G.E.create 1 100 5) let g = G.add_edge_e g (G.E.create 3 10 5) let g = G.add_edge_e g (G.E.create 4 20 3) let g = G.add_edge_e g (G.E.create 4 60 5) let g = G.remove_vertex g 4 let gc = G.add_edge_e g (G.E.create 5 10 1) let gc = G.add_vertex gc 6 module W = struct type edge = G.E.t type t = int let weight e = G.E.label e let zero = 0 let add = (+) let sub = (-) let compare = compare end module Dij = Path.Dijkstra(G)(W) let p,w = Dij.shortest_path gc 1 5 open G.E let () = List.iter (fun e -> printf "[%d -> %d]" (src e) (dst e)) p; printf "@." module Comp = Components.Make(G) let g = G.add_edge g 3 2 let n, f = Comp.scc g let () = G.iter_edges (fun u v -> printf "%d -> %d@." u v) g let () = printf "%d components@." n let () = G.iter_vertex (fun v -> printf " %d -> %d@." v (f v)) g ocamlgraph-2.0.0/tests/strat.ml0000644000175000001440000001013013735627615015035 0ustar rtusers(**************************************************************************) (* *) (* 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 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-2.0.0/tests/test_bf.expected0000644000175000001440000000111613735627615016523 0ustar rtusersRunning test with name: cycle_1 1 --(1)--> 2 2 --(1)--> 0 0 --(-3)--> 1 Running test with name: cycle_2 1 --(1)--> 2 2 --(1)--> 0 0 --(-10)--> 1 Running test with name: cycle_3 0 --(-10)--> 1 1 --(1)--> 3 3 --(1)--> 4 4 --(1)--> 0 Running test with name: cycle_4 0 --(-10)--> 1 1 --(1)--> 3 3 --(1)--> 4 4 --(1)--> 0 Running test with name: cycle_5 0 --(-10)--> 1 1 --(1)--> 2 2 --(1)--> 0 Running test with name: cycle_6 0 --(-10)--> 1 1 --(1)--> 2 2 --(1)--> 0 Running test with name: nocycle_1 No cycle found Running test with name: nocycle_2 No cycle found All tests succeeded. ocamlgraph-2.0.0/tests/test_chaotic.expected0000644000175000001440000000036413735627615017552 0ustar rtusersW = WTO, delay=40: 1 -> [-∞; +∞] 2 -> [0; +∞] 3 -> [0; 39] 4 -> [40; +∞] W = {3}, delay=39: 1 -> [-∞; +∞] 2 -> [0; +∞] 3 -> [0; +∞] 4 -> [40; +∞] W = WTO, delay=41: 1 -> [-∞; +∞] 2 -> [0; 40] 3 -> [0; 39] 4 -> [40; 40] ocamlgraph-2.0.0/tests/test_johnson.expected0000644000175000001440000000051413735627615017613 0ustar rtusers[2 -> 5 : -1] [5 -> 1 : 8] [2 -> 4 : 1] [2 -> 1 : 3] [3 -> 2 : 4] [3 -> 5 : 3] [5 -> 2 : 5] [1 -> 1 : 0] [2 -> 3 : -4] [1 -> 4 : 2] [5 -> 5 : 0] [4 -> 4 : 0] [5 -> 3 : 1] [1 -> 5 : -4] [4 -> 5 : -2] [1 -> 2 : 1] [2 -> 2 : 0] [4 -> 3 : -5] [3 -> 1 : 7] [3 -> 4 : 5] [4 -> 2 : -1] [4 -> 1 : 2] [1 -> 3 : -3] [5 -> 4 : 6] [3 -> 3 : 0] ocamlgraph-2.0.0/tests/dot.dot0000644000175000001440000000340613735627615014654 0ustar rtusersdigraph D { node [shape=plaintext fontname="Sans serif" fontsize="8"]; task_menu [ label=<
Task 1
Choose Menu
done
>]; task_ingredients [ label=<
Task 2
Buy ingredients
done
>]; task_invitation [ label=<
Task 4
Send invitation
done
>]; task_cook [ label=<
Task 5
Cook
todo
>]; task_table[ label=<
Task 3
Lay table
todo
>]; task_eat[ label=<
Task 6
Eat
todo
>]; task_menu -> task_ingredients; task_ingredients -> task_cook; task_invitation -> task_cook; task_table -> task_eat; task_cook -> task_eat; }ocamlgraph-2.0.0/tests/dune0000644000175000001440000000605713735627615014241 0ustar rtusers(test (name check) (libraries graph) (modules check)) (test (name test_topsort) (libraries graph) (modules test_topsort)) ;; Rules for the Bellman-Ford tests (rule (with-stdout-to test_bf.output (run ./test_bf.exe))) (rule (alias runtest) (action (progn (diff test_bf.expected test_bf.output) (echo "test_bf: all tests succeeded.\n")))) (executable (name test_bf) (modules test_bf) (libraries graph)) ;; Rules for the chaotic tests (rule (with-stdout-to test_chaotic.output (run ./test_chaotic.exe))) (rule (alias runtest) (action (progn (diff test_chaotic.expected test_chaotic.output) (echo "test_chaotic: all tests succeeded.\n")))) (executable (name test_chaotic) (modules test_chaotic) (libraries graph)) ;; Rules for the strat test (rule (with-stdout-to strat.output (run ./strat.exe))) (rule (alias runtest) (action (progn (diff strat.expected strat.output) (echo "strat: all tests succeeded.\n")))) (executable (name strat) (modules strat) (libraries graph)) ;; Rules for the fixpoint test (rule (with-stdout-to test_fixpoint.output (run ./test_fixpoint.exe))) (rule (alias runtest) (action (progn (diff test_fixpoint.expected test_fixpoint.output) (echo "test_fixpoint: all tests succeeded.\n")))) (executable (name test_fixpoint) (modules test_fixpoint) (libraries graph)) ;; Rules for the Johnson test (rule (with-stdout-to test_johnson.output (run ./test_johnson.exe))) (rule (alias runtest) (action (progn (diff test_johnson.expected test_johnson.output) (echo "test_johnson: all tests succeeded.\n")))) (executable (name test_johnson) (modules test_johnson) (libraries graph)) ;; Rules for the weak topological test (rule (with-stdout-to test_wto.output (run ./test_wto.exe))) (rule (alias runtest) (action (progn (diff test_wto.expected test_wto.output) (echo "test_wto: all tests succeeded.\n")))) (executable (name test_wto) (modules test_wto) (libraries graph)) ;; Rules for the basic test (rule (with-stdout-to basic.output (run ./basic.exe))) (rule (alias runtest) (action (progn (diff basic.expected basic.output) (echo "basic: all tests succeeded.\n")))) (executable (name basic) (modules basic) (libraries graph)) ;; Rules for the test_components test (rule (with-stdout-to test_components.output (run ./test_components.exe))) (rule (alias runtest) (action (progn (diff test_components.expected test_components.output) (echo "test_components: all tests succeeded.\n")))) (executable (name test_components) (modules test_components) (libraries graph)) ;; rules for the dot test (rule (deps dot.dot) (action (with-stdout-to dot.output (run ./dot.exe %{deps})))) (rule (alias runtest) (action (progn (diff dot.expected dot.output) (echo "dot: all tests succeeded.\n")))) (executable (name dot) (modules dot) (libraries graph)) ;; rules for the running the benchmark (rule (alias bench) (action (run ./bench.exe))) (executable (name bench) (modules bench) (libraries graph unix)) ocamlgraph-2.0.0/tests/test_bf.ml0000644000175000001440000000304413735627615015334 0ustar rtusers (* Test file for Bellman-Ford *) open Printf open Graph open Pack.Digraph (* TODO: This could be done a tiny bit better, no need for printing, this could use alcotest or equivalent *) let test ~name has_cycle spec = printf "Running test with name: %s\n" name; 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 "No cycle found\n"; assert (not has_cycle) end; print_newline (); flush stdout let () = test ~name:"cycle_1" true [ 0, (-3), 1; 1, 1, 2; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test ~name:"cycle_2" true [ 0, (-10), 1; 1, 1, 2; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test ~name:"cycle_3" true [ 0, (-10), 1; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test ~name:"cycle_4" true [ 0, (-10), 1; 1, 1, 2; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test ~name:"cycle_5" true [ 0, (-10), 1; 1, 1, 2; 2, 1, 0; 3, 1, 4; 4, 1, 0 ]; test ~name:"cycle_6" true [ 0, (-10), 1; 1, 1, 2; 2, 1, 0; 1, 1, 3; 4, 1, 0 ]; test ~name:"nocycle_1" false [ 1, 1, 2; 2, 1, 0; 1, 1, 3; 3, 1, 4; 4, 1, 0 ]; test ~name:"nocycle_2" false [ 0, (-10), 1; 1, 1, 2; 1, 1, 3; 3, 1, 4; ]; printf "All tests succeeded.\n" ocamlgraph-2.0.0/tests/test_wto.ml0000644000175000001440000000230413735627615015554 0ustar rtusersopen Graph (* The non-reducible example from Bourdoncle paper Reference is in WeakTopological source *) (* Execution should print something like (i and i' can be switched) : (1 4 1' 4') 2' 3' 2 3 (6 5' 6' 5) *) module Vertex = struct type t = string let compare = Stdlib.compare let hash = Hashtbl.hash let equal = ( = ) end module G = Persistent.Digraph.Concrete (Vertex) module Wto = WeakTopological.Make (G) let rec print_element = function | WeakTopological.Vertex v -> print_string v | WeakTopological.Component (head, components) -> (* Printf is for the weak *) print_string "("; print_string head; print_string " "; print_components components; print_string ")" and print_components components = WeakTopological.fold_left (fun () elem -> print_element elem; print_string " ") () components let edges = [ "1", "4"; "1", "2"; "2", "3"; "3", "6"; "4", "1'"; "5", "6"; "6", "5'"; "1'", "2'"; "1'", "4'"; "2'", "3'"; "3'", "6'"; "4'", "1"; "5'", "6'"; "6'", "5"; ] let g = List.fold_left (fun acc (v, w) -> G.add_edge acc v w) G.empty edges let result = Wto.recursive_scc g "1" let () = print_components result ocamlgraph-2.0.0/tests/test_johnson.ml0000644000175000001440000000164313735627615016426 0ustar rtusers (* Test file for Johnson *) open Graph module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module G = Imperative.Digraph.ConcreteLabeled(Int)(Int) module W = struct type edge = G.E.t type t = int let weight e = G.E.label e let zero = 0 let add = (+) let sub = (-) let compare = compare end module J = Path.Johnson(G)(W) let g = G.create () let () = G.add_edge_e g (G.E.create 1 3 2); G.add_edge_e g (G.E.create 1 (-4) 5); G.add_edge_e g (G.E.create 1 8 3); G.add_edge_e g (G.E.create 2 7 5); G.add_edge_e g (G.E.create 2 1 4); G.add_edge_e g (G.E.create 3 4 2); G.add_edge_e g (G.E.create 4 (-5) 3); G.add_edge_e g (G.E.create 4 2 1); G.add_edge_e g (G.E.create 5 6 4) let () = let test = J.all_pairs_shortest_paths g in J.HVV.iter (fun (v, u) d -> Printf.printf "[%d -> %d : %d]\n" v u d) test ocamlgraph-2.0.0/tests/test_topsort.ml0000644000175000001440000000463713735627615016470 0ustar rtusers (* 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 "test topsort: all tests succeeded.@." let () = tests Topological.iter (* let () = tests Topological.iter_stable *) let rec pow a = function | 0 -> 1 | 1 -> a | n -> let b = pow a (n / 2) in b * b * (if n mod 2 = 0 then 1 else a) let () = for n_iter = 0 to 5 do let n = pow 10 n_iter in 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 done ocamlgraph-2.0.0/tests/test_components.expected0000644000175000001440000000012313735627615020316 0ustar rtusers7 components 0 -> 0 1 -> 1 2 -> 1 3 -> 2 4 -> 3 5 -> 3 6 -> 4 7 -> 5 8 -> 6 9 -> 0 ocamlgraph-2.0.0/tests/test_fixpoint.expected0000644000175000001440000000044613735627615020001 0ustar rtusersLabels for 2: 2, 4, 6, 8, 10, 12, 14 Labels for 3: 3, 6, 9, 12, 15 Labels for 4: 4, 8, 12 Labels for 5: 5, 10, 15 Labels for 6: 6, 12 Labels for 7: 7, 14 Labels for 8: 8 Labels for 9: 9 Labels for 10: 10 Labels for 11: 11 Labels for 12: 12 Labels for 13: 13 Labels for 14: 14 Labels for 15: 15 ocamlgraph-2.0.0/tests/test_components.ml0000644000175000001440000000305713735627615017136 0ustar rtusers(**************************************************************************) (* *) (* 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 C = Components.Undirected(Pack.Graph) open Pack.Graph let () = let g = Rand.graph ~v:10 ~e:3 () in let n, f = C.components g in printf "%d components@." n; iter_vertex (fun v -> printf "%d -> %d@." (V.label v) (f v)) g (* Local Variables: compile-command: "ocaml -I .. graph.cma test_components.ml" End: *) ocamlgraph-2.0.0/tests/testgraphml.ml0000644000175000001440000000340113735627615016235 0ustar rtusers(******************************************************************************) (* *) (* 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.Print(G)(Gr) let print g = GraphPrinter.print Format.std_formatter 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-2.0.0/tests/basic.expected0000644000175000001440000000015513735627615016160 0ustar rtusers[1 -> 2][2 -> 3][3 -> 5] 1 -> 2 1 -> 5 2 -> 3 3 -> 2 3 -> 5 3 components 1 -> 2 2 -> 1 3 -> 1 5 -> 0 ocamlgraph-2.0.0/LICENSE0000644000175000001440000006561613735627615013234 0ustar rtusersThe 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-2.0.0/INSTALL.md0000644000175000001440000000102013735627615013632 0ustar rtusers The simplest way to install OCamlGraph is via opam. If instead you choose to compile OCamlGraph from sources, the simplest way is to use `dune`. Otherwise, you can still use the old way: - Configure with ``` autoconf ./configure ``` - Compile with ``` make ``` - Install (as root if needed) with ``` make install ``` To install somewhere else, with a different path prefix, use instead ``` make DESTDIR=/another/place install ``` findlib users may also do ``` make install-findlib ``` ocamlgraph-2.0.0/dune-project0000644000175000001440000000010413735627615014526 0ustar rtusers(lang dune 2.0) (name ocamlgraph) (formatting (enabled_for dune)) ocamlgraph-2.0.0/ocamlgraph.opam0000644000175000001440000000144613735627615015211 0ustar rtusersopam-version: "2.0" synopsis: "A generic graph library for OCaml" description: "Provides both graph data structures and graph algorithms" maintainer: ["filliatr@lri.fr"] authors: ["Sylvain Conchon" "Jean-Christophe Filliâtre" "Julien Signoles"] license: "LGPL-2.1-only" tags: [ "graph" "library" "algorithms" "directed graph" "vertice" "edge" "persistent" "imperative" ] homepage: "https://github.com/backtracking/ocamlgraph/" bug-reports: "https://github.com/backtracking/ocamlgraph/issues/new" depends: [ "ocaml" "stdlib-shims" "dune" {>= "2.0"} ] build: [ ["dune" "subst"] {pinned} [ "dune" "build" "-p" name "-j" jobs "@install" "@runtest" {with-test} "@doc" {with-doc} ] ] dev-repo: "git+https://github.com/backtracking/ocamlgraph.git" ocamlgraph-2.0.0/.merlin0000644000175000001440000000014013735627615013473 0ustar rtusersS src S lib S dgraph B src B lib B dgraph B . PKG lablgtk2 FLG -w +a -w -4 -w -44 -w -48 -w -29 ocamlgraph-2.0.0/examples/0000755000175000001440000000000013735627615014027 5ustar rtusersocamlgraph-2.0.0/examples/sudoku.ml0000644000175000001440000000617413735627615015703 0ustar rtusers(**************************************************************************) (* *) (* 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 () ocamlgraph-2.0.0/examples/demo.ml0000644000175000001440000002117113735627615015307 0ustar rtusers(**************************************************************************) (* *) (* 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 let v_ = ref 30 let prob_ = ref 0.5 let seed_ = ref None let interactive_ = ref false type algo = TransitiveClosure | TransitiveReduction | Prim | Kruskal | Dijkstra | Bfs | Dfs let algo = ref None let arg_spec = ["-v", Arg.Int (fun i -> v_ := 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"; "--transitive-closure", Arg.Unit (fun () -> algo := Some TransitiveClosure), " display transitive closure in blue"; "--transitive-reduction", Arg.Unit (fun () -> algo := Some TransitiveReduction), " display useless edges in blue"; "--prim", Arg.Unit (fun () -> algo := Some Prim), " Prim's algorithm"; "--kruskal", Arg.Unit (fun () -> algo := Some Kruskal), " Kruskal's algorithm"; "--dijkstra", Arg.Unit (fun () -> algo := Some Dijkstra), " Dijkstra's algorithm"; "--dfs", Arg.Unit (fun () -> algo := Some Dfs), " Depth-First Search's algorithm"; "--bfs", Arg.Unit (fun () -> algo := Some Bfs), " Breadth-First Search's algorithm"; "-i", Arg.Set interactive_, " run algorithms interactively"; ] let () = Arg.parse arg_spec (fun _ -> ()) "usage: color " let v = !v_ let prob = !prob_ let interactive = !interactive_ let seed = match !seed_ with | None -> Random.self_init (); Random.int (1 lsl 29) | Some s -> s let () = printf "seed = %d@." seed; Random.init seed let () = if interactive then printf "interactive mode (press any key to step in algorithm, q to quit)@." module G = struct module IntInt = struct type t = int * int let compare = Stdlib.compare let equal = (=) let hash = Hashtbl.hash end module Int = struct type t = int let compare = Stdlib.compare let hash = Hashtbl.hash let equal = (=) let default = 0 end include Imperative.Digraph.ConcreteLabeled(IntInt)(Int) end (* a random graph with n vertices *) module R = Rand.Planar.I(G) let g = R.graph ~xrange:(20,780) ~yrange:(20,580)~prob v module Draw = struct open Graphics let () = open_graph " 800x600" let vertex_radius = 5 let round f = truncate (f +. 0.5) let pi = 4.0 *. atan 1.0 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 draw_edge ?color ?width v1 v2 = draw_arrow ?color ?width (G.V.label v1) (G.V.label v2) let draw_vertex ?(color=red) ?(width=1) v = let (x,y) = G.V.label v in set_line_width width; set_color color; 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 ?color ?width g = clear_graph (); G.iter_vertex draw_vertex g; G.iter_edges (draw_edge ?color ?width) g let draw_edges ?(color=blue) ?(width=2) el = List.iter (fun e -> draw_edge ~color ~width (G.E.src e) (G.E.dst e); draw_vertex ~color ~width (G.E.src e); draw_vertex ~color ~width (G.E.dst e) ) el let pause () = let st = wait_next_event [Key_pressed] in if st.key = 'q' then begin close_graph (); exit 0 end let draw_iteration ?(interactive=false) f g = f (fun v -> color_vertex v Graphics.red; if interactive then pause ()) g end module W = struct type edge = G.E.t type t = int let weight = G.E.label let zero = 0 let add = (+) let sub = (-) let compare = compare end module PathWeight = struct type edge = G.E.t type t = int let weight x = G.E.label x let zero = 0 let add = (+) let sub = (-) let compare = compare end module Selection = struct 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 -> Draw.color_vertex v1 Graphics.blue | Two (v1, v2) -> Draw.color_vertex v1 Graphics.blue; Draw.color_vertex v2 Graphics.green let distance (x1,y1) (x2,y2) = let dx = float (x1 - x2) in let dy = float (y1 - y2) in Draw.round (sqrt (dx *. dx +. dy *. dy)) let select g = 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 = Graphics.mouse_pos () in try G.iter_vertex (fun v -> if distance p (G.V.label v) <= Draw.vertex_radius then begin select_vertex v; Draw.draw_graph g; draw_selection (); raise Exit end) g with Exit -> () let select2 g = printf "please select two vertices...@."; printf "press r to run...@."; printf "press q to quit...@."; let continue = ref true in while !continue do let st = Graphics.wait_next_event [ Graphics.Key_pressed; Graphics.Button_down ] in if st.Graphics.keypressed then match st.Graphics.key with | 'r' -> begin match !selection with | Two (_,_) -> continue := false | _ -> printf "please select two vertices...@." end | 'q' -> raise Exit | _ -> () else if st.Graphics.button then select g done; match !selection with | Two (v1,v2) -> (v1,v2) | _ -> assert false end let () = Draw.draw_graph g let () = match !algo with | Some Dijkstra -> () | _ -> ignore (Graphics.wait_next_event [Graphics.Key_pressed ]) let () = match !algo with | Some TransitiveClosure -> let module O = Oper.I(G) in let tg = O.transitive_closure g in G.iter_edges (fun v1 v2 -> if not (G.mem_edge g v1 v2) then Draw.draw_edge ~color:Graphics.blue v1 v2) tg | Some TransitiveReduction -> Draw.draw_graph ~color:Graphics.blue g; let module O = Oper.I(G) in let tr = O.transitive_reduction g in G.iter_edges Draw.draw_edge tr; ignore (Graphics.wait_next_event [Graphics.Key_pressed ]); Draw.draw_graph tr | Some Prim -> let module P = Prim.Make(G)(W) in let el = P.spanningtree g in Draw.draw_edges el | Some Kruskal -> let module P = Kruskal.Make(G)(W) in let el = P.spanningtree g in Draw.draw_edges el | Some Dijkstra -> let module Dij = Path.Dijkstra(G)(PathWeight) in let rec recherche () = let (v1, v2) = Selection.select2 g in begin try let (p, _) = Dij.shortest_path g v1 v2 in Draw.draw_edges ~color:Graphics.red p with Not_found -> printf "no path found...@."; recherche () end in recherche () | Some Dfs -> let module Dfs = Traverse.Dfs(G) in Draw.draw_iteration ~interactive Dfs.prefix g | Some Bfs -> let module Bfs = Traverse.Bfs(G) in Draw.draw_iteration ~interactive Bfs.iter g | None -> () let () = ignore (Graphics.wait_next_event [Graphics.Key_pressed ]); Graphics.close_graph () ocamlgraph-2.0.0/examples/demo_prim.ml0000644000175000001440000000753313735627615016344 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (* Demo of Prim's algorithm *) 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 let compare = compare let hash = Hashtbl.hash let equal = (=) let default = (0, 0) end module Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module G = Imperative.Graph.ConcreteLabeled(IntInt)(Int) (* 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 ?(color=black) v1 v2 = let (xu,yu) = G.V.label v1 in let (xv,yv) = G.V.label v2 in set_color color; 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 ?(color=red) v = let (x,y) = G.V.label v in set_color color; 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 W = struct type edge = G.E.t type label = G.E.label type t = int let weight (_, x, _: edge) : t = x let zero = 0 let add = (+) let compare = compare end module P = Prim.Make(G)(W) let () = draw_graph (); ignore (Graphics.wait_next_event [ Key_pressed ]); let el = P.spanningtree g0 in set_line_width 2; List.iter (fun e -> draw_edge ~color:blue (G.E.src e) (G.E.dst e); draw_vertex ~color:blue (G.E.src e); draw_vertex ~color:blue (G.E.dst e) ) el; ignore (Graphics.wait_next_event [ Key_pressed ]); close_graph () ocamlgraph-2.0.0/examples/compare_prim_kruskal.ml0000644000175000001440000000665613735627615020607 0ustar rtusers(**************************************************************************) (* *) (* 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. *) (* *) (**************************************************************************) (* Kruskal and Prim tests *) open Printf open Graph (* command line *) let v_ = ref 30 let e_ = ref 50 let seed_ = ref None let debug_ = ref false let arg_spec = ["-v", Arg.Int (fun i -> v_ := i), " number of vertices"; "-e", Arg.Int (fun i -> e_ := i), " number of edges"; "-seed", Arg.Int (fun n -> seed_ := Some n), " random seed"; "--debug", Arg.Set debug_, "set the debug flag"; ] let () = Arg.parse arg_spec (fun _ -> ()) "usage: color " let v = !v_ let e = !e_ let debug = !debug_ 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 Int = struct type t = int let compare = compare let hash = Hashtbl.hash let equal = (=) let default = 0 end module G = Imperative.Graph.AbstractLabeled(Int)(Int) module R = Rand.I(G) module W = struct type label = G.E.label type edge = G.E.t type t = int let weight x = G.E.label x let zero = 0 let add = (+) let compare = compare end 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 (* runs f 5 times, removes minimum and maximum timings, and returns the mean of the remaining three timings *) let time5 f x = let t = Array.init 5 (fun _ -> snd (utime f x)) in if debug then Array.iter (fun x -> Printf.printf "%2.2f\n" x) t; Array.sort Stdlib.compare t; (t.(1) +. t.(2) +. t.(3)) /. 3. let print f x = let (y,ut) = utime f x in printf "user time: %2.2f@." ut; y end module P1 = Kruskal.Make(G)(W) module P2 = Prim.Make(G)(W) let testp g =Time.time5 P1.spanningtree g let testk g = Time.time5 P2.spanningtree g let test nb_v nb_e = Printf.printf "Execution time v=%d - e=%d\n" nb_v nb_e; let g = R.graph ~v:nb_v ~e:nb_e () in let resp = testp g in Printf.printf "PRIM : %2.2fs\n" resp; let resk = testk g in Printf.printf "KRUSKAL : %2.2fs\n%!" resk let () = test v e ocamlgraph-2.0.0/examples/demo_planar.ml0000644000175000001440000002541013735627615016644 0ustar rtusers(**************************************************************************) (* *) (* 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 Stdlib.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 - `c' runs SCC - `j' runs Johnson 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 dump_graph () = G.iter_edges (fun v1 v2 -> let x1, y1 = G.V.label v1 in let x2, y2 = G.V.label v2 in Format.printf "%d,%d,%d,%d@\n" x1 y1 x2 y2) !g; Format.printf "@?" (* 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 edge = G.E.t type t = int let weight x = G.E.label x let zero = 0 let add = (+) let sub = (-) 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 | _ -> () module J = Path.Johnson(G)(W) let johnson () = match !selection with | Two (v1, v2) -> printf "running Johnson... "; flush stdout; let t_ = ref 0.0 in begin try let paths, t = utime (J.all_pairs_shortest_paths) !g in t_ := t; printf "path of length %d (%2.2f s)\n" (J.HVV.find paths (v1, v2)) t; flush stdout with Not_found -> printf "no path (%2.2f s)\n" !t_; flush stdout end | _ -> () let draw_iteration f = let pause () = for _ = 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 let golden_ratio = 0.618033988749895 let hsv_to_rgb h s v = let c = v *. s in let h = int_of_float h in let hh = (h mod 360)/60 in let hhf = (mod_float (float_of_int h) 360.) /. 60. in let x = c *. (1. -. (abs_float (mod_float hhf 2. -. 1.))) in let m = v -. c in let cc = int_of_float ((c +. m) *. 255.) in let xx = int_of_float ((x +. m) *. 255.) in let mm = int_of_float (m *. 255.) in match hh with | 0 -> cc, xx, mm | 1 -> xx, cc, mm | 2 -> mm, cc, xx | 3 -> mm, xx, cc | 4 -> xx, mm, cc | 5 -> cc, mm, xx | _ -> mm, mm, mm module Scc = Components.Make(G) let scc () = printf "running scc ... "; flush stdout; let (n_scc, map_scc) = Scc.scc !g in printf "number of components: %d\n" n_scc; flush stdout; let colors = Hashtbl.create n_scc in let inc = golden_ratio *. 360. in Random.self_init (); let h = ref (Random.float 360.) in G.iter_vertex ( fun v -> try let color = Hashtbl.find colors (map_scc v) in color_vertex v color with Not_found -> let color = hsv_to_rgb !h 0.7 0.95 in h := !h +. inc; let rgb (r, g, b) = rgb r g b in let c = rgb color in Hashtbl.add colors (map_scc v) c; color_vertex v c) !g (* 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 () | 'x' -> dump_graph () | 'c' -> scc () | 'j' -> johnson () (* | 'c' -> four_colors () *) | _ -> () else if st.button then select () done with Exit -> close_graph () ocamlgraph-2.0.0/examples/dune0000644000175000001440000000036613735627615014712 0ustar rtusers(executables (names color compare_prim_kruskal demo_planar demo_prim demo sudoku) (libraries graph unix graphics threads)) (alias (name runtest) (deps color.exe compare_prim_kruskal.exe demo_planar.exe demo_prim.exe demo.exe sudoku.exe)) ocamlgraph-2.0.0/examples/color.ml0000644000175000001440000001707313735627615015507 0ustar rtusers(**************************************************************************) (* *) (* 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 _ = 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 () ocamlgraph-2.0.0/COPYING0000644000175000001440000000114113735627615013241 0ustar rtusersOcamlgraph: 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-2.0.0/CREDITS0000644000175000001440000000023413735627615013230 0ustar rtusers Contributors, in alphabetic order Sylvain Conchon Jean-Christophe Filliâtre François Pottier Julien Signoles Vincent Simonet Matthieu Sozeau