[29] | 1 | /* boost random_demo.cpp profane demo |
---|
| 2 | * |
---|
| 3 | * Copyright Jens Maurer 2000 |
---|
| 4 | * Distributed under the Boost Software License, Version 1.0. (See |
---|
| 5 | * accompanying file LICENSE_1_0.txt or copy at |
---|
| 6 | * http://www.boost.org/LICENSE_1_0.txt) |
---|
| 7 | * |
---|
| 8 | * $Id: random_demo.cpp,v 1.17 2005/05/10 20:40:59 jmaurer Exp $ |
---|
| 9 | * |
---|
| 10 | * A short demo program how to use the random number library. |
---|
| 11 | */ |
---|
| 12 | |
---|
| 13 | #include <iostream> |
---|
| 14 | #include <fstream> |
---|
| 15 | #include <ctime> // std::time |
---|
| 16 | |
---|
| 17 | #include <boost/random/linear_congruential.hpp> |
---|
| 18 | #include <boost/random/uniform_int.hpp> |
---|
| 19 | #include <boost/random/uniform_real.hpp> |
---|
| 20 | #include <boost/random/variate_generator.hpp> |
---|
| 21 | |
---|
| 22 | // Sun CC doesn't handle boost::iterator_adaptor yet |
---|
| 23 | #if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530) |
---|
| 24 | #include <boost/generator_iterator.hpp> |
---|
| 25 | #endif |
---|
| 26 | |
---|
| 27 | #ifdef BOOST_NO_STDC_NAMESPACE |
---|
| 28 | namespace std { |
---|
| 29 | using ::time; |
---|
| 30 | } |
---|
| 31 | #endif |
---|
| 32 | |
---|
| 33 | // This is a typedef for a random number generator. |
---|
| 34 | // Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand |
---|
| 35 | typedef boost::minstd_rand base_generator_type; |
---|
| 36 | |
---|
| 37 | // This is a reproducible simulation experiment. See main(). |
---|
| 38 | void experiment(base_generator_type & generator) |
---|
| 39 | { |
---|
| 40 | // Define a uniform random number distribution of integer values between |
---|
| 41 | // 1 and 6 inclusive. |
---|
| 42 | typedef boost::uniform_int<> distribution_type; |
---|
| 43 | typedef boost::variate_generator<base_generator_type&, distribution_type> gen_type; |
---|
| 44 | gen_type die_gen(generator, distribution_type(1, 6)); |
---|
| 45 | |
---|
| 46 | #if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530) |
---|
| 47 | // If you want to use an STL iterator interface, use iterator_adaptors.hpp. |
---|
| 48 | // Unfortunately, this doesn't work on SunCC yet. |
---|
| 49 | boost::generator_iterator<gen_type> die(&die_gen); |
---|
| 50 | for(int i = 0; i < 10; i++) |
---|
| 51 | std::cout << *die++ << " "; |
---|
| 52 | std::cout << '\n'; |
---|
| 53 | #endif |
---|
| 54 | } |
---|
| 55 | |
---|
| 56 | int main() |
---|
| 57 | { |
---|
| 58 | // Define a random number generator and initialize it with a reproducible |
---|
| 59 | // seed. |
---|
| 60 | // (The seed is unsigned, otherwise the wrong overload may be selected |
---|
| 61 | // when using mt19937 as the base_generator_type.) |
---|
| 62 | base_generator_type generator(42u); |
---|
| 63 | |
---|
| 64 | std::cout << "10 samples of a uniform distribution in [0..1):\n"; |
---|
| 65 | |
---|
| 66 | // Define a uniform random number distribution which produces "double" |
---|
| 67 | // values between 0 and 1 (0 inclusive, 1 exclusive). |
---|
| 68 | boost::uniform_real<> uni_dist(0,1); |
---|
| 69 | boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist); |
---|
| 70 | |
---|
| 71 | std::cout.setf(std::ios::fixed); |
---|
| 72 | // You can now retrieve random numbers from that distribution by means |
---|
| 73 | // of a STL Generator interface, i.e. calling the generator as a zero- |
---|
| 74 | // argument function. |
---|
| 75 | for(int i = 0; i < 10; i++) |
---|
| 76 | std::cout << uni() << '\n'; |
---|
| 77 | |
---|
| 78 | /* |
---|
| 79 | * Change seed to something else. |
---|
| 80 | * |
---|
| 81 | * Caveat: std::time(0) is not a very good truly-random seed. When |
---|
| 82 | * called in rapid succession, it could return the same values, and |
---|
| 83 | * thus the same random number sequences could ensue. If not the same |
---|
| 84 | * values are returned, the values differ only slightly in the |
---|
| 85 | * lowest bits. A linear congruential generator with a small factor |
---|
| 86 | * wrapped in a uniform_smallint (see experiment) will produce the same |
---|
| 87 | * values for the first few iterations. This is because uniform_smallint |
---|
| 88 | * takes only the highest bits of the generator, and the generator itself |
---|
| 89 | * needs a few iterations to spread the initial entropy from the lowest bits |
---|
| 90 | * to the whole state. |
---|
| 91 | */ |
---|
| 92 | generator.seed(static_cast<unsigned int>(std::time(0))); |
---|
| 93 | |
---|
| 94 | std::cout << "\nexperiment: roll a die 10 times:\n"; |
---|
| 95 | |
---|
| 96 | // You can save a generator's state by copy construction. |
---|
| 97 | base_generator_type saved_generator = generator; |
---|
| 98 | |
---|
| 99 | // When calling other functions which take a generator or distribution |
---|
| 100 | // as a parameter, make sure to always call by reference (or pointer). |
---|
| 101 | // Calling by value invokes the copy constructor, which means that the |
---|
| 102 | // sequence of random numbers at the caller is disconnected from the |
---|
| 103 | // sequence at the callee. |
---|
| 104 | experiment(generator); |
---|
| 105 | |
---|
| 106 | std::cout << "redo the experiment to verify it:\n"; |
---|
| 107 | experiment(saved_generator); |
---|
| 108 | |
---|
| 109 | // After that, both generators are equivalent |
---|
| 110 | assert(generator == saved_generator); |
---|
| 111 | |
---|
| 112 | // as a degenerate case, you can set min = max for uniform_int |
---|
| 113 | boost::uniform_int<> degen_dist(4,4); |
---|
| 114 | boost::variate_generator<base_generator_type&, boost::uniform_int<> > deg(generator, degen_dist); |
---|
| 115 | std::cout << deg() << " " << deg() << " " << deg() << std::endl; |
---|
| 116 | |
---|
| 117 | #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE |
---|
| 118 | { |
---|
| 119 | // You can save the generator state for future use. You can read the |
---|
| 120 | // state back in at any later time using operator>>. |
---|
| 121 | std::ofstream file("rng.saved", std::ofstream::trunc); |
---|
| 122 | file << generator; |
---|
| 123 | } |
---|
| 124 | #endif |
---|
| 125 | // Some compilers don't pay attention to std:3.6.1/5 and issue a |
---|
| 126 | // warning here if "return 0;" is omitted. |
---|
| 127 | return 0; |
---|
| 128 | } |
---|