proj home

Files   Classes   Functions   Hierarchy  

minmonte.h

Go to the documentation of this file.
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 

Generated on Fri Mar 4 00:49:29 2011 for Chelton Evans Source by  doxygen 1.5.8