Added benchmarking funtions,
[SXSI/xpathcomp.git] / finiteCofinite.ml
1 (******************************************************************************)
2 (*  SXSI : XPath evaluator                                                    *)
3 (*  Kim Nguyen (Kim.Nguyen@nicta.com.au)                                      *)
4 (*  Copyright NICTA 2008                                                      *)
5 (*  Distributed under the terms of the LGPL (see LICENCE)                     *)
6 (******************************************************************************)
7 INCLUDE "utils.ml"
8
9 exception InfiniteSet
10 module type S = 
11 sig
12   type elt
13   type t
14   type set
15   val empty : t
16   val any : t
17   val is_empty : t -> bool
18   val is_any : t -> bool
19   val is_finite : t -> bool
20   val kind : t -> [ `Finite | `Cofinite ]
21   val singleton : elt -> t
22   val mem : elt -> t -> bool
23   val add : elt -> t -> t
24   val remove : elt -> t -> t
25   val cup : t -> t -> t
26   val cap : t -> t -> t
27   val diff : t -> t -> t
28   val neg : t -> t
29   val compare : t -> t -> int
30   val subset : t -> t -> bool
31   val kind_split : t list -> t * t
32   val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
33   val for_all : (elt -> bool) -> t -> bool
34   val exists : (elt -> bool) -> t -> bool
35   val filter : (elt -> bool) -> t -> t
36   val partition : (elt -> bool) -> t -> t * t
37   val cardinal : t -> int
38   val elements : t -> elt list
39   val from_list : elt list -> t
40   val choose : t -> elt
41   val hash : t -> int
42   val equal : t -> t -> bool
43   val uid : t -> int
44   val positive : t -> set
45   val negative : t -> set
46   val inj_positive : set -> t
47   val inj_negative : set -> t
48 end
49
50 module Make (E : Ptset.S) : S with type elt = E.elt and type set = E.t =
51 struct
52
53   type elt = E.elt
54   type node = Finite of E.t | CoFinite of E.t
55   type set = E.t
56   module Node = Hcons.Make(struct 
57                                   type t = node
58                                   let equal a b = 
59                                     match a,b with
60                                        (Finite(s1),Finite(s2))
61                                       | (CoFinite(s1),CoFinite(s2)) -> E.equal s1 s2
62                                       | _ -> false
63                                   let hash = function
64                                     Finite (s) -> HASHINT2(PRIME2,E.hash s)
65                                   | CoFinite(s) -> HASHINT2(PRIME7,E.hash s)
66                            end)
67   type t = Node.t
68   let empty = Node.make (Finite E.empty)
69   let any = Node.make (CoFinite E.empty)
70   let finite x = Node.make (Finite x)
71   let cofinite x = Node.make (CoFinite x)
72
73   let is_empty =  function
74       { Node.node = Finite s } when E.is_empty s -> true
75     | _ -> false
76
77   let is_any = function
78       { Node.node = CoFinite s } when E.is_empty s -> true
79     | _ -> false
80
81   let is_finite t = match t.Node.node with
82     | Finite _ -> true | _ -> false
83
84   let kind t = match t.Node.node with
85       Finite _ -> `Finite 
86     | _ -> `Cofinite 
87
88   let mem x t = match t.Node.node with
89     | Finite s -> E.mem x s
90     | CoFinite s -> not (E.mem x s)
91
92   let singleton x = finite (E.singleton x)
93   let add e t = match t.Node.node with
94     | Finite s -> finite (E.add e s)
95     | CoFinite s -> cofinite (E.remove e s)
96   let remove e t = match t.Node.node with
97     | Finite s -> finite (E.remove e s)
98     | CoFinite s -> cofinite (E.add e s)
99         
100   let cup s t = match (s.Node.node,t.Node.node) with
101     | Finite s, Finite t -> finite (E.union s t)
102     | CoFinite s, CoFinite t -> cofinite ( E.inter s t)
103     | Finite s, CoFinite t -> cofinite (E.diff t s)
104     | CoFinite s, Finite t-> cofinite (E.diff s t)
105
106   let cap s t = match (s.Node.node,t.Node.node) with
107     | Finite s, Finite t -> finite (E.inter s t)
108     | CoFinite s, CoFinite t -> cofinite (E.union s t)
109     | Finite s, CoFinite t -> finite (E.diff s t)
110     | CoFinite s, Finite t-> finite (E.diff t s)
111         
112   let diff s t = match (s.Node.node,t.Node.node) with
113     | Finite s, Finite t -> finite (E.diff s t)
114     | Finite s, CoFinite t -> finite(E.inter s t)
115     | CoFinite s, Finite t -> cofinite(E.union t s)
116     | CoFinite s, CoFinite t -> finite (E.diff t s)
117
118   let neg t = match t.Node.node with
119     | Finite s -> cofinite s
120     | CoFinite s -> finite s
121         
122   let compare s t = match (s.Node.node,t.Node.node) with
123     | Finite s , Finite t -> E.compare s t
124     | CoFinite s , CoFinite t -> E.compare t s
125     | Finite _, CoFinite _ -> -1
126     | CoFinite _, Finite _ -> 1
127         
128   let subset s t = match (s.Node.node,t.Node.node) with
129     | Finite s , Finite t -> E.subset s t
130     | CoFinite s , CoFinite t -> E.subset t s
131     | Finite s, CoFinite t -> E.is_empty (E.inter s t)
132     | CoFinite _, Finite _ -> false
133
134         (* given a  list l of type t list, 
135            returns two sets (f,c) where :
136            - f is the union of all the finite sets of l
137            - c is the union of all the cofinite sets of l
138            - f and c are disjoint
139            Invariant : cup f c = List.fold_left cup empty l
140
141            We treat the CoFinite part explicitely :
142         *)
143
144   let kind_split l =
145     
146     let rec next_finite_cofinite facc cacc = function 
147       | [] -> finite facc, cofinite (E.diff cacc facc)
148       | { Node.node = Finite s } ::r -> next_finite_cofinite (E.union s facc) cacc r
149       | { Node.node = CoFinite _ } ::r when E.is_empty cacc -> next_finite_cofinite facc cacc r
150       | { Node.node = CoFinite s } ::r -> next_finite_cofinite facc (E.inter cacc s) r
151     in
152     let rec first_cofinite facc = function
153       | [] -> empty,empty
154       | { Node.node = Finite s } :: r-> first_cofinite (E.union s facc) r
155       | { Node.node = CoFinite s } :: r -> next_finite_cofinite facc s r  
156     in
157       first_cofinite E.empty l
158         
159   let fold f t a = match t.Node.node with
160     | Finite s -> E.fold f s a
161     | CoFinite _ -> raise InfiniteSet
162
163   let for_all f t = match t.Node.node with
164     | Finite s -> E.for_all f s
165     | CoFinite _ -> raise InfiniteSet
166
167   let exists f t = match t.Node.node with
168     | Finite s -> E.exists f s
169     | CoFinite _ -> raise InfiniteSet
170
171   let filter f t = match t.Node.node with
172     | Finite s -> finite (E.filter f s)
173     | CoFinite _ -> raise InfiniteSet
174
175   let partition f t = match t.Node.node with
176     | Finite s -> let a,b = E.partition f s in finite a,finite b
177     | CoFinite _ -> raise InfiniteSet
178
179   let cardinal t = match t.Node.node with
180     | Finite s -> E.cardinal s
181     | CoFinite _ -> raise InfiniteSet
182
183   let elements t = match t.Node.node with
184     | Finite s -> E.elements s
185     | CoFinite _ -> raise InfiniteSet
186         
187   let from_list l = 
188     finite (List.fold_left (fun x a -> E.add a x ) E.empty l)
189
190   let choose t = match t.Node.node with
191       Finite s -> E.choose s
192     | _ -> raise InfiniteSet
193
194   let equal = (==)
195
196   let hash t = t.Node.key
197
198   let uid t = t.Node.id
199   
200
201   let positive t =  
202     match t.Node.node with
203       | Finite x -> x
204       | _ -> E.empty
205
206   let negative t = 
207     match t.Node.node with
208       | CoFinite x -> x
209       | _ -> E.empty
210
211   let inj_positive t = finite t
212   let inj_negative t = cofinite t
213 end
214