Search code examples
c++c++11stdmt19937

Save and Load Random Number Generator State in C++11


This question has been asked before (stackoverflow) but the (accepted) answer is not satisfactory.

The following example saves and loads the state but depending on the number of generated values it works or it doesn't:

#include <fstream>
#include <iostream>
#include <random>
#include <cassert>

int main()
{
  const int preN = 4;
  const int middleN = 0;

  // initialize randGen
  std::mt19937 randGen1;
  std::normal_distribution<double> distribution1;


  // print some initial random numbers
  for (int i=0;i<preN;++i)
    std::cout << distribution1(randGen1)<<" ";

  // save state
  std::cout << std::endl << "Saving...\n";
  {
    std::ofstream fout("seed.dat");
    fout << randGen1;
  }

  // maybe advance randGen1
  for (int i=0;i<middleN;++i)
    std::cout << distribution1(randGen1)<<" ";

  // load saved state into randGen2 
  std::cout << std::endl << "Loading...\n";
  std::ifstream fin("seed.dat");
  std::mt19937 randGen2;
  fin >> randGen2;
  std::normal_distribution<double> distribution2;

  // are both randGen equal?
  assert(randGen1 == randGen2);

  // print numbers from both generators
  std::cout << "Generator1\tGenerator2\n";
  std::cout << distribution1(randGen1) << "\t"
            << distribution2(randGen2) << "\n";

  return 0;

}    

With these parameters it works like expected. However, if I set preN=3 the output looks like:

0.13453 -0.146382 0.46065 
Saving...

Loading...
Generator1  Generator2
-1.87138    0.163712

Why did the assert not apply? Now I set preN=3 and middleN=1 and the output is

0.13453 -0.146382 0.46065 
Saving...
-1.87138 
Loading...
Generator1  Generator2
0.163712    0.163712

If I set middleN to anything larger than 1 the assert applies. Can anyone explain what is going on? What am I doing wrong or not understanding?

Tested with GCC5.4.0 and CLANG3.8.0 on Linux


Solution

  • The problem is not your random number generator's state. The problem is your distribution's state. Yes, distributions can have state too.

    You can get the same values by resetting the normal distribution's state with reset. Alternatively, you can preserve and reconstitute the distribution's state too, using << and >>.