using bind vs using pointers with random number generators - c++

I had the following implementation in my code:
// first solution
//random.h
class Random{
public:
std::mt19937* gen;
std::uniform_real_distribution<double>* dis;
}
//random.cpp
Random::Random()
{
std::mt19937_64::result_type seed = chrono::high_resolution_clock::now().time_since_epoch().count();
gen = new std::mt19937(seed);
dis = new std::uniform_real_distribution<double>(0.0,1.0);
}
double Random::next()
{
double rand = 0;
rand_int = (*dis)(*gen);
return rand;
}
On the other hand someone else in the company did a different implementation, where he used the bind feature from c++11 as follows:
// second solution
//random.h
class Random{
public:
std::function<double()> real_rand;
}
//random.cpp
Random::Random()
{
std::mt19937_64::result_type seed = chrono::high_resolution_clock::now().time_since_epoch().count();
real_rand = std::bind(std::uniform_real_distribution<double>(0.0,1.0), mt19937_64(seed))
}
double Random::next()
{
double rand = 0;
rand = real_rand();
return rand;
}
Taking into account that you are supposed to have only one PRNG object, and you are supposed to seed it once, then you call that object every time you need a new random number, as the seed is used to create a series of random numbers in the PRNG. I can clearly see this being the case for the first solution.
The question is, how is bind() working behind the scenes? Is it creating a new object on every call? Is it really calling the (constructor) or the function()? How can it tell which one to call? Are there any differences between the solutions?

std::bind generates a function object which encapsulates the arguments provided to it. In effect your colleague's code generates the following object:
struct random_call
{
random_call(unsigned seed)
: _mt19937_64(seed)
, _uniform_real(0.0, 1.0)
{}
double operator() {
return _uniform_real(_mt19937_64);
}
std::mt19937_64 _mt19937_64;
std::uniform_real_distribution<double> _uniform_real;
};
so it looks ok (and actually pretty clever) to me!
One caveat is that you probably wouldn't want to make any copies of the binder object - even if it turns out to be copyable, copying it and then calling operator() on the original and the copy will yield the same numbers.

Related

How to declare a class template in a structure and initialize later?

I am trying to model a tolerance stackup. I made a structure Layer that holds the lower limit (tol[0]) and upper (tol[1]) limit of the tolerance range. I want to generate a random value between tol[0] and tol[1] and assign it to val.
My implementation declares the uniform_real_distribution class template in the structure and initializes it in main(), but I'm getting errors during compilation that make me think I can't use class templates this way.
#include <random>
struct Layer {
double tol[2];
double val;
std::string name;
std::uniform_real_distribution<double> distribution;
};
int main()
{
Layer block;
block.tol[0] = .240;
block.tol[1] = .260;
std::default_random_engine generator;
block.distribution(block.tol[0],block.tol[1]);
block.val = block.distribution(generator);
return 0;
}
I'm getting the following error from g++:
error: no match for call to '(std::uniform_real_distribution<double>) (double&, double&)'
block.distribution(block.tol[0],block.tol1[]);
^
I've got quite a few Layer structures that I create so I was hoping to associate the distribution with struct, but I'm not sure that it is possible anymore.
At this stage, the object is already constructed, so you can do:
block.distribution = std::uniform_real_distribution<double>(block.tol[0],block.tol[1]);
You can also initialize the structure directly:
Layer block{{.240,.260}, 0, "", std::uniform_real_distribution<double>(.240, .260)};

Factory class driven by a map for determining the object type

I'm having a brain freeze and can't figure out how to best solve this issue. I'm creating objects from my factory class by calling
CreateEnvironment<T>(ARGS);
Now lets say that i want to save alot of class-types into a map and iterate through the map and call the method at runtime like this:
ITERATION:
CrateEnvironment<(*it)>(world);
(*it) should be the class type, which could be FOO or BAR for example. How do i achieve this instead of having alot of if statements?
Best regards
For each class you could have a function that would serve as generator and create a new object and return a pointer to it (or better, a shared_ptr).
In your container you could then store a the generator function pointers.
Step by step explanations:
Suppose you have these classes to populate your world:
struct GO { virtual void say_hello()=0; }; // Game Object
struct A:GO { void say_hello() { cout<<"I'm a werewolf\n";} };
struct B:GO { void say_hello() { cout<<"I'm a soldier\n";}};
You can then define a generic GO generator:
template <class T>
shared_ptr<GO> generator() {
return make_shared<T>();
};
This would serve as subsititue for your "type" container (for the simplicity of the example I've used a vector, but you could easily opt for a map):
typedef shared_ptr<GO> (*gen_fn)();
vector <gen_fn> generators{generator<A>, generator<B>};
You could then populate your universe like this, without any if:
vector<shared_ptr<GO>> universe;
default_random_engine generator;
uniform_int_distribution<int> distribution(0,generators.size()-1);
for (int i=0; i<10; i++) {
int mytype = distribution(generator);
universe.push_back(generators[mytype]());
}
for (auto x: universe)
x->say_hello();
And here an online demo.
Statistical remark: As the distribution is uniform, you will have a high probability of having the roughly the same proportion of each type of object. If you'd like to have different distribution, you could add several times generators of the same type. For example, with generators{generator<A>, generator<B>, generator<B>}; you'd have around 66% of soldiers and 33% of werewolves.

thread safe random number with same seed for intel TBB threads

I have a function object for parallelizing a for_each() algorithm using Thread Building Blocks,
The function object uses a random number generator RND whose operator method () generates a random number.
Problem: I need a random number number generator to 1) initialize only once in the function object 2) should be threadsafe and 3) can be provided same seed so that same results could be obtained.
I dont know much about generating thread safe random number generators in function objects as such. I tried using my own random generator class (using engine, distribution and generators) (using boost libraries)
but I need something simple such as erand() ? or something like that for which we dont need to do write separate code.
struct func {
public:
func() { }
func(int t_) : t(t_) { }
template <typename house_t>
void operator()(house_t house) const {
if ( RND() )
{ //do something with the house }
} //operator
private:
int t;
};
//Parallel for_each
tbb::parallel_for_each( house.begin(), house.end(), func(t) );
Please suggest

How to std::bind() to create a data member?

I'm generating random values with C++11 nice new generators and distributions. In a function it works like a charm and looks like this:
void foo() {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
auto dice = bind(distribution, generator);
// dice() will now give a random unsigned value
}
But how can I put all three objects in a class as data members? I can simply write generator and distribution as data members, but how do I make dice a data member without knowing (or wanting to know) its exact type? Suprisingly this
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
decltype(bind(distribution, generator)) dice;
};
yields the error error C2660: 'bind' : function does not take 2 arguments in Visual Studio 2013.
You could always gasp write a function instead of using a lambda/bind/etc.:
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
public:
auto dice() -> decltype(distribution(generator)) {
return distribution(generator);
}
// or alternatively
auto operator() () -> decltype(distribution(generator)) {
return distribution(generator);
}
};
Bonus points for parameterizing on the type of the generator and/or distribution, and for holding the generator with a std::shared_ptr so that you can make several objects with differing distributions that share the same engine. You'll eventually want a constructor to seed the generator as well - Ideally with something like std::random_device{}().
Or, the answer I think you are looking for:
class X {
mt19937 generator{std::random_device{}()};
uniform_int_distribution<unsigned> distribution{1,6};
public:
decltype(bind(std::ref(distribution), std::ref(generator))) dice{
bind(std::ref(distribution), std::ref(generator))
};
};
I'm sorry I mocked you for trying to use bind in the first place: it's actually kind of neat that you can write this class with "no code" in C++11. We need to get type-inference for class member declarations in C++17 so this could be:
class X {
auto generator = mt19937{std::random_device{}()};
auto distribution = uniform_int_distribution<unsigned>{1,6};
public:
auto dice = bind(std::ref(distribution), std::ref(generator));
};
Given that the latest Concepts Lite paper proposes using concept names anywhere in the language where auto can appear to mean "infer type, ill-formed if type doesn't model named concept," auto member declarations may not be out of the question.
It works on GCC. I’m pretty sure that’s just a compiler bug. Unfortunately this means that you have to bite the bitter pill and use one of the workarounds described in the other answers.
The result of std::bind is unspecified: this means that you cannot store its raw result without type inference. However, you can use std::function to encapsulate the result of bind:
#include <functional>
std::function<unsigned()> dice(std::bind(distribution, generator));
auto result = dice();
EDIT: As whoever said above, this is most clearly a Visual Studio issue. I can confirm that this compiles with VS2013:
#include <functional>
#include <random>
using namespace std;
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
std::function<unsigned()> dice;
public:
X() : dice(bind(distribution, generator)) {}
unsigned roll() { return dice(); }
};
but changing the type of dice to decltype(bind(distribution, generator)) makes the whole thing fail with flying colors (even though it still works with clang).

c++ class members and delayed initialization [duplicate]

This question already has an answer here:
c++ calling non-default constructor as member [duplicate]
(1 answer)
Closed 9 years ago.
I am currently looking into new c++11 random library. For simplification, I created following class
class my_rand {
private:
std::mt19937_64 eng;
public:
my_rand() {
std::array<int, std::mt19937::state_size> seed_data;
std::random_device rd;
std::generate_n(seed_data.data(), seed_data.size(), std::ref(rd));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
this->eng.seed(seq);
};
unsigned long long operator() () {
return this->eng();
};
};
so that I can just do my_rand rand; once and then repeatedly call rand() to generate random numbers.
However, now I want to use std::uniform_int_distribution to set bound to numbers I get. It seams obvious to specify bounds while creating the object, so that invocations stay the same. The problem is, if I add private member (something like std::uniform_int_distribution<long long> uid;) then later in constructor I will not be able to set bounds because uid will already be initialized. I could not find method of std::uniform_int_distribution which allowed to set limits after it is created.
I may well be missing some point here, so thanks in advance for any help.
Use initializer lists to construct member variables or base classes. (See here for more info)
my_rand(...arguments...) : uid(...arguments...) //<-- Initializer list
{
//...stuff...
} //<-- No semicolon after function definition.
If that doesn't suit your needs, you can always go like this:
myVar = int(27);
For example:
//Initial construction:
std::uniform_int_distribution<> testA(1, 6);
//Re-assignment by copy-construction (move-construction actually)
//and a temporary object.
testA = std::uniform_int_distribution<>(5, 10);