rust-random / rand

A Rust library for random number generation.
https://crates.io/crates/rand
Other
1.67k stars 432 forks source link

Use Poisson distribution to generate integers (not floats) #1497

Closed nielsle closed 1 month ago

nielsle commented 1 month ago

Background

What is your motivation?

I would like to use simulate a stochastic process where the number of events in each time window follows a Poisson distribution.

let poisson = Poisson::new(lambda).unwrap();
for _step in 0..n_steps {
    let n_attempts: u64 = poisson.sample(&mut rand::thread_rng()));
    for _sub_step in 0..n_attempts {
        //do_stuff
    }
}

This code fails because the poisson.sample() distribution can only return a float

I can fix this by rounding off the float, but my code would be prettier if poisson.sample() could return an integer :-)

What type of application is this? (E.g. cryptography, game, numerical simulation)

Numerical simulation of a spin-system similar to the Ising model.

Feature request

Introduce a version of the Poisson distribution that implements Distribution<u64> or Distribution<i64>

See also https://rust-random.github.io/rand/src/rand_distr/poisson.rs.html#118-180

dhardy commented 1 month ago

See also: #1220, 1093, #1323.

Supporting an additional type potentially breaks type inference, but I don't think this is a big concern (but this does require a breaking release).

I suggest that we support u64 and maybe u32. We should probably do a saturating-cast on overflow, though this is mostly a theoretical concern (unless λ is large). Want to make a PR? (Maybe for Zipf too.)

clarfonthey commented 1 month ago

Not to be too picky, but I figured I would point out the typo in the issue title, since "poison distribution" sounds a bit dangerous. :p

benjamin-lieser commented 1 month ago

I suggest that we support u64 and maybe u32. We should probably do a saturating-cast on overflow, though this is mostly a theoretical concern (unless λ is large). Want to make a PR? (Maybe for Zipf too.)

In this case a big λ would lead to this sampling only u64::MAX, this should then probably be rejected in the constructor which is not really possible because for Distribution<f64> it works good enough. Denying big λ completely would also solve https://github.com/rust-random/rand/issues/1312

I think we should implement only u64 and make sure we do not accept λ which will saturate this (except very extremely rare events)