How to make boost::exponential_distribution work? - c++

I have been playing with Boost.Random for a day now, and while boost::uniform_int_distribution<> works well, I am having trouble with boost::exponential_distribution<>.
A simple program is worth a thousand words:
#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/exponential_distribution.hpp>
int main() {
boost::mt19937 gen;
boost::exponential_distribution<> dis;
std::cout << dis(gen) << "\n";
return 0;
}
Compiled with Clang 3.0, using Boost 1.39.1 (no, I cannot upgrade Boost).
The output is invariably the same: nan.
I could not find any reported issue so I guess it's me not using the library correctly... Any clue would be appreciated.

Given a random number r, uniformly distributed on [0,1), -log(r) is distributed on (0,infinity) with the distribution exp(-x).
The former is boost::uniform_01().
If you need a distribution p exp(-px), then it's -(1/p)log(r).
In both cases here log(x) is a natural log (base e).
UPD: Using boost::variate_generator seems to work for me (boost 1.43):
#include <iostream>
#include<boost/random.hpp>
int main() {
boost::mt19937 rng(11u);
boost::variate_generator< boost::mt19937&, boost::exponential_distribution<> > rndm(rng, boost::exponential_distribution<>()) ;
std::cout<<rndm()<<"\n";
}
I did not check the distribution though.

Related

Using boost multiprecision with trigonometric function

Consider the following code which creates a multiprecision floating-point number 'a' by using boost.
How do I use boost library to invoke trigonometric functions?
For example, I hope to calculate sin(a).
#include <iostream>
#include "boost/multiprecision/cpp_bin_float.hpp"
using namespace std;
using namespace boost::multiprecision;
typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> float32;
int main (void) {
float32 a("0.5");
return 0;
}
It looks like there is a limitation in the library. When the precision is dropped too low, the sin implementation no longer compiles.
Some intermediate calculations are being done in double precision. The assignment into the result type would be lossy and hence doesn't compile.
Your chosen type actually corresponds to cpp_bin_float_single. That doesn't compile.
As soon as you select cpp_bin_float_double (precision 53 binary digits) or higher, you'll be fine.
I suppose this limitation could be viewed as a bug in some respects. You might report it to the library devs, who will be able to judge whether the related code could use single-precision floats there without hurting the convergence of the sin approximation.
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <iostream>
using namespace std;
using namespace boost::multiprecision;
int main() {
cpp_bin_float_100 a = 1;
cout << setprecision(50) << endl;
cout << sin(a) << endl;
return 0;
}
I've verified digits with Wolfram Mathematica and they are correct:

Generating very large Random numbers using Boost library

I am using boost library for generating very very large Random numbers in the range [0-2^32-1]. But boost library is not working well with this range. It just displaying an error message "Assertion failed min_arg<=max_arg"
Kindly help me out ! here is the code:
#include <iostream>
#include <ctime>
#include <cmath>
#include "boost/random.hpp"
#include <stdint.h>
using namespace std;
int main()
{
long double rangeMin = 0;
long long int rangeMax = (pow(2.0,32.0)-1);
typedef boost::uniform_int<> NumberDistribution;
typedef boost::mt19937 RandomNumberGenerator;
typedef boost::variate_generator<RandomNumberGenerator&,
NumberDistribution> Generator;
NumberDistribution distribution(rangeMin, rangeMax);
RandomNumberGenerator generator;
Generator numberGenerator(generator, distribution);
generator.seed(time(0)); // seed with the current time
cout << numberGenerator() <<endl;
return 0;
}
As per documentation, the default value of the template parameter of boost::uniform_int is int. If you want to generate long long int's, you'll need to use boost::uniform_int<long long int>.

efficient generation of numbers with Boost

I wish to generate more than 10^8 random numbers with Boost. They must be normally distributed with standard deviation 1 and mean 0. Here is my MWE:
#include <iostream>
#include <vector>
#include <time.h>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>
using namespace std;
int main()
{
typedef boost::mt19937 ENG;
typedef boost::normal_distribution<double> DIST;
typedef boost::variate_generator<ENG,DIST> GEN;
ENG eng;
DIST dist(0,1);
GEN gen(eng,dist);
gen.engine().seed(time(0));
vector<double> nums;
for(int i=0; i<500; i++)
{
nums.push_back(gen());
}
return 0;
}
I have 2 questions in this regard:
Is the approach I am using to seed the engine correct? Or do I need to seed it before each number?
Is my method efficient? Or is there a better way?
EDIT Note that there is no bottleneck in the code as such. I am just wondering if my approach is correct from a professional point of view
I should say that the numbers (all of them) have to be scaled by a proper constant afterwards. My plan is to use a for-loop for this.
Best,
Niles.

How to generate random numbers in C++ using <random> header members?

I learned to program in C# and have started to learn C++. I'm using the Visual Studio 2010 IDE. I am trying to generate random numbers with the distribution classes available in <random>. For example I tried doing the following:
#include <random>
std::normal_distribution<double> *normal = new normal_distribution<double>(0.0, 0.0);
std::knuth_b *engine = new knuth_b();
std::variate_generator<knuth_b, normal_distribution<double>> *rnd;
rnd = new variate_generator<knuth_b, normal_distribution<double>>(engine, normal);
The last line gives a compiler error:
IntelliSense: no instance of constructor "std::tr1::variate_generator<_Engine, _Distrib>::variate_generator [with _Engine=std::tr1::knuth_b, _Distrib=std::tr1::normal_distribution]" matches the argument list
My arguments look ok to me, what am I doing wrong? When the variate_generator class here is instantiated, which method do you call to get the next random number i.e. .NET's System.Random.Next()?
There is no variate_generator in C++0x, but std::bind works just as well. The following compiles and runs in GCC 4.5.2 and MSVC 2010 Express:
#include <random>
#include <functional>
#include <iostream>
int main()
{
std::normal_distribution<> normal(10.0, 3.0); // mean 10, sigma 3
std::random_device rd;
std::mt19937 engine(rd()); // knuth_b fails in MSVC2010, but compiles in GCC
std::function<double()> rnd = std::bind(normal, engine);
std::cout << rnd() << '\n';
std::cout << rnd() << '\n';
std::cout << rnd() << '\n';
std::cout << rnd() << '\n';
}
PS: avoid new when you can.
ALERT: Note that the above solution binds a copy of the engine, not a reference to the engine. Thus, if you also do:
std::function rnd2 = std::bind(normal, engine);
then the rnd object and the rnd2 object will produce the exact same sequence of random numbers.

C++: generate gaussian distribution

I would like to know if in C++ standard libraries there is any gaussian distribution number generator, or if you have any code snippet to pass.
Thanks in advance.
The standard library does not. Boost.Random does, however. I'd use that if I were you.
C++ Technical Report 1 adds support for random number generation. So if you're using a relatively recent compiler (visual c++ 2008 GCC 4.3), chances are that it is available out of the box.
See here for sample usage of std::tr1::normal_distribution (and many more).
The GNU Scientific Libraries has this feature. GSL - Gaussian Distribution
The answer to this question changes with C++11 which has the random header which includes std::normal_distribution. Walter Brown's paper N3551, Random Number Generation in C++11 is probably one of the better introductions to this library.
The following code demonstrates how to use this header (see it live):
#include <iostream>
#include <iomanip>
#include <map>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 e2(rd());
std::normal_distribution<> dist(2, 2);
std::map<int, int> hist;
for (int n = 0; n < 10000; ++n) {
++hist[std::floor(dist(e2))];
}
for (auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}
I provide a more general set of examples to random number generation in C++11 in my answer to C++ random float number generation with an example in Boost and using rand() as well.