How to initialize boost :: mt19937 with multiple values ​​without using C ++ 11

I can use:

boost::mt19937 gen(43); 

this works fine, but what if I want more than a 32-bit seed before using the random number generator? Is there an easy way to put 64-bit or 128-bit seed in a Mersenne Twister?

I found some examples of loading multiple values ​​before generating the results, but none of them work.

There are several problems with this code:

 std::vector<unsigned int> seedv(1000, 11); std::vector<unsigned int>::iterator i=seedv.begin(); boost::mt19937 gen2(i, seedv.end()); 

First, calling gen2 () always returns the same value. I don’t know how I ruined it.

Secondly, I do not want 1000 seeds, but when I lower it to 600, it "throws an instance of std :: invalid_argument with enough notes in the call for the seed"

Can this method be reduced to a few seeds?

Here is another sample code that looks easy:

 std::string seedv("thisistheseed"); std::seed_seq q(seedv.begin(),seedv.end()); boost::mt19937 gen2(q); 

but it will not compile. I finally realized that std :: seed_seq is only available in C ++ 11. I was stuck with gcc 4.7 as long as the libraries I depend on are stable.

I suppose I can just stick to the 32 bit seed, but I wanted a little more.

I read this article: Boost Mersenne Twister: how to sow more than one value?

I like the idea of ​​initializing the entire vector from:

 mersenne_twister(seed1) ^ mersenne_twister(seed2) 

but I see no way to do this without changing Mersenne_Twister.hpp

Any suggestions?

UPDATE: another way not to do this!

 unsigned long seedv[4]; seedv[0]=1; seedv[1]=2; seedv[2]=3; seedv[3]=4; boost::mt19937 gen2(seedv,4); 

With proper casting, this should work, but every cast that I tried will still not pass the compiler. I can draw something in C, but C ++ still drinks me ...

+6
source share
4 answers

Use boost::seed_seq instead of std::seed_seq .

Update: Use

 boost::random_device rd; boost::mt19937 eng(rd); 

boost::mt19937 allows boost::mt19937 to sow it either with one value up to 32 bits wide (parameter w base boost::mersenne_twister_engine ), or with a sequence of 624 values ​​(parameter n base template). 624 - the number of elements in the internal state mt19937 .

If you read the documentation, you will see that these two mechanisms distinguish the state of the engine.

  • A single value visit sets each element of the engine state using the complex function of this single value. Segment
  • with a sequence of 624 values, sets each element of the engine condition exactly to the corresponding initial value.

The fact is that boost::mt19937 by itself does not include a mechanism for comparing an arbitrary number of initial values ​​with a fixed number of elements in the internal state. It allows you to set the state directly (using 624 values), and for convenience, it offers a built-in mapping from single 32-bit values ​​to complete, 624 element states.


If you want to use an arbitrary number of input seed values, you will need to implement a mapping of arbitrary sequence sizes to 624 element states.

Keep in mind that the mapping must be designed so that the resulting internal state is a “good” state for the mersenne twister algorithm. This algorithm is based on a shift register and can be subject to internal states that provide a relatively predictable output . Inline matching for single values ​​was designed to minimize this problem, and everything you implement should be the same.

Probably the best way to implement such a comparison, rather than doing the mathematical analysis itself, is simply to use the standard mersenne twister mine clearance algorithm. According to the comment on this answer , C ++ 11 std::seed_seq is specified to perform such a warm-up. Boost includes boost::seed_seq , which apparently does the exact same thing.


Update: Instead of using any arbitrary number of values ​​to compute a sequence of 624 values, you can simply use exactly 624 random values. If the values ​​are unbiased and evenly distributed over a range of 32-bit values, then you will not need a warm-up (well, if you are not astronomically unlucky).

The boost <random> library supports this directly:

 boost::random_device rd; boost::mt19937 eng(rd); 

Please note that the C ++ 11 <random> library does not support seeding in this way.

+4
source

For this reason, there is an assistant seed sequence generator:

The seed_seq class stores a sequence of 32-bit words for planting a pseudo-random number generator. These words will be combined to fill the entire state of the generator. http://www.boost.org/doc/libs/1_57_0/doc/html/boost/random/seed_seq.html

 #include <boost/random.hpp> #include <boost/random/seed_seq.hpp> int main() { boost::random::seed_seq ss({1ul, 2ul, 3ul, 4ul}); boost::mt19937 gen2(ss); } 

You can also pass a pair of iterators to an existing range.

Live on coliru

+3
source

The standard Mersenne Twister is the following typedef:

typedef mersenne_twister_engine<uint32_t,32,624,397,31,0x9908b0df, 11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253> mt19937;

The first type of template is called UintType and is used as an argument to the seed method:

void seed(UIntType value);

Thus, you can use the predefined boost :: mt19937_64 to have a 64-bit seed. You can also create your own mersenne_twister_engine if you want to customize it more.

+2
source

This is not very, but it should be possible:

 std::vector<unsigned int> seedv(1000); seedv[0] = 1; seedv[1] = 2; seedv[2] = 3; seedv[3] = 4; // etc. boost::mt19937 gen2(seedv.begin(), seedv.end()); 

That is, 1000 seeds still pass, although most of them are 0. However, as @ bames53 mentions in a comment, this is not a good idea . It is legal and compiles, but does not do for good seed.

By the way, the array approach should work (at least it should compile):

 unsigned long seedv[4]; seedv[0]=1; seedv[1]=2; seedv[2]=3; seedv[3]=4; boost::mt19937 gen2(seedv, seedv + 4); 

This is an example of using pointers as iterators. 4 not an iterator (usually), but seedv + 4 is (this is the address of the element immediately after the end of seedv ) ..

0
source

Source: https://habr.com/ru/post/973516/


All Articles