Biorithm  1.1
 All Classes Functions Variables Typedefs Friends
random.h
00001 /**************************************************************************
00002  * Copyright (c) 2002-2011 T. M. Murali                                   *
00003  *                                                                        *
00004  * This file is part of Biorithm.                                         *
00005  *                                                                        *
00006  * Biorithm is free software: you can redistribute it and/or modify       *
00007  * it under the terms of the GNU General Public License as published by   *
00008  * the Free Software Foundation, either version 3 of the License, or      *
00009  * (at your option) any later version.                                    *
00010  *                                                                        *
00011  * Biorithm is distributed in the hope that it will be useful,            *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
00014  * GNU General Public License for more details.                           *
00015  *                                                                        *
00016  * You should have received a copy of the GNU General Public License      *
00017  * along with Biorithm.  If not, see <http://www.gnu.org/licenses/>.      *
00018  *                                                                        *
00019  **************************************************************************/
00020 
00021 #ifndef _RANDOM_H
00022 #define _RANDOM_H
00023 
00024 #include <vector>
00025 #include <time.h>
00026 #include <math.h>
00027 
00028 #include "constants.h"
00029 // Test for GCC >= 4.3. from http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html. See definition of GCC_VERSION macro in libutil/constants.h
00030 #if GCC_VERSION >= 40300
00031 // see http://gcc.gnu.org/gcc-4.3/changes.html
00032 #include <tr1/unordered_set>
00033 using namespace std::tr1;
00034 #else
00035 #include <ext/hash_map>
00036 using namespace __gnu_cxx;
00037 #define unordered_set hash_set;
00038 #define unordered_map hash_map;
00039 #endif
00040 
00041 using namespace std;
00042 
00043 #include "global.h"
00044 #include "Mersennetwister.h"
00045 
00046 // have to specialise template in the same namespace as its definition.
00047 
00048 #ifdef __GNUC__
00049 #if __GNUC__ < 3
00050 namespace Sgi { using ::hash_map; }; // inherit globals
00051 #else
00052 #if __GNUC_MINOR__ == 0
00053 namespace Sgi = std;               // GCC 3.0
00054 #else
00055 namespace Sgi = ::__gnu_cxx;       // GCC 3.1 and later
00056 #endif
00057 #endif
00058 #else      // ...  there are other compilers, right?
00059 namespace Sgi = std;
00060 #endif
00061 
00062 #if (GCC_VERSION < 40300)
00063 // i need to define some hash templates.
00064 namespace __gnu_cxx
00065 {
00066 template <> struct hash< double >
00067 {
00068   // this function is not great but all the hash functions in
00069   // stl_hash_fun.h that take numbers as parameters simply return
00070   // their argument so doing so for double may be ok.
00071   size_t operator()(const double& num) const { return static_cast< size_t >(num); }
00072 };
00073 }
00074 #endif // GCC_VERSION
00075 
00076 // dummy class just so that i can define generators for every type i
00077 // want by using partial specialisation and calling the appropriate
00078 // MTRand function.
00079 template <class MyNT> class MyRand : public MTRand
00080 {
00081 public:
00082   MyRand()
00083       : MTRand()
00084     {}
00085   virtual ~MyRand()
00086     {}
00087   
00088   MyNT operator()();
00089   MyNT operator()(MyNT num);
00090   MyNT operator()(MyNT low, MyNT high);
00091 };
00092 
00093 template <> int MyRand< int >::operator()();
00094 template <> int MyRand< int >::operator()(int num);
00095 template <> int MyRand< int >::operator()(int low, int high);
00096 template <> double MyRand< double >::operator()();
00097 template <> double MyRand< double >::operator()(double num);
00098 template <> double MyRand< double >::operator()(double low, double high);
00099 
00100 enum MyUniqueRandomStatus {MyUniqueRandomStatus_OK, MyUniqueRandomStatus_NONE};
00101 
00102 
00103 // make this templated? if so, define a function that returns a random
00104 // number of that type.
00105 template < class MyNT > class MyUniqueRandom
00106 {
00107 public:
00108   // can only be called with l and h. makes them set for the lifetime
00109   // of the instance. therefore, i dont have to worry about dealing
00110   // with the user changing low and high in the middle of the lifetime
00111   // of the instance.
00112   MyUniqueRandom(MyNT l, MyNT h)
00113       : low(l), high(h), generator(), unique()
00114     {
00115     }
00116 //   MyUniqueRandom(MyUniqueRandom& r)
00117 //       : low(r.low), high(r.high), generator(), unique(r.unique)
00118 //     {
00119 //     }
00120 //   MyUniqueRandom& operator=(const MyUniqueRandom& rhs)
00121 //     {
00122 //       if (this != &rhs)
00123 //         {
00124 //           low = rhs.low;
00125 //           high = rhs.high;
00126 //           unique = rhs.unique;
00127 //         }
00128 //       return(*this);
00129 //     }
00130   
00131   virtual ~MyUniqueRandom()
00132     {}
00133 
00134   // forget all the random numbers you have generated and stored so far.
00135   void reset()
00136     {
00137       // resize() doesn't decrease size of hash_maps.
00138       unique.clear();
00139     }
00140 
00141   // eventhough the compiler (gcc) will not inline the generate()
00142   // functions, i have to put their defns. in the header file.
00143   // otherwise, i have to use the export keyword either before the
00144   // MyUniqueRandom class or before the defns. of these functions in
00145   // random.C. however, gcc 2.96 does not support the export keyword.
00146   // see sec 18 and sec 16.8.2, in particular, of effective c++.
00147   MyUniqueRandomStatus generate(MyNT& num)
00148     {
00149       if (allGenerated(unique.size()))
00150         {
00151           cerr << "ERROR! All unique random numbers between " << low << " and " << high
00152                << " have been generated." << endl;
00153           return(MyUniqueRandomStatus_NONE);
00154         }
00155       
00156       while (true)
00157         {
00158           num = generator(low, high);
00159           if (unique.end() == unique.find(num))
00160             {
00161               unique.insert(num);
00162               return(MyUniqueRandomStatus_OK);
00163         }
00164         }
00165     }
00166 
00167   // need to duplicate code in MyUniqueRandomStatus generate(MyNT&
00168   // num) because i can't specify a default value for numsToAvoid. if
00169   // i pass a pointer, then i have to check if the pointer is NULL at
00170   // two places, which is costly. if i pass a hash set of size 0 then
00171   // a function that just wants a random number has to pass an empty
00172   // hash set to generate(), which seems wrong.
00173   //
00174   // generate 1 random number between this->low and this->high. the
00175   // random number should not be in numsToAvoid. return it in 1.
00176   MyUniqueRandomStatus generate(
00177     MyNT& num,
00178 #if GCC_VERSION >= 40300
00179     const unordered_set< MyNT, hash< MyNT > >& numsToAvoid)
00180 #else
00181     const hash_set< MyNT, hash< MyNT > >& numsToAvoid)
00182 #endif
00183     {
00184       if (allGenerated(unique.size() + numsToAvoid.size()))
00185         {
00186           cerr << "ERROR! All unique random numbers between " << low << " and " << high
00187                << " have been generated." << endl;
00188           return(MyUniqueRandomStatus_NONE);
00189         }
00190       
00191       while (true)
00192         {
00193           num = generator(low, high);
00194           if ((unique.end() == unique.find(num)) &&
00195               (numsToAvoid.end() == numsToAvoid.find(num)))
00196             {
00197               unique.insert(num);
00198               return(MyUniqueRandomStatus_OK);
00199             }
00200         }
00201     }
00202 
00203 
00204   // generate count random numbers between this->low and this->high. the
00205   // random numbers should not be in numsToAvoid. return them in nums.
00206   MyUniqueRandomStatus generate(
00207     int count,
00208 #if GCC_VERSION >= 40300
00209     const unordered_set< MyNT, hash< MyNT > >& numsToAvoid,
00210 #else
00211     const hash_set< MyNT, hash< MyNT > >& numsToAvoid,
00212 #endif
00213     vector< MyNT >& nums)
00214     {
00215       if (!canGenerate(count + numsToAvoid.size()))
00216         {
00217           cerr << "ERROR! MyUniqueRandom::generate(): cannot generate " <<
00218             count + numsToAvoid.size() << " unique random numbers between "
00219                << low << " and " << high << "." << endl;
00220           return(MyUniqueRandomStatus_NONE);
00221     }
00222       // TODO: DESIGN. making localUnique static for the same reason
00223       // as making randomIncides static in MyPointSet::generate(int
00224       // num, vector< int >& indices, bool forbidChosen = true).
00225 #if GCC_VERSION >= 40300
00226       static unordered_set< MyNT, hash< MyNT > > localUnique;
00227 #else
00228       static hash_set< MyNT, hash< MyNT > > localUnique;
00229 #endif
00230       MyNT num;
00231       while (0 < count)
00232         {
00233           num = generator(low, high);
00234           // TODO: BUG. what if i have already generated all possible
00235           // numbers between low and high, especially when MyNT = int? i
00236           // go into a infinite loop here.
00237           if ((localUnique.end() == localUnique.find(num)) &&
00238               (numsToAvoid.end() == numsToAvoid.find(num)))
00239             {
00240               localUnique.insert(num);
00241               nums[--count] = num;
00242             }
00243         }
00244       localUnique.clear();
00245       return(MyUniqueRandomStatus_OK);
00246     }
00247 
00248   
00249 
00250   // generate count random numbers from those in numsToUse. i am
00251   // guaranteeing that each number is between low and high. the random
00252   // numbers should not be in numsToAvoid. return them in nums.
00253   MyUniqueRandomStatus generate(
00254     int count, 
00255     const vector< int >& numsToUse,
00256 #if GCC_VERSION >= 40300
00257     const unordered_set< MyNT, hash< MyNT > >& numsToAvoid,
00258 #else
00259     const hash_set< MyNT, hash< MyNT > >& numsToAvoid,
00260 #endif
00261     vector< MyNT >& nums)
00262     {
00263          // i want a number in the range [0, numsToUse.size() - 1]. 
00264          if (!canGenerate(0, numsToUse.size() - 1, 
00265                                    count + numsToAvoid.size()))
00266         {
00267           cerr << "ERROR! MyUniqueRandom::generate(): cannot generate " <<
00268             count + numsToAvoid.size() << " unique random numbers between "
00269                << 0 << " and " << numsToUse.size() - 1 << "." << endl;
00270           return(MyUniqueRandomStatus_NONE);
00271            }
00272       // TODO: DESIGN. making localUnique static for the same reason
00273       // as making randomIncides static in MyPointSet::generate(int
00274       // num, vector< int >& indices, bool forbidChosen = true).
00275 #if GCC_VERSION >= 40300
00276       static unordered_set< MyNT, hash< MyNT > > localUnique;
00277 #else
00278       static hash_set< MyNT, hash< MyNT > > localUnique;
00279 #endif
00280       MyNT num, randomNum;
00281       while (0 < count)
00282         {
00283                 //          num = generator(low, high);
00284           randomNum = generator(0, numsToUse.size() - 1);
00285           num = numsToUse[randomNum];
00286           // TODO: BUG. what if i have already generated all possible
00287           // numbers between low and high, especially when MyNT = int? i
00288           // go into a infinite loop here.
00289                 //
00290                 // look like i have to first cheque if the hash is empty.
00291           if ((localUnique.empty() ||
00292                         (localUnique.end() == localUnique.find(num))) &&
00293                     (numsToAvoid.empty() ||
00294                         (numsToAvoid.end() == numsToAvoid.find(num))))
00295             {
00296               localUnique.insert(num);
00297               nums[--count] = num;
00298             }
00299         }
00300       localUnique.clear();
00301       return(MyUniqueRandomStatus_OK);
00302     }
00303   
00304 private:
00305   int numPossibleUnique() const;
00306   bool allGenerated(int num) const;
00307   bool canGenerate(int num) const;
00308   // don't use MyUniqueRandom::[low,high] but the ones passed.
00309   bool canGenerate(int newlow, int newhigh, int num) const;
00310   
00311 private:
00312   MyNT low;
00313   MyNT high;
00314   MyRand< MyNT > generator;
00315 #if GCC_VERSION >= 40300
00316   unordered_set< MyNT > unique;    
00317 #else
00318   hash_set< MyNT > unique;  
00319 #endif
00320 };
00321 
00322 
00323 
00324 #endif // _RANDOM_H 
 All Classes Functions Variables Typedefs Friends