Skip to content

Commit b830f44

Browse files
committed
Comments
1 parent caee8ba commit b830f44

File tree

2 files changed

+19
-10
lines changed

2 files changed

+19
-10
lines changed

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
# Urns in Rust (WIP)
1+
# Random Urns
22
A Rust implementation of the Urn data structure [(Lampropulos et al. 2017)](https://dl.acm.org/doi/pdf/10.1145/3122955.3122959) for efficient purely functional random sampling over discrete distributions.
33

44
Adapted from:
5-
- Lampropulos et al.'s [original Haskell implementation](https://github.com/antalsz/urn-random/tree/master)
6-
- [Justin Frank's OCaml port](https://github.com/laelath/ocaml-urn/tree/main?tab=readme-ov-file).
5+
- Lampropulos et al.'s [original Haskell implementation](https://github.com/antalsz/urn-random)
6+
- Justin Frank's [OCaml implementation](https://github.com/laelath/ocaml-urn).
7+
(I've tried to follow the Haskell/OCaml implementations as close as possible.)
78

src/urn.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ fn sample_weight(w: Weight) -> Weight {
4141
/* Methods for Urn<T> */
4242
/* -------------------------------------------------------------------------- */
4343

44-
/// Creates a singleton urn containing element `a` with weight `w`
44+
/// Creates a singleton urn containing element `a` with weight `w`.
45+
/// Time complexity: `O(1)`.
4546
pub fn singleton<T: Clone>(w: Weight, a: T) -> Urn<T> {
4647
Urn {
4748
size: 1,
@@ -50,8 +51,8 @@ pub fn singleton<T: Clone>(w: Weight, a: T) -> Urn<T> {
5051
}
5152

5253
/// Naive implementation of `from_list`, which just folds `insert` over a
53-
/// vector of (weight, element) pairs.
54-
/// TODO: add QC property that says `from_list` behaves the same as `from_list_naive`
54+
/// vector of (weight, element) pairs.
55+
/// Time complexity: `O(n log n)`.
5556
pub fn from_list_naive<T: Clone>(elems: Vec<(Weight, T)>) -> Option<Urn<T>> {
5657
match elems.as_slice() {
5758
[] => None,
@@ -65,7 +66,8 @@ pub fn from_list_naive<T: Clone>(elems: Vec<(Weight, T)>) -> Option<Urn<T>> {
6566
}
6667

6768
/// An optimized version of `from_list`, which builds an almost perfect tree
68-
/// in linear time (see `almost_perfect.rs`)
69+
/// in linear time (see `almost_perfect.rs`)
70+
/// Time complexity: `O(n)`.
6971
pub fn from_list<T: Clone>(elems: Vec<(Weight, T)>) -> Option<Urn<T>> {
7072
if elems.is_empty() {
7173
None
@@ -134,7 +136,8 @@ impl<T: Clone> Urn<T> {
134136
)
135137
}
136138

137-
/// Inserts a new element `a` with weight `w` into the `Urn`
139+
/// Inserts a new element `a` with weight `w` into the `Urn`.
140+
/// Time complexity: `O(log n)`.
138141
pub fn insert(self, w_outer: Weight, a_outer: T) -> Self {
139142
/// Helper function which updates the weights on all the
140143
/// nodes encountered on a `path` through the `tree`.
@@ -185,7 +188,7 @@ impl<T: Clone> Urn<T> {
185188
/// `uninsert`s (deletes) the most-recently-inserted weighted value `(w, a)`
186189
/// from the urn, returning `(w, a)`, the lower bound `lb` for the bucket
187190
/// that previously contained `a`, and an optional new urn
188-
/// (since `uninsert`-ing from an `Urn` of size 1 produces `None`)
191+
/// (since `uninsert`-ing from an `Urn` of size 1 produces `None`).
189192
pub fn uninsert(self) -> ((Weight, T), Weight, Option<Self>) {
190193
fn go<T: Clone>(
191194
path: u32,
@@ -247,10 +250,12 @@ impl<T: Clone> Urn<T> {
247250
}
248251

249252
/* -------------------------------------------------------------------------- */
250-
/* Random methods for Urns */
253+
/* Randomized methods for Urns */
251254
/* -------------------------------------------------------------------------- */
252255

253256
impl<T: Clone> Urn<T> {
257+
/// Randomly sample an element from the distribution represented by the urn.
258+
/// Time complexity: `O(log n)`.
254259
pub fn sample(self) -> T {
255260
let i = sample_weight(self.weight());
256261
self.sample_index(i)
@@ -269,6 +274,9 @@ impl<T: Clone> Urn<T> {
269274
self.replace_index(w, a, i)
270275
}
271276

277+
/// Removes a random element from the urn, returning it along with its weight,
278+
/// and the resultant urn in an `Option` (which is `None` if the urn is empty).
279+
/// Time complexity: `O(log n)`.
272280
pub fn remove(self) -> ((Weight, T), Option<Self>) {
273281
let i = sample_weight(self.weight());
274282
self.remove_index(i)

0 commit comments

Comments
 (0)