Skip to content

Commit 8d70f50

Browse files
authored
Clarify documentation of choose_weighted(_mut) mentioning accurate behavior with floats (#1245)
* Fix the documentation for `choose_weighted(_mut)` as discussed in #1243. * Mention that elements of zero weight are handled as expected by `WeightedIndex` as discussed in #1243. Additionally fix some minor issues. * Let the second example of `WeightedIndex` use floats to stress that they are handled correctly for the zero case. * Manually indent doc comments.
1 parent 766c7ec commit 8d70f50

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

src/distributions/weighted_index.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ use serde::{Serialize, Deserialize};
2525
/// Sampling a `WeightedIndex` distribution returns the index of a randomly
2626
/// selected element from the iterator used when the `WeightedIndex` was
2727
/// created. The chance of a given element being picked is proportional to the
28-
/// value of the element. The weights can use any type `X` for which an
29-
/// implementation of [`Uniform<X>`] exists.
28+
/// weight of the element. The weights can use any type `X` for which an
29+
/// implementation of [`Uniform<X>`] exists. The implementation guarantees that
30+
/// elements with zero weight are never picked, even when the weights are
31+
/// floating point numbers.
3032
///
3133
/// # Performance
3234
///
@@ -42,8 +44,8 @@ use serde::{Serialize, Deserialize};
4244
/// weights of type `X`, where `N` is the number of weights. However, since
4345
/// `Vec` doesn't guarantee a particular growth strategy, additional memory
4446
/// might be allocated but not used. Since the `WeightedIndex` object also
45-
/// contains, this might cause additional allocations, though for primitive
46-
/// types, [`Uniform<X>`] doesn't allocate any memory.
47+
/// contains an instance of `X::Sampler`, this might cause additional allocations,
48+
/// though for primitive types, [`Uniform<X>`] doesn't allocate any memory.
4749
///
4850
/// Sampling from `WeightedIndex` will result in a single call to
4951
/// `Uniform<X>::sample` (method of the [`Distribution`] trait), which typically
@@ -65,7 +67,7 @@ use serde::{Serialize, Deserialize};
6567
/// println!("{}", choices[dist.sample(&mut rng)]);
6668
/// }
6769
///
68-
/// let items = [('a', 0), ('b', 3), ('c', 7)];
70+
/// let items = [('a', 0.0), ('b', 3.0), ('c', 7.0)];
6971
/// let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
7072
/// for _ in 0..100 {
7173
/// // 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c'

src/seq/mod.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,21 +123,25 @@ pub trait SliceRandom {
123123
/// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`.
124124
///
125125
/// For slices of length `n`, complexity is `O(n)`.
126-
/// See also [`choose_weighted_mut`], [`distributions::weighted`].
126+
/// For more information about the underlying algorithm,
127+
/// see [`distributions::WeightedIndex`].
128+
///
129+
/// See also [`choose_weighted_mut`].
127130
///
128131
/// # Example
129132
///
130133
/// ```
131134
/// use rand::prelude::*;
132135
///
133-
/// let choices = [('a', 2), ('b', 1), ('c', 1)];
136+
/// let choices = [('a', 2), ('b', 1), ('c', 1), ('d', 0)];
134137
/// let mut rng = thread_rng();
135-
/// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c'
138+
/// // 50% chance to print 'a', 25% chance to print 'b', 25% chance to print 'c',
139+
/// // and 'd' will never be printed
136140
/// println!("{:?}", choices.choose_weighted(&mut rng, |item| item.1).unwrap().0);
137141
/// ```
138142
/// [`choose`]: SliceRandom::choose
139143
/// [`choose_weighted_mut`]: SliceRandom::choose_weighted_mut
140-
/// [`distributions::weighted`]: crate::distributions::weighted
144+
/// [`distributions::WeightedIndex`]: crate::distributions::WeightedIndex
141145
#[cfg(feature = "alloc")]
142146
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
143147
fn choose_weighted<R, F, B, X>(
@@ -161,11 +165,14 @@ pub trait SliceRandom {
161165
/// therefore `weight(x) / s`, where `s` is the sum of all `weight(x)`.
162166
///
163167
/// For slices of length `n`, complexity is `O(n)`.
164-
/// See also [`choose_weighted`], [`distributions::weighted`].
168+
/// For more information about the underlying algorithm,
169+
/// see [`distributions::WeightedIndex`].
170+
///
171+
/// See also [`choose_weighted`].
165172
///
166173
/// [`choose_mut`]: SliceRandom::choose_mut
167174
/// [`choose_weighted`]: SliceRandom::choose_weighted
168-
/// [`distributions::weighted`]: crate::distributions::weighted
175+
/// [`distributions::WeightedIndex`]: crate::distributions::WeightedIndex
169176
#[cfg(feature = "alloc")]
170177
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
171178
fn choose_weighted_mut<R, F, B, X>(

0 commit comments

Comments
 (0)