I am trying to save the state of a random number generator as follows:
std::mt19937 rng
std::ofstream ofile("RngState.txt");
ofile << rng;
ofile.close();
What I observe is the state is a vector of 1248 numbers And only 624 numbers get written in the file. Is there a way to write and read all the 1248 numbers in one attempt(I guess I am trying to increase the capacity/size of ofstream).
Thanks in advance.
As #knivil said, state could be represented with only 624 numbers. Please tell us how did you observe 1248?
EDIT:
I have consistent results with this code, could you run it and check too?
#include <fstream>
#include <random>
#include <iostream>
std::mt19937 deser(std::string fname)
{
std::ifstream f{fname, std::ifstream::binary};
std::mt19937 res;
f >> res;
return res;
}
void ser(std::string fname, std::mt19937 rng)
{
std::ofstream f(fname, std::ofstream::binary);
f << rng;
}
void printRand(std::mt19937 rng)
{
std::uniform_int_distribution<> uid{1, 100};
std::cout << uid(rng) << std::endl;
}
int main()
{
auto fname{"R:\\RngState.txt"};
std::mt19937 rng{std::random_device{}()};
ser(fname, rng);
printRand(rng);
rng = deser(fname);
printRand(rng);
return 0;
}
As evident from the algorithm, a Mersenne Twister engine needs to remember
n = "degree of occurrence"
integers of size
w = "word size"
bits to generate the series. For mt19937, it holds n = 624 and w = 32 by definition. So the state of mt19937 is uniquely determined by 624 32-bit integers.
Your implementation of the generator may of course safe more temporary results to speed up computation, but the state of the engine is given by exactly those 624 integers, there is no point in writing the rest of the state.
Related
How do I generate a random double in C++ that uses exponential distribution, and a mean with or without a standard deviation? For example, I want to make a simulation where there is a queue with processes in it. Knowing that the mean run time of the processes is 60 seconds, how can I generate random run time values for each process?
When you mention mean and standard deviation, I think what you're looking for is normal distribution, not exponential distribution.
You may be interested to take a look at std::normal_distribution.
If you look at the linked documentation, you'll find an example of how to use it:
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
int main()
{
std::random_device rd{};
std::mt19937 gen{rd()};
// values near the mean are the most likely
// standard deviation affects the dispersion of generated values from the mean
std::normal_distribution<> d{5,2};
std::map<int, int> hist{};
for(int n=0; n<10000; ++n) {
++hist[std::round(d(gen))];
}
for(auto p : hist) {
std::cout << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
From cppreference.com
Exponential distribution is not the same thing, and it takes a single parameter, the rate of events, called lambda.
For future readers looking for exponential distribution (since the question explicitly mention it in the title), the standard implements the exponential distribution through std::exponential_distribution.
The C++ Standard Library provides std::exponential_distribution(1), which
Produces random non-negative floating-point values x, distributed according to probability density function:
P(x|λ) = λe-λx
Given such a distribution(2),
The mean or expected value of an exponentially distributed random variable X with rate parameter λ is given by
E[X] = 1 / λ
So that you can derive the parameter lambda from the required mean:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::seed_seq ss{ rd(), rd(), rd() };
std::mt19937 gen{ss};
constexpr double mean{ 60 };
constexpr double lambda{ 1.0 / mean };
std::exponential_distribution<> d(lambda);
for( int n=0; n<10; ++n ) {
std::cout << d(gen) << '\n';
}
}
https://en.cppreference.com/w/cpp/numeric/random/exponential_distribution
https://en.wikipedia.org/wiki/Exponential_distribution
string bolsa_letras::letters_generator(int quantity){
int already_generated = 0;
map<char, int> aux = values;
string out;
while(already_generated != quantity){
char generated_char = 'A' + rand()%26;
if(aux[generated_char] > 0){
out.push_back(generated_char);
aux[generated_char]--;
already_generated++;
}
}
return out;
}
Above is the code that given a number generates random letters.
The map saves the letters and the times that letters can be appeared. The problem is that every time i run the code, it prints the same: NLRBBMQH. Why is so?
I have include cstdlib for the rand function.
A deterministic program cannot naturally generate randomness. We need to get that randomness from elsewhere. In the old days of rand(), we'd generally seed the RNG with the result of std::time(NULL) to produce a different state at each run.
Nowadays, we use the tools provided by <random> which are "more random".
From cppreference.com's documentation on std::uniform_int_distribution you can find an example for integers of type int. Now, char is an integer type too. Let us tweak their example a tiny bit:
#include <random>
#include <iostream>
int main()
{
std::random_device rd; // Will be used to obtain a seed for the random number engine
std::mt19937 gen(rd()); // Standard mersenne_twister_engine seeded with rd()
std::uniform_int_distribution<char> dis('A', 'Z');
for (int n=0; n<10; ++n) {
std::cout << dis(gen) << ' ';
}
std::cout << '\n';
}
And tadaaaa! a random letter generator :)
Live demo
For my program, I needed so far to draw one random value in [0..k[ from time to time, and using C++11 <random> features works really well. My current code is something like
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
Now, I need to draw in a row n different values in [0..k[. I was looking for something in <random> allowing that, but either I am not able to find it, or such a thing does not exist yet. Is there a clever, more elegant way to proceed than calling my getRandNum function and repeat until I get n different values?
EDIT: to give an idea, in my program k is some thousands and n some tens.
This solution is not C++ specific but can be easily implemented in any language.
What you want is essentially shuffle numbers 0 to k and pick the first n numbers, where n <= k.
This can be done using a reservoir sampling algorithm. See this wikipedia link for the pseudocode.
Note that it is possible to get the n numbers without storing all k numbers and shuffling them. That is, it is possible to just use O(n) space, where n is the number of random numbers you wish to obtain, instead of O(k). The time complexity for this algorithm is O(k), if we assume generating the random number takes O(1) time.
If k is several thousands and n is tens, then a permutation generation is really not the best choise. But calling getRandNum is not what you want too, because it can return the same value several times.
One option is to generate random sequence all at once, checking that the numbers don't repeat. The easiest (and may be even the most efficient) way to achieve this is to use a set.
Like so:
#include <vector>
#include <set>
#include <iostream>
#include <random>
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
std::set<int> getRandSequence(int limit, int n);
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
std::set<int> Random::getRandSequence(int limit, int n)
{
std::set<int> generatedSequence;
while (generatedSequence.size() < n) //size() for set is O(1) if I'm not mistaken
generatedSequence.insert(getRandNum(limit));
return generatedSequence;
}
int main()
{
Random r;
auto sequence = r.getRandSequence(1000, 10);
std::cout << "Seq;uence: " << std::endl;
for (int number : sequence)
std::cout << number << std::endl;
std::cout << "End" << std::endl;
return 0;
}
Ideone demo.
By the way, random_device creation is expensive, but uniform_int_distribution creation, as far as I remember, is not. So this might be even more efficient:
std::set<int> Random::getRandSequence(int limit, int n)
{
std::uniform_int_distribution<int> uiniformDistribution(0, limit);
std::set<int> generatedSequence;
while (generatedSequence.size() < n)
generatedSequence.insert(uiniformDistribution(rng));
return generatedSequence;
}
Besides, when you get a uniform distribution and then apply % limit to it, you don't get a uniform distribution anymore.
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, 1500); // define the range
for(int a=0; a<limit; a++){
cout << distr(eng); //draw random nubmer
Is there a function for obtaining uniformly distributed pseudo-random integers in some specified range? I could write my own function using rand, but this seems like a common enough situation that there's probably something in the STL for it.
Boost provides many tools for random number generation.
For uniform distributions you have this one:
http://www.boost.org/doc/libs/1_49_0/doc/html/boost/random/uniform_real_distribution.html
EDIT: updated to include the new C++11 implementation. For the case of integers, here you have the reference:
http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
A simple example would be:
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 6);
for(int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
To generate pseudo-random numbers in C++, a very good option is using the Mersenne twister pseudo-random number generator engine: std::mt19937 from the <random> header.
We can think of this engine as a black-box that spits out high-quality random bits.
Then, these random bits can be shaped in some integers output using a distribution; in particular, to get uniformly distributed pseudo-random numbers, a std::uniform_int_distribution can be used.
Note that the engine object must be initialized with a seed.
std::random_device can be used for that purpose.
So, this process can be summarized in three logical steps:
Create an instance of std::random_device, to get a non-deterministic seed for the Mersenne twister engine.
Create an instance of std::mt19937 engine, to get high-quality pseudo-random bits.
Use a std::uniform_int_distribution to shape these random bits in uniformly-distributed integers.
Compilable C++ code follows:
#include <iostream> // for console output
#include <random> // for pseudo-random number generators and distributions
int main()
{
// Use random_device to generate a seed for Mersenne twister engine.
std::random_device rd;
// Use Mersenne twister engine to generate pseudo-random numbers.
std::mt19937 engine(rd());
// "Filter" MT engine's output to generate pseudo-random integer values,
// **uniformly distributed** on the closed interval [0, 99].
// (Note that the range is [inclusive, inclusive].)
std::uniform_int_distribution<int> dist(0, 99);
// Generate and print 10 pseudo-random integers
for (int i = 0; i < 10; ++i)
{
std::cout << dist(engine) << ' ';
}
std::cout << std::endl;
}
For more details on generating pseudo-random numbers in C++ (including reasons why rand() is not good), see this video by Stephan T. Lavavej (from Going Native 2013):
rand() Considered Harmful
To generate one or specified number of random variables with uniform distribution on integer domain using std::generate_n and boost:
#include <iostream>
#include <algorithm>
#include <boost/random.hpp>
/*
*
*/
int main(int argc, char** argv) {
boost::mt19937 rand_generator(std::time(NULL));
boost::random::uniform_int_distribution<> int_distribution(0, 100);
//Need to pass generator
std::cout << int_distribution(rand_generator) << std::endl;
//Associate generator with distribution
boost::random::variate_generator<boost::mt19937&,
boost::random::uniform_int_distribution<>
> int_variate_generator(rand_generator, int_distribution);
//No longer need to pass generator
std::cout << int_variate_generator() << std::endl;
std::generate_n( std::ostream_iterator<int>(std::cout, ","), 3, int_variate_generator);
return 0;
}
Is there a function for obtaining uniformly distributed pseudo-random integers in some specified range? I could write my own function using rand, but this seems like a common enough situation that there's probably something in the STL for it.
Boost provides many tools for random number generation.
For uniform distributions you have this one:
http://www.boost.org/doc/libs/1_49_0/doc/html/boost/random/uniform_real_distribution.html
EDIT: updated to include the new C++11 implementation. For the case of integers, here you have the reference:
http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
A simple example would be:
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 6);
for(int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
To generate pseudo-random numbers in C++, a very good option is using the Mersenne twister pseudo-random number generator engine: std::mt19937 from the <random> header.
We can think of this engine as a black-box that spits out high-quality random bits.
Then, these random bits can be shaped in some integers output using a distribution; in particular, to get uniformly distributed pseudo-random numbers, a std::uniform_int_distribution can be used.
Note that the engine object must be initialized with a seed.
std::random_device can be used for that purpose.
So, this process can be summarized in three logical steps:
Create an instance of std::random_device, to get a non-deterministic seed for the Mersenne twister engine.
Create an instance of std::mt19937 engine, to get high-quality pseudo-random bits.
Use a std::uniform_int_distribution to shape these random bits in uniformly-distributed integers.
Compilable C++ code follows:
#include <iostream> // for console output
#include <random> // for pseudo-random number generators and distributions
int main()
{
// Use random_device to generate a seed for Mersenne twister engine.
std::random_device rd;
// Use Mersenne twister engine to generate pseudo-random numbers.
std::mt19937 engine(rd());
// "Filter" MT engine's output to generate pseudo-random integer values,
// **uniformly distributed** on the closed interval [0, 99].
// (Note that the range is [inclusive, inclusive].)
std::uniform_int_distribution<int> dist(0, 99);
// Generate and print 10 pseudo-random integers
for (int i = 0; i < 10; ++i)
{
std::cout << dist(engine) << ' ';
}
std::cout << std::endl;
}
For more details on generating pseudo-random numbers in C++ (including reasons why rand() is not good), see this video by Stephan T. Lavavej (from Going Native 2013):
rand() Considered Harmful
To generate one or specified number of random variables with uniform distribution on integer domain using std::generate_n and boost:
#include <iostream>
#include <algorithm>
#include <boost/random.hpp>
/*
*
*/
int main(int argc, char** argv) {
boost::mt19937 rand_generator(std::time(NULL));
boost::random::uniform_int_distribution<> int_distribution(0, 100);
//Need to pass generator
std::cout << int_distribution(rand_generator) << std::endl;
//Associate generator with distribution
boost::random::variate_generator<boost::mt19937&,
boost::random::uniform_int_distribution<>
> int_variate_generator(rand_generator, int_distribution);
//No longer need to pass generator
std::cout << int_variate_generator() << std::endl;
std::generate_n( std::ostream_iterator<int>(std::cout, ","), 3, int_variate_generator);
return 0;
}