package ocamlgraph
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
A generic graph library for OCaml
Install
dune-project
Dependency
Authors
Maintainers
Sources
ocamlgraph-2.0.0.tbz
sha256=20fe267797de5322088a4dfb52389b2ea051787952a8a4f6ed70fcb697482609
sha512=c4973ac03bdff52d1c8a1ed01c81e0fbe2f76486995e57ff4e4a11bcc7b1793556139d52a81ff14ee8c8de52f1b40e4bd359e60a2ae626cc630ebe8bccefb3f1
doc/src/ocamlgraph/merge.ml.html
Source file merge.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249(**************************************************************************) (* *) (* 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: *)
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>