Note that there are some explanatory texts on larger screens.

plurals
  1. POMersenne twister warm up vs. reproducibility
    text
    copied!<p>In my current C++11 project I need to perform M simulations. For each simulation <code>m = 1, ..., M</code>, I randomly generate a data set by using a <code>std::mt19937</code> object, constructed as follows:</p> <pre><code>std::mt19937 generator(m); DatasetFactory dsf(generator); </code></pre> <p>According to <a href="https://stackoverflow.com/a/15509942/1849221">https://stackoverflow.com/a/15509942/1849221</a> and <a href="https://stackoverflow.com/a/14924350/1849221">https://stackoverflow.com/a/14924350/1849221</a>, the Mersenne Twister PRNG benefits from a warm up phase, which is currently absent in my code. I report for convenience the proposed snippet of code:</p> <pre><code>#include &lt;random&gt; std::mt19937 get_prng() { std::uint_least32_t seed_data[std::mt19937::state_size]; std::random_device r; std::generate_n(seed_data, std::mt19937::state_size, std::ref(r)); std::seed_seq q(std::begin(seed_data), std::end(seed_data)); return std::mt19937{q}; } </code></pre> <p>The problem in my case is that I need reproducibility of results, i.e., among different executions, for each simulation, the data set has to be the same. That's the reason why in my current solution I use the current simulation to seed the Mersenne Twister PRNG. It seems to me that the usage of <code>std::random_device</code> prevents data from being the same (AFAIK, this is the exact purpose of <code>std::random_device</code>). </p> <p><strong>EDIT:</strong> by <em>different executions</em> I mean re-launching the executable.</p> <p>How can I introduce the afore-mentioned warm up phase in my code without affecting reproducibility? Thanks.</p> <h2>Possible solution #1</h2> <p>Here's a tentative implementation based on the second proposal by @SteveJessop</p> <pre><code>#include &lt;random&gt; std::mt19937 get_generator(unsigned int seed) { std::minstd_rand0 lc_generator(seed); std::uint_least32_t seed_data[std::mt19937::state_size]; std::generate_n(seed_data, std::mt19937::state_size, std::ref(lc_generator)); std::seed_seq q(std::begin(seed_data), std::end(seed_data)); return std::mt19937{q}; } </code></pre> <h2>Possible solution #2</h2> <p>Here's a tentative implementation based on the joint contribution by @SteveJassop and @AndréNeve. The <code>sha256</code> function is adapted from <a href="https://stackoverflow.com/a/10632725/1849221">https://stackoverflow.com/a/10632725/1849221</a></p> <pre><code>#include &lt;openssl/sha.h&gt; #include &lt;sstream&gt; #include &lt;iomanip&gt; #include &lt;random&gt; std::string sha256(const std::string str) { unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256_CTX sha256; SHA256_Init(&amp;sha256); SHA256_Update(&amp;sha256, str.c_str(), str.size()); SHA256_Final(hash, &amp;sha256); std::stringstream ss; for(int i = 0; i &lt; SHA256_DIGEST_LENGTH; i++) ss &lt;&lt; std::hex &lt;&lt; std::setw(2) &lt;&lt; std::setfill('0') &lt;&lt; (int)hash[i]; return ss.str(); } std::mt19937 get_generator(unsigned int seed) { std::string seed_str = sha256(std::to_string(seed)); std::seed_seq q(seed_str.begin(), seed_str.end()); return std::mt19937{q}; } </code></pre> <p>Compile with: <code>-I/opt/ssl/include/ -L/opt/ssl/lib/ -lcrypto</code> </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload