Random number library

Hi, one of my students tried some time in vain to use the random number generator from the boost library, but he couldn't understand the documentation. I must say, the documentation is not exactly "user-friendly". Here's the problem: Given integers min and max, we want to have a pseudo-random-number generator for random numbers from min, min + 1, ..., max (uniform distribution). The generator should take a seed, and then producing a sequence of pseudo-random numbers (and we should be able to find out about the period of the generator). I couldn't think of anything more basic for a library on random numbers, and so I would expect an example of how to get such a thing in the documentation. (I mean, a real example, complete with code, explanations, and how to use it.) But there's no such a thing, which I find rather strange. We have the concept of a "Uniform Random Number Generator", which looks exactly what we want, but, alas, it seems to be more of a fictitious concept, since no models seem to be provided?!?! So well, let's have a look at "Random Distribution". Only that it needs as input a "Uniform Random Number Generator", and the library does not seem to provide these things?!?! (We have the "Random Number Library Generators", but this library seems to provide only models for the most general concept, the concept of a "Number Generator", but not of a "Uniform Random Number Generator".) Let's ignore this for a moment, and continue our investigations into "Random Distribution". Here are actually some models, most useful for our purpose seems to be "Class template uniform_smallint" and "Class template uniform_int". Now, even if we would know where to get the argument urng from, still we wouldn't know which to choose: The documentation on these class templates is rather cryptic, and additionally asks us to be "wise". Shouldn't this be the job of the library?! Final rescue: "random_demo.cpp". The macros don't enhance readability. But there is an example "Define a uniform random number distribution of integer values between // 1 and 6 inclusive." where I find the text misleading (since we don't define a distribution, which is an assignment of probabilities to certain events, but we define a generator), but looking at the output of the program experiment: roll a die 10 times: 3 3 2 6 6 5 5 6 6 3 it seems to be what we want. So I could copy and past the relevant parts of the program (which is not completely trivial), and I would get close to my goals. If only I would understood the meaning of what I'm doing! Unfortunately, variate_generator.hpp seems to be of some importance, but is not documented. Sigh. --------------------------- My student didn't get to this point, although he is rather good. But there are too many unknowns in the "equation" to solve (starting with the concept of a concept, ...), so the job becomes overwhelming. Now it doesn't look too complicated for me to write a nice explanation for the above problem in a tutorial style, explaining on the way all the concepts and concepts of concepts in the library, and that's what I wanted to kindly request with my e-mail. (And also the rest of the documentation could need a sentence here and there, as mentioned in the above case study.) And, of course, for any example of the best way how to solve the above problem with the library, and explanations how it works, I would be glad! Oliver

--- Oliver Kullmann <O.Kullmann@Swansea.ac.uk> wrote:
Hi,
Hello!
one of my students tried some time in vain to use the random number generator from the boost library, but he couldn't understand the documentation. I must say, the documentation is not exactly "user-friendly".
Did he try playing around with the "very quick start" example? It should at least have gotten him started. See below for a more thorough explanation.
Here's the problem:
Given integers min and max, we want to have a pseudo-random-number generator for random numbers from min, min + 1, ..., max (uniform distribution). The generator should take a seed, and then producing a sequence of pseudo-random numbers (and we should be able to find out about the period of the generator).
I couldn't think of anything more basic for a library on random numbers, and so I would expect an example of how to get such a thing in the documentation. (I mean, a real example, complete with code, explanations, and how to use it.) But there's no such a thing, which I find rather strange.
Assuming min and max are plain-vanilla integers, the following instructions: typedef boost::uniform_int<> UniformDist; UniformDist dist(min,max); produce an object named dist that holds your uniform distribution. The following instructions: typedef boost::mt19937 BaseRNG; BaseRNG rng; produce a "base pseudo-random number generator", which produces numbers along the *entire* range of integers (-2^31 to +2^31 or something like that). boost::mt19937 is one of many such generators provided by the library. The following instruction puts it all together and gives you the random integer generator you want: boost::variate_generator<BaseRNG&,UniformDist> your_generator(rng, dist); Note the ampersand; your program will fail silently if you omit it. The base random number generator (rng) holds the seed function; simply call rng.seed(42L); or whatever seed you want to provide. Finally, assuming you want to store your sequence in a vector<int>: vector<int> sample; for (int c = 0; c < desired_size; c++) { sample.push_back(your_generator()); }
We have the concept of a "Uniform Random Number Generator", which looks exactly what we want, but, alas, it seems to be more of a fictitious concept, since no models seem to be provided?!?!
Actually, they do exist. In the main page is a section called "Library Organization"; though the concepts don't exactly map to the subsections, you should be able to find what you're looking for now that I've (hopefully) made things clearer. [snip other complaints]
My student didn't get to this point, although he is rather good. But there are too many unknowns in the "equation" to solve (starting with the concept of a concept, ...), so the job becomes overwhelming. Now it doesn't look too complicated for me to write a nice explanation for the above problem in a tutorial style, explaining on the way all the concepts and concepts of concepts in the library, and that's what I wanted to kindly request with my e-mail. (And also the rest of the documentation could need a sentence here and there, as mentioned in the above case study.)
We'll see what Jens Maurer has to say on that. In the meantime, tell your student not to give up! Cromwell Enage __________________________________ Do you Yahoo!? Yahoo! Mail is new and improved - Check it out! http://promotions.yahoo.com/new_mail

one of my students tried some time in vain to use the random number generator from the boost library, but he couldn't understand the documentation. I must say, the documentation is not exactly "user-friendly".
Did he try playing around with the "very quick start" example? It should at least have gotten him started. See below for a more thorough explanation.
The problem with the "very quick start" is, that without already understanding the architecture of the library it seems impossible to understand it. It should be quite a bit longer, with output and some explanations.
Here's the problem:
Given integers min and max, we want to have a pseudo-random-number generator for random numbers from min, min + 1, ..., max (uniform distribution). The generator should take a seed, and then producing a sequence of pseudo-random numbers (and we should be able to find out about the period of the generator).
I couldn't think of anything more basic for a library on random numbers, and so I would expect an example of how to get such a thing in the documentation. (I mean, a real example, complete with code, explanations, and how to use it.) But there's no such a thing, which I find rather strange.
Assuming min and max are plain-vanilla integers, the following instructions:
typedef boost::uniform_int<> UniformDist; UniformDist dist(min,max);
produce an object named dist that holds your uniform distribution. The following instructions:
typedef boost::mt19937 BaseRNG; BaseRNG rng;
produce a "base pseudo-random number generator", which produces numbers along the *entire* range of integers (-2^31 to +2^31 or something like that). boost::mt19937 is one of many such generators provided by the library.
The following instruction puts it all together and gives you the random integer generator you want:
boost::variate_generator<BaseRNG&,UniformDist> your_generator(rng, dist);
Note the ampersand; your program will fail silently if you omit it.
I don't understand the need for the reference type --- otherwise the object rng would be copied, which should also be alright?!
The base random number generator (rng) holds the seed function; simply call
rng.seed(42L);
or whatever seed you want to provide.
I see; this wouldn't work without the reference.
Finally, assuming you want to store your sequence in a vector<int>:
vector<int> sample; for (int c = 0; c < desired_size; c++) { sample.push_back(your_generator()); }
We have the concept of a "Uniform Random Number Generator", which looks exactly what we want, but, alas, it seems to be more of a fictitious concept, since no models seem to be provided?!?!
Actually, they do exist. In the main page is a section called "Library Organization"; though the concepts don't exactly map to the subsections, you should be able to find what you're looking for now that I've (hopefully) made things clearer.
Perhaps one should emphasise, that models of pseudo-random generators are models of uniform random generators, and that also for example uniform_int yields a model of a uniform random generator. Inclusion of something like the above explanations into the documentation would already help a lot!
[snip other complaints]
My student didn't get to this point, although he is rather good. But there are too many unknowns in the "equation" to solve (starting with the concept of a concept, ...), so the job becomes overwhelming. Now it doesn't look too complicated for me to write a nice explanation for the above problem in a tutorial style, explaining on the way all the concepts and concepts of concepts in the library, and that's what I wanted to kindly request with my e-mail. (And also the rest of the documentation could need a sentence here and there, as mentioned in the above case study.)
We'll see what Jens Maurer has to say on that. In the meantime, tell your student not to give up!
Thanks for your help! Oliver

--- Oliver Kullmann <O.Kullmann@Swansea.ac.uk> wrote:
The problem with the "very quick start" is, that without already understanding the architecture of the library it seems impossible to understand it.
Actually, there was a major change in the library architecture between boost versions 1.30 and 1.31. The change had to do with conformance to the WG21 specification, available at this link: <http://www.boost.org/libs/random/wg21-proposal.html>
It should be quite a bit longer, with output and some explanations.
The main page also provides a link to a working program, random_demo.cpp, with quite a bit more detailed comments than what I've already provided.
boost::variate_generator<BaseRNG&,UniformDist> your_generator(rng, dist);
Note the ampersand; your program will fail silently if you omit it.
I don't understand the need for the reference type --- otherwise the object rng would be copied, which should also be alright?!
Nope. Withoout the reference type, a call like: int random_number = your_generator(); would invoke the constructor instead of the () member operator; hence, the silent failure.
Perhaps one should emphasise, that models of pseudo-random generators are models of uniform random generators,
Yes, it says so in the concept documentation, which the reader is told to look at first, although the "emphasis" is rather weak, IMHO.
and that also for example uniform_int yields a model of a uniform random generator.
Not quite. uniform_int models a uniform distribution over which random number generators should generate random numbers. variate_generator is the front-end number generator that applies the distribution constraint to the base random number generator.
Inclusion of something like the above explanations into the documentation would already help a lot!
Ideally, it would be so. The problem here is when Jens Maurer will find the time; presumably he's also working on improving the above-mentioned WG21 spec and preparing for the upcoming 1.32 release. Cromwell Enage __________________________________ Do you Yahoo!? Yahoo! Mail - You care about security. So do we. http://promotions.yahoo.com/new_mail

--- Oliver Kullmann <O.Kullmann@Swansea.ac.uk> wrote:
The problem with the "very quick start" is, that without already understanding the architecture of the library it seems impossible to understand it.
Actually, there was a major change in the library architecture between boost versions 1.30 and 1.31. The change had to do with conformance to the WG21 specification, available at this link:
aha, thanks for the link; I was aware only of the general Technical Report on Standard Library Extensions (Draft), which I found actually more helpful than the Boost documentation.
boost::variate_generator<BaseRNG&,UniformDist> your_generator(rng, dist);
Note the ampersand; your program will fail silently if you omit it.
I don't understand the need for the reference type --- otherwise the object rng would be copied, which should also be alright?!
Nope. Without the reference type, a call like:
int random_number = your_generator();
would invoke the constructor instead of the () member operator; hence, the silent failure.
I don't understand this. According to the draft (N1648, available at http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/#post_sydney) section 5.1.3, just using a non-reference type BaseRNG should work.
Perhaps one should emphasise, that models of pseudo-random generators are models of uniform random generators,
Yes, it says so in the concept documentation, which the reader is told to look at first, although the "emphasis" is rather weak, IMHO.
I just feel that the whole concept of "concepts" and "models" is not so easy to grasp, and thus I think it would be beneficial to say things several times.
and that also for example uniform_int yields a model of a uniform random generator.
Not quite. uniform_int models a uniform distribution over which random number generators should generate random numbers. variate_generator is the front-end number generator that applies the distribution constraint to the base random number generator.
In the draft, section 5.1.7.1 it says, that "a uniform_int random distribution satisfies all the requirements of a uniform number generator", and I guess that means that uniform_int is a model of a uniform random generator, or?!
Inclusion of something like the above explanations into the documentation would already help a lot!
Ideally, it would be so. The problem here is when Jens Maurer will find the time; presumably he's also working on improving the above-mentioned WG21 spec and preparing for the upcoming 1.32 release.
Of course; I just hope that this little e-mail stream might already help for some improvements (and every bit helps). Oliver

Every time when I used the random number library, I was wondering why I needed variate_generator. The existence of variate_generator made me feel like I had to use it, because I thought that other uses of the library (like passing the generator as an argument to the distribution) were undocumented, and could therefore be changed in next versions of the library. variate_generator looks like some sort of glue with virtually the same functionality that bind provides, but it still wasn't clear to me why I needed to use variate_generator instead of passing the generator as argument to the distribution. The wg21 proposal gives a few reasons why variate_generator could be useful, and although I haven't read it thoroughly, I'm getting the inpression that variate_generator is only useful in some specific cases. In the way I normally use random number generators, it suffices to pass the generator as argument to the distribution. If a generator (as in, a function taking 0 parameters) is needed, bind could provide the desired functionality. Would it therefore not be a good idea to make this clear in the documentation, by stating that normally the generator can be passed as an argument to the distribution, and treating variate_generator in a separate documentation section where the first few lines explain when variate_generator gives you more functionality than using the direct approach or using bind? Of course, if I'm wrong in stating that variate_generator isn't actually required to make use of the random number library, please tell me. best regards, Richard Peters

I vote for these instructions to go near the top of the docs; I also couldn't work out what I needed to do when I looked at Boost.Random a few months back, but these instructions make it sound fairly simple. What I wanted to do was generate a random number in the full range of a integer template parameter, e.g. whether I used the template with unsigned char, or a 128-bit integer. (in the end I decided to come back to this when I needed that flexibility and implemented using 32-bit integers and the standard library's srand48() and mrand48()). So, can Boost.Random generate a random number to match the type? Darren
Assuming min and max are plain-vanilla integers, the following instructions:
typedef boost::uniform_int<> UniformDist; UniformDist dist(min,max);
produce an object named dist that holds your uniform distribution. The following instructions:
typedef boost::mt19937 BaseRNG; BaseRNG rng;
produce a "base pseudo-random number generator", which produces numbers along the *entire* range of integers (-2^31 to +2^31 or something like that). boost::mt19937 is one of many such generators provided by the library.
The following instruction puts it all together and gives you the random integer generator you want:
boost::variate_generator<BaseRNG&,UniformDist> your_generator(rng, dist);
Note the ampersand; your program will fail silently if you omit it.
The base random number generator (rng) holds the seed function; simply call
rng.seed(42L);
or whatever seed you want to provide.
Finally, assuming you want to store your sequence in a vector<int>:
vector<int> sample; for (int c = 0; c < desired_size; c++) { sample.push_back(your_generator()); }

Hello, Darren. --- Darren Cook <darren@dcook.org> wrote:
What I wanted to do was generate a random number in the full range of an integer template parameter, e.g. whether I used the template with unsigned char, or a 128-bit integer. (in the end I decided to come back to this when I needed that flexibility and implemented using 32-bit integers and the standard library's srand48() and mrand48()).
So, can Boost.Random generate a random number to match the type?
This should be possible. Try boost::uniform_int<T> dist( (std::numeric_limits<T>::min)(), (std::numeric_limits<T>::max)() ); as your distribution. (The extra parentheses arise from a recent thread on using min/max.) For a user-defined type such as your 128-bit integer, you'll have to provide a template specialization of std::numeric_limits before creating the distribution. Make sure your base rng engine can actually cover at least the integer range specified in std::numeric_limits; boost::mt19937 should be good enough for your purposes. HTH Cromwell Enage __________________________________ Do you Yahoo!? New and Improved Yahoo! Mail - Send 10MB messages! http://promotions.yahoo.com/new_mail

-- Oliver Kullmann <O.Kullmann@Swansea.ac.uk> wrote:
Nope. Without the reference type, a call like:
int random_number = your_generator();
would invoke the constructor instead of the () member operator; hence, the silent failure.
I don't understand this. According to the draft (N1648, available at
http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/#post_sydney)
section 5.1.3, just using a non-reference type BaseRNG should work.
I'm assuming you meant N1647. I'll try to code some test cases in which using a non-reference type BaseRNG works (at least with the compiler I'm using, MinGW 3.2), but in my limited experience it hasn't worked so far.
I just feel that the whole concept of "concepts" and
"models" is not so easy to grasp, and thus I think it would be beneficial to say things several times.
I'd vote for a more unified (Boost-wide) look-and-feel of the library documentation that is loosely based on SGI's STL website so that the ideas of "concept" and "model" are reinforced in the library user's mind. I believe that's what they're going to do with the upcoming BoostBook documentation system, but it'll take some time if that's going to happen. I'm not sure your student has surfed through it already, but in the meantime, he can study the STL Programmer's Guide, hosted by SGI: <http://www.sgi.com/tech/stl/> The "Introduction" gives the definitions of "concept", "model", and other imporant ideas; and the "Table of Contents" applies the definitions to the various class templates available in the STL. Your student should find these resources especially useful since Boost libraries are supposed to work well with (and maybe become a part of) the C++ Standard Library (of which STL is a major part).
In the draft, section 5.1.7.1 it says, that "a uniform_int random distribution satisfies all the requirements of a uniform number generator", and I guess that means that uniform_int is a model of a uniform random generator, or?!
Well, you can't call the () member operator of uniform_int the way uniform number generators are required to by table 5.1 of section 5.1.1, but uniform_int does satisfy the random *distribution* requirements set forth in table 5.3 of that same section. I'm not sure if the table number and associated caption in section 5.1.7.1 are typos, but for an answer on that particular point you may have to contact the report's author directly.
Of course; I just hope that this little e-mail stream might already help for some improvements (and every bit helps).
Agreed. I'll be on-and-off, though; my grandfather's in bad health and the family needs my support. Cromwell Enage __________________________________ Do you Yahoo!? New and Improved Yahoo! Mail - Send 10MB messages! http://promotions.yahoo.com/new_mail

Hi, following the request for some improved documentation in my first e-mail (illustrated by some "case study" from a student's experience) I would like to propose to include the following class template RandomGeneratorInterval into the documentation of the random number library (a first draft, more explanations should be added; of course, names can be changed). It solves the task from my previous e-mail, and seems to me a very typical first use of the library: template <class bgt = boost::minstd_rand, class dt = boost::uniform_int<> > class RandomGeneratorInterval { public : typedef bgt base_generator_type; typedef dt distribution_type; typedef boost::variate_generator<base_generator_type, distribution_type> generator_type; typedef typename generator_type::result_type interval_type; typedef typename base_generator_type::result_type seed_type; RandomGeneratorInterval(interval_type min, interval_type max) : min(min), max(max) {} generator_type operator() (seed_type seed = 1) const { assert(seed != 0); return generator_type(base_generator_type(seed), distribution_type(min, max)); } private : const interval_type min, max; }; // An object rgi defined by "RandomGeneratorInterval rgi(min, max)" can create a random number generator g via g = rgi(seed). // Random numbers in the interval from min to max then are created with g(). // It is g() of type interval_type as well as min and max, while seed is of type seed_type; g itself is of type generator_type. // g is a model of a uniform random number generator (even a model of a pseudo-random number generator?!). Examples for usage are typedef Algorithms::RandomGeneratorInterval<> RI; RI rgi(10,20); RI::generator_type g1 = rgi(456); RI::generator_type g2 = rgi(); RI::generator_type g3 = rgi(1); assert(g1.min() == 10); assert(g1.max() == 20); assert(g1() == 10); assert(g1() == 18); assert(g1() == 12); assert(g2() == 10); assert(g2() == 10); assert(g2() == 16); assert(g3() == 10); assert(g3() == 10); assert(g3() == 16); // Attention: std::cout << g1() << " " << g1() results in implementation-defined behaviour (could be "10 18" or "18 12") ! (The last line seems a typical trap to me one has to be aware of, and thus it seems worth to be included.) Does the above code look reasonable?! Oliver
participants (4)
-
Cromwell Enage
-
Darren Cook
-
Oliver Kullmann
-
Richard Peters