module type Heterogeneous = sig
type key
type item
type itemset
type t
val find: key -> t -> itemset
val add: key -> itemset -> t -> t
val update: key -> (itemset -> itemset) -> t -> t
val mkedge: key -> item -> t -> t
val rmedge: key -> item -> t -> t
val iter: (key * item -> unit) -> t -> unit
val fold: (key * item -> 'a -> 'a) -> t -> 'a -> 'a
val pick: t -> (key * item -> bool) -> (key * item) option
end
module MakeHetero
(Set : sig
type elt
type t
val empty: t
val is_empty: t -> bool
val add: elt -> t -> t
val remove: elt -> t -> t
val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a
end)
(Map : sig
type key
type 'a t
val add: key -> 'a -> 'a t -> 'a t
val find: key -> 'a t -> 'a
val remove: key -> 'a t -> 'a t
val fold: (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
end)
= struct
type key = Map.key
type item = Set.elt
type itemset = Set.t
type t = Set.t Map.t
let find x m =
try
Map.find x m
with Not_found ->
Set.empty
let add x is m =
if Set.is_empty is then
Map.remove x m
else
Map.add x is m
let update x f m =
add x (f (find x m)) m
let mkedge x i m =
update x (Set.add i) m
let rmedge x i m =
update x (Set.remove i) m
let fold f m accu =
Map.fold (fun source targets accu ->
Set.fold (fun target accu ->
f (source, target) accu
) targets accu
) m accu
let iter f m =
fold (fun edge () -> f edge) m ()
exception Picked of (key * item)
let pick m p =
try
iter (fun edge ->
if p edge then
raise (Picked edge)
) m;
None
with Picked edge ->
Some edge
end
module type Homogeneous = sig
include Heterogeneous
val mkbiedge: key -> key -> t -> t
val rmbiedge: key -> key -> t -> t
val reverse: t -> t
val restrict: (key -> bool) -> t -> t
end
module MakeHomo
(Set : sig
type elt
type t
val empty: t
val is_empty: t -> bool
val add: elt -> t -> t
val remove: elt -> t -> t
val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a
val filter: (elt -> bool) -> t -> t
end)
(Map : sig
type key = Set.elt
type 'a t
val empty: 'a t
val add: key -> 'a -> 'a t -> 'a t
val find: key -> 'a t -> 'a
val remove: key -> 'a t -> 'a t
val fold: (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
end)
= struct
include MakeHetero(Set)(Map)
let symmetric transform x1 x2 m =
transform x1 x2 (transform x2 x1 m)
let mkbiedge =
symmetric mkedge
let rmbiedge =
symmetric rmedge
let reverse m =
Map.fold (fun source targets predecessors ->
Set.fold (fun target predecessors ->
mkedge target source predecessors
) targets predecessors
) m Map.empty
let restrict p m =
Map.fold (fun source targets m ->
if p source then
let targets = Set.filter p targets in
if Set.is_empty targets then
m
else
Map.add source targets m
else
m
) m Map.empty
end