00001
00002 #define USE_GSL_MULTIMIN
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef BLMINIMIZE_HH
00023 #define BLMINIMIZE_HH
00024
00025 #include <stdio.h>
00026 #include <vector>
00027 #include <string>
00028
00029 #include "globals.hh"
00030 #include "BLAssert.hh"
00031
00032
00033
00034
00035 class BLMinimizeFunction {
00036 public:
00037 BLMinimizeFunction() { }
00038 virtual ~BLMinimizeFunction() { }
00039
00040
00041
00042
00043 virtual double operator()(const std::vector<double> &x) = 0;
00044 };
00045
00046 #ifdef USE_GSL_MULTIMIN
00047
00048 #include <gsl/gsl_multimin.h>
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 class BLMinimize {
00072 std::vector<double> scale;
00073 std::vector<double> arg;
00074 std::vector<std::string> name;
00075 double val;
00076 double size;
00077 int iter;
00078 int print;
00079 double chisqMin;
00080 BLMinimizeFunction *func;
00081 gsl_multimin_function ff;
00082 gsl_multimin_fminimizer *m;
00083 private:
00084
00085 static double f(const gsl_vector *x, void *param) {
00086 BLMinimize *p = (BLMinimize*)param;
00087 return p->call(x);
00088 }
00089
00090 double call(const gsl_vector *x) {
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)
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 }
00104 public:
00105
00106 BLMinimize(int _print=2) : scale(), arg(), name()
00107 { val=GSL_NAN; size=GSL_NAN; iter=0; print=_print;
00108 chisqMin=GSL_NAN; func=0; ff.f=0; ff.n=0; ff.params=0; m=0;
00109 }
00110
00111 virtual ~BLMinimize() { if(m) gsl_multimin_fminimizer_free(m); }
00112
00113
00114
00115
00116
00117 void setFunc(BLMinimizeFunction &f, const std::vector<double> &_scale,
00118 const std::string &names="") {
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 }
00141
00142
00143
00144
00145 void setPrintDetail(int v=0) { print = v; }
00146
00147
00148
00149
00150
00151
00152 void setChisqMin(double v) { chisqMin = v; }
00153
00154
00155
00156
00157
00158
00159
00160
00161 int minimize(std::vector<double> &x, double tolerance=1e-3,
00162 int maxIter=100) {
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];
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 }
00213
00214
00215 double value() const { return val; }
00216
00217
00218 double getSize() { return size; }
00219
00220
00221 int getIterations() { return iter; }
00222
00223 private:
00224 std::vector<std::string> splitString(const std::string &s) {
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 }
00235 };
00236
00237 #endif // USE_GSL_MULTIMIN
00238
00239 #ifdef USE_TMINUIT
00240
00241 #include "TMinuit.h"
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 class BLMinimize {
00252 std::vector<double> scale;
00253 std::vector<std::string> name;
00254 std::vector<double> arg;
00255 double val;
00256 int iter;
00257 int print;
00258 double chisqMin;
00259 BLMinimizeFunction *func;
00260 TMinuit *tm;
00261 static BLMinimize *current;
00262 private:
00263 static void fcn(Int_t &npar, Double_t *grad, Double_t &val, Double_t *x,
00264 Int_t iflag) {
00265 BLAssert(current != 0);
00266 val = current->call(npar,x);
00267 }
00268 double call(int npar, double *x) {
00269
00270 for(unsigned i=0; i<arg.size(); ++i)
00271 arg[i] = x[i];
00272 return (*func)(arg);
00273 }
00274 public:
00275
00276 BLMinimize(int _print=2) : scale(), name(), arg()
00277 { val=0.0; iter=0; print=_print; chisqMin=0.0; func=0; tm=0; }
00278
00279 virtual ~BLMinimize() { }
00280
00281
00282
00283
00284
00285 void setFunc(BLMinimizeFunction &f, const std::vector<double> &_scale,
00286 const std::string &names="") {
00287 func = &f;
00288 scale.clear();
00289 name.clear();
00290 arg.clear();
00291 std::vector<std::string> n = splitString(names);
00292 for(unsigned i=0; i<_scale.size(); ++i) {
00293 double s=_scale[i];
00294 scale.push_back(s);
00295 name.push_back(i<n.size() ? n[i] : "");
00296 arg.push_back(0.0);
00297 }
00298
00299 if(tm) delete tm;
00300 tm = new TMinuit();
00301 tm->SetFCN(fcn);
00302 tm->SetPrintLevel(-1);
00303 tm->Command("SET PRINTOUT -1");
00304 }
00305
00306
00307
00308
00309 void setPrintDetail(int v=0) { print = v; }
00310
00311
00312
00313
00314
00315
00316 void setChisqMin(double v) { chisqMin = v; }
00317
00318
00319
00320
00321
00322
00323
00324 int minimize(std::vector<double> &x, double tolerance=1e-3,
00325 int maxIter=100) {
00326 BLAssert(tm != 0);
00327 BLAssert(x.size() == scale.size());
00328 for(unsigned i=0; i<scale.size(); ++i) {
00329 tm->DefineParameter(i,name[i].c_str(),x[i],scale[i],0.0,0.0);
00330 }
00331
00332 tm->SetMaxIterations(maxIter);
00333 current = this;
00334 int retval = tm->Migrad();
00335 current = 0;
00336 for(unsigned i=0; i<scale.size(); ++i) {
00337 double err;
00338 tm->GetParameter(i,x[i],err);
00339 }
00340 val = (*func)(x);
00341 return retval;
00342 }
00343
00344
00345 double value() const { return val; }
00346
00347
00348 double getSize() { return 0.0; }
00349
00350
00351 int getIterations() { return iter; }
00352
00353 private:
00354 std::vector<std::string> splitString(const std::string &s) {
00355 std::string tmp(s);
00356 std::vector<std::string> v;
00357 while(tmp.size() > 0) {
00358 unsigned i=tmp.find_first_of(":");
00359 if(i > tmp.size()) i = tmp.size();
00360 v.push_back(tmp.substr(0,i));
00361 tmp.erase(0,i+1);
00362 }
00363 return v;
00364 }
00365 };
00366
00367
00368 #endif // USE_TMINUIT
00369
00370 #endif // BLMINIMIZE_HH