#include <BLMinimize.hh>
Uses the the Simplex algorithm of Nelder and Mead.
Compilation for simple programs: g++ -I... test.cc -lgsl -lgslcblas -lm
NOTE: the parameters to the minimizer must all have scales that are comparable, or the minimizer will often converge to a wildly incorrect value. This applies to track fitting, where positions have scales of 1 (millimeters), but angles have scales of 0.001 (milliradians). This class scales the parameters appropriately. it also permits the function to have arguments that are held constant during the minimization by setting their scale to 0.0.
NOTE: only a single instance of BLMinimize can be active at a time (i.e. inside the minimize() function). Any number of instances can exist. This basically means your BLMinimizeFunction cannot itself use a minimizer internally.
Public Member Functions | |
BLMinimize (int _print=2) | |
Constructor. | |
virtual | ~BLMinimize () |
void | setFunc (BLMinimizeFunction &f, const std::vector< double > &_scale, const std::string &names="") |
setFunc() will set the function to minimize and the scale of its arguments. The number of non-zero entries in _scale[] determines the number of variables to minimize. names is a colon-separated list of parameter names. | |
void | setPrintDetail (int v=0) |
setPrintDetail() sets the detail of printing per iteration: 0=no print, 1=print value and size only, 2=print value, size, and x. the default is 2. | |
void | setChisqMin (double v) |
setChisqMin() sets an additional convergence criterium of chisq less than the given value. Can only be used when the function is positive definite, usually a chi-squared. Required for track- fitting of test tracks that have truly 0 chisq -- the normal convergence often fails for such tracks. | |
int | minimize (std::vector< double > &x, double tolerance=1e-3, int maxIter=100) |
minimize() finds the minimum, returning status (0=success). x the initial and then the final argument values tolerance the convergence limit on the simplex size NOTE: this is after scaling! maxIter limits the number of iterations The initial step for x[i] is scale[i] (x[i] is scaled, so the step to the gsl routine is 1.0). | |
double | value () const |
value() returns the function value from the previous minimize(). | |
double | getSize () |
getSize() returns the Simplex size from the previous minimize(). | |
int | getIterations () |
getIterations() returns the # iterations of the previous minimize(). | |
Private Member Functions | |
double | call (const gsl_vector *x) |
std::vector< std::string > | splitString (const std::string &s) |
Static Private Member Functions | |
static double | f (const gsl_vector *x, void *param) |
Private Attributes | |
std::vector< double > | scale |
std::vector< double > | arg |
std::vector< std::string > | name |
double | val |
double | size |
int | iter |
int | |
double | chisqMin |
BLMinimizeFunction * | func |
gsl_multimin_function | ff |
gsl_multimin_fminimizer * | m |
BLMinimize::BLMinimize | ( | int | _print = 2 |
) | [inline] |
virtual BLMinimize::~BLMinimize | ( | ) | [inline, virtual] |
static double BLMinimize::f | ( | const gsl_vector * | x, | |
void * | param | |||
) | [inline, static, private] |
References call().
Referenced by setFunc().
00085 { 00086 BLMinimize *p = (BLMinimize*)param; 00087 return p->call(x); 00088 }
double BLMinimize::call | ( | const gsl_vector * | x | ) | [inline, private] |
References arg, print, and scale.
Referenced by f().
00090 { 00091 if(print >= 2) printf("BLMinimize call args:"); 00092 int j=0; 00093 for(unsigned i=0; i<scale.size(); ++i) { 00094 if(scale[i] != 0.0) // fixed args are already set 00095 arg[i] = gsl_vector_get(x,j++) * scale[i]; 00096 if(print >= 2) 00097 printf(" %.4g",arg[i]); 00098 } 00099 if(print >= 2) printf("\n"); 00100 double v = (*func)(arg); 00101 if(print >= 2) printf("BLMinimize call returns value=%.4g\n",v); 00102 return v; 00103 }
void BLMinimize::setFunc | ( | BLMinimizeFunction & | f, | |
const std::vector< double > & | _scale, | |||
const std::string & | names = "" | |||
) | [inline] |
setFunc() will set the function to minimize and the scale of its arguments. The number of non-zero entries in _scale[] determines the number of variables to minimize. names is a colon-separated list of parameter names.
References arg, f(), ff, func, m, name, scale, and splitString().
Referenced by BLCMDtracker::fitTrack().
00118 { 00119 func = &f; 00120 scale.clear(); 00121 arg.clear(); 00122 name.clear(); 00123 std::vector<std::string> n = splitString(names); 00124 int nx = 0; 00125 for(unsigned i=0; i<_scale.size(); ++i) { 00126 double s=_scale[i]; 00127 scale.push_back(s); 00128 arg.push_back(s); 00129 name.push_back(i<n.size() ? n[i] : ""); 00130 if(s != 0.0) ++nx; 00131 } 00132 ff.f=BLMinimize::f; 00133 ff.n=nx; 00134 ff.params=this; 00135 if(m) gsl_multimin_fminimizer_free(m); 00136 m = 0; 00137 if(nx == 0) return; 00138 m = gsl_multimin_fminimizer_alloc( 00139 gsl_multimin_fminimizer_nmsimplex,nx); 00140 }
void BLMinimize::setPrintDetail | ( | int | v = 0 |
) | [inline] |
setPrintDetail() sets the detail of printing per iteration: 0=no print, 1=print value and size only, 2=print value, size, and x. the default is 2.
References print.
00145 { print = v; }
void BLMinimize::setChisqMin | ( | double | v | ) | [inline] |
setChisqMin() sets an additional convergence criterium of chisq less than the given value. Can only be used when the function is positive definite, usually a chi-squared. Required for track- fitting of test tracks that have truly 0 chisq -- the normal convergence often fails for such tracks.
References chisqMin.
Referenced by BLCMDtracker::fitTrack().
00152 { chisqMin = v; }
int BLMinimize::minimize | ( | std::vector< double > & | x, | |
double | tolerance = 1e-3 , |
|||
int | maxIter = 100 | |||
) | [inline] |
minimize() finds the minimum, returning status (0=success). x the initial and then the final argument values tolerance the convergence limit on the simplex size NOTE: this is after scaling! maxIter limits the number of iterations The initial step for x[i] is scale[i] (x[i] is scaled, so the step to the gsl routine is 1.0).
References arg, BLAssert, chisqMin, ff, iter, m, print, scale, size, and val.
Referenced by BLCMDtracker::fitTrack().
00162 { 00163 if(ff.n <= 0) return GSL_EINVAL; 00164 BLAssert(x.size()==scale.size()); 00165 gsl_vector *init = gsl_vector_alloc(ff.n); 00166 gsl_vector *istep = gsl_vector_alloc(ff.n); 00167 unsigned j=0; 00168 for(unsigned i=0; i<scale.size(); ++i) { 00169 arg[i] = x[i]; // fixed args, variable ones overwritten 00170 if(scale[i] != 0.0) { 00171 gsl_vector_set(init,j,x[i]/scale[i]); 00172 gsl_vector_set(istep,j,1.0); 00173 ++j; 00174 } 00175 } 00176 BLAssert(j==ff.n); BLAssert(m!=0); 00177 gsl_multimin_fminimizer_set(m,&ff,init,istep); 00178 for(iter=1; iter<=maxIter; ++iter) { 00179 int status = gsl_multimin_fminimizer_iterate(m); 00180 if(status) { 00181 if(print >= 1) 00182 printf("BLMinimize FAILED status=%d\n", 00183 status); 00184 gsl_vector_free(init); 00185 gsl_vector_free(istep); 00186 return status; 00187 } 00188 val = m->fval; 00189 size = gsl_multimin_fminimizer_size(m); 00190 if(print >= 1) 00191 printf("BLMinimize Iter %d: val=%.4g size=%.4g\n", 00192 iter,val,size); 00193 status = gsl_multimin_test_size(size,tolerance); 00194 if(status == GSL_SUCCESS || (!gsl_isnan(chisqMin) && 00195 val <= chisqMin)) { 00196 unsigned j=0; 00197 for(unsigned i=0; i<scale.size(); ++i) { 00198 if(scale[i] != 0.0) 00199 x[i] = gsl_vector_get(m->x,j++) * 00200 scale[i]; 00201 } 00202 gsl_vector_free(init); 00203 gsl_vector_free(istep); 00204 if(print >= 1) printf("BLMinimize SUCCESS\n"); 00205 return 0; 00206 } 00207 } 00208 gsl_vector_free(init); 00209 gsl_vector_free(istep); 00210 if(print >= 1) printf("BLMinimize FAILED iter > %d\n",maxIter); 00211 return GSL_EMAXITER; 00212 }
double BLMinimize::value | ( | ) | const [inline] |
value() returns the function value from the previous minimize().
References val.
Referenced by BLCMDtracker::fitTrack().
00215 { return val; }
double BLMinimize::getSize | ( | ) | [inline] |
getSize() returns the Simplex size from the previous minimize().
References size.
Referenced by BLCMDtracker::fitTrack().
00218 { return size; }
int BLMinimize::getIterations | ( | ) | [inline] |
getIterations() returns the # iterations of the previous minimize().
References iter.
Referenced by BLCMDtracker::fitTrack().
00221 { return iter; }
std::vector<std::string> BLMinimize::splitString | ( | const std::string & | s | ) | [inline, private] |
Referenced by setFunc().
00224 { 00225 std::string tmp(s); 00226 std::vector<std::string> v; 00227 while(tmp.size() > 0) { 00228 unsigned i=tmp.find_first_of(":"); 00229 if(i > tmp.size()) i = tmp.size(); 00230 v.push_back(tmp.substr(0,i)); 00231 tmp.erase(0,i+1); 00232 } 00233 return v; 00234 }
std::vector<double> BLMinimize::scale [private] |
Referenced by call(), minimize(), and setFunc().
std::vector<double> BLMinimize::arg [private] |
Referenced by call(), minimize(), and setFunc().
std::vector<std::string> BLMinimize::name [private] |
Referenced by setFunc().
double BLMinimize::val [private] |
Referenced by BLMinimize(), minimize(), and value().
double BLMinimize::size [private] |
Referenced by BLMinimize(), getSize(), and minimize().
int BLMinimize::iter [private] |
Referenced by BLMinimize(), getIterations(), and minimize().
int BLMinimize::print [private] |
Referenced by BLMinimize(), call(), minimize(), and setPrintDetail().
double BLMinimize::chisqMin [private] |
Referenced by BLMinimize(), minimize(), and setChisqMin().
BLMinimizeFunction* BLMinimize::func [private] |
Referenced by BLMinimize(), and setFunc().
gsl_multimin_function BLMinimize::ff [private] |
Referenced by BLMinimize(), minimize(), and setFunc().
gsl_multimin_fminimizer* BLMinimize::m [private] |
Referenced by BLMinimize(), minimize(), setFunc(), and ~BLMinimize().