···11+#require "fmt"
22+(* #directory "_build/src" *)
33+(* #load "psq.cma" *)
44+55+let shuff arr =
66+ let n = Array.length arr in
77+ for i = 0 to n - 2 do
88+ let j = Random.int (n - i) + i in
99+ let t = arr.(i) in
1010+ arr.(i) <- arr.(j);
1111+ arr.(j) <- t
1212+ done
1313+1414+let permutation n =
1515+ let arr = Array.init n (fun x -> x) in
1616+ shuff arr;
1717+ Array.to_list arr
1818+1919+let rec (--) a b = if a > b then [] else a :: succ a -- b
2020+2121+module I = struct type t = int let compare = compare end
2222+module Q = Psq.Make (I) (I)
2323+2424+let pp_q = Q.pp_dump Fmt.int Fmt.int
2525+;;
2626+#install_printer pp_q
···11+## v0.2.1 2022-10-25
22+33+- added `push` to bump priorities
44+- added `split_at`
55+- changed `++`, `of_list` to select the lowest, not the last/rightmost priority
66+77+## v0.2.0 2019-04-09
88+99+Semantics cleanup.
1010+1111+- flipped args to `adjust` **breaking**
1212+- `of_list` now always chooses the rightmost binding
1313+- `update`, `(++)`, `add_seq`, `to_priority_list`
1414+- somewhat faster
1515+1616+## v0.1.1 2019-04-06
1717+1818+- `Seq.t` conversions
1919+- property tests
2020+- fixed key ordering of interval queries
2121+- key order tie-breaks `min`
2222+2323+## v0.1.0 2016-11-20
2424+2525+First release.
+13
vendor/opam/psq/LICENSE.md
···11+Copyright (c) 2016 David Kaloper Meršinjak
22+33+Permission to use, copy, modify, and/or distribute this software for any
44+purpose with or without fee is hereby granted, provided that the above
55+copyright notice and this permission notice appear in all copies.
66+77+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
88+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
99+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1010+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1111+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1212+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1313+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+23
vendor/opam/psq/README.md
···11+## psq — Functional Priority Search Queues
22+33+%%VERSION%%
44+55+psq provides a functional priority search queue for OCaml. This structure
66+behaves both as a finite map, containing bindings `k -> p`, and a priority queue
77+over `p`. It provides efficient access along more than one axis: to any binding
88+by `k`, and to the binding(s) with the least `p`.
99+1010+Typical applications are searches, schedulers and caches. If you ever scratched
1111+your head because that A\* didn't look quite right, a PSQ is what you needed.
1212+1313+The implementation is backed by [priority search pennants][hinze].
1414+1515+psq is distributed under the ISC license.
1616+1717+[hinze]: https://www.cs.ox.ac.uk/ralf.hinze/publications/ICFP01.pdf
1818+1919+## Documentation
2020+2121+Documentation is generated by `odoc`. It can be browsed [online][doc].
2222+2323+[doc]: https://pqwy.github.io/psq/doc/psq/
···11+(* Copyright (c) 2016 David Kaloper Meršinjak. All rights reserved.
22+ See LICENSE.md *)
33+44+type 'a fmt = Format.formatter -> 'a -> unit
55+66+let pf = Format.fprintf
77+88+module type Ordered = sig type t val compare : t -> t -> int end
99+1010+module type S = sig
1111+ type t
1212+ type k
1313+ type p
1414+ val empty : t
1515+ val sg : k -> p -> t
1616+ val (++) : t -> t -> t
1717+ val is_empty : t -> bool
1818+ val size : t -> int
1919+ val mem : k -> t -> bool
2020+ val find : k -> t -> p option
2121+ val add : k -> p -> t -> t
2222+ val push : k -> p -> t -> t
2323+ val remove : k -> t -> t
2424+ val adjust : k -> (p -> p) -> t -> t
2525+ val update : k -> (p option -> p option) -> t -> t
2626+ val split_at : k -> t -> t * t
2727+ val min : t -> (k * p) option
2828+ val rest : t -> t option
2929+ val pop : t -> ((k * p) * t) option
3030+ val fold_at_most : p -> (k -> p -> 'a -> 'a) -> 'a -> t -> 'a
3131+ val iter_at_most : p -> (k -> p -> unit) -> t -> unit
3232+ val to_seq_at_most : p -> t -> (k * p) Seq.t
3333+ val of_list : (k * p) list -> t
3434+ val of_sorted_list : (k * p) list -> t
3535+ val of_seq : (k * p) Seq.t -> t
3636+ val add_seq : (k * p) Seq.t -> t -> t
3737+ val to_list : t -> (k * p) list
3838+ val to_seq : t -> (k * p) Seq.t
3939+ val fold : (k -> p -> 'a -> 'a) -> 'a -> t -> 'a
4040+ val iter : (k -> p -> unit) -> t -> unit
4141+ val to_priority_list : t -> (k * p) list
4242+ val to_priority_seq : t -> (k * p) Seq.t
4343+ val filter : (k -> p -> bool) -> t -> t
4444+ val partition : (k -> p -> bool) -> t -> t * t
4545+ val pp : ?sep:(unit fmt) -> (k * p) fmt -> t fmt
4646+ val pp_dump : k fmt -> p fmt -> t fmt
4747+ val depth : t -> int
4848+end
4949+5050+module Make (K: Ordered) (P: Ordered) :
5151+ S with type k = K.t and type p = P.t =
5252+struct
5353+5454+ type k = K.t
5555+ type p = P.t
5656+5757+ type t = (* SEARCH PENNANTS *)
5858+ N
5959+ | T of (k * p) * k * tree
6060+6161+ and tree = (* LOSER TREES, OH MY *)
6262+ Lf
6363+ | NdL of (k * p) * tree * k * tree * int
6464+ | NdR of (k * p) * tree * k * tree * int
6565+6666+ let empty = N
6767+ let sg (k, _ as kp) = T (kp, k, Lf)
6868+6969+ let is_empty = function N -> true | _ -> false
7070+7171+ let size_t = function
7272+ Lf -> 0
7373+ | NdL (_, _, _, _, w)
7474+ | NdR (_, _, _, _, w) -> w
7575+7676+ let size = function N -> 0 | T (_, _, t) -> size_t t + 1
7777+7878+ let nd_l kp t1 sk t2 = NdL (kp, t1, sk, t2, size_t t1 + size_t t2 + 1)
7979+ let nd_r kp t1 sk t2 = NdR (kp, t1, sk, t2, size_t t1 + size_t t2 + 1)
8080+8181+ let nd (k, _ as kp) t1 sk t2 =
8282+ if K.compare k sk <= 0 then nd_l kp t1 sk t2 else nd_r kp t1 sk t2
8383+8484+8585+ let outweighs s1 s2 = s1 * 100 > s2 * 375
8686+8787+ let (@<=@) (k1, p1) (k2, p2) =
8888+ match P.compare p1 p2 with 0 -> K.compare k1 k2 <= 0 | c -> c < 0
8989+ [@@inline]
9090+9191+ let rot_l kp1 t1 sk1 = function
9292+ NdL (kp2, t2, sk2, t3, _) when kp1 @<=@ kp2 ->
9393+ nd kp1 (nd kp2 t1 sk1 t2) sk2 t3
9494+ | NdL (kp2, t2, sk2, t3, _) | NdR (kp2, t2, sk2, t3, _) ->
9595+ nd kp2 (nd kp1 t1 sk1 t2) sk2 t3
9696+ | Lf -> assert false
9797+9898+ let rot_r kp1 tt sk2 t3 = match tt with
9999+ NdR (kp2, t1, sk1, t2, _) when kp1 @<=@ kp2 ->
100100+ nd kp1 t1 sk1 (nd kp2 t2 sk2 t3)
101101+ | NdL (kp2, t1, sk1, t2, _) | NdR (kp2, t1, sk1, t2, _) ->
102102+ nd kp2 t1 sk1 (nd kp1 t2 sk2 t3)
103103+ | Lf -> assert false
104104+105105+ let rot_ll kp1 t1 sk1 = function
106106+ NdL (kp2, t2, sk2, t3, _) | NdR (kp2, t2, sk2, t3, _) ->
107107+ rot_l kp1 t1 sk1 (rot_r kp2 t2 sk2 t3)
108108+ | Lf -> assert false
109109+110110+ let rot_rr kp1 tt sk2 t3 = match tt with
111111+ NdL (kp2, t1, sk1, t2, _) | NdR (kp2, t1, sk1, t2, _) ->
112112+ rot_r kp1 (rot_l kp2 t1 sk1 t2) sk2 t3
113113+ | Lf -> assert false
114114+115115+ (* Precond: at most one of t1, t2 is at most 1 away from a balanced
116116+ configuration. *)
117117+ let nd_bal kp t1 sk t2 =
118118+ let s1 = size_t t1 and s2 = size_t t2 in
119119+ match (t1, t2) with
120120+ ((NdL (_, t11, _, t12, _) | NdR (_, t11, _, t12, _)), _)
121121+ when s1 > 1 && outweighs s1 s2 ->
122122+ if size_t t11 > size_t t12 then
123123+ rot_r kp t1 sk t2
124124+ else rot_rr kp t1 sk t2
125125+ | (_, (NdL (_, t21, _, t22, _) | NdR (_, t21, _, t22, _)))
126126+ when s2 > 1 && outweighs s2 s1 ->
127127+ if size_t t21 < size_t t22 then
128128+ rot_l kp t1 sk t2
129129+ else rot_ll kp t1 sk t2
130130+ | _ -> nd kp t1 sk t2
131131+132132+ let (><) t1 t2 = match (t1, t2) with
133133+ (N, t) | (t, N) -> t
134134+ | (T (kp1, sk1, t1), T (kp2, sk2, t2)) ->
135135+ if kp1 @<=@ kp2 then
136136+ T (kp1, sk2, nd_bal kp2 t1 sk1 t2)
137137+ else T (kp2, sk2, nd_bal kp1 t1 sk1 t2)
138138+ [@@inline]
139139+140140+ let (>|<) (k1, _ as kp1) (k2, _ as kp2) =
141141+ if kp1 @<=@ kp2 then
142142+ T (kp1, k2, NdR (kp2, Lf, k1, Lf, 1))
143143+ else T (kp2, k2, NdL (kp1, Lf, k1, Lf, 1))
144144+ [@@inline]
145145+146146+ let rec promote sk0 = function
147147+ Lf -> N
148148+ | NdL (kp, t1, sk, t2, _) -> T (kp, sk, t1) >< promote sk0 t2
149149+ | NdR (kp, t1, sk, t2, _) -> promote sk t1 >< T (kp, sk0, t2)
150150+151151+ let min = function N -> None | T (kp, _, _) -> Some kp
152152+ let rest = function N -> None | T (_, sk, t) -> Some (promote sk t)
153153+ let pop = function N -> None | T (kp, sk, t) -> Some (kp, promote sk t)
154154+155155+ let find k0 t =
156156+ let rec go k0 = function
157157+ Lf -> None
158158+ | NdL ((k, p), t1, sk, t2, _)
159159+ | NdR ((k, p), t1, sk, t2, _) ->
160160+ if K.compare k0 k = 0 then Some p else
161161+ if K.compare k0 sk <= 0 then go k0 t1 else go k0 t2 in
162162+ match t with
163163+ N -> None
164164+ | T ((k, p), _, t) -> if K.compare k0 k = 0 then Some p else go k0 t
165165+166166+ let mem k0 t =
167167+ let rec go k0 = function
168168+ Lf -> false
169169+ | NdL ((k, _), t1, sk, t2, _)
170170+ | NdR ((k, _), t1, sk, t2, _) ->
171171+ K.compare k0 k = 0 ||
172172+ if K.compare k0 sk <= 0 then go k0 t1 else go k0 t2 in
173173+ match t with N -> false | T ((k, _), _, t) -> K.compare k0 k = 0 || go k0 t
174174+175175+ let foldr_at_most p0 f t z =
176176+ let rec f1 p0 (_, p as kp) f z t =
177177+ if P.compare p p0 <= 0 then f2 p0 kp f z t else z ()
178178+ and f2 p0 kp0 f z = function
179179+ Lf -> f kp0 z
180180+ | NdL (kp, t1, _, t2, _) -> f1 p0 kp f (fun () -> f2 p0 kp0 f z t2) t1
181181+ | NdR (kp, t1, _, t2, _) -> f2 p0 kp0 f (fun () -> f1 p0 kp f z t2) t1 in
182182+ match t with T (kp0, _, t) -> f1 p0 kp0 f z t | _ -> z ()
183183+184184+ let fold_at_most p0 f z t =
185185+ foldr_at_most p0 (fun (k, p) a -> f k p (a ())) t (fun () -> z)
186186+187187+ let iter_at_most p0 f t =
188188+ foldr_at_most p0 (fun (k, p) i -> f k p; i ()) t ignore
189189+190190+ let to_seq_at_most p0 t () =
191191+ foldr_at_most p0 (fun kp seq -> Seq.Cons (kp, seq)) t Seq.empty
192192+193193+ (* type view = Nv | Sgv of (k * p) | Binv of t * K.t * t *)
194194+195195+ (* let view = function *)
196196+ (* N -> Nv *)
197197+ (* | T (kp, _, Lf) -> Sgv kp *)
198198+ (* | T (kp1, sk1, NdL (kp2, t1, sk2, t2, _)) -> *)
199199+ (* Binv (T (kp2, sk2, t1), sk2, T (kp1, sk1, t2)) *)
200200+ (* | T (kp1, sk1, NdR (kp2, t1, sk2, t2, _)) -> *)
201201+ (* Binv (T (kp1, sk2, t1), sk2, T (kp2, sk1, t2)) *)
202202+203203+ (* let rec add (k0, _ as kp0) t = match view t with *)
204204+ (* | Nv -> sg kp0 *)
205205+ (* | Sgv (k, _) -> *)
206206+ (* let c = K.compare k0 k and t' = sg kp0 in *)
207207+ (* if c < 0 then t' >< t else if c > 0 then t >< t' else t' *)
208208+ (* | Binv (t1, sk, t2) -> *)
209209+ (* if K.compare k0 sk <= 0 then add kp0 t1 >< t2 else t1 >< add kp0 t2 *)
210210+211211+ (* let remove k0 t = *)
212212+ (* let rec go k0 t = match view t with *)
213213+ (* Binv (t1, sk, t2) -> *)
214214+ (* if K.compare k0 sk <= 0 then go k0 t1 >< t2 else t1 >< go k0 t2 *)
215215+ (* | Sgv (k, _) when K.compare k k0 = 0 -> N *)
216216+ (* | Sgv _ | Nv -> raise_notrace Exit in *)
217217+ (* try go k0 t with Exit -> t *)
218218+219219+ (* let adjust k0 f t = *)
220220+ (* let rec go f k0 t = match view t with *)
221221+ (* Binv (t1, sk, t2) -> *)
222222+ (* if K.compare k0 sk <= 0 then go f k0 t1 >|< t2 else t1 >|< go f k0 t2 *)
223223+ (* | Sgv (k, p) when K.compare k k0 = 0 -> sg (k, f p) *)
224224+ (* | Sgv _ | Nv -> raise_notrace Exit in *)
225225+ (* try go f k0 t with Exit -> t *)
226226+227227+ (* let rec filter pf t = match view t with *)
228228+ (* Nv -> N *)
229229+ (* | Sgv (k, p as kp) -> if pf k p then sg kp else N *)
230230+ (* | Binv (t1, _, t2) -> filter pf t1 >< filter pf t2 *)
231231+232232+ let update =
233233+ let rec go k0 f (k1, p1 as kp1) sk1 = function
234234+ Lf ->
235235+ let c = K.compare k0 k1 in
236236+ if c = 0 then
237237+ match f (Some p1) with
238238+ | Some p when p == p1 -> raise_notrace Exit
239239+ | Some p -> sg (k0, p)
240240+ | None -> N
241241+ else ( match f None with
242242+ | Some p when c < 0 -> (k0, p) >|< kp1
243243+ | Some p -> kp1 >|< (k0, p)
244244+ | None -> raise_notrace Exit )
245245+ | NdL (kp2, t1, sk2, t2, _) ->
246246+ if K.compare k0 sk2 <= 0 then
247247+ go k0 f kp2 sk2 t1 >< T (kp1, sk1, t2)
248248+ else T (kp2, sk2, t1) >< go k0 f kp1 sk1 t2
249249+ | NdR (kp2, t1, sk2, t2, _) ->
250250+ if K.compare k0 sk2 <= 0 then
251251+ go k0 f kp1 sk2 t1 >< T (kp2, sk1, t2)
252252+ else T (kp1, sk2, t1) >< go k0 f kp2 sk1 t2 in
253253+ fun k0 f -> function
254254+ | N -> (match f None with Some p -> sg (k0, p) | _ -> N)
255255+ | T (kp, sk, t1) as t -> try go k0 f kp sk t1 with Exit -> t
256256+257257+ let add k p t = update k (fun _ -> Some p) t
258258+ let push k p t = update k (function
259259+ | Some p0 -> Some (if P.compare p p0 < 0 then p else p0)
260260+ | None -> Some p) t
261261+ let remove k t = update k (fun _ -> None) t
262262+ let adjust k f t = update k (function Some p -> Some (f p) | _ -> None) t
263263+264264+ let filter =
265265+ let rec go pf kp1 sk1 = function
266266+ Lf -> if pf (fst kp1) (snd kp1) then sg kp1 else N
267267+ | NdL (kp2, t1, sk2, t2, _) -> go pf kp2 sk2 t1 >< go pf kp1 sk1 t2
268268+ | NdR (kp2, t1, sk2, t2, _) -> go pf kp1 sk2 t1 >< go pf kp2 sk1 t2 in
269269+ fun pf -> function N -> N | T (kp, sk, t) -> go pf kp sk t
270270+271271+ let partition pf t = filter pf t, filter (fun k p -> not (pf k p)) t
272272+273273+ let split_at =
274274+ let rec go k0 pk sk = function
275275+ | Lf -> if K.compare (fst pk) k0 <= 0 then sg pk, empty else empty, sg pk
276276+ | NdL (pk1, t1, sk1, t2, _) ->
277277+ if K.compare k0 sk1 <= 0 then
278278+ let t11, t12 = go k0 pk1 sk1 t1 in t11, t12 >< T (pk, sk, t2)
279279+ else let t21, t22 = go k0 pk sk t2 in T (pk1, sk1, t1) >< t21, t22
280280+ | NdR (pk1, t1, sk1, t2, _) ->
281281+ if K.compare k0 sk1 <= 0 then
282282+ let t11, t12 = go k0 pk sk1 t1 in t11, t12 >< T (pk1, sk, t2)
283283+ else let t21, t22 = go k0 pk1 sk t2 in T (pk, sk1, t1) >< t21, t22 in
284284+ fun k0 -> function N -> N, N | T (pk, sk, t) -> go k0 pk sk t
285285+286286+ let rec (++) =
287287+ let app q1 = function
288288+ | N -> q1
289289+ | T ((k, p), _, Lf) -> push k p q1
290290+ | T ((k1, p1), _,
291291+ (NdL ((k2, p2), Lf, _, Lf, _) |
292292+ NdR ((k2, p2), Lf, _, Lf, _))) -> push k1 p1 (push k2 p2 q1)
293293+ | T (kp, sk, NdL (kp1, t1, sk1, t2, _)) ->
294294+ let q11, q12 = split_at sk1 q1 in
295295+ (q11 ++ T (kp1, sk1, t1)) >< (q12 ++ T (kp, sk, t2))
296296+ | T (kp, sk, NdR (kp1, t1, sk1, t2, _)) ->
297297+ let q11, q12 = split_at sk1 q1 in
298298+ (q11 ++ T (kp, sk1, t1)) >< (q12 ++ T (kp1, sk, t2)) in
299299+ fun q1 q2 -> if size q1 < size q2 then app q2 q1 else app q1 q2
300300+301301+ let of_sorted_list =
302302+ let rec group1 = function
303303+ | [] -> []
304304+ | [x] -> [sg x]
305305+ | [x;y] -> [x >|< y]
306306+ | [x;y;z] -> [(x >|< y) >< sg z]
307307+ | x::y::z::w::xs -> ((x >|< y) >< (z >|< w)) :: group1 xs
308308+ and group2 = function
309309+ | [] | [_] as r -> r
310310+ | [x;y] -> [x >< y]
311311+ | [x;y;z] -> [(x >< y) >< z]
312312+ | x::y::z::w::xs -> ((x >< y) >< (z >< w)) :: group2 xs
313313+ and go = function [] -> N | [t] -> t | ts -> go (group2 ts) in
314314+ fun xs -> go (group1 xs)
315315+316316+ let of_list =
317317+ let rec sieve k0 a = function
318318+ | [] -> a
319319+ | (k, _) as kv :: kvs ->
320320+ if K.compare k0 k = 0 then sieve k0 a kvs else sieve k (kv :: a) kvs in
321321+ let cmp_kv (k1, p1) (k2, p2) =
322322+ match K.compare k2 k1 with 0 -> P.compare p1 p2 | r -> r in
323323+ fun xs -> match List.sort cmp_kv xs with
324324+ | [] -> empty
325325+ | (k, _) as kv :: kvs -> sieve k [kv] kvs |> of_sorted_list
326326+327327+ let of_seq xs = Seq.fold_left (fun xs a -> a::xs) [] xs |> of_list
328328+329329+ let add_seq xs q = Seq.fold_left (fun q (k, p) -> add k p q) q xs
330330+331331+ let iter =
332332+ let rec go (p0, k0 as pk0) f = function
333333+ Lf -> f p0 k0
334334+ | NdL (pk, t1, _, t2, _) -> go pk f t1; go pk0 f t2
335335+ | NdR (pk, t1, _, t2, _) -> go pk0 f t1; go pk f t2 in
336336+ fun f -> function N -> () | T (pk, _, t) -> go pk f t
337337+338338+ let foldr =
339339+ let rec go kp0 f z = function
340340+ Lf -> f kp0 z
341341+ | NdL (kp, t1, _, t2, _) -> go kp f (go kp0 f z t2) t1
342342+ | NdR (kp, t1, _, t2, _) -> go kp0 f (go kp f z t2) t1 in
343343+ fun f z -> function N -> z | T (kp, _, t) -> go kp f z t
344344+345345+ let lfoldr =
346346+ let rec go kp0 f z = function
347347+ Lf -> f kp0 z
348348+ | NdL (kp, t1, _, t2, _) -> go kp f (fun () -> go kp0 f z t2) t1
349349+ | NdR (kp, t1, _, t2, _) -> go kp0 f (fun () -> go kp f z t2) t1 in
350350+ fun f z -> function T (kp, _, t) -> go kp f z t | N -> z ()
351351+352352+ let fold f z t = foldr (fun (k, p) z -> f k p z) z t
353353+ let to_list t = foldr (fun kp xs -> kp :: xs) [] t
354354+ let to_seq t () = lfoldr (fun kp xs -> Seq.Cons (kp, xs)) Seq.empty t
355355+356356+ let to_priority_list =
357357+ let rec (--) xs ys = match xs, ys with
358358+ [], l | l, [] -> l
359359+ | x::xt, y::yt -> if x @<=@ y then x :: (xt -- ys) else y :: (xs -- yt) in
360360+ let rec go = function
361361+ Lf -> []
362362+ | NdL (kp2, t1, _, t2, _) -> (kp2 :: go t1) -- go t2
363363+ | NdR (kp2, t1, _, t2, _) -> go t1 -- (kp2 :: go t2) in
364364+ function N -> [] | T (kp, _, t) -> kp :: go t
365365+366366+ let to_priority_seq t () =
367367+ let open Seq in
368368+ let rec (--) n1 n2 = match n1, n2 with
369369+ Nil, n | n, Nil -> n
370370+ | Cons (x, xt), Cons (y, yt) ->
371371+ if x @<=@ y then
372372+ Cons (x, fun _ -> xt () -- n2)
373373+ else Cons (y, fun _ -> n1 -- yt ()) in
374374+ let rec go = function
375375+ Lf -> Nil
376376+ | NdL (kp2, t1, _, t2, _) -> Cons (kp2, fun _ -> go t1) -- go t2
377377+ | NdR (kp2, t1, _, t2, _) -> go t1 -- Cons (kp2, fun _ -> go t2) in
378378+ match t with N -> Nil | T (kp, _, t) -> Cons (kp, fun _ -> go t)
379379+380380+ let sg k p = sg (k, p)
381381+382382+ let depth t =
383383+ let rec go = function
384384+ Lf -> 0
385385+ | NdL (_, t1, _, t2, _) | NdR (_, t1, _, t2, _) ->
386386+ max (go t1) (go t2) + 1 in
387387+ match t with N -> 0 | T (_, _, t) -> go t + 1
388388+389389+ let pp ?(sep = Format.pp_print_space) pp ppf t =
390390+ let first = ref true in
391391+ let k ppf = iter @@ fun k p ->
392392+ ( match !first with true -> first := false | _ -> sep ppf ());
393393+ pp ppf (k, p) in
394394+ pf ppf "@[%a@]" k t
395395+396396+ let pp_dump ppk ppp ppf =
397397+ let sep ppf () = pf ppf ";@ "
398398+ and ppkp ppf (k, p) = pf ppf "(@[%a,@ %a@])" ppk k ppp p in
399399+ pf ppf "of_sorted_list [%a]" (pp ~sep ppkp)
400400+end
+223
vendor/opam/psq/src/psq.mli
···11+(* Copyright (c) 2016 David Kaloper Meršinjak. All rights reserved.
22+ See LICENSE.md *)
33+44+(** Functional Priority Search Queues
55+66+ [Psq] provides a functional structure that behaves as both a finite map and
77+ a priority queue.
88+99+ {ul
1010+ {- The structure contains a collection of bindings [k -> p], and allows
1111+ efficient {{!S.add}addition}, {{!S.find}lookup} and {{!S.remove}removal}
1212+ of bindings by key.}
1313+ {- It additionally supports {{!S.min}access} to, and {{!S.rest}removal} of
1414+ the binding [k -> p] with the least [p].}}
1515+1616+ The implementation is backed by a weight-balanced semi-heap. Access by key
1717+ is [O(log n)]. Access to the minimal [p] is [O(1)], and its removal is
1818+ [O(log n)].
1919+2020+ {b References}
2121+ {ul
2222+ {- Ralf Hinze.
2323+ {{:https://www.cs.ox.ac.uk/ralf.hinze/publications/ICFP01.pdf} A Simple
2424+ Implementation Technique for Priority Search Queues}. 2001.}}
2525+2626+ {e %%VERSION%% — {{:%%PKG_HOMEPAGE%% }homepage}} *)
2727+2828+(** {1 Psq} *)
2929+3030+(** Signature of priority search queues. *)
3131+module type S = sig
3232+3333+ (** {1 Priority Search Queue} *)
3434+3535+ type t
3636+ (** A search queue. *)
3737+3838+ type k
3939+ (** Keys in {{!t}[t]}. *)
4040+4141+ type p
4242+ (** Priorities in {{!t}[t]}. *)
4343+4444+ val empty : t
4545+ (** [empty] is the search queue that contains no bindings. *)
4646+4747+ val sg : k -> p -> t
4848+ (** [sg k p] is the singleton search queue, containing only the
4949+ binding [k -> p]. *)
5050+5151+ val (++) : t -> t -> t
5252+ (** [t1 ++ t2] contains bindings from [t1] and [t2]. If a key [k] is bound in
5353+ both, the result has the binding with lower priority.
5454+5555+ Hence,
5656+ {ul
5757+ {- [t1 ++ t2 = t2 ++ t1]}
5858+ {- [(t1 ++ t2) ++ t3 = t1 ++ (t2 ++ t3)]}} *)
5959+6060+ val is_empty : t -> bool
6161+ (** [is_empty t] is [true] iff [t] is {{!empty}[empty]}. *)
6262+6363+ val size : t -> int
6464+ (** [size t] is the number of distinct bindings in [t]. *)
6565+6666+ (** {1 Access by [k]} *)
6767+6868+ val mem : k -> t -> bool
6969+ (** [find k t] is [true] iff [k] is bound in [t]. *)
7070+7171+ val find : k -> t -> p option
7272+ (** [find k t] is [Some p] if [t] contains the binding [k -> p], or [None]
7373+ otherwise. *)
7474+7575+ val add : k -> p -> t -> t
7676+ (** [add k p t] is [t] with the binding [k -> p].
7777+7878+ Note that [add] does {e not} commute:
7979+ [add k p2 (add k p1 q) <> add k p1 (add k p2 q)] when [p1 <> p2].
8080+ Compare {!push}. *)
8181+8282+ val push : k -> p -> t -> t
8383+ (** [push k p t] is [t] with [k] bound to the lower of [p] and its previous
8484+ priority in [t], if it exists — when [t] contains [k -> p0], the result
8585+ contains [k -> min p0 p], otherwise it contains [k -> p].
8686+8787+ Note that [push] commutes:
8888+ [push k p1 (push k p2 q) = push k p2 (push k p1 q)]. Compare {!add}. *)
8989+9090+ val remove : k -> t -> t
9191+ (** [remove k t] is [t] without any bindings for [k]. *)
9292+9393+ val adjust : k -> (p -> p) -> t -> t
9494+ (** [adjust k f t] is [t] with the binding [k -> p] replaced by [k -> f p].
9595+ When [k] is not bound in [t], the result is [t]. *)
9696+9797+ val update : k -> (p option -> p option) -> t -> t
9898+ (** [update k f t] is [t] with the binding for [k] given by [f].
9999+100100+ When [t] contains a binding [k -> p], the new binding is given by
101101+ [f (Some p)]; otherwise, by [f None].
102102+103103+ When the result of applying [f] is [Some p'], the binding [k -> p'] is
104104+ added to [t]; otherwise, the binding for [k] is removed from [t]. *)
105105+106106+ val split_at : k -> t -> t * t
107107+ (** [split_at k t] splits [t] into [(t0, t1)], such that for all keys [k0] in
108108+ [t0], [k0 <= k], for all keys [k1] in [t1], [k1 > k], and [t = t0 ++ t1]. *)
109109+110110+ (** {1 Access by min [p]} *)
111111+112112+ val min : t -> (k * p) option
113113+ (** [min t] is the binding [Some (k, p)] where [p] is minimal in [t], or
114114+ [None] if [t] is {{!empty}[empty]}.
115115+116116+ When several keys share the minimal priority, [min t] is the binding with
117117+ the smallest key. *)
118118+119119+ val rest : t -> t option
120120+ (** [rest t] is [t] without the binding [min t], or [None]. *)
121121+122122+ val pop : t -> ((k * p) * t) option
123123+ (** [pop t] is [(min t, rest t)], or [None]. *)
124124+125125+ val fold_at_most : p -> (k -> p -> 'a -> 'a) -> 'a -> t -> 'a
126126+ (** [fold_at_most p0 f z q] folds [f] over bindings [k -> p] where [p] is not
127127+ larger than [p0], in key-ascending order. *)
128128+129129+ val iter_at_most : p -> (k -> p -> unit) -> t -> unit
130130+ (** [iter_at_most p0 f q] applies [f] to the bindings [k -> p] where [p] is
131131+ not larger than [p0], in key-ascending order. *)
132132+133133+ val to_seq_at_most : p -> t -> (k * p) Seq.t
134134+ (** [iter_at_most p0 f q] is the sequence of bindings [k -> p] where [p] not
135135+ larger than [p0], in key-ascending order. *)
136136+137137+ (** {1 Aggregate construction} *)
138138+139139+ val of_list : (k * p) list -> t
140140+ (** [of_list kps] is [t] with bindings [kps].
141141+142142+ When [pks] contains multiple priorities for a given [k], the lowest one
143143+ wins. *)
144144+145145+ val of_sorted_list : (k * p) list -> t
146146+ (** [of_sorted_list kps] is [t] with bindings [kps].
147147+ [kps] must contain the bindings in key-ascending order without
148148+ repetitions. When this is not the case, the result is undefined.
149149+150150+ {b Note} When applicable, this operation is faster than
151151+ {{!of_list}[of_list]}. *)
152152+153153+ val of_seq : (k * p) Seq.t -> t
154154+ (** [of_seq kps] is [of_list (List.of_seq kps)]. *)
155155+156156+ val add_seq : (k * p) Seq.t -> t -> t
157157+ (** [of_seq kps t] is [t ++ of_seq kps]. *)
158158+159159+ (** {1 Whole-structure access} *)
160160+161161+ val to_list : t -> (k * p) list
162162+ (** [to_list t] are all the bindings in [t] in key-ascending order. *)
163163+164164+ val to_seq : t -> (k * p) Seq.t
165165+ (** [to_seq t] iterates over bindings in [t] in key-ascending order. *)
166166+167167+ val fold : (k -> p -> 'a -> 'a) -> 'a -> t -> 'a
168168+ (** [fold f z t] is [f k0 p0 (f k1 p1 ... (f kn pn z))], where
169169+ [k0, k1, ..., kn] are in ascending order. *)
170170+171171+ val iter : (k -> p -> unit) -> t -> unit
172172+ (** [iter f t] applies [f] to all bindings in [t] in key-ascending order. *)
173173+174174+ val to_priority_list : t -> (k * p) list
175175+ (** [to_priority_list t] are the bindings in [t] in priority-ascending order.
176176+177177+ {b Note} Priority-ordered traversal is slower than key-ordered traversal. *)
178178+179179+ val to_priority_seq : t -> (k * p) Seq.t
180180+ (** [to_priority_seq t] is the sequence version of [to_priority_list].
181181+182182+ {b Note} For traversing the whole [t], [to_priority_list] is more
183183+ efficient. *)
184184+185185+ val filter : (k -> p -> bool) -> t -> t
186186+ (** [filter p t] is the search queue with exactly the bindings in [t] which
187187+ satisfy the predicate [p]. *)
188188+189189+ val partition : (k -> p -> bool) -> t -> t * t
190190+ (** [partition p t] is [(filter p t, filter np t)] where [np] is the negation
191191+ of [p]. *)
192192+193193+ (** {1 Pretty-printing} *)
194194+195195+ open Format
196196+197197+ val pp : ?sep:(formatter -> unit -> unit) -> (formatter -> k * p -> unit) ->
198198+ formatter -> t -> unit
199199+ (** [pp ?sep pp_kp ppf t] pretty-prints [t] to [ppf], using [pp_kp] to print
200200+ the bindings and [~sep] to separate them.
201201+202202+ [~sep] defaults to {!Format.print_space}. *)
203203+204204+ val pp_dump : (formatter -> k -> unit) -> (formatter -> p -> unit) ->
205205+ formatter -> t -> unit
206206+ (** [pp_dump pp_k pp_f ppf t] is a handier pretty-printer for development. *)
207207+208208+ (**/**)
209209+ (* Debug. *)
210210+ val depth : t -> int
211211+ (**/**)
212212+end
213213+214214+(** Signature of ordered types. *)
215215+module type Ordered = sig
216216+ type t
217217+ val compare : t -> t -> int
218218+ (** [compare] is a total order on {{!t}[t]}. *)
219219+end
220220+221221+(** [Make(K)(P)] is the {{!S}priority search queue} with bindings [K.t -> P.t]. *)
222222+module Make (K: Ordered) (P: Ordered):
223223+ S with type k = K.t and type p = P.t
+86
vendor/opam/psq/test/bench.ml
···11+(* Copyright (c) 2016 David Kaloper Meršinjak. All rights reserved.
22+ See LICENSE.md *)
33+44+let shuffle arr =
55+ let n = Array.length arr in
66+ for i = 0 to n - 2 do
77+ let j = Random.int (n - i) + i in
88+ let t = arr.(i) in
99+ arr.(i) <- arr.(j); arr.(j) <- t
1010+ done
1111+1212+let permutation n =
1313+ let arr = Array.init n (fun x -> x) in
1414+ shuffle arr;
1515+ Array.to_list arr
1616+1717+let r_bindings n = permutation n |> List.rev_map (fun x -> x, x)
1818+1919+module type S = sig
2020+ type t
2121+ val add : int -> int -> t -> t
2222+ val find : int -> t -> int option
2323+ val remove : int -> t -> t
2424+ val of_list : (int * int) list -> t
2525+end
2626+module I = struct type t = int let compare (a: int) b = compare a b end
2727+module Q = Psq.Make (I)(I)
2828+let q = (module Q: S)
2929+let m = (module struct
3030+ module M = Map.Make (I)
3131+ type t = int M.t
3232+ let find, add, remove = M.(find_opt, add, remove)
3333+ let of_list xs = List.fold_left (fun m (k, v) -> M.add k v m) M.empty xs
3434+end: S)
3535+3636+open Unmark
3737+3838+let runs ((module M: S)) size =
3939+ let xs = r_bindings size in
4040+ let q = M.of_list xs
4141+ and q' = List.rev_map (fun (k, p) -> (k * 2, p * 2)) xs |> M.of_list in
4242+ group (Fmt.strf "x%d" size) [
4343+ bench "find" (fun () -> M.find (Random.int size) q)
4444+ ; bench "add" (fun () -> let k = Random.int size + 1 in M.add k k q')
4545+ ; bench "remove" (fun () -> M.remove (Random.int size) q)
4646+ ]
4747+4848+let runs1 size =
4949+ let xs = r_bindings size in
5050+ let q = Q.of_list xs in
5151+ group (Fmt.strf "x%d" size) [
5252+ group "of_" [
5353+ bench "of_sorted_list" (fun () -> Q.of_sorted_list xs)
5454+ ; bench "of_list" (fun () -> Q.of_list xs)
5555+ ; bench "of_seq" (fun () -> Q.of_seq (List.to_seq xs))
5656+ ; bench "add_seq" (fun () -> Q.(add_seq (List.to_seq xs) empty))
5757+ ];
5858+ group "to_" [
5959+ bench "to_p_list" (fun () -> Q.to_priority_list q)
6060+ ; bench "to_seq" (fun () -> Q.to_seq q |> Seq.iter ignore)
6161+ ; bench "to_list" (fun () -> Q.to_list q)
6262+ ]
6363+ ]
6464+6565+let runs2 size =
6666+ let r_key () = Random.int (size * 5) in
6767+ let gen n = List.init n Random.(fun _ -> r_key (), int n) |> Q.of_list in
6868+ let xs, ys, zs = gen size, gen size, gen 10 in
6969+ group (Fmt.strf "x%d" size) [
7070+ bench "split" (fun () -> Q.split_at (r_key ()) xs);
7171+ bench "filter" (fun () ->
7272+ let x = r_key () in Q.filter (fun k _ -> k <= x) xs);
7373+ bench "++" (fun () -> Q.(xs ++ ys));
7474+ bench "++ k" (fun () -> Q.(xs ++ zs));
7575+ ]
7676+7777+7878+let arg = Cmdliner.Arg.(
7979+ value @@ opt (list int) [10; 100; 1000] @@ info ["sizes"])
8080+let _ = Unmark_cli.main_ext "psq" ~arg @@ fun ns -> [
8181+ bench "Random.int" (fun () -> Random.int 1000)
8282+ ; group "map" (List.map (runs m) ns)
8383+ ; group "psq" (List.map (runs q) ns)
8484+ ; group "psq1" (List.map runs1 ns)
8585+ ; group "psq2" (List.map runs2 ns)
8686+]
···11+(* Copyright (c) 2016 David Kaloper Meršinjak. All rights reserved.
22+ See LICENSE.md *)
33+44+let rec mem ?(cmp=compare) a = function
55+ | [] -> false | x::xs -> cmp a x = 0 || mem ~cmp a xs
66+77+let rec add ?(cmp=compare) a = function
88+ | [] -> [a]
99+ | x::xs ->
1010+ match cmp a x with -1 -> a::x::xs | 1 -> x::add ~cmp a xs | _ -> x::xs
1111+1212+let astar (type a) ?(cmp=compare) start graph h sat =
1313+ let module K = struct type t = a let compare = cmp end in
1414+ let module P = struct
1515+ type t = int * a list
1616+ let compare (a: t) b = compare (fst a) (fst b)
1717+ end in
1818+ let module Q = Psq.Make(K)(P) in
1919+ let rec go q = match Q.pop q with
2020+ | Some ((a, (dist, path)), q) ->
2121+ if sat a then Some (dist, a, List.rev path) else
2222+ let f q (w, b) =
2323+ let d' = w + h b in
2424+ if mem ~cmp b path then q else
2525+ match Q.find b q with
2626+ | Some (d, _) when d <= d' -> q
2727+ | _ -> Q.add b (d', a::path) q in
2828+ go @@ List.fold_left f q @@ graph a
2929+ | None -> None in
3030+ go Q.(sg start (0, []))
3131+3232+let labyrinth p0 (pn_m, pn_n as pn) grid =
3333+ let (m0, n0) = Array.(length grid, length grid.(0)) in
3434+ let h (m, n) = abs (pn_m - m) + abs (pn_n - n)
3535+ and sat mn = mn = pn
3636+ and graph (m, n) =
3737+ (if m > 0 && grid.(m-1).(n) = `o then [1, (m-1, n)] else []) @
3838+ (if m < m0-1 && grid.(m+1).(n) = `o then [1, (m+1, n)] else []) @
3939+ (if n > 0 && grid.(m).(n-1) = `o then [1, (m, n-1)] else []) @
4040+ (if n < n0-1 && grid.(m).(n+1) = `o then [1, (m, n+1)] else []) in
4141+ match astar ~cmp:compare p0 graph h sat with
4242+ | None -> Fmt.pr "not found\n%!"
4343+ | Some (dist, (m, n), path) ->
4444+ Fmt.(pr "@[(%d, %d), dist: %d@;steps: %a@]\n%!"
4545+ m n dist (Dump.(list (pair int int))) path)
4646+4747+let l : [`X|`o] array array =
4848+[|[| `o; `X; `o; `o; `o; `o; |];
4949+ [| `o; `X; `X; `X; `o; `o; |];
5050+ [| `o; `o; `o; `o; `X; `o; |];
5151+ [| `o; `X; `X; `X; `o; `o; |];
5252+ [| `o; `X; `o; `o; `o; `o; |];
5353+ [| `o; `o; `o; `X; `X; `o; |]|]
5454+5555+let () = labyrinth (0, 0) (5, 5) l
+201
vendor/opam/psq/test/test.ml
···11+(* Copyright (c) 2016 David Kaloper Meršinjak. All rights reserved.
22+ See LICENSE.md *)
33+44+let id x = x
55+let (%) f g x = f (g x)
66+77+module I = struct type t = int let compare (a: int) b = compare a b end
88+module Q = Psq.Make (I) (I)
99+1010+let list_of_iter_2 i =
1111+ let xs = ref [] in i (fun a b -> xs := (a, b) :: !xs); List.rev !xs
1212+let rec unfold f s = match f s with Some (x, s) -> x :: unfold f s | _ -> []
1313+1414+let cmpi (a: int) b = compare a b
1515+let (%%) f g a b = f (g a) (g b)
1616+let (=>) cmp1 cmp2 a b = match cmp1 a b with 0 -> cmp2 a b | r -> r
1717+let k_order xs = List.sort (cmpi %% fst) xs
1818+let pk_order xs = List.sort (cmpi %% snd => cmpi %% fst) xs
1919+let k_order_uniq xs =
2020+ let cmp_kp = cmpi %% fst => cmpi %% snd and cmp_k = cmpi %% fst in
2121+ match List.sort_uniq cmp_kp xs with
2222+ | [] -> []
2323+ | kp0::kps ->
2424+ let f kp xs kp0 = if cmp_k kp kp0 = 0 then xs kp0 else kp :: xs kp in
2525+ kp0 :: List.fold_right f kps (fun _ -> []) kp0
2626+2727+let is_balanced q =
2828+ let (n, d) = Q.(size q, depth q) in
2929+ n <= 1 || float d < log (float n) *. log 10. *. 3.75
3030+3131+let (!) q = `Sem (Q.to_list q)
3232+let sem xs = `Sem (k_order_uniq xs)
3333+3434+let g_size = QCheck.Gen.(small_nat >|= fun x -> x mod 1_000)
3535+let bindings = QCheck.(
3636+ make Gen.(list_size g_size (pair small_nat small_nat))
3737+ ~print:Fmt.(to_to_string Dump.(pair int int |> list))
3838+ ~shrink:Shrink.list)
3939+let psq = QCheck.(
4040+ map Q.of_list bindings ~rev:Q.to_list |>
4141+ set_print Fmt.(to_to_string (Q.pp_dump int int)))
4242+let kv = QCheck.small_nat
4343+let psq_w arb = QCheck.pair psq arb
4444+let psq_w_any_key = psq_w kv
4545+4646+let test name gen p =
4747+ QCheck.Test.make ~count:200 ~name gen p |> QCheck_alcotest.to_alcotest
4848+4949+let () = Alcotest.run "psq" [
5050+5151+ "of_list", [
5252+ test "sem" bindings (fun xs -> !(Q.of_list xs) = sem xs);
5353+ test "of_sorted_list sem" bindings
5454+ (fun xs -> !(Q.of_sorted_list (k_order_uniq xs)) = sem xs);
5555+ test "bal" bindings (fun xs -> is_balanced (Q.of_list xs));
5656+ ];
5757+5858+ "to_list", [
5959+ test "order" psq (fun q -> Q.to_list q = k_order (Q.to_list q));
6060+ ];
6161+6262+ "to_priority_list", [
6363+ test "sem" psq (fun q -> Q.to_priority_list q = pk_order (Q.to_list q))
6464+ ];
6565+6666+ "size", [
6767+ test "sem" psq (fun q -> Q.size q = List.length (Q.to_list q));
6868+ ];
6969+7070+ "sg", [
7171+ test "sem" kv (fun x -> !Q.(sg x x) = sem [x, x]);
7272+ ];
7373+7474+ "(++)", [
7575+ test "sem" QCheck.(pair bindings bindings)
7676+ (fun (xs1, xs2) -> !Q.(of_list xs1 ++ of_list xs2) = sem (xs1 @ xs2));
7777+ test "comm" QCheck.(pair psq psq)
7878+ (fun (q1, q2) -> !Q.(q1 ++ q2) = !Q.(q2 ++ q1));
7979+ test "assoc" QCheck.(pair psq psq |> pair psq)
8080+ (fun (q1, (q2, q3)) -> !Q.((q1 ++ q2) ++ q3) = !Q.(q1 ++ (q2 ++ q3)));
8181+ ];
8282+8383+ "split_at", [
8484+ test "sem" psq_w_any_key (fun (q, k) ->
8585+ let q1, q2 = Q.split_at k q
8686+ and xs1, xs2 = List.partition (fun (k1, _) -> k1 <= k) (Q.to_list q) in
8787+ !q1 = sem xs1 && !q2 = sem xs2);
8888+ test "inv" psq_w_any_key (fun (q, k) ->
8989+ let q1, q2 = Q.split_at k q in !q = !Q.(q1 ++ q2));
9090+ ];
9191+9292+ "membership", [
9393+ test "find sem" psq_w_any_key
9494+ (fun (q, x) -> Q.find x q = List.assoc_opt x (Q.to_list q));
9595+ test "mem ==> find" psq_w_any_key
9696+ (fun (q, k) -> QCheck.assume Q.(mem k q); Q.find k q <> None);
9797+ test "find ==> mem" psq_w_any_key
9898+ (fun (q, k) -> QCheck.assume (Q.find k q <> None); Q.mem k q);
9999+ ];
100100+101101+ "update", [
102102+ test "sem" (psq_w QCheck.(pair kv (option kv)))
103103+ (fun (q, (x, yy)) ->
104104+ let kp = match yy with Some y -> [x, y] | _ -> [] in
105105+ !(Q.update x (fun _ -> yy) q) =
106106+ sem (kp @ List.remove_assoc x (Q.to_list q)));
107107+ test "bal" (psq_w QCheck.(pair kv (option kv)))
108108+ (fun (q, (x, yy)) -> is_balanced (Q.update x (fun _ -> yy) q));
109109+ test "phys" psq_w_any_key (fun (q, x) -> Q.update x id q == q);
110110+ ];
111111+112112+ "add", [
113113+ test "sem" psq_w_any_key
114114+ (fun (q, x) ->
115115+ !(Q.add x x q) = sem ((x, x) :: List.remove_assoc x (Q.to_list q)));
116116+ test "bal" psq_w_any_key (fun (q, k) -> is_balanced (Q.add k k q));
117117+ ];
118118+119119+ "push", [
120120+ test "sem" psq_w_any_key
121121+ (fun (q, x) ->
122122+ let p = match List.assoc_opt x (Q.to_list q) with
123123+ | Some p0 -> min x p0
124124+ | None -> x in
125125+ !(Q.push x x q) = sem ((x, p) :: List.remove_assoc x (Q.to_list q)));
126126+ test "mono" psq_w_any_key
127127+ (fun (q, x) ->
128128+ QCheck.assume (Q.mem x q);
129129+ Q.find x (Q.push x x q) <= Q.find x q);
130130+ test "comm" (psq_w (QCheck.pair kv kv))
131131+ (fun (q, (x, y)) ->
132132+ !Q.(q |> push x x |> push x y) = !Q.(q |> push x y |> push x x));
133133+ test "= of_list" bindings
134134+ (fun xs ->
135135+ !(Q.of_list xs) =
136136+ !(List.fold_left (fun q (k, p) -> Q.push k p q) Q.empty xs));
137137+ ];
138138+139139+ "remove", [
140140+ test "sem" psq_w_any_key
141141+ (fun (q, k) ->
142142+ !(Q.remove k q) = sem (List.remove_assoc k (Q.to_list q)));
143143+ test "phys" psq_w_any_key
144144+ (fun (q, k) -> QCheck.assume (not (Q.mem k q)); Q.remove k q == q);
145145+ test "bal" psq_w_any_key (fun (q, k) -> Q.(remove k q |> is_balanced));
146146+ ];
147147+148148+ "adjust", [
149149+ test "sem" psq_w_any_key
150150+ (fun (q, x) ->
151151+ !(Q.adjust x succ q) =
152152+ sem (Q.to_list q |>
153153+ List.map (fun (k, p) -> (k, if k = x then succ p else p))));
154154+ ];
155155+156156+ "pop", [
157157+ test "sem1" psq (fun q -> unfold Q.pop q = pk_order (Q.to_list q));
158158+ test "sem2" psq (fun q -> unfold Q.pop q = Q.to_priority_list q);
159159+ test "min, rest" psq
160160+ (fun q ->
161161+ QCheck.assume (not (Q.is_empty q));
162162+ match Q.(pop q, min q, rest q) with
163163+ Some (kp1, q1), Some kp2, Some q2 -> kp1 = kp2 && !q1 = !q2
164164+ | _ -> false);
165165+ ];
166166+167167+ "at_most", [
168168+ test "sem" psq_w_any_key
169169+ (fun (q, x) ->
170170+ List.of_seq (Q.to_seq_at_most x q) =
171171+ List.filter (fun kp -> snd kp <= x) (Q.to_list q));
172172+ test "seq = fold" psq_w_any_key
173173+ (fun (q, x) ->
174174+ List.of_seq (Q.to_seq_at_most x q) =
175175+ Q.fold_at_most x (fun k p xs -> (k, p)::xs) [] q);
176176+ test "seq = iter" psq_w_any_key
177177+ (fun (q, x) ->
178178+ List.of_seq (Q.to_seq_at_most x q) =
179179+ list_of_iter_2 (fun f -> Q.iter_at_most x f q));
180180+ ];
181181+182182+ "to_stuff", [
183183+ test "to_list = to_seq" psq
184184+ (fun q -> Q.to_list q = (Q.to_seq q |> List.of_seq));
185185+ test "to_list = fold" psq
186186+ (fun q -> Q.to_list q = Q.fold (fun k p xs -> (k, p) :: xs) [] q);
187187+ test "to_list = iter" psq
188188+ (fun q -> Q.to_list q = list_of_iter_2 (fun f -> Q.iter f q));
189189+ test "to_priority_seq" psq
190190+ (fun q -> Q.to_priority_list q = List.of_seq (Q.to_priority_seq q));
191191+ ];
192192+193193+ "filter", [
194194+ test "sem" psq_w_any_key
195195+ (fun (q, k0) ->
196196+ !(Q.filter (fun k _ -> k <= k0) q) =
197197+ sem (List.filter (fun (k, _) -> k <= k0) (Q.to_list q)));
198198+ test "bal" psq_w_any_key
199199+ (fun (q, k0) -> is_balanced (Q.filter (fun k _ -> k <= k0) q));
200200+ ];
201201+]