#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().
00083 { 00084 BLMinimize *p = (BLMinimize*)param; 00085 return p->call(x); 00086 }
double BLMinimize::call | ( | const gsl_vector * | x | ) | [inline, private] |
References arg, print, and scale.
Referenced by f().
00088 { 00089 if(print >= 2) printf("BLMinimize call args:"); 00090 int j=0; 00091 for(unsigned i=0; i<scale.size(); ++i) { 00092 if(scale[i] != 0.0) // fixed args are already set 00093 arg[i] = gsl_vector_get(x,j++) * scale[i]; 00094 if(print >= 2) 00095 printf(" %.4g",arg[i]); 00096 } 00097 if(print >= 2) printf("\n"); 00098 double v = (*func)(arg); 00099 if(print >= 2) printf("BLMinimize call returns value=%.4g\n",v); 00100 return v; 00101 }
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().
00116 { 00117 func = &f; 00118 scale.clear(); 00119 arg.clear(); 00120 name.clear(); 00121 std::vector<std::string> n = splitString(names); 00122 int nx = 0; 00123 for(unsigned i=0; i<_scale.size(); ++i) { 00124 double s=_scale[i]; 00125 scale.push_back(s); 00126 arg.push_back(s); 00127 name.push_back(i<n.size() ? n[i] : ""); 00128 if(s != 0.0) ++nx; 00129 } 00130 ff.f=BLMinimize::f; 00131 ff.n=nx; 00132 ff.params=this; 00133 if(m) gsl_multimin_fminimizer_free(m); 00134 m = 0; 00135 if(nx == 0) return; 00136 m = gsl_multimin_fminimizer_alloc( 00137 gsl_multimin_fminimizer_nmsimplex,nx); 00138 }
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.
00143 { 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().
00150 { 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, chisqMin, ff, iter, m, print, scale, size, and val.
Referenced by BLCMDtracker::fitTrack().
00160 { 00161 if(ff.n <= 0) return GSL_EINVAL; 00162 assert(x.size()==scale.size()); 00163 gsl_vector *init = gsl_vector_alloc(ff.n); 00164 gsl_vector *istep = gsl_vector_alloc(ff.n); 00165 unsigned j=0; 00166 for(unsigned i=0; i<scale.size(); ++i) { 00167 arg[i] = x[i]; // fixed args, variable ones overwritten 00168 if(scale[i] != 0.0) { 00169 gsl_vector_set(init,j,x[i]/scale[i]); 00170 gsl_vector_set(istep,j,1.0); 00171 ++j; 00172 } 00173 } 00174 assert(j==ff.n); assert(m!=0); 00175 gsl_multimin_fminimizer_set(m,&ff,init,istep); 00176 for(iter=1; iter<=maxIter; ++iter) { 00177 int status = gsl_multimin_fminimizer_iterate(m); 00178 if(status) { 00179 if(print >= 1) 00180 printf("BLMinimize FAILED status=%d\n", 00181 status); 00182 gsl_vector_free(init); 00183 gsl_vector_free(istep); 00184 return status; 00185 } 00186 val = m->fval; 00187 size = gsl_multimin_fminimizer_size(m); 00188 if(print >= 1) 00189 printf("BLMinimize Iter %d: val=%.4g size=%.4g\n", 00190 iter,val,size); 00191 status = gsl_multimin_test_size(size,tolerance); 00192 if(status == GSL_SUCCESS || (!gsl_isnan(chisqMin) && 00193 val <= chisqMin)) { 00194 unsigned j=0; 00195 for(unsigned i=0; i<scale.size(); ++i) { 00196 if(scale[i] != 0.0) 00197 x[i] = gsl_vector_get(m->x,j++) * 00198 scale[i]; 00199 } 00200 gsl_vector_free(init); 00201 gsl_vector_free(istep); 00202 if(print >= 1) printf("BLMinimize SUCCESS\n"); 00203 return 0; 00204 } 00205 } 00206 gsl_vector_free(init); 00207 gsl_vector_free(istep); 00208 if(print >= 1) printf("BLMinimize FAILED iter > %d\n",maxIter); 00209 return GSL_EMAXITER; 00210 }
double BLMinimize::value | ( | ) | const [inline] |
value() returns the function value from the previous minimize().
References val.
Referenced by BLCMDtracker::fitTrack().
00213 { return val; }
double BLMinimize::getSize | ( | ) | [inline] |
getSize() returns the Simplex size from the previous minimize().
References size.
Referenced by BLCMDtracker::fitTrack().
00216 { return size; }
int BLMinimize::getIterations | ( | ) | [inline] |
getIterations() returns the # iterations of the previous minimize().
References iter.
Referenced by BLCMDtracker::fitTrack().
00219 { return iter; }
std::vector<std::string> BLMinimize::splitString | ( | const std::string & | s | ) | [inline, private] |
Referenced by setFunc().
00222 { 00223 std::string tmp(s); 00224 std::vector<std::string> v; 00225 while(tmp.size() > 0) { 00226 unsigned i=tmp.find_first_of(":"); 00227 if(i > tmp.size()) i = tmp.size(); 00228 v.push_back(tmp.substr(0,i)); 00229 tmp.erase(0,i+1); 00230 } 00231 return v; 00232 }
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().