1 (* Pasted from Pottier's PP compiler *)
3 (* This signature defines a few operations over maps of keys to
4 nonempty sets of items. Keys and items can have distinct types,
5 hence the name [Heterogeneous].
7 These maps can be used to represent directed bipartite graphs whose
8 source vertices are keys and whose target vertices are items. Each
9 key is mapped to the set of its successors. *)
11 module type Heterogeneous = sig
13 (* These are the types of keys, items, and sets of items. *)
19 (* This is the type of maps of keys to sets of items. *)
23 (* [find x m] is the item set associated with key [x] in map [m], if
24 such an association is defined; it is the empty set otherwise. *)
26 val find: key -> t -> itemset
28 (* [add x is m] extends [m] with a binding of [x] to the item set
29 [is], if [is] is nonempty. If [is] is empty, it removes [x] from
32 val add: key -> itemset -> t -> t
34 (* [update x f m] is [add x (f (find x m)) m]. *)
36 val update: key -> (itemset -> itemset) -> t -> t
38 (* [mkedge x i m] extends [m] with a binding of [x] to the union of
39 the set [m x] and the singleton [i], where [m x] is taken to be
40 empty if undefined. In terms of graphs, [mkedge x i m] extends
41 the graph [m] with an edge of [x] to [i]. *)
43 val mkedge: key -> item -> t -> t
45 (* [rmedge x i m] extends [m] with a binding of [x] to the
46 difference of the set [m x] and the singleton [i], where the
47 binding is considered undefined if that difference is empty. In
48 terms of graphs, [rmedge x i m] removes an edge of [x] to [i]
51 val rmedge: key -> item -> t -> t
53 (* [iter] and [fold] iterate over all edges in the graph. *)
55 val iter: (key * item -> unit) -> t -> unit
56 val fold: (key * item -> 'a -> 'a) -> t -> 'a -> 'a
58 (* [pick m p] returns an arbitrary edge that satisfies predicate
59 [p], if the graph contains one. *)
61 val pick: t -> (key * item -> bool) -> (key * item) option
65 (* This functor offers an implementation of [Heterogeneous] out of
66 standard implementations of sets and maps. *)
73 val is_empty: t -> bool
74 val add: elt -> t -> t
75 val remove: elt -> t -> t
76 val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a
81 val add: key -> 'a -> 'a t -> 'a t
82 val find: key -> 'a t -> 'a
83 val remove: key -> 'a t -> 'a t
84 val fold: (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
100 if Set.is_empty is then
106 add x (f (find x m)) m
109 update x (Set.add i) m
112 update x (Set.remove i) m
115 Map.fold (fun source targets accu ->
116 Set.fold (fun target accu ->
117 f (source, target) accu
122 fold (fun edge () -> f edge) m ()
124 exception Picked of (key * item)
138 (* This signature defines a few common operations over maps of keys
139 to sets of keys -- that is, keys and items have the same type,
140 hence the name [Homogeneous].
142 These maps can be used to represent general directed graphs. *)
144 module type Homogeneous = sig
146 include Heterogeneous (* [key] and [item] intended to be equal *)
148 (* [mkbiedge x1 x2 m] is [mkedge x1 x2 (mkedge x2 x1 m)]. *)
150 val mkbiedge: key -> key -> t -> t
152 (* [rmbiedge x1 x2 m] is [rmedge x1 x2 (rmedge x2 x1 m)]. *)
154 val rmbiedge: key -> key -> t -> t
156 (* [reverse m] is the reverse of graph [m]. *)
160 (* [restrict m] is the graph obtained by keeping only the vertices
161 that satisfy predicate [p]. *)
163 val restrict: (key -> bool) -> t -> t
172 val is_empty: t -> bool
173 val add: elt -> t -> t
174 val remove: elt -> t -> t
175 val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a
176 val filter: (elt -> bool) -> t -> t
182 val add: key -> 'a -> 'a t -> 'a t
183 val find: key -> 'a t -> 'a
184 val remove: key -> 'a t -> 'a t
185 val fold: (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
189 include MakeHetero(Set)(Map)
191 let symmetric transform x1 x2 m =
192 transform x1 x2 (transform x2 x1 m)
201 Map.fold (fun source targets predecessors ->
202 Set.fold (fun target predecessors ->
204 (* We have a direct edge from [source] to [target]. Thus, we
205 record the existence of a reverse edge from [target] to
208 mkedge target source predecessors
210 ) targets predecessors
214 Map.fold (fun source targets m ->
216 let targets = Set.filter p targets in
217 if Set.is_empty targets then
220 Map.add source targets m