|
|
|
@ -7,112 +7,134 @@
|
|
|
|
|
|
|
|
|
|
(** Qset - Set with (signed) rational multiplicity for each element *)
|
|
|
|
|
|
|
|
|
|
open Base
|
|
|
|
|
open Import0
|
|
|
|
|
|
|
|
|
|
type ('elt, 'cmp) t = ('elt, Q.t, 'cmp) Map.t
|
|
|
|
|
|
|
|
|
|
module M (Elt : sig
|
|
|
|
|
module type S = sig
|
|
|
|
|
type elt
|
|
|
|
|
type t
|
|
|
|
|
type comparator_witness
|
|
|
|
|
end) =
|
|
|
|
|
struct
|
|
|
|
|
type nonrec t = (Elt.t, Elt.comparator_witness) t
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module type Sexp_of_m = sig
|
|
|
|
|
type t [@@deriving sexp_of]
|
|
|
|
|
end
|
|
|
|
|
val compare : t -> t -> int
|
|
|
|
|
val equal : t -> t -> bool
|
|
|
|
|
val hash_fold_t : elt Hash.folder -> t Hash.folder
|
|
|
|
|
val sexp_of_t : t -> Sexp.t
|
|
|
|
|
val t_of_sexp : (Sexp.t -> elt) -> Sexp.t -> t
|
|
|
|
|
val pp : (unit, unit) fmt -> (elt * Q.t) pp -> t pp
|
|
|
|
|
|
|
|
|
|
module type M_of_sexp = sig
|
|
|
|
|
type t [@@deriving of_sexp]
|
|
|
|
|
val empty : t
|
|
|
|
|
(** The empty multiset over the provided order. *)
|
|
|
|
|
|
|
|
|
|
include Comparator.S with type t := t
|
|
|
|
|
end
|
|
|
|
|
val add : t -> elt -> Q.t -> t
|
|
|
|
|
(** Add to multiplicity of single element. [O(log n)] *)
|
|
|
|
|
|
|
|
|
|
val remove : t -> elt -> t
|
|
|
|
|
(** Set the multiplicity of an element to zero. [O(log n)] *)
|
|
|
|
|
|
|
|
|
|
val union : t -> t -> t
|
|
|
|
|
(** Sum multiplicities pointwise. [O(n + m)] *)
|
|
|
|
|
|
|
|
|
|
val length : t -> int
|
|
|
|
|
(** Number of elements with non-zero multiplicity. [O(1)]. *)
|
|
|
|
|
|
|
|
|
|
val count : t -> elt -> Q.t
|
|
|
|
|
(** Multiplicity of an element. [O(log n)]. *)
|
|
|
|
|
|
|
|
|
|
val map : t -> f:(elt -> Q.t -> elt * Q.t) -> t
|
|
|
|
|
(** Map over the elements in ascending order. Preserves physical equality
|
|
|
|
|
if [f] does. *)
|
|
|
|
|
|
|
|
|
|
val map_counts : t -> f:(elt -> Q.t -> Q.t) -> t
|
|
|
|
|
(** Map over the multiplicities of the elements in ascending order. *)
|
|
|
|
|
|
|
|
|
|
module type Compare_m = sig end
|
|
|
|
|
module type Hash_fold_m = Hasher.S
|
|
|
|
|
val fold : t -> f:(elt -> Q.t -> 's -> 's) -> init:'s -> 's
|
|
|
|
|
(** Fold over the elements in ascending order. *)
|
|
|
|
|
|
|
|
|
|
let sexp_of_q q = Sexp.Atom (Q.to_string q)
|
|
|
|
|
let q_of_sexp = function Sexp.Atom s -> Q.of_string s | _ -> assert false
|
|
|
|
|
let hash_fold_q state q = Hash.fold_int state (Hashtbl.hash q)
|
|
|
|
|
val iter : t -> f:(elt -> Q.t -> unit) -> unit
|
|
|
|
|
(** Iterate over the elements in ascending order. *)
|
|
|
|
|
|
|
|
|
|
let sexp_of_m__t (type elt) (module Elt : Sexp_of_m with type t = elt) t =
|
|
|
|
|
Map.sexp_of_m__t (module Elt) sexp_of_q t
|
|
|
|
|
val exists : t -> f:(elt -> Q.t -> bool) -> bool
|
|
|
|
|
(** Search for an element satisfying a predicate. *)
|
|
|
|
|
|
|
|
|
|
let m__t_of_sexp (type elt cmp)
|
|
|
|
|
(module Elt : M_of_sexp
|
|
|
|
|
with type t = elt
|
|
|
|
|
and type comparator_witness = cmp) sexp =
|
|
|
|
|
Map.m__t_of_sexp (module Elt) q_of_sexp sexp
|
|
|
|
|
val min_elt : t -> (elt * Q.t) option
|
|
|
|
|
(** Minimum element. *)
|
|
|
|
|
|
|
|
|
|
let compare_m__t (module Elt : Compare_m) = Map.compare_direct Q.compare
|
|
|
|
|
let equal_m__t (module Elt : Compare_m) = Map.equal Q.equal
|
|
|
|
|
val min_elt_exn : t -> elt * Q.t
|
|
|
|
|
(** Minimum element. *)
|
|
|
|
|
|
|
|
|
|
let hash_fold_m__t (type elt) (module Elt : Hash_fold_m with type t = elt)
|
|
|
|
|
state =
|
|
|
|
|
Map.hash_fold_m__t (module Elt) hash_fold_q state
|
|
|
|
|
val to_list : t -> (elt * Q.t) list
|
|
|
|
|
(** Convert to a list of elements in ascending order. *)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module Make (Elt : OrderedType) = struct
|
|
|
|
|
module M = Stdlib.Map.Make (Elt)
|
|
|
|
|
|
|
|
|
|
type elt = Elt.t
|
|
|
|
|
type t = Q.t M.t
|
|
|
|
|
|
|
|
|
|
let hash_m__t (type elt) (module Elt : Hash_fold_m with type t = elt) =
|
|
|
|
|
Hash.of_fold (hash_fold_m__t (module Elt))
|
|
|
|
|
let compare = M.compare Q.compare
|
|
|
|
|
let equal = M.equal Q.equal
|
|
|
|
|
|
|
|
|
|
type ('elt, 'cmp) comparator =
|
|
|
|
|
(module Comparator.S with type t = 'elt and type comparator_witness = 'cmp)
|
|
|
|
|
let hash_fold_t hash_fold_elt s m =
|
|
|
|
|
let hash_fold_q s q = Hash.fold_int s (Hashtbl.hash q) in
|
|
|
|
|
M.fold
|
|
|
|
|
(fun key data state -> hash_fold_q (hash_fold_elt state key) data)
|
|
|
|
|
m
|
|
|
|
|
(Hash.fold_int s (M.cardinal m))
|
|
|
|
|
|
|
|
|
|
let empty cmp = Map.empty cmp
|
|
|
|
|
let sexp_of_t s =
|
|
|
|
|
let sexp_of_q q = Sexp.Atom (Q.to_string q) in
|
|
|
|
|
List.sexp_of_t
|
|
|
|
|
(Sexplib.Conv.sexp_of_pair Elt.sexp_of_t sexp_of_q)
|
|
|
|
|
(M.bindings s)
|
|
|
|
|
|
|
|
|
|
let t_of_sexp elt_of_sexp sexp =
|
|
|
|
|
let q_of_sexp = function
|
|
|
|
|
| Sexp.Atom s -> Q.of_string s
|
|
|
|
|
| _ -> assert false
|
|
|
|
|
in
|
|
|
|
|
List.fold_left
|
|
|
|
|
~f:(fun m (k, v) -> M.add k v m)
|
|
|
|
|
~init:M.empty
|
|
|
|
|
(List.t_of_sexp
|
|
|
|
|
(Sexplib.Conv.pair_of_sexp elt_of_sexp q_of_sexp)
|
|
|
|
|
sexp)
|
|
|
|
|
|
|
|
|
|
let pp sep pp_elt fs s = List.pp sep pp_elt fs (M.bindings s)
|
|
|
|
|
let empty = M.empty
|
|
|
|
|
let if_nz q = if Q.equal Q.zero q then None else Some q
|
|
|
|
|
|
|
|
|
|
let add m x i =
|
|
|
|
|
Map.change m x ~f:(function Some j -> if_nz Q.(i + j) | None -> if_nz i)
|
|
|
|
|
M.update x (function Some j -> if_nz Q.(i + j) | None -> if_nz i) m
|
|
|
|
|
|
|
|
|
|
let remove m x = Map.remove m x
|
|
|
|
|
let remove m x = M.remove x m
|
|
|
|
|
|
|
|
|
|
let union m n =
|
|
|
|
|
Map.merge m n ~f:(fun ~key:_ -> function
|
|
|
|
|
| `Both (i, j) -> if_nz Q.(i + j) | `Left i | `Right i -> Some i )
|
|
|
|
|
|
|
|
|
|
let length m = Map.length m
|
|
|
|
|
let count m x = match Map.find m x with Some q -> q | None -> Q.zero
|
|
|
|
|
|
|
|
|
|
let count_and_remove m x =
|
|
|
|
|
let found = ref Q.zero in
|
|
|
|
|
let m =
|
|
|
|
|
Map.change m x ~f:(function
|
|
|
|
|
| None -> None
|
|
|
|
|
| Some i ->
|
|
|
|
|
found := i ;
|
|
|
|
|
None )
|
|
|
|
|
in
|
|
|
|
|
if Q.equal !found Q.zero then None else Some (!found, m)
|
|
|
|
|
|
|
|
|
|
let min_elt = Map.min_elt
|
|
|
|
|
let min_elt_exn = Map.min_elt_exn
|
|
|
|
|
let fold m ~f ~init = Map.fold m ~f:(fun ~key ~data s -> f key data s) ~init
|
|
|
|
|
M.merge
|
|
|
|
|
(fun _ m_q n_q ->
|
|
|
|
|
match (m_q, n_q) with
|
|
|
|
|
| Some i, Some j -> if_nz Q.(i + j)
|
|
|
|
|
| Some i, None | None, Some i -> Some i
|
|
|
|
|
| None, None -> None )
|
|
|
|
|
m n
|
|
|
|
|
|
|
|
|
|
let length m = M.cardinal m
|
|
|
|
|
let count m x = try M.find x m with Not_found -> Q.zero
|
|
|
|
|
let fold m ~f ~init = M.fold (fun key data s -> f key data s) m init
|
|
|
|
|
|
|
|
|
|
let map m ~f =
|
|
|
|
|
let m' = Map.empty (Map.comparator_s m) in
|
|
|
|
|
let m' = M.empty in
|
|
|
|
|
let m, m' =
|
|
|
|
|
fold m ~init:(m, m') ~f:(fun x i (m, m') ->
|
|
|
|
|
let x', i' = f x i in
|
|
|
|
|
if phys_equal x' x then
|
|
|
|
|
if Q.equal i' i then (m, m') else (Map.set m ~key:x ~data:i', m')
|
|
|
|
|
else (Map.remove m x, add m' x' i') )
|
|
|
|
|
if x' == x then
|
|
|
|
|
if Q.equal i' i then (m, m') else (M.add x i' m, m')
|
|
|
|
|
else (M.remove x m, add m' x' i') )
|
|
|
|
|
in
|
|
|
|
|
fold m' ~init:m ~f:(fun x i m -> add m x i)
|
|
|
|
|
|
|
|
|
|
let fold_map m ~f ~init:s =
|
|
|
|
|
let m' = Map.empty (Map.comparator_s m) in
|
|
|
|
|
let m, m', s =
|
|
|
|
|
fold m ~init:(m, m', s) ~f:(fun x i (m, m', s) ->
|
|
|
|
|
let x', i', s = f x i s in
|
|
|
|
|
if phys_equal x' x then
|
|
|
|
|
if Q.equal i' i then (m, m', s)
|
|
|
|
|
else (Map.set m ~key:x ~data:i', m', s)
|
|
|
|
|
else (Map.remove m x, add m' x' i', s) )
|
|
|
|
|
in
|
|
|
|
|
(fold m' ~init:m ~f:(fun x i m -> add m x i), s)
|
|
|
|
|
|
|
|
|
|
let for_all m ~f = Map.for_alli m ~f:(fun ~key ~data -> f key data)
|
|
|
|
|
let map_counts m ~f = Map.mapi m ~f:(fun ~key ~data -> f key data)
|
|
|
|
|
let iter m ~f = Map.iteri m ~f:(fun ~key ~data -> f key data)
|
|
|
|
|
let exists m ~f = Map.existsi m ~f:(fun ~key ~data -> f key data)
|
|
|
|
|
let to_list m = Map.to_alist m
|
|
|
|
|
let map_counts m ~f = M.mapi (fun key data -> f key data) m
|
|
|
|
|
let iter m ~f = M.iter (fun key data -> f key data) m
|
|
|
|
|
let exists m ~f = M.exists (fun key data -> f key data) m
|
|
|
|
|
let min_elt = M.min_binding_opt
|
|
|
|
|
let min_elt_exn = M.min_binding
|
|
|
|
|
let to_list m = M.bindings m
|
|
|
|
|
end
|
|
|
|
|