Files Classes Functions Hierarchy
00001 #ifndef MINMONTE_H 00002 #define MINMONTE_H 00003 00004 #include <algorithm> 00005 #include <cassert> 00006 #include <iostream> 00007 00008 using namespace std; 00009 00010 00011 // Toggle debug 00012 #define DEBUG_MINMONTE 00013 00014 00015 // Brief: Helper class: associate a value with an index. 00016 template< typename T > 00017 class valueindex 00018 { 00019 public: 00020 00021 unsigned int index; 00022 T val; 00023 00024 bool const operator < (valueindex<T> const & x) 00025 { return val < x.val; } 00026 00027 ostream& print(ostream& os) const; 00028 00029 }; 00030 00031 template< typename T > 00032 ostream& operator << (ostream& os, valueindex<T> const & x) { return x.print(os); } 00033 00034 00035 // Brief: Mimimization algorithm by an adaptive monte carlo method. 00036 // Assumes the minimum is in the bounding volume. 00037 00038 template 00039 < 00040 typename F, // Function functional object ()(T&,T[]). 00041 typename R, // Random number functional object T r(). 00042 typename T, // Number type. 00043 unsigned int Arraysz, // Maximum number of sampled points. 00044 unsigned int Dim // Dimension (number of independent variables). 00045 > 00046 class minmonte 00047 { 00048 protected: 00049 00050 00051 F func; // Function to be minimized. 00052 R r; // Random number in [0,1]. 00053 00054 T a[Dim]; // Lower bounding box. 00055 T b[Dim]; // Upper bounding box. 00056 T lenab[Dim]; // b-a 00057 00058 unsigned int s; // The current number of samples. 00059 T v[Arraysz][Dim]; // Points. 00060 valueindex<T> pti[Arraysz]; // Value of functon applied to point. 00061 00062 void calcboundingbox(); 00063 00064 void printv(unsigned int k); 00065 00066 00067 public: 00068 00069 // Constructors. 00070 minmonte() {} 00071 minmonte(F func_, R r_) : func(func_), r(r_) {} 00072 00073 // Client must configure the bounding box/volume. 00074 template< typename V > 00075 void setboundingbox( V const & a_, V const & b_); 00076 template< typename V > 00077 void getboundingbox( V & a_, V & b_ ) const; 00078 00079 void setfunction( F const & func_); 00080 00081 // Access the top s results from the random sample. 00082 // k=0..s-1 sorted, k=0 is best. 00083 void getresult( T& val, T* p, unsigned int const k ) const; 00084 00085 // Evaluate one iteration of the adaptive monte carlo method. 00086 // ns is the number of samples. 00087 // s is the best s cases are used to build a bounding box. 00088 void operator () (unsigned int s_, unsigned int ns = Arraysz ); 00089 00090 // 00091 void printab() const; 00092 00093 }; 00094 00095 00096 // 00097 // Implementation 00098 // --------------------------------------------------------------- 00099 00100 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00101 void minmonte<F,R,T,Arraysz,Dim>::getresult 00102 ( 00103 T& val, 00104 T* p, 00105 unsigned int const k 00106 ) const 00107 { 00108 #ifdef DEBUG_MINMONTE 00109 assert(k<s); 00110 #endif 00111 00112 val = pti[k].val; 00113 unsigned int index = pti[k].index; 00114 for (unsigned int i=0; i<Dim; ++i, ++p) 00115 *p = v[index][i]; 00116 } 00117 00118 00119 00120 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00121 template< typename V > 00122 void minmonte<F,R,T,Arraysz,Dim>::getboundingbox(V & a_, V & b_) const 00123 { 00124 for (unsigned int i=0; i<Dim; ++i) 00125 { 00126 a_[i] = a[i]; 00127 b_[i] = b[i]; 00128 } 00129 } 00130 00131 00132 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00133 template< typename V > 00134 void minmonte<F,R,T,Arraysz,Dim>::setboundingbox(V const & a_, V const & b_) 00135 { 00136 for (unsigned int i=0; i<Dim; ++i) 00137 { 00138 a[i] = a_[i]; 00139 b[i] = b_[i]; 00140 lenab[i] = b[i]-a[i]; 00141 #ifdef DEBUG_MINMONTE 00142 assert(a[i]<b[i]); 00143 #endif 00144 } 00145 00146 } 00147 00148 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00149 void minmonte<F,R,T,Arraysz,Dim>::setfunction(F const & func_) 00150 { 00151 func = func_; 00152 } 00153 00154 00155 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00156 void minmonte<F,R,T,Arraysz,Dim>::operator () (unsigned int s_, unsigned int ns ) 00157 { 00158 00159 #ifdef DEBUG_MINMONTE 00160 00161 if (false) 00162 cout << "Entering minmonte ()" << endl; 00163 00164 assert( ns <= Arraysz ); 00165 assert(s_>0); 00166 assert(s_<=ns); 00167 00168 #endif 00169 00170 s = s_; 00171 00172 //<TODO> I had trouble with pointer arithmetic. 00173 // Possibly the use of inline function? In the mean time pass 00174 // a single array. For some reason passing a double array as a single failed. 00175 T temp[Dim]; 00176 00177 for (unsigned int i=0; i<ns; ++i) 00178 { 00179 for (unsigned int k=0; k<Dim; ++k) 00180 temp[k] = v[i][k] = a[k] + lenab[k]*r(); 00181 00182 func(pti[i].val,temp); 00183 //func(pti[i].val,(T*)(v+i*Dim)); 00184 pti[i].index = i; 00185 00186 #ifdef DEBUG_MINMONTE 00187 if (false) 00188 { 00189 cout << pti[i]; 00190 printv(i); 00191 cout << endl; 00192 } 00193 #endif 00194 00195 }; 00196 00197 partial_sort(pti,pti+s,pti+ns); 00198 00199 00200 #ifdef DEBUG_MINMONTE 00201 if (false) 00202 { 00203 cout << "After partial sort." << endl; 00204 for (unsigned int i=0; i<s; ++i) 00205 { 00206 cout << "pti[" << i << "]=" << pti[i] << " "; 00207 printv(pti[i].index); 00208 cout << endl; 00209 } 00210 } 00211 #endif 00212 00213 calcboundingbox(); 00214 00215 } 00216 00217 00218 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00219 void minmonte<F,R,T,Arraysz,Dim>::calcboundingbox() 00220 { 00221 // Assume a and b are valid. 00222 for (unsigned int k=0; k<Dim; ++k) 00223 a[k] = b[k] = v[pti[0].index][k]; 00224 00225 #ifdef DEBUG_MINMONTE 00226 if(false) 00227 { 00228 cout << "***" << endl; 00229 printv( pti[0].index ); 00230 cout << endl; 00231 printab(); 00232 } 00233 #endif 00234 00235 for (unsigned int k=0; k<Dim; ++k) 00236 { 00237 for (unsigned int i=1; i<s; ++i) 00238 { 00239 a[k] = min(a[k],v[pti[i].index][k]); 00240 b[k] = max(b[k],v[pti[i].index][k]); 00241 } 00242 } 00243 00244 for (unsigned int k=0; k<Dim; ++k) 00245 lenab[k] = b[k]-a[k]; 00246 } 00247 00248 00249 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00250 void minmonte<F,R,T,Arraysz,Dim>::printv(unsigned int k) 00251 { 00252 cout << "v[" << k << "]=["; 00253 for (unsigned int i=0; i<Dim-1; ++i) 00254 cout << v[k][i] << ","; 00255 cout << v[k][Dim-1] << "]"; 00256 } 00257 00258 template< typename F, typename R, typename T, unsigned int Arraysz, unsigned int Dim > 00259 void minmonte<F,R,T,Arraysz,Dim>::printab() const 00260 { 00261 cout << "a=["; 00262 for (unsigned int i=0; i<Dim-1; ++i) 00263 cout << a[i] << ","; 00264 cout << a[Dim-1] << "]" << " "; 00265 cout << "b=["; 00266 for (unsigned int i=0; i<Dim-1; ++i) 00267 cout << b[i] << ","; 00268 cout << b[Dim-1] << "]" << " "; 00269 cout << "lenab=["; 00270 for (unsigned int i=0; i<Dim-1; ++i) 00271 cout << lenab[i] << ","; 00272 cout << lenab[Dim-1] << "]" << endl; 00273 } 00274 00275 template< typename T > 00276 ostream& valueindex<T>::print(ostream& os) const 00277 { 00278 os << "(" << index << "," << val << ")"; 00279 return os; 00280 } 00281 00282 00283 00284 #endif 00285 00286
1.5.8