-
Notifications
You must be signed in to change notification settings - Fork 465
/
Copy pathset_gen.ml
481 lines (424 loc) · 13.5 KB
/
set_gen.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
(***********************************************************************)
(* *)
(* OCaml *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1996 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU Library General Public License, with *)
(* the special exception on linking described in file ../LICENSE. *)
(* *)
(***********************************************************************)
(** balanced tree based on stdlib distribution *)
type 'a t =
| Empty
| Node of 'a t * 'a * 'a t * int
type 'a enumeration =
| End | More of 'a * 'a t * 'a enumeration
let rec cons_enum s e =
match s with
| Empty -> e
| Node(l,v,r,_) -> cons_enum l (More(v,r,e))
let rec height = function
| Empty -> 0
| Node(_,_,_,h) -> h
(* Smallest and greatest element of a set *)
let rec min_elt = function
Empty -> raise Not_found
| Node(Empty, v, r, _) -> v
| Node(l, v, r, _) -> min_elt l
let rec max_elt = function
Empty -> raise Not_found
| Node(l, v, Empty, _) -> v
| Node(l, v, r, _) -> max_elt r
let empty = Empty
let is_empty = function Empty -> true | _ -> false
let rec cardinal_aux acc = function
| Empty -> acc
| Node (l,_,r, _) ->
cardinal_aux (cardinal_aux (acc + 1) r ) l
let cardinal s = cardinal_aux 0 s
let rec elements_aux accu = function
| Empty -> accu
| Node(l, v, r, _) -> elements_aux (v :: elements_aux accu r) l
let elements s =
elements_aux [] s
let choose = min_elt
let rec iter f = function
| Empty -> ()
| Node(l, v, r, _) -> iter f l; f v; iter f r
let rec fold f s accu =
match s with
| Empty -> accu
| Node(l, v, r, _) -> fold f r (f v (fold f l accu))
let rec for_all p = function
| Empty -> true
| Node(l, v, r, _) -> p v && for_all p l && for_all p r
let rec exists p = function
| Empty -> false
| Node(l, v, r, _) -> p v || exists p l || exists p r
let max_int3 (a : int) b c =
if a >= b then
if a >= c then a
else c
else
if b >=c then b
else c
let max_int_2 (a : int) b =
if a >= b then a else b
exception Height_invariant_broken
exception Height_diff_borken
let rec check_height_and_diff =
function
| Empty -> 0
| Node(l,_,r,h) ->
let hl = check_height_and_diff l in
let hr = check_height_and_diff r in
if h <> max_int_2 hl hr + 1 then raise Height_invariant_broken
else
let diff = (abs (hl - hr)) in
if diff > 2 then raise Height_diff_borken
else h
let check tree =
ignore (check_height_and_diff tree)
(*
Invariants:
1. {[ l < v < r]}
2. l and r balanced
3. [height l] - [height r] <= 2
*)
let create l v r =
let hl = match l with Empty -> 0 | Node (_,_,_,h) -> h in
let hr = match r with Empty -> 0 | Node (_,_,_,h) -> h in
Node(l,v,r, if hl >= hr then hl + 1 else hr + 1)
(* Same as create, but performs one step of rebalancing if necessary.
Invariants:
1. {[ l < v < r ]}
2. l and r balanced
3. | height l - height r | <= 3.
Proof by indunction
Lemma: the height of [bal l v r] will bounded by [max l r] + 1
*)
(*
let internal_bal l v r =
match l with
| Empty ->
begin match r with
| Empty -> Node(Empty,v,Empty,1)
| Node(rl,rv,rr,hr) ->
if hr > 2 then
begin match rl with
| Empty -> create (* create l v rl *) (Node (Empty,v,Empty,1)) rv rr
| Node(rll,rlv,rlr,hrl) ->
let hrr = height rr in
if hrr >= hrl then
Node
((Node (Empty,v,rl,hrl+1))(* create l v rl *),
rv, rr, if hrr = hrl then hrr + 2 else hrr + 1)
else
let hrll = height rll in
let hrlr = height rlr in
create
(Node(Empty,v,rll,hrll + 1))
(* create l v rll *)
rlv
(Node (rlr,rv,rr, if hrlr > hrr then hrlr + 1 else hrr + 1))
(* create rlr rv rr *)
end
else Node (l,v,r, hr + 1)
end
| Node(ll,lv,lr,hl) ->
begin match r with
| Empty ->
if hl > 2 then
(*if height ll >= height lr then create ll lv (create lr v r)
else*)
begin match lr with
| Empty ->
create ll lv (Node (Empty,v,Empty, 1))
(* create lr v r *)
| Node(lrl,lrv,lrr,hlr) ->
if height ll >= hlr then
create ll lv
(Node(lr,v,Empty,hlr+1))
(*create lr v r*)
else
let hlrr = height lrr in
create
(create ll lv lrl)
lrv
(Node(lrr,v,Empty,hlrr + 1))
(*create lrr v r*)
end
else Node(l,v,r, hl+1)
| Node(rl,rv,rr,hr) ->
if hl > hr + 2 then
begin match lr with
| Empty -> create ll lv (create lr v r)
| Node(lrl,lrv,lrr,_) ->
if height ll >= height lr then create ll lv (create lr v r)
else
create (create ll lv lrl) lrv (create lrr v r)
end
else
if hr > hl + 2 then
begin match rl with
| Empty ->
let hrr = height rr in
Node(
(Node (l,v,Empty,hl + 1))
(*create l v rl*)
,
rv,
rr,
if hrr > hr then hrr + 1 else hl + 2
)
| Node(rll,rlv,rlr,_) ->
let hrr = height rr in
let hrl = height rl in
if hrr >= hrl then create (create l v rl) rv rr else
create (create l v rll) rlv (create rlr rv rr)
end
else
Node(l,v,r, if hl >= hr then hl+1 else hr + 1)
end
*)
let internal_bal l v r =
let hl = match l with Empty -> 0 | Node(_,_,_,h) -> h in
let hr = match r with Empty -> 0 | Node(_,_,_,h) -> h in
if hl > hr + 2 then begin
match l with
Empty -> assert false
| Node(ll, lv, lr, _) ->
if height ll >= height lr then
(* [ll] >~ [lr]
[ll] >~ [r]
[ll] ~~ [ lr ^ r]
*)
create ll lv (create lr v r)
else begin
match lr with
Empty -> assert false
| Node(lrl, lrv, lrr, _)->
(* [lr] >~ [ll]
[lr] >~ [r]
[ll ^ lrl] ~~ [lrr ^ r]
*)
create (create ll lv lrl) lrv (create lrr v r)
end
end else if hr > hl + 2 then begin
match r with
Empty -> assert false
| Node(rl, rv, rr, _) ->
if height rr >= height rl then
create (create l v rl) rv rr
else begin
match rl with
Empty -> assert false
| Node(rll, rlv, rlr, _) ->
create (create l v rll) rlv (create rlr rv rr)
end
end else
Node(l, v, r, (if hl >= hr then hl + 1 else hr + 1))
let rec remove_min_elt = function
Empty -> invalid_arg "Set.remove_min_elt"
| Node(Empty, v, r, _) -> r
| Node(l, v, r, _) -> internal_bal (remove_min_elt l) v r
let singleton x = Node(Empty, x, Empty, 1)
(*
All elements of l must precede the elements of r.
Assume | height l - height r | <= 2.
weak form of [concat]
*)
let internal_merge l r =
match (l, r) with
| (Empty, t) -> t
| (t, Empty) -> t
| (_, _) -> internal_bal l (min_elt r) (remove_min_elt r)
(* Beware: those two functions assume that the added v is *strictly*
smaller (or bigger) than all the present elements in the tree; it
does not test for equality with the current min (or max) element.
Indeed, they are only used during the "join" operation which
respects this precondition.
*)
let rec add_min_element v = function
| Empty -> singleton v
| Node (l, x, r, h) ->
internal_bal (add_min_element v l) x r
let rec add_max_element v = function
| Empty -> singleton v
| Node (l, x, r, h) ->
internal_bal l x (add_max_element v r)
(**
Invariants:
1. l < v < r
2. l and r are balanced
Proof by induction
The height of output will be ~~ (max (height l) (height r) + 2)
Also use the lemma from [bal]
*)
let rec internal_join l v r =
match (l, r) with
(Empty, _) -> add_min_element v r
| (_, Empty) -> add_max_element v l
| (Node(ll, lv, lr, lh), Node(rl, rv, rr, rh)) ->
if lh > rh + 2 then
(* proof by induction:
now [height of ll] is [lh - 1]
*)
internal_bal ll lv (internal_join lr v r)
else
if rh > lh + 2 then internal_bal (internal_join l v rl) rv rr
else create l v r
(*
Required Invariants:
[t1] < [t2]
*)
let internal_concat t1 t2 =
match (t1, t2) with
| (Empty, t) -> t
| (t, Empty) -> t
| (_, _) -> internal_join t1 (min_elt t2) (remove_min_elt t2)
let rec filter p = function
| Empty -> Empty
| Node(l, v, r, _) ->
(* call [p] in the expected left-to-right order *)
let l' = filter p l in
let pv = p v in
let r' = filter p r in
if pv then internal_join l' v r' else internal_concat l' r'
let rec partition p = function
| Empty -> (Empty, Empty)
| Node(l, v, r, _) ->
(* call [p] in the expected left-to-right order *)
let (lt, lf) = partition p l in
let pv = p v in
let (rt, rf) = partition p r in
if pv
then (internal_join lt v rt, internal_concat lf rf)
else (internal_concat lt rt, internal_join lf v rf)
let of_sorted_list l =
let rec sub n l =
match n, l with
| 0, l -> Empty, l
| 1, x0 :: l -> Node (Empty, x0, Empty, 1), l
| 2, x0 :: x1 :: l -> Node (Node(Empty, x0, Empty, 1), x1, Empty, 2), l
| 3, x0 :: x1 :: x2 :: l ->
Node (Node(Empty, x0, Empty, 1), x1, Node(Empty, x2, Empty, 1), 2),l
| n, l ->
let nl = n / 2 in
let left, l = sub nl l in
match l with
| [] -> assert false
| mid :: l ->
let right, l = sub (n - nl - 1) l in
create left mid right, l
in
fst (sub (List.length l) l)
let of_sorted_array l =
let rec sub start n l =
if n = 0 then Empty else
if n = 1 then
let x0 = Array.unsafe_get l start in
Node (Empty, x0, Empty, 1)
else if n = 2 then
let x0 = Array.unsafe_get l start in
let x1 = Array.unsafe_get l (start + 1) in
Node (Node(Empty, x0, Empty, 1), x1, Empty, 2) else
if n = 3 then
let x0 = Array.unsafe_get l start in
let x1 = Array.unsafe_get l (start + 1) in
let x2 = Array.unsafe_get l (start + 2) in
Node (Node(Empty, x0, Empty, 1), x1, Node(Empty, x2, Empty, 1), 2)
else
let nl = n / 2 in
let left = sub start nl l in
let mid = start + nl in
let v = Array.unsafe_get l mid in
let right = sub (mid + 1) (n - nl - 1) l in
create left v right
in
sub 0 (Array.length l) l
let is_ordered cmp tree =
let rec is_ordered_min_max tree =
match tree with
| Empty -> `Empty
| Node(l,v,r,_) ->
begin match is_ordered_min_max l with
| `No -> `No
| `Empty ->
begin match is_ordered_min_max r with
| `No -> `No
| `Empty -> `V (v,v)
| `V(l,r) ->
if cmp v l < 0 then
`V(v,r)
else
`No
end
| `V(min_v,max_v)->
begin match is_ordered_min_max r with
| `No -> `No
| `Empty ->
if cmp max_v v < 0 then
`V(min_v,v)
else
`No
| `V(min_v_r, max_v_r) ->
if cmp max_v min_v_r < 0 then
`V(min_v,max_v_r)
else `No
end
end in
is_ordered_min_max tree <> `No
let invariant cmp t =
check t ;
is_ordered cmp t
let rec compare_aux cmp e1 e2 =
match (e1, e2) with
(End, End) -> 0
| (End, _) -> -1
| (_, End) -> 1
| (More(v1, r1, e1), More(v2, r2, e2)) ->
let c = cmp v1 v2 in
if c <> 0
then c
else compare_aux cmp (cons_enum r1 e1) (cons_enum r2 e2)
let compare cmp s1 s2 =
compare_aux cmp (cons_enum s1 End) (cons_enum s2 End)
module type S = sig
type elt
type t
val empty: t
val is_empty: t -> bool
val iter: (elt -> unit) -> t -> unit
val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a
val for_all: (elt -> bool) -> t -> bool
val exists: (elt -> bool) -> t -> bool
val singleton: elt -> t
val cardinal: t -> int
val elements: t -> elt list
val min_elt: t -> elt
val max_elt: t -> elt
val choose: t -> elt
val of_sorted_list : elt list -> t
val of_sorted_array : elt array -> t
val partition: (elt -> bool) -> t -> t * t
val mem: elt -> t -> bool
val add: elt -> t -> t
val remove: elt -> t -> t
val union: t -> t -> t
val inter: t -> t -> t
val diff: t -> t -> t
val compare: t -> t -> int
val equal: t -> t -> bool
val subset: t -> t -> bool
val filter: (elt -> bool) -> t -> t
val split: elt -> t -> t * bool * t
val find: elt -> t -> elt
val of_list: elt list -> t
val of_sorted_list : elt list -> t
val of_sorted_array : elt array -> t
val invariant : t -> bool
end