Generate a random number using a mean value and exponential distribution c++ - c++

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

Related

How to generate lognormal distributed random variable using c++ boost library

I am trying to generate different random numbers following different distributions to conduct some experiments on them. I choose the boost library in c++ because I saw a large number of functions build in there. For example, in lognormal distribution, I followed this page https://www.boost.org/doc/libs/1_43_0/libs/math/doc/sf_and_dist/html/math_toolkit/dist/dist_ref/dists/lognormal_dist.html and some more. But I cannot understand how I can actually generate the random number. I tried
int main(){boost::math::lognormal_distribution<> myLognormal{0,8};cout << myLognormal() << endl; return 0;}
but its doing nothing but error.
You have had some helpful comments already. Let me tie it together into an example:
Using Standard Library (C++11 and up)
Live On Coliru
#include <random>
#include <iostream>
int main() {
std::mt19937 engine; // uniform random bit engine
// seed the URBG
std::random_device dev{};
engine.seed(dev());
// setup a distribution:
double mu = 1.0;
double sigma = 1.0;
std::lognormal_distribution<double> dist(mu, sigma);
for (int i = 1'000; i--;) {
std::cout << dist(engine) << "\n";
}
}
Plotting those numbers:
https://plotly.com/~sehe/27/
Using Boost Random
Same with Boost Random:
Live On Coliru
#include <boost/random.hpp>
#include <boost/random/random_device.hpp>
#include <iostream>
int main() {
boost::random::mt19937 engine; // uniform random bit engine
// seed the URBG
boost::random::random_device dev;
engine.seed(dev); // actually without call operator is better with boost
// setup a distribution:
double mu = 1.0;
double sigma = 1.0;
boost::random::lognormal_distribution<double> dist(mu, sigma);
for (int i = 1'000; i--;) {
std::cout << dist(engine) << "\n";
}
}
Note that you need to link the Boost Random library then.

Can I use a single `default_random_engine` to create multiple normally distributed sets of numbers?

I want to generate a set of unit vectors (for any arbitrary dimension), which are evenly distributed across all directions. For this I generate normally distributed numbers for each vector component and scale the result by the inverse of the magnitude.
My question: Can I use a single std::default_random_engine to generate numbers for all components of my vector or does every component require its own engine?
Afaik, each component needs to be Gaussian-distributed independently for the math to work out and I cannot assess the difference between the two scenarios. Here's a MWE with a single RNG (allocation and normalization of vectors is omitted here).
std::vector<std::vector<double>> GenerateUnitVecs(size_t dimension, size_t count)
{
std::vector<std::vector<double>> result;
/* Set up a _single_ RNG */
size_t seed = GetSeed(); // system_clock
std::default_random_engine gen(seed);
std::normal_distribution<double> distribution(0.0, 1.0);
/* Generate _multiple_ (independent?) distributions */
for(size_t ii = 0; ii < count; ++ii){
std::vector<double> vec;
for(size_t comp = 0; comp < dimension; ++comp)
vec.push_back(distribution(gen)); // <-- random number goes here
result.push_back(vec);
}
return result;
}
Thank you.
The OP asked:
My question: Can I use a single std::default_random_engine to generate numbers for all components of my vector or does every component require its own engine?
I would suggest as others have stated in the comments about not using std::default_random_engine and instead use std::random_device or std::chrono::high_resolution_clock
To use random_device for a normal distribution or Gaussian it is quite simple:
#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';
}
}
To use std::chrono::high_resolution_clock: there is a little more work but just as easy.
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
#include <limits>
#include <chrono>
class ChronoClock {
public:
using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock>;
static unsigned int getTimeNow() {
unsigned int now = static_cast<unsigned int>(Clock::now().time_since_epoch().count());
return now;
}
};
int main() {
/*static*/ std::mt19937 gen{}; // Can be either static or not.
gen.seed( ChronoClock::getTimeNow() );
// 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';
}
}
As you can see from the examples above where these are shown here from cppreference.comthere is a single engine, single seed, and a single distribution, that it is generating random numbers or sets of random numbers with a single engine.
EDIT - Additionally you can use a class that I've written as a wrapper class for random engines and random distributions. You can refer to this answer of mine here.
I am assuming you are not generating random numbers in parallel. Then theoretically, there is no problem with generating random independent Gaussian vectors with one engine.
Each call to std::normal_distribution's () operator gives you a random real-valued number following specified Gaussian distribution. Successive calls of () operator give you independent samples. The implementation in gcc (my version: 4.8) uses the Marsaglia Polar method for standard normal random number generation. You can read this Wikipedia page for more detail.
However, for rigorous scientific research that demands high quality randomness and a huge amount of random samples, I would recommend using the Mersenne-Twister engine (mt19937 32-bit or 64-bit) instead of the default engine, since it is based on a well-established method, has long period and performs well on statistical random tests.

Extract values from a set according to a given probability distribution

I have to tackle this problem:
vector<int> myset={1,2,3,4};
vector<double> distribution ={0.01,0.1,0.3,0.59};
I have to pick a number of values from myset according to given distribution. Actually distribution and myset aren't fixed. They are of the same dimension, but this dimension can change and be pretty large too. I could uniformly extract a number in the range [0 100] and do like this:
int extracted_numb;
int numb = rand(0,100);
if(numb<1)
extracted_numb=myset[0];
else if(numb<11)
extracted_numb=myset[1];
else if(numb<41)
extracted_numb=myset[2];
else
extracted_numb=myset[3];
But I repeat, I don't know in the real case the dimension of distribution and myset (because is a user parameter) and thus I don't know how many if to do.
I ask if there is a good algorithm for this problem, and maybe some native library of C++ or in Boost that already accomplish it
(I'm using Boost 1.63 and C++11)
With C++11, use random::discrete_distribution to select an index into myset. (Boost has a similar function.)
Example (adapted from the cppreference link):
#include <iostream>
#include <map>
#include <random>
#include <vector>
int main()
{
std::vector<int> myset = {10,22,35,47};
std::vector<double> distribution = {0.01,0.1,0.3,0.59};
std::random_device rd;
std::mt19937 gen(rd());
std::discrete_distribution<> d(distribution.begin(), distribution.end());
std::map<int, int> m;
for(int n=0; n<10000; ++n) {
++m[myset[d(gen)]];
}
for(auto p : m) {
std::cout << p.first << " generated " << p.second << " times\n";
}
}
(Live on coliru)

Math.Random equivalent in C++

I have been programming in Java for three years, and have been using Math.random() to get a random number. I'm fairly new to C++, and I was wondering if there was equivalent to that but in C++? A specific function or method that I could use? Also include an explanation. Thanks so much!
C++ provides a fairly nice random number library, <random>, but it doesn't yet have the sort of dead simple API beginners generally want. It's easy to produce such an API, as I show below, and hopefully some such API will be included at some point.
The C++ API splits random number generation into two parts, sources of 'randomness', and machinery for turning randomness into numbers with specific distributions. Many basic uses of random numbers don't particularly care how good (or fast, or small) the source of 'randomness' is, and they only need 'uniform' distributions. So the typically recommended source of randomness is the "Mersenne Twister" engine. You create one of these and seed it like so:
#include <random>
int main() {
std::mt19937 eng{42};
}
Now eng is an object that can be passed around and used as a source for random bits. It's a value-type so you can make copies of it, assign to it, etc. like a normal value. In terms of thread safety, accessing this value is like accessing any other, so if you need multiple threads you should either put an engine on each thread or use mutual exclusion.
To turn data from an engine into random values, use a distribution object. Typical uses need 'uniform' distributions, so for integral values use std::uniform_int_distribution<int>.
std::uniform_int_distribution<int> dice{1, 6};
A distribution object is a function object, and you get values from it by calling it and passing it the source of randomness it will use:
auto die_roll = dice(eng);
One thing to keep in mind is that the math for producing random values should be encapsulated inside a distribution object. If you find yourself doing some kind of transformation on the results then you probably should be using a different distribution. Don't do things like dist(eng) % 10 or dist(eng) / 6.0 + 10.0. There are several other distributions provided in the library, including ones for producing floating point values with various distributions.
Here's a pretty easy way to wrap the <random> functionality for simple usage:
#include <iostream>
#include <random>
std::mt19937 seeded_eng() {
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
return std::mt19937(seed);
}
class Random {
std::mt19937 eng = seeded_eng();
public:
auto operator()(int a, int b) {
std::uniform_int_distribution<int> dist(a, b);
return dist(eng);
}
};
int main() {
Random random;
for (int i = 0; i < 10; ++i) {
std::cout << "Dice: " << random(1, 6) << " " << random(1, 6) << '\n';
}
}
#include <iostream>
#include <ctime>
int main()
{
srand((unsigned int) time (NULL)); //activates the generator
//...
int a = rand()%10; //gives a random from 0 to 9
double r = ((double) rand() / (RAND_MAX)); //gives a random from 0 to 1
int max, min;
//...
int c = (rand()%(max - min)) + min; //gives a random from min to max
//...
return 0;
}
These ways are the simpliest.
Sometimes it means "the best", sometimes - not.
1.srand((unsigned) time(0)) will make sure that everytime you run your program that the rand() function will get a new seed causing it to produce a different or "random" output. Without stand((unsigned) time(0)), the rand() will produce the same output.
2.int Number, is used to store the random number that is being generated by the rand() function. The rand() % 27 will give you numbers 0-26.
#include <iostream>
#include <ctime>
int main()
{
srand((unsigned)time(0))
int Number = ((rand() % 27));
cout << Number << endl;
return 0;
}
Here is a simple solution. The function random is overloaded. One instance is used to acquire a random number generator for integers. Another instance is used to acquire a random number generator for doubles. After you have these two functions, applications becomes rather trivial as can be observed in the main function.
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <ostream>
#include <random>
// Single global engine, a better version of std::rand
std::mt19937 engine{ std::random_device()() };
// Returns a generator producing uniform random integers in the closed range [a, b]
std::function<int()> random(int a, int b)
{
auto dist = std::uniform_int_distribution<>(a, b);
return std::bind(dist, std::ref(engine));
}
// Returns a generator producing uniform random doubles in the half-open range [x, y)
std::function<double()> random(double x, double y)
{
auto dist = std::uniform_real_distribution<>(x, y);
return std::bind(dist, std::ref(engine));
}
int main()
{
const auto no_iterations = int{ 12 };
auto dice = random(1, 6);
// Roll the dice a few times and observe the outcome
std::generate_n(std::ostream_iterator<int>(std::cout, " "),
no_iterations, dice);
std::cout << std::endl;
// U is a uniform random variable on the unit interval [0, 1]
auto U = random(0.0, 1.0);
// Generate some observations
std::vector<double> observations;
std::generate_n(std::back_inserter(observations), no_iterations, U);
// Calculate the mean of the observations
auto sum = std::accumulate(observations.cbegin(), observations.cend(), 0.0);
auto mean = sum / no_iterations;
std::cout << "The mean is " << mean << std::endl;
return 0;
}

What's the standard way for getting uniformly distributed random integers in C++?

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;
}