 ### Added [OST], for fun.

parent 9b252108
 (* This is a variant of OCaml's [Set] module, where each node in the binary search tree carries its size (i.e., the number of its elements). The tree is thus an ordered statistics tree, and supports [select] and [rank] in logarithmic time and [cardinal] in constant time. *) (* This implementation is minimalistic -- many set operations are missing. *) module Make (Ord : Set.OrderedType) = struct type elt = Ord.t type t = Empty | Node of t * elt * t * (* height: *) int * (* size: *) int let height = function Empty -> 0 | Node(_, _, _, h, _) -> h let size = function Empty -> 0 | Node(_, _, _, _, s) -> s let create l v r = let hl = height l in let hr = height r in Node(l, v, r, (if hl >= hr then hl + 1 else hr + 1), size l + 1 + size r) let bal l v r = let hl = height l in let hr = height r in if hl > hr + 2 then begin match l with Empty -> invalid_arg "Set.bal" | Node(ll, lv, lr, _, _) -> if height ll >= height lr then create ll lv (create lr v r) else begin match lr with Empty -> invalid_arg "Set.bal" | Node(lrl, lrv, lrr, _, _)-> create (create ll lv lrl) lrv (create lrr v r) end end else if hr > hl + 2 then begin match r with Empty -> invalid_arg "Set.bal" | Node(rl, rv, rr, _, _) -> if height rr >= height rl then create (create l v rl) rv rr else begin match rl with Empty -> invalid_arg "Set.bal" | 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), size l + 1 + size r) let rec add x = function Empty -> Node(Empty, x, Empty, 1, 1) | Node(l, v, r, _, _) as t -> let c = Ord.compare x v in if c = 0 then t else if c < 0 then let ll = add x l in if l == ll then t else bal ll v r else let rr = add x r in if r == rr then t else bal l v rr let empty = Empty let cardinal = size let rec select i = function | Empty -> (* [i] is out of bounds *) assert false | Node (l, v, r, _, s) -> assert (0 <= i && i < s); let sl = size l in if i < sl then select i l else if i = sl then v else select (i - sl - 1) r let pick xs = let s = size xs in if s = 0 then raise Not_found else select (Random.int s) xs let rec rank accu x = function | Empty -> raise Not_found | Node (l, v, r, _, _) -> let c = Ord.compare x v in if c = 0 then accu + size l else if c < 0 then rank accu x l else rank (accu + size l + 1) x r let rank = rank 0 end
 (* This is a variant of OCaml's [Set] module, where each node in the binary search tree carries its size (i.e., the number of its elements). The tree is thus an ordered statistics tree, and supports [select] and [rank] in logarithmic time and [cardinal] in constant time. *) (* This implementation is minimalistic -- many set operations are missing. *) module Make (Ord : Set.OrderedType) : sig (* The type of set elements. *) type elt = Ord.t (* The type of sets. *) type t (* [empty] is the empty set. *) val empty: t (* [add x xs] is the union of the singleton set [x] and of the set [xs]. *) val add: elt -> t -> t (* [cardinal xs] is the number of elements in the set [xs]. *) val cardinal: t -> int (* [select i xs] returns the [i]-th element of the set [xs], viewed as an increasing sequence. The index [i] must lie between 0 (included) and [cardinal xs] (excluded). *) val select: int -> t -> elt (* [pick xs] returns a randomly-distributed random element of the set [xs]. If [xs] is empty, the exception [Not_found] is raised. *) val pick: t -> elt (* [rank x xs] returns the rank of the element [x] in the set [xs], viewed as an increasing sequence. This rank is comprised between 0 (included) and [cardinal xs] (excluded). If [x] is not a member of [xs], the exception [Not_found] is raised. *) val rank: elt -> t -> int end
 open Term module StringSet = OST.Make(String) (* Randomly split an integer [n] into [n1 + n2]. *) let split n = assert (n >= 0); let n1 = Random.int (n + 1) in ... ... @@ -8,25 +13,18 @@ let split n = assert (0 <= n2 && n2 <= n); n1, n2 let random_variable () = (* Randomly generate a name between "a" and "z". *) let random_name () = let i = Random.int 26 in let c = Char.chr (Char.code 'a' + i) in String.make 1 c module StringSet = Set.Make(String) let random_set_element xs = (* inefficient *) let n = StringSet.cardinal xs in assert (n > 0); let i = Random.int n in List.nth (StringSet.elements xs) i let rec generate env n = assert (n >= 0); assert (not (StringSet.is_empty env)); assert (StringSet.cardinal env > 0); if n = 0 then TVar (random_set_element env) TVar (StringSet.pick env) else match Random.int 2 with | 0 -> ... ... @@ -39,7 +37,7 @@ let rec generate env n = and generate_lambda env n = let n = n - 1 in let x = random_variable () in let x = random_name () in let env = StringSet.add x env in TLambda (x, generate env n) ... ...
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment