indii/ml/aux/Random.cpp

00001 //#if defined(__GNUC__) && defined(GCC_PCH)
00002 //  #include "aux.hpp"
00003 //#else
00004   #include "Random.hpp"
00005 //#endif
00006 
00007 #include "boost/mpi.hpp"
00008 #include "boost/numeric/bindings/traits/ublas_vector.hpp"
00009 #include "boost/numeric/bindings/traits/ublas_matrix.hpp"
00010 #include "boost/numeric/bindings/lapack/lapack.hpp"
00011 
00012 #include <time.h>
00013 #include <assert.h>
00014 
00015 using namespace indii::ml::aux;
00016 
00017 namespace ublas = boost::numeric::ublas;
00018 namespace lapack = boost::numeric::bindings::lapack;
00019 
00020 bool Random::isInit = false;
00021 
00022 gsl_rng* Random::rng = NULL;
00023 
00024 void Random::seed(unsigned int seed) {
00025   if (!isInit) {
00026     init();
00027   }
00028   gsl_rng_set(rng, seed);
00029 }
00030 
00031 void Random::init() {
00032   int seed;
00033 
00034   /* construct random number generator */
00035   gsl_rng_env_setup();
00036   //rng = gsl_rng_alloc(gsl_rng_ranlxd2); // best randomness
00037   rng = gsl_rng_alloc(gsl_rng_mt19937); // best randomness/speed tradeoff
00038 
00039   /* select seed */
00040   seed = time(NULL);
00041   if (boost::mpi::environment::initialized()) {
00042     /* ensure two nodes aren't seeded with the same number */
00043     boost::mpi::communicator world;
00044     const int rank = world.rank();
00045     seed += 1000 * rank;
00046   }
00047 
00048   /* seed random number generator */
00049   gsl_rng_set(rng, seed);
00050   isInit = true;
00051 
00052   /* post-condition */
00053   assert (isInit);
00054 }
00055 
00056 void Random::terminate() {
00057   if (isInit) {
00058     gsl_rng_free(rng);
00059   }
00060 }
00061 
00062 vector Random::unitVector(const unsigned int N) {
00063   if (!isInit) {
00064     init();
00065   }
00066   
00067   aux::vector s(N);
00068   double x[N]; 
00069   gsl_ran_dir_nd(rng, N, x);
00070   arrayToVector(x, s);
00071   
00072   return s;
00073 }
00074 
00075 matrix Random::orthonormalMatrix(const unsigned int N) {
00076   if (!isInit) {
00077     init();
00078   }
00079   
00080   identity_matrix I(N,N);
00081   matrix random(N,N);  // random matrix
00082   matrix Q(I), H(I);
00083   vector v(N), tau(N);
00084   unsigned int i, j;
00085   int ierr;
00086 
00087   /* create random matrix */
00088   for (j = 0; j < N; j++) {
00089     for (i = 0; i < N; i++) {
00090       random(i,j) = Random::uniform(-1.0, 1.0);
00091     }
00092   }
00093   /**
00094    * @todo Should check random for full rank, just in case, although it's
00095    * highly unlikely that the set is linearly dependent.
00096    */
00097 
00098   /* QR factorisation */
00099   ierr = lapack::geqrf(random, tau);
00100   assert (ierr == 0);
00101 
00102   /* rebuild Q from reflectors (see LAPACK documentation for how Q is
00103      returned) */
00104   ublas::triangular_adaptor<aux::matrix, ublas::lower> L(random);
00105 
00106   for (i = 0; i < N; i++) {
00107     v = column(L,i);
00108     v(i) = 1.0;
00109  
00110     H = I - tau(i) * ublas::outer_prod(v,v);
00111     Q = prod(Q,H);
00112   }
00113 
00114   return Q;
00115 }
00116 

Generated on Wed Dec 17 15:11:57 2008 for dysii Dynamical Systems Library by  doxygen 1.5.3