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
00072
00073
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
00102
00103
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
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
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
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 }
00222
00224
00225 #endif // #ifndef OPENGM_RANDOM_HXX