Questions with using boost for generating normal random numbers - c++

I was hoping to learning how to generate numbers from normal distribution in C++ when I saw This Post. It gives a very good example, but still I am not sure what the & in boost::variate_generator<boost::mt19937&, boost::normal_distribution<> > var_nor(rng, nd); means. What effect will it produce if I did not include this & here?
Also, when reading the tutorial on Boost's official website, I found that after generating a distribution object with boost::random::uniform_int_distribution<> dist(1, 6), they were able to directly generate random numbers with it by calling dist(gen)(gen here is the random engine), without invoking the "variate_generator" object. Of course, this is for generating uniform random numbers, but I am curious if I can do the same with normal distribution, as an alternative way to calling "variate_generator"?

Short background information
One approach to generate random numbers with a specific distribution, is to generate uniformly distributed random numbers from the interval [0, 1), for example, and then apply some maths on these numbers to shape them into the desired distribution. So you have two objects: one generator for random numbers from [0, 1) and one distribution object, which
takes uniformly distributed random numbers and spits out random numbers in the desired (e.g. the normal) distribution.
Why passing the generator by reference
The var_nor object in your code couples the generator rnd with the normal distribution nd. You have to pass your generator via reference, which is the & in the template argument. This is really essential, because the random number generator has an internal state from which it computes the next (pseudo-)random number. If you would not pass the generator via reference, you would create a copy of it and this might lead to code, which always creates the same random number. See this blog post as an example.
Why the variate_generator is necessary
Now to the part, why not to use the distribution directly with the generator. If you try the following code
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>
int main()
{
boost::mt19937 generator;
boost::normal_distribution<> distribution(0.0, 1.0);
// WARNING: THIS DOES NOT WORK AS MIGHT BE EXPECTED!!
for (int i = 0; i < 100; ++i)
std::cout << distribution(generator) << std::endl;
return 0;
}
you will see, that it outputs NaNs only (I've tested it with Boost 1.46). The reason is that the Mersenne twister returns a uniformly distributed integer random number. However, most (probably even all) continuous distributions require floating point random numbers from the range [0, 1). The example given in the Boost documentation works because uniform_int_distribution is a discrete distribution and thus can deal with integer RNGs.
Note: I have not tried the code with a newer version of Boost. Of course, it would be nice if the compiler threw an error if a discrete RNG is used together with a continuous distributuon.

Related

Do you have a function (else than random) to find random dice(from 1 to 6) numbers(in C++)

I am writing a code for a game with seven dices and I have a problem. If I use a random function(dice = rand()%6 + 1) I realized the probability to get for instance a sequence such as 123456 (a sequence that makes points in my game) has a much higher probability to get out.
Mathematically, this sequence has 1.54% probability to show up but When I use a random function with 100 millions iterations it appears up to 5.4% of the time!
That leads me to my question. Do you know another way I could randomize the dice so that they would respect the probability? Or a way to fix that problem anyway?
Thanks in advance!
The problem you are facing is well known and a very natural result of using the modulo operator with random.
C++11 solves these problems by providing not only uniformly distributed random numbers but several different types of distributions like the Bernoulli distribution, the normal distribution and the Poisson distribution.
The new header providing all these generators and distributions is random.
Let's do an example: We want do have a random number generator that gives us some numbers and we want to have a distribution that shapes these numbers as we want them (uniformly, Bernoulli ...).
#include <iostream>
#include <random>
int main(){
std::mt19937(6473); // The random number generator using a deterministic seed
std::uniform_int_distribution<int> dist(1,6); // The distribution that gives us random numbers in [1, 6)
for(int i=0;i<10;i++){
std::cout << dist(mt) << std::endl;
}
}
This gives us pseudo-random numbers uniformly distributed into an interval we chose! But C++11 provides even more! It provides a real random number generator (see implementations for more details) which we can use as follows:
#include <iostream>
#include <random>
int main(){
std::random_device rd;
std::mt19937 mt(rd()); // The random number generator using a non-deterministic random device
std::uniform_int_distribution<int> dist(1,6); // The distribution that gives us random numbers in [1,6)
for(int i=0;i<10;i++){
std::cout << dist(mt) << std::endl;
}
}
It is this easy to provide real high quality random numbers distributed as you want into and interval you want using C++11. I got the knowlege about this topic from a talk of Stephen T. Lavavej (STL) held at GoingNative 2013 that you can watch on Channel 9 and that is called rand() Considered Harmful.
Fun fact: The title is a reference to an essay from the great Edsger Wybe Dijkstra called "Go to considered harmful." in which Dijkstra explained why no programmer should use the goto statement.
If you want some good random numbers using the boost library random function is a good place to start. Also has the example of working with dice like you are asking. http://www.boost.org/doc/libs/1_61_0/doc/html/boost_random.html

Random number generator repeats every time?

I'm trying to find a random number generator that will give me a single random number each time I run it. I have spent a week trying dozens of different ones, both from this site and others. Every time I run it, it gives me the same number! The only time it changes is if I change the range, and then it just gives me the new number over and over.
I am running Code::Blocks ver. 16.01 on Windows 7. Can anyone help?? I'm at my wits' end!
This code gives me a decently ramdom string of numbers, but still the same string each time!
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 eng(rd()); std::uniform_int_distribution<> distr(0, 10);
for(int n=0; n<100; ++n)
std::cout << distr(eng) << '\t';
}
I have tried the code on my compiler app on my phone as well.
Every pseudo random number generator will return the same sequence of numbers for the same initial seed value.
What you want to do is to use a different seed every time you run the program. Otherwise you'll just be using the same default seed every time and get the same values.
Picking good seeds is not as easy as you might think. Using the output from time(nullptr) for example still gives the same results if two copies of the program run within the same second. Using the value of getpid() is also bad since pid values wrap and thus sometimes you'll get the same value for different runs. Luckily you have other options. std::seed_seq lets you combine multiple bad sources and returns a good (or rather, pretty good) seed value you can use. There is also std::random_device which (on all sane implementations) returns raw entropy - perfect for seeding a pseudo random generator (or you can just use it directly if it is fast enough for your purpose) or you can combine it with std::seed_seq and the bad sources to seed a generator if you are worried it might be implemented as a prng on your implementation.
I would advice you to read this page: http://en.cppreference.com/w/cpp/numeric/random for an overview of how to deal with random number generation in modern C++.
The standard allows std::random_device to be implemented in terms of a pseudo-random number generator if there is no real random source on the system.
You may need to find a different entropy source, such as the time, or user touch co-ordinates.

Independence with boost random

I am trying to use mersenne twister to generate samples from various distribution. I have one generator and it is used to generate all of them. Something strange (to me at least) happens here. On one hand calculating the correlation coefficient of the various samples gives me almost zero, which seems nice. But when I change a parameter of one distribution (which is used nowhere else), it somehow also changes the results I get in others. Specifically:
#include <boost/random.hpp>
using namespace boost; // boost random library for random generators
mt19937 generator(7687); // mersenne twister random number generator, seed = 7687
double normal_sample(double mu, double sigma)
// returns a sample from normal distribution with mean mu and variance sigma
{
normal_distribution<> norm_dist;
variate_generator<mt19937&, normal_distribution<> > norm_rnd(generator, norm_dist);
return(mu + sigma * norm_rnd());
}
double poisson_sample(double intensity)
// returns a number of points in a realization of a Poisson point process
{
poisson_distribution<> poiss_dist(intensity);
variate_generator<mt19937&, poisson_distribution<> > poiss_rnd(generator, poiss_dist);
return(poiss_rnd());
}
This is the code...the generator part, then I draw from those two distributions, changing the parameter called intensity. This changes not only the Poisson sample, but the normal one as well...actually, now that I think of it, it kind of makes sense, because my Poisson sample determines a number of points that are also randomly generated using the same generator...so then then depending on how many of them there are, I get something else, because the normal sample is generated using different numbers in the sequence. Is that correct?
If so, how would one go about changing that? Should I use multiple generators?
It probably means that depending on the parameters fewer or more random samples are extracted from the mersenne twister.
This logically implies that all other results are shifted, making all other outcomes different.
[...] it kind of makes sense, because my Poisson sample determines a number of points that are also randomly generated using the same generator...so then then depending on how many of them there are, I get something else, because the normal sample is generated using different numbers in the sequence. Is that correct?
Seems to me you got it figured out already, yes.
If you wanted repeatable PRNG, use separate PRNG states, i.e. different mersenne egnines.

C++ RNG (Mersenne Twister) needs seed

I have written a RNG class which holds different algorithms, however it does not work as expected. Besides the fact that i want use normal (rather than uniform) distribution my code always returns either the same number (max) or just 2 numbers out of the interval [min,max]:
std::function<int(int, int)> mt19937 =
[](int min, int max) -> int {
std::uniform_int_distribution<int> distribution(min, max);
std::mt19937 engine;
engine.seed(time(null));
auto generator = std::bind(distribution, engine);
return generator();
};
Can anyone explain me what is missing to solve this puzzle? Furthermore, how can i implement normal distribution? Last time i tried out std::normal_distribution i was not able to enter bounds!
EDIT: When i speak of a normal distribution i mean that the results of the RNG near the two bounds should not be generated as often as the mean of both. E.g. look at the graphical representation of the standard Gauss distribution. I am referring to it because it visualizes the probabilities of the resulting values which i want to implement/use this way, if you understand.
The normal distribution is just this (x is a random uniform number):
But I see something that could be problematic:
std::uniform_int_distribution<int> distribution(min, max);
Isn't this giving your number generator an int type?
To fix the seeding problem, create your engine outside of the lambda and seed it when you create it.
A RNG uses an algorithm that produces numbers that appear random, but have a a very large period of repetition (a highlight of the Mersenne Twister). When you seed, you give the RNG an initial value to start the process with. Each time you ask for another number, it spits out another iteration of the algorithm.
When you seed every iteration:
time(NULL)
this code changes only every second, so when you request a new random number, it will only change every second.

Random numbers from binomial distribution

I need to generate quickly lots of random numbers from binomial distributions for dramatically different trial sizes (most, however, will be small). I was hoping not to have to code an algorithm by hand (see, e.g., this related discussion from November), because I'm a novice programmer and don't like reinventing wheels. It appears Boost does not supply a generator for binomially distributed variates, but TR1 and GSL do. Is there a good reason to choose one over the other, or is it better that I write something customized to my situation? I don't know if this makes sense, but I'll alternate between generating numbers from uniform distributions and binomial distributions throughout the program, and I'd like for them to share the same seed and to minimize overhead. I'd love some advice or examples for what I should be considering.
Boost 1.43 appears to support binomial distributions. You can use boost::variate_generator to connect your source of randomness to the type
of distribution you want to sample from.
So your code might look something like this (Disclaimer: not tested!):
boost::mt19937 rng; // produces randomness out of thin air
// see pseudo-random number generators
const int n = 20;
const double p = 0.5;
boost::binomial<> my_binomial(n,p); // binomial distribution with n=20, p=0.5
// see random number distributions
boost::variate_generator<boost::mt19937&, boost::binomial<> >
next_value(rng, my_binomial); // glues randomness with mapping
int x = next_value(); // simulate flipping a fair coin 20 times
You misunderstand the Boost model - you choose a random number generator type and then a distribution on which to spread the values the RNG produces over. There's a very simple example in this answer, which uses a uniform distribution, but other distributions use the same basic pattern - the generator and the distribution are completely decoupled.