Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating a non-uniform, integer distribution using tr1 <random>

Right now I use the following code to create a uniform distribution of integers with a range. (I took out the seeding code)

int random(int min, int max)
{
    static std::mt19937 gen;
    std::uniform_int<int> dist(min, max);
    return dist(gen);

}

I am trying to modify it to give a distribution that favors twords the min value, and almost never produces nears the max value. I can see all of the pre-made distributions, but none of them are integer. And also I can't tell which one fits my needs based on any of the documentation. The closest I have come is the chi squared distribution as shown on wikipedia, where k=2

But I can't figure out, based on the documentation how to use it with integers, let alone set the k value.

How can I set up my function to use an appropriate non-uniform, integer distribution?


still working on choosing the correct distro: here are the results of std::poisson_distribution<int> dist((max - min) * .1); from 0 to 20:

not quite there yet, as 0 should be more frequent than 1, but it should help the next person out, will post more results as they come.


well my final solution became a combination of methods:

int randomDist(int min, int max)
{
    static std::mt19937 gen;
    std::chi_squared_distribution<double> dist(2);

    int x;
    do
    {
    x = (int)(max*dist(gen)/10) + min;
    }
    while (x > max);
    return x;
}

giving the result of:

like image 642
Zak Avatar asked Mar 14 '11 09:03

Zak


People also ask

How do you create a random uniform distribution?

If u is a uniform random number on (0,1), then x = F - 1 ( u ) generates a random number x from any continuous distribution with the specified cdf F .

What is non uniformly distributed random number?

Non-uniform random variate generation or pseudo-random number sampling is the numerical practice of generating pseudo-random numbers (PRN) that follow a given probability distribution. Methods are typically based on the availability of a uniformly distributed PRN generator.

How do you create an exponential distribution in C++?

Generating an exponential distribution random variable can be done by: -ln(U)/lambda (where U~Uniform(0,1)). In exponential distribution: lamda = 1/mean , so it gets you: myVar = -ln(U) * mean (where U~Uniform(0,1)).

What is uniform distribution and random number?

The uniform distribution is the underlying distribution for an uniform random variable. A continuous uniform random variable, denoted as , take continuous values within a given interval. , with equal probability. Therefore, the PDF of such a random variable is a constant over the given interval is.


1 Answers

There are other integer distributions there, they just don't have int in their names. They do have typedef IntType result_type in their class definitions.

The ones which behave as you describe are:

  • binomial_distribution(t, p)

    This generates numbers in the range 0 ≤ xt, so you need to translate the range by min. The mean is at t·p, so choose a p near 0.

    std::binomial_distribution<int> dist(max - min, .1);
    return dist(gen) + min;

  • poisson_distribution(λ)

    This generates numbers 0 ≤ x < ∞, but large numbers are progressively less likely. You can censor anything above max to limit it to a range. The parameter λ is the mean. Choosing it to match the previous example:

    std::poisson_distribution<int> dist((max - min) * .1);
    int x;
    do
        x = dist(gen) + min;
    while (x > max);
    return x;

  • geometric_distribution(p)

    Also generates numbers 0 ≤ x < ∞, but 0 is the most likely outcome and every subsequent number is less likely than the previous. Again choosing the parameter to match the mean of the previous example:

    std::geometric_distribution<int> dist(1 / ((max - min) * .1 + 1));
    int x;
    do
        x = dist(gen) + min;
    while (x > max);
    return x;

You can also use any of the continuous distributions to generate a double and then round it to an int.

like image 191
aaz Avatar answered Oct 26 '22 09:10

aaz