renamed Enum into Gen (for "generator"), and updated code and test to reflect so

This commit is contained in:
Simon Cruanes 2013-03-21 17:25:02 +01:00
parent dfbce71324
commit 2033f07aff
9 changed files with 179 additions and 175 deletions

View file

@ -1,6 +1,6 @@
Cache
Deque
Enum
Gen
FHashtbl
FQueue
FlatHashtbl

View file

@ -38,6 +38,8 @@ and 'a generator = unit -> 'a
let start enum = enum ()
(** {2 Transient generators} *)
module Gen = struct
let empty () = raise EOG

View file

@ -42,6 +42,8 @@ and 'a generator = unit -> 'a
val start : 'a t -> 'a generator
(** Create a new generator *)
(** {2 Transient generators} *)
module Gen : sig
val empty : 'a generator

View file

@ -41,7 +41,7 @@ type ('id, 'v, 'e) t = {
other vertices, or to Empty if the identifier is not part of the graph. *)
and ('id, 'v, 'e) node =
| Empty
| Node of 'id * 'v * ('e * 'id) Enum.t
| Node of 'id * 'v * ('e * 'id) Gen.t
(** A single node of the graph, with outgoing edges *)
and ('id, 'e) path = ('id * 'e * 'id) list
(** A reverse path (from the last element of the path to the first). *)
@ -56,7 +56,7 @@ let empty =
let singleton ?(eq=(=)) ?(hash=Hashtbl.hash) v label =
let force v' =
if eq v v' then Node (v, label, Enum.empty) else Empty in
if eq v v' then Node (v, label, Gen.empty) else Empty in
{ force; eq; hash; }
let make ?(eq=(=)) ?(hash=Hashtbl.hash) force =
@ -69,7 +69,7 @@ let from_fun ?(eq=(=)) ?(hash=Hashtbl.hash) f =
let force v =
match f v with
| None -> Empty
| Some (l, edges) -> Node (v, l, Enum.of_list edges) in
| Some (l, edges) -> Node (v, l, Gen.of_list edges) in
{ eq; hash; force; }
(** {2 Polymorphic utils} *)
@ -157,7 +157,7 @@ module Mutable = struct
let map = mk_hmap ~eq ~hash in
let force v =
try let node = map#get v in
Node (v, node.mut_v, Enum.of_list node.mut_outgoing)
Node (v, node.mut_v, Gen.of_list node.mut_outgoing)
with Not_found -> Empty in
let graph = { eq; hash; force; } in
map, graph
@ -208,9 +208,9 @@ module Full = struct
let explored = explored () in
let id = ref id in
let q = Queue.create () in (* queue of nodes to explore *)
Enum.iter (fun v -> Queue.push (FullEnter (v,[])) q) vertices;
Gen.iter (fun v -> Queue.push (FullEnter (v,[])) q) vertices;
let rec next () =
if Queue.is_empty q then raise Enum.EOG else
if Queue.is_empty q then raise Gen.EOG else
match Queue.pop q with
| FullEnter (v', path) ->
if explored#mem v' then next ()
@ -219,7 +219,7 @@ module Full = struct
| Node (_, label, edges) ->
explored#add v';
(* explore neighbors *)
Enum.iter
Gen.iter
(fun (e,v'') ->
let path' = (v'',e,v') :: path in
Queue.push (FullFollowEdge path') q)
@ -254,9 +254,9 @@ module Full = struct
let explored = explored () in
let id = ref id in
let s = Stack.create () in (* stack of nodes to explore *)
Enum.iter (fun v -> Stack.push (FullEnter (v,[])) s) vertices;
Gen.iter (fun v -> Stack.push (FullEnter (v,[])) s) vertices;
let rec next () =
if Stack.is_empty s then raise Enum.EOG else
if Stack.is_empty s then raise Gen.EOG else
match Stack.pop s with
| FullExit v' -> ExitVertex v'
| FullEnter (v', path) ->
@ -269,7 +269,7 @@ module Full = struct
(* prepare to exit later *)
Stack.push (FullExit v') s;
(* explore neighbors *)
Enum.iter
Gen.iter
(fun (e,v'') ->
Stack.push (FullFollowEdge ((v'', e, v') :: path)) s)
edges;
@ -294,20 +294,20 @@ module Full = struct
end
let bfs ?id ?explored graph v =
Enum.filterMap
Gen.filterMap
(function
| Full.EnterVertex (v, l, i, _) -> Some (v, l, i)
| _ -> None)
(Full.bfs_full ?id ?explored graph (Enum.singleton v))
(Full.bfs_full ?id ?explored graph (Gen.singleton v))
let dfs ?id ?explored graph v =
Enum.filterMap
Gen.filterMap
(function
| Full.EnterVertex (v, l, i, _) -> Some (v, l, i)
| _ -> None)
(Full.dfs_full ?id ?explored graph (Enum.singleton v))
(Full.dfs_full ?id ?explored graph (Gen.singleton v))
let enum graph v = (Enum.empty, Enum.empty) (* TODO *)
let enum graph v = (Gen.empty, Gen.empty) (* TODO *)
let depth graph v =
failwith "not implemented" (* TODO *)
@ -326,7 +326,7 @@ let union ?(combine=fun x y -> x) g1 g2 =
| ((Node _) as n), Empty -> n
| Empty, ((Node _) as n) -> n
| Node (_, l1, e1), Node (_, l2, e2) ->
Node (v, combine l1 l2, Enum.append e1 e2)
Node (v, combine l1 l2, Gen.append e1 e2)
in { eq=g1.eq; hash=g1.hash; force; }
let map ~vertices ~edges g =
@ -334,7 +334,7 @@ let map ~vertices ~edges g =
match g.force v with
| Empty -> Empty
| Node (_, l, edges_enum) ->
let edges_enum' = Enum.map (fun (e,v') -> (edges e), v') edges_enum in
let edges_enum' = Gen.map (fun (e,v') -> (edges e), v') edges_enum in
Node (v, vertices l, edges_enum')
in { eq=g.eq; hash=g.hash; force; }
@ -344,7 +344,7 @@ let filter ?(vertices=(fun v l -> true)) ?(edges=fun v1 e v2 -> true) g =
| Empty -> Empty
| Node (_, l, edges_enum) when vertices v l ->
(* filter out edges *)
let edges_enum' = Enum.filter (fun (e,v') -> edges v e v') edges_enum in
let edges_enum' = Gen.filter (fun (e,v') -> edges v e v') edges_enum in
Node (v, l, edges_enum')
| Node _ -> Empty (* filter out this vertex *)
in { eq=g.eq; hash=g.hash; force; }
@ -356,8 +356,8 @@ let product g1 g2 =
| _, Empty -> Empty
| Node (_, l1, edges1), Node (_, l2, edges2) ->
(* product of edges *)
let edges = Enum.product edges1 edges2 in
let edges = Enum.map (fun ((e1,v1'),(e2,v2')) -> ((e1,e2),(v1',v2'))) edges in
let edges = Gen.product edges1 edges2 in
let edges = Gen.map (fun ((e1,v1'),(e2,v2')) -> ((e1,e2),(v1',v2'))) edges in
Node ((v1,v2), (l1,l2), edges)
and eq (v1,v2) (v1',v2') =
g1.eq v1 v1' && g2.eq v2 v2'
@ -412,17 +412,17 @@ module Dot = struct
(* print preamble *)
Format.fprintf formatter "@[<v2>digraph %s {@;" name;
(* traverse *)
Enum.iter
Gen.iter
(function
| Full.EnterVertex (v, attrs, _, _) ->
Format.fprintf formatter " @[<h>%a [%a];@]@." pp_vertex v
(Enum.pp ~sep:"," print_attribute) (Enum.of_list attrs)
(Gen.pp ~sep:"," print_attribute) (Gen.of_list attrs)
| Full.ExitVertex _ -> ()
| Full.MeetEdge (v2, attrs, v1, _) ->
Format.fprintf formatter " @[<h>%a -> %a [%a];@]@."
pp_vertex v1 pp_vertex v2
(Enum.pp ~sep:"," print_attribute)
(Enum.of_list attrs))
(Gen.pp ~sep:"," print_attribute)
(Gen.of_list attrs))
events;
(* close *)
Format.fprintf formatter "}@]@;@?";
@ -446,15 +446,15 @@ let divisors_graph =
if i > 2
then
let l = divisors [] 2 i in
let edges = Enum.map (fun i -> (), i) (Enum.of_list l) in
let edges = Gen.map (fun i -> (), i) (Gen.of_list l) in
Node (i, i, edges)
else
Node (i, i, Enum.empty)
Node (i, i, Gen.empty)
in make force
let collatz_graph =
let force i =
if i mod 2 = 0
then Node (i, i, Enum.singleton ((), i / 2))
else Node (i, i, Enum.singleton ((), i * 3 + 1))
then Node (i, i, Gen.singleton ((), i / 2))
else Node (i, i, Gen.singleton ((), i * 3 + 1))
in make force

View file

@ -44,7 +44,7 @@ type ('id, 'v, 'e) t = {
other vertices, or to Empty if the identifier is not part of the graph. *)
and ('id, 'v, 'e) node =
| Empty
| Node of 'id * 'v * ('e * 'id) Enum.t
| Node of 'id * 'v * ('e * 'id) Gen.t
(** A single node of the graph, with outgoing edges *)
and ('id, 'e) path = ('id * 'e * 'id) list
(** A reverse path (from the last element of the path to the first). *)
@ -70,8 +70,8 @@ val make : ?eq:('id -> 'id -> bool) -> ?hash:('id -> int) ->
(** Build a graph from the [force] function *)
val from_enum : ?eq:('id -> 'id -> bool) -> ?hash:('id -> int) ->
vertices:('id * 'v) Enum.t ->
edges:('id * 'e * 'id) Enum.t ->
vertices:('id * 'v) Gen.t ->
edges:('id * 'e * 'id) Gen.t ->
('id, 'v, 'e) t
(** Concrete (eager) representation of a Graph (XXX not implemented)*)
@ -143,27 +143,27 @@ module Full : sig
| EdgeTransverse (* toward a totally explored part of the graph *)
val bfs_full : ?id:int -> ?explored:(unit -> 'id set) ->
('id, 'v, 'e) t -> 'id Enum.t ->
('id, 'v, 'e) traverse_event Enum.t
('id, 'v, 'e) t -> 'id Gen.t ->
('id, 'v, 'e) traverse_event Gen.t
(** Lazy traversal in breadth first from a finite set of vertices *)
val dfs_full : ?id:int -> ?explored:(unit -> 'id set) ->
('id, 'v, 'e) t -> 'id Enum.t ->
('id, 'v, 'e) traverse_event Enum.t
('id, 'v, 'e) t -> 'id Gen.t ->
('id, 'v, 'e) traverse_event Gen.t
(** Lazy traversal in depth first from a finite set of vertices *)
end
(** The traversal functions assign a unique ID to every traversed node *)
val bfs : ?id:int -> ?explored:(unit -> 'id set) ->
('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Enum.t
('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Gen.t
(** Lazy traversal in breadth first *)
val dfs : ?id:int -> ?explored:(unit -> 'id set) ->
('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Enum.t
('id, 'v, 'e) t -> 'id -> ('id * 'v * int) Gen.t
(** Lazy traversal in depth first *)
val enum : ('id, 'v, 'e) t -> 'id -> ('id * 'v) Enum.t * ('id * 'e * 'id) Enum.t
val enum : ('id, 'v, 'e) t -> 'id -> ('id * 'v) Gen.t * ('id * 'e * 'id) Gen.t
(** Convert to an enumeration. The traversal order is undefined. *)
val depth : ('id, _, 'e) t -> 'id -> ('id, int, 'e) t
@ -220,12 +220,12 @@ module Dot : sig
val pp_enum : ?eq:('id -> 'id -> bool) -> ?hash:('id -> int) ->
name:string -> Format.formatter ->
('id,attribute list,attribute list) Full.traverse_event Enum.t ->
('id,attribute list,attribute list) Full.traverse_event Gen.t ->
unit
val pp : name:string -> ('id, attribute list, attribute list) t ->
Format.formatter ->
'id Enum.t -> unit
'id Gen.t -> unit
(** Pretty print the given graph (starting from the given set of vertices)
to the channel in DOT format *)
end

View file

@ -6,7 +6,7 @@ let suite =
"all_tests" >:::
[ Test_pHashtbl.suite;
Test_vector.suite;
Test_enum.suite;
Test_gen.suite;
Test_deque.suite;
Test_fHashtbl.suite;
Test_fQueue.suite;

View file

@ -1,130 +0,0 @@
open OUnit
open Enum.Infix
let pint i = string_of_int i
let plist l = Utils.sprintf "%a"
(Sequence.pp_seq Format.pp_print_int) (Sequence.of_list l)
let pstrlist l = Utils.sprintf "%a"
(Sequence.pp_seq Format.pp_print_string) (Sequence.of_list l)
let test_singleton () =
let e = Enum.singleton 42 in
let gen = Enum.start e in
OUnit.assert_equal 42 (Enum.Gen.next gen);
OUnit.assert_raises Enum.EOG (fun () -> Enum.Gen.next gen);
OUnit.assert_equal 1 (Enum.length e);
()
let test_iter () =
let e = 1 -- 10 in
OUnit.assert_equal ~printer:pint 10 (Enum.length e);
OUnit.assert_equal [1;2] (Enum.to_list (1 -- 2));
OUnit.assert_equal [1;2;3;4;5] (Enum.to_list (Enum.take 5 e));
()
let test_map () =
let e = 1 -- 10 in
let e' = Enum.map string_of_int e in
OUnit.assert_equal ~printer:pstrlist ["9"; "10"] (Enum.to_list (Enum.drop 8 e'));
()
let test_append () =
let e = (1 -- 5) @@ (6 -- 10) in
OUnit.assert_equal [10;9;8;7;6;5;4;3;2;1] (Enum.to_rev_list e);
()
let test_flatMap () =
let e = 1 -- 3 in
let e' = e >>= (fun x -> x -- (x+1)) in
OUnit.assert_equal [1;2;2;3;3;4] (Enum.to_list e');
()
let test_zip () =
let e = Enum.zipWith (+) (Enum.repeat 1) (4--7) in
OUnit.assert_equal [5;6;7;8] (Enum.to_list e);
()
let test_filterMap () =
let f x = if x mod 2 = 0 then Some (string_of_int x) else None in
let e = Enum.filterMap f (1 -- 10) in
OUnit.assert_equal ["2"; "4"; "6"; "8"; "10"] (Enum.to_list e);
()
let test_merge () =
let e = Enum.of_list [1--3; 4--6; 7--9] in
let e' = Enum.merge e in
OUnit.assert_equal [1;4;7;2;5;8;3;6;9] (Enum.to_list e');
()
let test_persistent () =
let i = ref 0 in
let gen () =
let j = !i in
if j > 5 then raise Enum.EOG else (incr i; j)
in
let e = Enum.persistent gen in
OUnit.assert_equal [0;1;2;3;4;5] (Enum.to_list e);
OUnit.assert_equal [0;1;2;3;4;5] (Enum.to_list e);
OUnit.assert_equal [0;1;2;3;4;5] (Enum.to_list e);
()
let test_round_robin () =
let e = Enum.round_robin ~n:2 (1--10) in
let e = Enum.map Enum.persistent e in
let l = Enum.to_list e in
match l with
| [a;b] ->
OUnit.assert_equal [1;3;5;7;9] (Enum.to_list a);
OUnit.assert_equal [2;4;6;8;10] (Enum.to_list b)
| _ -> OUnit.assert_failure "wrong list lenght"
let test_big_rr () =
let e = Enum.round_robin ~n:3 (1 -- 999) in
let l = Enum.to_list e in
let l' = List.map Enum.Gen.length l in
OUnit.assert_equal [333;333;333] l';
()
let test_merge_sorted () =
Enum.of_list [Enum.of_list [1;3;5]; Enum.of_list [0;1;1;3;4;6;10]; Enum.of_list [2;2;11]]
|> Enum.merge_sorted ?cmp:None
|> Enum.to_list
|> OUnit.assert_equal ~printer:Helpers.print_int_list [0;1;1;1;2;2;3;3;4;5;6;10;11]
let test_interleave () =
let e1 = Enum.of_list [1;3;5;7;9] in
let e2 = Enum.of_list [2;4;6;8;10] in
let e = Enum.interleave e1 e2 in
OUnit.assert_equal [1;2;3;4;5;6;7;8;9;10] (Enum.to_list e);
()
let test_intersperse () =
let e = 1 -- 5 in
let e' = Enum.intersperse 0 e in
OUnit.assert_equal [1;0;2;0;3;0;4;0;5] (Enum.to_list e');
()
let test_product () =
let e = Enum.product (1--3) (4--5) in
OUnit.assert_equal [1,4; 1,5; 2,4; 2,5; 3,4; 3,5] (Enum.to_list e);
()
let suite =
"test_enum" >:::
[ "test_singleton" >:: test_singleton;
"test_iter" >:: test_iter;
"test_map" >:: test_map;
"test_append" >:: test_append;
"test_flatMap" >:: test_flatMap;
"test_zip" >:: test_zip;
"test_filterMap" >:: test_filterMap;
"test_merge" >:: test_merge;
"test_persistent" >:: test_persistent;
"test_round_robin" >:: test_round_robin;
"test_big_rr" >:: test_big_rr;
"test_merge_sorted" >:: test_merge_sorted;
"test_interleave" >:: test_interleave;
"test_intersperse" >:: test_intersperse;
"test_product" >:: test_product;
]

View file

@ -13,10 +13,10 @@ let test_mvar () =
()
let test_parallel () =
let open Enum.Infix in
let open Gen.Infix in
let l = 1 -- 300
|> Enum.map (fun _ -> Future.spawn (fun () -> Thread.delay 0.1; 1))
|> Enum.to_list in
|> Gen.map (fun _ -> Future.spawn (fun () -> Thread.delay 0.1; 1))
|> Gen.to_list in
let l' = List.map Future.get l in
OUnit.assert_equal 300 (List.fold_left (+) 0 l');
()

130
tests/test_gen.ml Normal file
View file

@ -0,0 +1,130 @@
open OUnit
open Gen.Infix
let pint i = string_of_int i
let plist l = Utils.sprintf "%a"
(Sequence.pp_seq Format.pp_print_int) (Sequence.of_list l)
let pstrlist l = Utils.sprintf "%a"
(Sequence.pp_seq Format.pp_print_string) (Sequence.of_list l)
let test_singleton () =
let e = Gen.singleton 42 in
let gen = Gen.start e in
OUnit.assert_equal 42 (Gen.Gen.next gen);
OUnit.assert_raises Gen.EOG (fun () -> Gen.Gen.next gen);
OUnit.assert_equal 1 (Gen.length e);
()
let test_iter () =
let e = 1 -- 10 in
OUnit.assert_equal ~printer:pint 10 (Gen.length e);
OUnit.assert_equal [1;2] (Gen.to_list (1 -- 2));
OUnit.assert_equal [1;2;3;4;5] (Gen.to_list (Gen.take 5 e));
()
let test_map () =
let e = 1 -- 10 in
let e' = Gen.map string_of_int e in
OUnit.assert_equal ~printer:pstrlist ["9"; "10"] (Gen.to_list (Gen.drop 8 e'));
()
let test_append () =
let e = (1 -- 5) @@ (6 -- 10) in
OUnit.assert_equal [10;9;8;7;6;5;4;3;2;1] (Gen.to_rev_list e);
()
let test_flatMap () =
let e = 1 -- 3 in
let e' = e >>= (fun x -> x -- (x+1)) in
OUnit.assert_equal [1;2;2;3;3;4] (Gen.to_list e');
()
let test_zip () =
let e = Gen.zipWith (+) (Gen.repeat 1) (4--7) in
OUnit.assert_equal [5;6;7;8] (Gen.to_list e);
()
let test_filterMap () =
let f x = if x mod 2 = 0 then Some (string_of_int x) else None in
let e = Gen.filterMap f (1 -- 10) in
OUnit.assert_equal ["2"; "4"; "6"; "8"; "10"] (Gen.to_list e);
()
let test_merge () =
let e = Gen.of_list [1--3; 4--6; 7--9] in
let e' = Gen.merge e in
OUnit.assert_equal [1;4;7;2;5;8;3;6;9] (Gen.to_list e');
()
let test_persistent () =
let i = ref 0 in
let gen () =
let j = !i in
if j > 5 then raise Gen.EOG else (incr i; j)
in
let e = Gen.persistent gen in
OUnit.assert_equal [0;1;2;3;4;5] (Gen.to_list e);
OUnit.assert_equal [0;1;2;3;4;5] (Gen.to_list e);
OUnit.assert_equal [0;1;2;3;4;5] (Gen.to_list e);
()
let test_round_robin () =
let e = Gen.round_robin ~n:2 (1--10) in
let e = Gen.map Gen.persistent e in
let l = Gen.to_list e in
match l with
| [a;b] ->
OUnit.assert_equal [1;3;5;7;9] (Gen.to_list a);
OUnit.assert_equal [2;4;6;8;10] (Gen.to_list b)
| _ -> OUnit.assert_failure "wrong list lenght"
let test_big_rr () =
let e = Gen.round_robin ~n:3 (1 -- 999) in
let l = Gen.to_list e in
let l' = List.map Gen.Gen.length l in
OUnit.assert_equal [333;333;333] l';
()
let test_merge_sorted () =
Gen.of_list [Gen.of_list [1;3;5]; Gen.of_list [0;1;1;3;4;6;10]; Gen.of_list [2;2;11]]
|> Gen.sorted_merge_n ?cmp:None
|> Gen.to_list
|> OUnit.assert_equal ~printer:Helpers.print_int_list [0;1;1;1;2;2;3;3;4;5;6;10;11]
let test_interleave () =
let e1 = Gen.of_list [1;3;5;7;9] in
let e2 = Gen.of_list [2;4;6;8;10] in
let e = Gen.interleave e1 e2 in
OUnit.assert_equal [1;2;3;4;5;6;7;8;9;10] (Gen.to_list e);
()
let test_intersperse () =
let e = 1 -- 5 in
let e' = Gen.intersperse 0 e in
OUnit.assert_equal [1;0;2;0;3;0;4;0;5] (Gen.to_list e');
()
let test_product () =
let e = Gen.product (1--3) (4--5) in
OUnit.assert_equal [1,4; 1,5; 2,4; 2,5; 3,4; 3,5] (Gen.to_list e);
()
let suite =
"test_gen" >:::
[ "test_singleton" >:: test_singleton;
"test_iter" >:: test_iter;
"test_map" >:: test_map;
"test_append" >:: test_append;
"test_flatMap" >:: test_flatMap;
"test_zip" >:: test_zip;
"test_filterMap" >:: test_filterMap;
"test_merge" >:: test_merge;
"test_persistent" >:: test_persistent;
"test_round_robin" >:: test_round_robin;
"test_big_rr" >:: test_big_rr;
"test_merge_sorted" >:: test_merge_sorted;
"test_interleave" >:: test_interleave;
"test_intersperse" >:: test_intersperse;
"test_product" >:: test_product;
]