Bojan Nikolic: Numerical and Quantitative Methods in C++

[website home] | [BN Algorithms]

Mersenne Twister Generators

The Mersenne Twister is a relatively new and complex algorithm for generating random numbers described in detail elsewhere on the web. It has been designed with Monte-Carlo applications in mind but it is of course useful for any application which requires uniform random numbers. The algorithm is now widely used in practice.

The boost implementation of this generator is available in the <boost/random/mersenne_twister.hpp> header. Both the algorithm itself and the boost implementation have a significant number of parameters. The most frequently used standard parametrisation is the MT19937 version and this parametrisation is defined in the header for easy use – it is recommended you use this parametrisation.

A simple example of using the Mersenne Twister algorithm from boost is shown below:

#include <iostream>
#include <boost/random/mersenne_twister.hpp>

int main(void)
{
  boost::mt19937 gen;
  
  const size_t n=10;
  for(size_t i=0; i<n; ++i)
  {
    std::cout<<gen()
	     <<std::endl;
  }
}

Seeding the generator

Since the state of Mersenne Twister generator is relatively long, there are a number of ways of seeding the generator, illustrated in the following program

#include <iostream>
#include <vector>

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/linear_congruential.hpp>

int main(void)
{
  // Use the default seed
  boost::mt19937 gen;

  // Seed from an interger number
  boost::mt19937 gen2(43);

  // Seed using a sequence of unsigned intergers (in this case, they
  // are all 11, but it is probably best to use different numbers!)
  std::vector<unsigned int> seedv(1000, 11);
  std::vector<unsigned int>::iterator i=seedv.begin();
  // Note the first parameter will be taken a reference and therefore
  // it *must* be a l-value
  boost::mt19937 gen3(i, seedv.end());
  // boost::mt19937 gen3(seedv.begin(), seedv.end()) will *not* work
  // because you can not take a reference of seedv.begin()

  // Seed from another generator
  boost::minstd_rand lcggen;
  boost::mt19937 gen4(lcggen);
  
  
}

Seeding from a simple integer number is likely to be sufficient for many applications, especially if care is taken that generators are not reseeded too frequently (for example, by ensuring long-lived generator objects exist in the program).

Saving and restoring the state of the generator

Since the Mersenne Twister algorithm has a very long period, and reseeding the algorithm should be avoided as far as possible, it is sometimes useful to be able to save and restore the state of the generator. One typical example of this is when a long-running calculation must be interrupted for maintenance of the computer.

Both the saving and restoring operations are very easily implemented using the overloaded << and >> operators as illustrated in the following short program:

#include <iostream>
#include <fstream>

#include <boost/random/mersenne_twister.hpp>

int main(void)
{
  boost::mt19937 gen(433);

  // Save the state of the generator to file "temp/mttest.dat" 
  std::ofstream fo("temp/mttest.dat", 
		   std::ios_base::out);
  fo<<gen;

  // Print a random number using the generator
  std::cout<<gen()<<std::endl;

  // Load the state back up
  std::ifstream fi("temp/mttest.dat");
  fi>>gen;

  // Print a number from the generator and verify it is restarteed at
  // the number already printed 
  std::cout<<gen()<<std::endl;
}