Files Classes Functions Hierarchy
00001 #ifndef LINEOPGOLD_H 00002 #define LINEOPGOLD_H 00003 00004 #include <vec.h> 00005 #include <typeop.h> 00006 00007 /* 00008 \brief Golden ratio line optimization. 00009 00010 Find the minimum in an interval. 00011 */ 00012 template< typename EXP > 00013 class lineopgold 00014 { 00015 00016 public: 00017 00018 00019 // typedef typename typeop<EXP>::Tconst::Tconst Tconst 00020 typedef typename typeop<EXP>::Tbare::Ttype T; 00021 typedef typename typeop<EXP>::Tref EXP2; 00022 00023 typedef T const Tconst; 00024 00026 EXP2 exp; 00027 00028 uintc N; 00029 00031 T* di; 00032 00034 lineopgold(EXP2 _exp); 00036 ~lineopgold(); 00037 00039 T const hlarge() const; 00040 00042 bool const minimize( T const hstep, uintc kiterations ); 00043 00044 protected: 00045 00047 T* X0; 00049 T X0fmin; 00050 00052 T ti[4]; 00053 00055 T fxk[4]; 00056 00058 static T goldratio; 00059 00060 #ifndef NDEBUG 00061 bool const verifyti( uintc ai0, uintc ai1, uintc ai2, uintc ai3) const; 00062 #endif 00063 00064 }; 00065 00066 00067 template< typename EXP > 00068 typename lineopgold<EXP>::T lineopgold<EXP>::goldratio = 0.61803398875; 00069 00070 00071 template< typename EXP > 00072 bool const lineopgold<EXP>::minimize( T const hstep, uintc kiterations ) 00073 { 00074 assert( kiterations>6); // Make minimization effective, min 4+k function evaluations. 00075 // Save the current state. 00076 uint k; 00077 for ( k=0; k<N; ++k) 00078 X0[k] = exp.xi[k]; 00079 X0fmin = exp.fn.fmin; 00080 00081 // Indexes to vectors. 00082 uint ai0=0; 00083 uint ai1=1; 00084 uint ai2=2; 00085 uint ai3=3; 00086 uint rej; 00087 00088 // these are the 4 points about xi which are being sampled. 00089 T len = goldratio*hstep*2.0; 00090 ti[0] = -hstep; 00091 ti[3] = hstep; 00092 ti[1] = ti[3]-len; 00093 ti[2] = ti[0]+len; 00094 00095 // Evaluate the function at the 4 points. 00096 for ( k=0; k<N; ++k) 00097 exp.xi[k] = X0[k] + di[k]*ti[ai0]; 00098 exp.fn(fxk[ai0]); 00099 00100 for ( k=0; k<N; ++k) 00101 exp.xi[k] = X0[k] + di[k]*ti[ai3]; 00102 exp.fn(fxk[ai3]); 00103 00104 for ( k=0; k<N; ++k) 00105 exp.xi[k] = X0[k] + di[k]*ti[ai1]; 00106 exp.fn(fxk[ai1]); 00107 00108 for ( k=0; k<N; ++k) 00109 exp.xi[k] = X0[k] + di[k]*ti[ai2]; 00110 exp.fn(fxk[ai2]); 00111 00112 // Minimization 00113 for (uint i=0; i<kiterations; ++i) 00114 { 00115 len *= goldratio; 00116 00117 // Test - reject x0 if successful. 00118 if (fxk[ai2]<fxk[ai1]) 00119 { 00120 // Reject x0 00121 rej = ai0; 00122 ai0 = ai1; 00123 ai1 = ai2; 00124 ai2 = rej; 00125 ti[ai2] = ti[ai3]-len; 00126 assert(verifyti(ai0,ai1,ai2,ai3)); 00127 for ( k=0; k<N; ++k) 00128 exp.xi[k] = X0[k] + di[k]*ti[ai2]; 00129 exp.fn(fxk[ai2]); 00130 } 00131 else 00132 { 00133 // Reject x3 00134 rej = ai3; 00135 ai3 = ai2; 00136 ai2 = ai1; 00137 ai1 = rej; 00138 ti[ai1] = ti[ai0]+len; 00139 assert(verifyti(ai0,ai1,ai2,ai3)); 00140 for ( k=0; k<N; ++k) 00141 exp.xi[k] = X0[k] + di[k]*ti[ai1]; 00142 exp.fn(fxk[ai1]); 00143 } 00144 } 00145 00146 // Find the new minimum. 00147 if (fxk[ai1]<fxk[ai2]) 00148 { 00149 if (fxk[ai1]<X0fmin) 00150 { 00151 for ( k=0; k<N; ++k) 00152 exp.xi[k] = X0[k] + di[k]*ti[ai1]; 00153 exp.fmin = fxk[ai1]; 00154 00155 return true; 00156 } 00157 } 00158 else 00159 { 00160 if (fxk[ai2]<X0fmin) 00161 { 00162 for ( k=0; k<N; ++k) 00163 exp.xi[k] = X0[k] + di[k]*ti[ai2]; 00164 exp.fmin = fxk[ai2]; 00165 00166 return true; 00167 } 00168 } 00169 00170 // Restore the original position, no change. 00171 for ( k=0; k<N; ++k) 00172 exp.xi[k] = X0[k]; 00173 exp.fmin = X0fmin; 00174 00175 return false; 00176 } 00177 00178 00179 template< typename EXP > 00180 lineopgold<EXP>::lineopgold(EXP2 _exp) 00181 : exp(_exp), N(exp.N), di(new T[N]), 00182 X0(new T[N]) 00183 { 00184 } 00185 00186 00187 template< typename EXP > 00188 lineopgold<EXP>::~lineopgold() 00189 { 00190 delete[] di; 00191 delete[] X0; 00192 } 00193 00194 00195 template< typename EXP > 00196 typename lineopgold<EXP>::T const lineopgold<EXP>::hlarge() const 00197 { 00198 T h = exp.hi[0]; 00199 if (h<0) 00200 h *= -1.0; 00201 T y; 00202 for (uint i=1; i<N; ++i) 00203 { 00204 y = exp.hi[0]; 00205 if (y<0) 00206 y += -1.0; 00207 00208 if (y>h) 00209 h=y; 00210 } 00211 00212 return h; 00213 } 00214 00215 00216 template< typename EXP > 00217 bool const lineopgold<EXP>::verifyti 00218 ( 00219 uintc ai0, 00220 uintc ai1, 00221 uintc ai2, 00222 uintc ai3 00223 ) const 00224 { 00225 bool valid=true; 00226 00227 if ( ti[ai1] < ti[ai0] ) 00228 valid=false; 00229 if ( ti[ai2] < ti[ai0] ) 00230 valid=false; 00231 if ( ti[ai3] < ti[ai0] ) 00232 valid=false; 00233 00234 if ( ti[ai2] < ti[ai1] ) 00235 valid=false; 00236 if ( ti[ai3] < ti[ai1] ) 00237 valid=false; 00238 00239 if ( ti[ai3] < ti[ai2] ) 00240 valid=false; 00241 00242 if (valid==false) 00243 { 00244 cout << "error: ai indexes incorrect" << endl; 00245 cout << SHOW(ai0) << " " << SHOW(ai1) << " "; 00246 cout << SHOW(ai2) << " " << SHOW(ai3) << endl; 00247 00248 cout << SHOW(ti[0]) << " " << SHOW(ti[1]) << " "; 00249 cout << SHOW(ti[2]) << " " << SHOW(ti[3]) << endl; 00250 } 00251 00252 return valid; 00253 } 00254 00255 00256 00257 00258 #endif 00259 00260
1.5.8