random.hxx

Go to the documentation of this file.
00001 #pragma once
00002 #ifndef OPENGM_RANDOM_HXX
00003 #define OPENGM_RANDOM_HXX
00004 
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <time.h>
00010 
00011 #include "opengm/opengm.hxx"
00012 
00013 namespace opengm {
00014 
00015 template<class T>
00016    class RandomUniformBase;
00017 template<class T>
00018    class RandomUniformFloatingPoint;
00019 template<class T>
00020    class RandomUniformInteger;
00021 template<class T>
00022    class RandomUniformUnknown;
00023 template<class T>
00024    class RandomUniform;
00025 
00026 template<class T>
00027 class RandomUniformBase
00028 {
00029 public:
00030    RandomUniformBase& operator=(const RandomUniformBase& src)
00031    {
00032       if(this!=&src) {
00033          low_=src.low_;
00034          high_=src.high_;
00035       }
00036       return *this;
00037    }
00038 
00039    RandomUniformBase(const T low = 0, const T high = 1)
00040    :  low_(low), 
00041       high_(high) 
00042    {}
00043 
00044 private:
00045    T low_;
00046    T high_;
00047 
00048 template<class> friend class RandomUniformInteger;
00049 template<class> friend class RandomUniformFloatingPoint;
00050 template<class> friend class RandomUniformUnknown;
00051 template<class> friend class RandomUniform;
00052 };
00053 
00054 template<class T>
00055 class RandomUniformInteger
00056 : RandomUniformBase<T>
00057 {
00058 public:
00059    RandomUniformInteger(const T low = 0, const T high = 1)
00060    :  RandomUniformBase<T>(low, high)
00061    {}
00062 
00063    RandomUniformInteger(const T low, const T high, const size_t seed)
00064    :  RandomUniformBase<T>(low, high)
00065    {
00066       srand(time_t(seed));
00067    }
00068 
00069    T operator()() const
00070    {
00071       // intended semantics: random number is drawn from [low_, high)
00072       // however, not all std random number generators behave like this
00073       // thus this trivial work-around:
00074       T randomNumber = this->high_;
00075       while(randomNumber == this->high_) {
00076          randomNumber = static_cast<T>((rand() % (this->high_ - this->low_)) + this->low_);
00077       }
00078       return randomNumber;
00079    }
00080 
00081 template<class> friend class RandomUniform;
00082 };
00083 
00084 template<class T>
00085 class RandomUniformFloatingPoint
00086 :  RandomUniformBase<T>
00087 {
00088 public:
00089    RandomUniformFloatingPoint(const T low = 0, const T high = 1)
00090    :  RandomUniformBase<T>(low, high)
00091    {}
00092    
00093    RandomUniformFloatingPoint(const T low, const T high, const size_t seed)
00094    :  RandomUniformBase<T>(low, high)
00095    {
00096       srand(time_t(seed));
00097    }
00098    
00099    T operator()() const
00100    {
00101       // intended semantics: random number is drawn from [low_, high)
00102       // however, not all std random number generators behave like this
00103       // thus this trivial work-around:
00104       T randomNumber = this->high_;
00105       while(randomNumber == this->high_) {
00106          randomNumber = (static_cast<T>(rand()) / static_cast<T>(RAND_MAX)) * (this->high_ - this->low_) + this->low_;
00107       }
00108       return randomNumber;
00109    }
00110 
00111 template<class> friend class RandomUniform;
00112 };
00113 
00114 template<class T>
00115 class RandomUniformUnknown : RandomUniformBase<T> {
00116 template<class> friend class RandomUniform;
00117 };
00118 
00119 template<class T>
00120 class RandomUniform
00121 : public
00122       opengm::meta::If
00123       <
00124          opengm::meta::IsFundamental<T>::value, 
00125          typename opengm::meta::If
00126          <
00127             opengm::meta::IsFloatingPoint<T>::value, 
00128             opengm::RandomUniformFloatingPoint<T>, 
00129             opengm::RandomUniformInteger<T>
00130          >::type, 
00131          RandomUniformUnknown<T>
00132       >::type
00133 {
00134 private:
00135    typedef typename opengm::meta::If
00136    <
00137       opengm::meta::IsFundamental<T>::value, 
00138       typename opengm::meta::If
00139       <
00140          opengm::meta::IsFloatingPoint<T>::value, 
00141          opengm::RandomUniformFloatingPoint<T>, 
00142          opengm::RandomUniformInteger<T>
00143       >::type, 
00144       RandomUniformUnknown<T>
00145    >::type BaseType;
00146 
00147 public:
00148    RandomUniform(const T low = 0, const T high = 1)
00149    :  BaseType(low, high)
00150    {}
00151 
00152    RandomUniform(const T low, const T high, const size_t seed)
00153    :  BaseType(low, high, seed)
00154    {}
00155 };
00156 
00157 template<class T, class U>
00158 class RandomDiscreteWeighted
00159 {
00160 public:
00161    RandomDiscreteWeighted() {}
00162 
00163    template<class Iterator>
00164    RandomDiscreteWeighted(Iterator begin, Iterator end)
00165    :  probSum_(std::distance(begin, end)), 
00166       randomFloatingPoint_(0, 1)
00167    {
00168       U sum = 0;
00169       // normalization
00170       for(size_t i=0;i<probSum_.size();++i) {
00171          probSum_[i]=static_cast<U>(*begin);
00172          ++begin;
00173          sum+=probSum_[i];
00174       }
00175       probSum_[0]/=sum;
00176       for(size_t i=1;i<probSum_.size();++i) {
00177          probSum_[i]/=sum;
00178          probSum_[i]+=probSum_[i-1];
00179       }
00180    }
00181 
00182    template<class Iterator>
00183    RandomDiscreteWeighted(Iterator begin, Iterator end, size_t seed)
00184    :  probSum_(std::distance(begin, end)), 
00185       randomFloatingPoint_(0, 1, seed)
00186    {
00187       U sum=0;
00188       // normalization
00189       for(size_t i=0;i<probSum_.size();++i) {
00190          probSum_[i]=static_cast<U>(*begin);
00191          ++begin;
00192          sum+=probSum_[i];
00193       }
00194       probSum_[0]/=sum;
00195       // accumulatives
00196       for(size_t i=1;i<probSum_.size();++i) {
00197          probSum_[i]/=sum;
00198          probSum_[i]+=probSum_[i-1];
00199       }
00200    }
00201 
00202    T operator()() const
00203    {
00204       U rnd = randomFloatingPoint_();
00205       if(rnd < probSum_[0]) {
00206          return 0;
00207       }
00208       for(size_t i=0;i<probSum_.size()-1;++i) {
00209          if(probSum_[i]<=rnd && rnd<probSum_[i+1]) {
00210             return static_cast<T>(i+1);
00211          }
00212       }
00213       return static_cast<T>(probSum_.size() - 1);
00214    }
00215 
00216 private:
00217    std::vector<U> probSum_;
00218    opengm::RandomUniform<U> randomFloatingPoint_;
00219 };
00220 
00221 } // namespace opengm
00222 
00224 
00225 #endif // #ifndef OPENGM_RANDOM_HXX
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Mon Jun 17 16:31:05 2013 for OpenGM by  doxygen 1.6.3