package ocamlgraph
Source file classic.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(**************************************************************************) (* *) (* 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 type vertex val divisors : int -> graph val de_bruijn : int -> graph val vertex_only : int -> graph val full : ?self:bool -> int -> graph val cycle : int -> graph * vertex array val grid : n:int -> m:int -> graph * vertex array array val kneser : n:int -> k:int -> graph val petersen : unit -> graph end module Generic(B : Builder.INT) = struct type graph = B.G.t type vertex = B.G.V.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 ())) let cycle n = if n < 0 then invalid_arg "cycle"; let v = Array.init n (fun i -> B.G.V.create i) in let g = Array.fold_left B.add_vertex (B.empty ()) v in let rec loop g i = if i = n then g else let g = B.add_edge g v.(i) v.((i+1) mod n) in loop g (i+1) in loop g 0, v let grid ~n ~m = if n < 0 || m < 0 then invalid_arg "grid"; let create i j = B.G.V.create (m * i + j) in let v = Array.init n (fun i -> Array.init m (fun j -> create i j)) in let g = Array.fold_left (Array.fold_left B.add_vertex) (B.empty ()) v in let rec loop g i j = if i = n then g else if j = m then loop g (i+1) 0 else let g = if j < m-1 then B.add_edge g v.(i).(j) v.(i).(j+1) else g in let g = if i < n-1 then B.add_edge g v.(i).(j) v.(i+1).(j) else g in loop g i (j+1) in loop g 0 0, v let kneser ~n ~k = if n < 0 || n > Sys.int_size || k < 0 || k > n then invalid_arg "kneser"; let vert = Hashtbl.create (1 lsl n) in let add x = Hashtbl.add vert x (B.G.V.create x) in let rec visit mask n k = assert (0 <= k && k <= n); if k = 0 then add mask else if k = n then add (mask lor (1 lsl n - 1)) else ( let n = n - 1 in visit mask n k ; visit (mask lor (1 lsl n)) n (k - 1); ) in visit 0 n k; let g = Hashtbl.fold (fun _ v g -> B.add_vertex g v) vert (B.empty ()) in let g = Hashtbl.fold (fun i vi g -> Hashtbl.fold (fun j vj g -> if i <> j && i land j = 0 then B.add_edge g vi vj else g) vert g) vert g in g let petersen () = kneser ~n:5 ~k:2 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))