00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "Math/IFunctionfwd.h"
00031 #include "Math/IFunction.h"
00032 #include "Math/Error.h"
00033 #include <vector>
00034
00035 #include "GSLMonteFunctionWrapper.h"
00036
00037 #include "Math/GSLMCIntegrator.h"
00038 #include "GSLMCIntegrationWorkspace.h"
00039 #include "GSLRngWrapper.h"
00040
00041 #include <algorithm>
00042 #include <functional>
00043 #include <ctype.h>
00044
00045
00046 #include "gsl/gsl_monte_vegas.h"
00047 #include "gsl/gsl_monte_miser.h"
00048 #include "gsl/gsl_monte_plain.h"
00049
00050
00051
00052 namespace ROOT {
00053 namespace Math {
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 GSLMCIntegrator::GSLMCIntegrator(MCIntegration::Type type, double absTol, double relTol, unsigned int calls):
00075 fType(type),
00076 fDim(0),
00077 fCalls((calls > 0) ? calls : IntegratorMultiDimOptions::DefaultNCalls()),
00078 fAbsTol((absTol >0) ? absTol : IntegratorMultiDimOptions::DefaultAbsTolerance() ),
00079 fRelTol((relTol >0) ? relTol : IntegratorMultiDimOptions::DefaultRelTolerance() ),
00080 fResult(0),fError(0),fStatus(-1),
00081 fWorkspace(0),
00082 fFunction(0)
00083 {
00084
00085 SetType(type);
00086
00087 fRng = new GSLRngWrapper();
00088 fRng->Allocate();
00089
00090
00091 if (fType == MCIntegration::kVEGAS) {
00092 IOptions * opts = IntegratorMultiDimOptions::FindDefault("VEGAS");
00093 if (opts != 0) SetParameters( VegasParameters(*opts) );
00094 }
00095 else if (fType == MCIntegration::kMISER) {
00096 IOptions * opts = IntegratorMultiDimOptions::FindDefault("MISER");
00097 if (opts != 0) SetParameters( MiserParameters(*opts) );
00098 }
00099
00100 }
00101
00102 GSLMCIntegrator::GSLMCIntegrator(const char * type, double absTol, double relTol, unsigned int calls):
00103 fDim(0),
00104 fCalls(calls),
00105 fAbsTol(absTol),
00106 fRelTol(relTol),
00107 fResult(0),fError(0),fStatus(-1),
00108 fWorkspace(0),
00109 fFunction(0)
00110 {
00111
00112 SetTypeName(type);
00113
00114
00115 fRng = new GSLRngWrapper();
00116 fRng->Allocate();
00117
00118 if (fType == MCIntegration::kVEGAS) {
00119 IOptions * opts = IntegratorMultiDimOptions::FindDefault("VEGAS");
00120 if (opts != 0) SetParameters( VegasParameters(*opts) );
00121 }
00122 else if (fType == MCIntegration::kMISER) {
00123 IOptions * opts = IntegratorMultiDimOptions::FindDefault("MISER");
00124 if (opts != 0) SetParameters( MiserParameters(*opts) );
00125 }
00126
00127 }
00128
00129
00130
00131 GSLMCIntegrator::~GSLMCIntegrator()
00132 {
00133
00134 if (fWorkspace) delete fWorkspace;
00135 if (fRng != 0) delete fRng;
00136 if (fFunction != 0) delete fFunction;
00137 fRng = 0;
00138
00139 }
00140
00141
00142
00143
00144
00145 GSLMCIntegrator::GSLMCIntegrator(const GSLMCIntegrator &) :
00146 VirtualIntegratorMultiDim()
00147 {}
00148
00149 GSLMCIntegrator & GSLMCIntegrator::operator=(const GSLMCIntegrator &) { return *this; }
00150
00151
00152
00153
00154
00155 void GSLMCIntegrator::SetFunction(const IMultiGenFunction &f)
00156 {
00157
00158 if(fFunction == 0) fFunction = new GSLMonteFunctionWrapper();
00159 fFunction->SetFunction(f);
00160 fDim = f.NDim();
00161 }
00162
00163 void GSLMCIntegrator::SetFunction( GSLMonteFuncPointer f, unsigned int dim, void * p )
00164 {
00165
00166 if(fFunction == 0) fFunction = new GSLMonteFunctionWrapper();
00167 fFunction->SetFuncPointer( f );
00168 fFunction->SetParams ( p );
00169 fDim = dim;
00170 }
00171
00172
00173
00174 double GSLMCIntegrator::Integral(const double* a, const double* b)
00175 {
00176
00177 assert(fRng != 0);
00178 gsl_rng* fr = fRng->Rng();
00179 assert(fr != 0);
00180 if (!CheckFunction()) return 0;
00181
00182
00183
00184 DoInitialize();
00185
00186 if ( fType == MCIntegration::kVEGAS)
00187 {
00188 GSLVegasIntegrationWorkspace * ws = dynamic_cast<GSLVegasIntegrationWorkspace *>(fWorkspace);
00189 assert(ws != 0);
00190 fStatus = gsl_monte_vegas_integrate( fFunction->GetFunc(), (double *) a, (double*) b , fDim, fCalls, fr, ws->GetWS(), &fResult, &fError);
00191 }
00192 else if (fType == MCIntegration::kMISER)
00193 {
00194 GSLMiserIntegrationWorkspace * ws = dynamic_cast<GSLMiserIntegrationWorkspace *>(fWorkspace);
00195 assert(ws != 0);
00196 fStatus = gsl_monte_miser_integrate( fFunction->GetFunc(), (double *) a, (double *) b , fDim, fCalls, fr, ws->GetWS(), &fResult, &fError);
00197 }
00198 else if (fType == MCIntegration::kPLAIN)
00199 {
00200 GSLPlainIntegrationWorkspace * ws = dynamic_cast<GSLPlainIntegrationWorkspace *>(fWorkspace);
00201 assert(ws != 0);
00202 fStatus = gsl_monte_plain_integrate( fFunction->GetFunc(), (double *) a, (double *) b , fDim, fCalls, fr, ws->GetWS(), &fResult, &fError);
00203 }
00204
00205 else
00206 {
00207
00208 fResult = 0;
00209 fError = 0;
00210 fStatus = -1;
00211 std::cerr << "GSLIntegrator - Error: Unknown integration type" << std::endl;
00212 throw std::exception();
00213 }
00214
00215 return fResult;
00216
00217 }
00218
00219
00220 double GSLMCIntegrator::Integral(const GSLMonteFuncPointer & f, unsigned int dim, double* a, double* b, void * p )
00221 {
00222
00223 SetFunction(f,dim,p);
00224 return Integral(a,b);
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 double GSLMCIntegrator::Result() const { return fResult; }
00241
00242
00243
00244
00245 double GSLMCIntegrator::Error() const { return fError; }
00246
00247
00248
00249
00250 int GSLMCIntegrator::Status() const { return fStatus; }
00251
00252
00253
00254
00255
00256
00257
00258 void GSLMCIntegrator::SetRelTolerance(double relTol){ this->fRelTol = relTol; }
00259
00260
00261
00262
00263 void GSLMCIntegrator::SetAbsTolerance(double absTol){ this->fAbsTol = absTol; }
00264
00265 void GSLMCIntegrator::SetGenerator(GSLRngWrapper* r){ this->fRng = r; }
00266
00267 void GSLMCIntegrator::SetType (MCIntegration::Type type)
00268 {
00269
00270 fType=type;
00271 if (fWorkspace != 0) {
00272 if (type == fWorkspace->Type() ) return;
00273 delete fWorkspace;
00274 fWorkspace = 0;
00275 }
00276
00277 if (type == MCIntegration::kPLAIN) {
00278 fWorkspace = new GSLPlainIntegrationWorkspace();
00279 }
00280 else if (type == MCIntegration::kMISER) {
00281 fWorkspace = new GSLMiserIntegrationWorkspace();
00282 }
00283 else {
00284
00285 if (type != MCIntegration::kVEGAS) {
00286 MATH_WARN_MSG("GSLMCIntegration","Invalid integration type : use Vegas as default");
00287 fType = MCIntegration::kVEGAS;
00288 }
00289 fWorkspace = new GSLVegasIntegrationWorkspace();
00290 }
00291 }
00292
00293 void GSLMCIntegrator::SetTypeName(const char * type)
00294 {
00295
00296 std::string typeName = (type!=0) ? type : "VEGAS";
00297 if (type == 0) MATH_INFO_MSG("GSLMCIntegration::SetTypeName","use default Vegas integrator method");
00298 std::transform(typeName.begin(), typeName.end(), typeName.begin(), (int(*)(int)) toupper );
00299
00300 MCIntegration::Type integType = MCIntegration::kVEGAS;
00301
00302 if (typeName == "PLAIN") {
00303 integType = MCIntegration::kPLAIN;
00304 }
00305 else if (typeName == "MISER") {
00306 integType = MCIntegration::kMISER;
00307 }
00308 else if (typeName != "VEGAS") {
00309 MATH_WARN_MSG("GSLMCIntegration::SetTypeName","Invalid integration type : use Vegas as default");
00310 }
00311
00312
00313 if (integType != fType) SetType(integType);
00314 }
00315
00316
00317 void GSLMCIntegrator::SetMode(MCIntegration::Mode mode)
00318 {
00319
00320 if(fType == ROOT::Math::MCIntegration::kVEGAS)
00321 {
00322 GSLVegasIntegrationWorkspace * ws = dynamic_cast<GSLVegasIntegrationWorkspace *>(fWorkspace);
00323 assert(ws != 0);
00324 if(mode == MCIntegration::kIMPORTANCE) ws->GetWS()->mode = GSL_VEGAS_MODE_IMPORTANCE;
00325 else if(mode == MCIntegration::kSTRATIFIED) ws->GetWS()->mode = GSL_VEGAS_MODE_STRATIFIED;
00326 else if(mode == MCIntegration::kIMPORTANCE_ONLY) ws->GetWS()->mode = GSL_VEGAS_MODE_IMPORTANCE_ONLY;
00327 }
00328
00329 else std::cerr << "Mode not matching integration type";
00330 }
00331
00332 void GSLMCIntegrator::SetOptions(const ROOT::Math::IntegratorMultiDimOptions & opt)
00333 {
00334
00335 SetTypeName(opt.Integrator().c_str() );
00336 SetAbsTolerance( opt.AbsTolerance() );
00337 SetRelTolerance( opt.RelTolerance() );
00338 fCalls = opt.NCalls();
00339
00340
00341
00342
00343 ROOT::Math::IOptions * extraOpt = opt.ExtraOptions();
00344 if (extraOpt) {
00345 if (fType == MCIntegration::kVEGAS ) {
00346 VegasParameters p(*extraOpt);
00347 SetParameters(p);
00348 }
00349 else if (fType == MCIntegration::kMISER ) {
00350 MiserParameters p(fDim);
00351 p = (*extraOpt);
00352 SetParameters(p);
00353 }
00354 else {
00355 MATH_WARN_MSG("GSLMCIntegrator::SetOptions","Invalid options set for the chosen integration type - ignore them");
00356 }
00357 }
00358 }
00359
00360
00361 void GSLMCIntegrator::SetParameters(const VegasParameters &p)
00362 {
00363
00364 if (fType == MCIntegration::kVEGAS)
00365 {
00366 GSLVegasIntegrationWorkspace * ws = dynamic_cast<GSLVegasIntegrationWorkspace *>(fWorkspace);
00367 assert(ws != 0);
00368 ws->SetParameters(p);
00369 }
00370 else
00371 MATH_ERROR_MSG("GSLIntegrator::SetParameters"," Parameters not matching integration type");
00372 }
00373
00374 void GSLMCIntegrator::SetParameters(const MiserParameters &p)
00375 {
00376
00377 if (fType == MCIntegration::kMISER)
00378 {
00379 GSLMiserIntegrationWorkspace * ws = dynamic_cast<GSLMiserIntegrationWorkspace *>(fWorkspace);
00380 assert(ws != 0);
00381 ws->SetParameters(p);
00382 }
00383 else
00384 MATH_ERROR_MSG("GSLIntegrator::SetParameters"," Parameters not matching integration type");
00385 }
00386
00387
00388 void GSLMCIntegrator::DoInitialize ( )
00389 {
00390
00391
00392 if (fWorkspace == 0) return;
00393 if (fDim == fWorkspace->NDim() && fType == fWorkspace->Type() )
00394 return;
00395
00396
00397 fWorkspace->Clear();
00398
00399 fWorkspace->Init(fDim);
00400 }
00401
00402
00403
00404
00405
00406 double GSLMCIntegrator::Sigma()
00407 {
00408
00409 if(fType == MCIntegration::kVEGAS)
00410 {
00411 GSLVegasIntegrationWorkspace * ws = dynamic_cast<GSLVegasIntegrationWorkspace *>(fWorkspace);
00412 assert (ws != 0);
00413 return ws->GetWS()->sigma;
00414 }
00415 else
00416 {
00417 std::cerr << "Parameter not mathcing integration type";
00418 return 0;
00419 }
00420
00421 }
00422
00423
00424
00425
00426 double GSLMCIntegrator::ChiSqr()
00427 {
00428
00429 if(fType == MCIntegration::kVEGAS)
00430 {
00431 GSLVegasIntegrationWorkspace * ws = dynamic_cast<GSLVegasIntegrationWorkspace *>(fWorkspace);
00432 assert(ws != 0);
00433 return ws->GetWS()->chisq;
00434 }
00435 else
00436 {
00437 std::cerr << "Parameter not mathcing integration type";
00438 return 0;
00439 }
00440 }
00441
00442
00443
00444 bool GSLMCIntegrator::CheckFunction()
00445 {
00446
00447 return true;
00448
00449
00450
00451
00452
00453
00454 }
00455
00456 const char * GSLMCIntegrator::GetTypeName() const {
00457 if (fType == MCIntegration::kVEGAS) return "VEGAS";
00458 if (fType == MCIntegration::kMISER) return "MISER";
00459 if (fType == MCIntegration::kPLAIN) return "PLAIN";
00460 return "UNDEFINED";
00461 }
00462
00463 ROOT::Math::IntegratorMultiDimOptions GSLMCIntegrator::Options() const {
00464 IOptions * extraOpts = ExtraOptions();
00465 ROOT::Math::IntegratorMultiDimOptions opt(extraOpts);
00466 opt.SetAbsTolerance(fAbsTol);
00467 opt.SetRelTolerance(fRelTol);
00468 opt.SetNCalls(fCalls);
00469 opt.SetWKSize(0);
00470 opt.SetIntegrator(GetTypeName() );
00471 return opt;
00472 }
00473
00474 ROOT::Math::IOptions * GSLMCIntegrator::ExtraOptions() const {
00475 if (!fWorkspace) return 0;
00476 return fWorkspace->Options();
00477 }
00478
00479
00480 }
00481 }
00482
00483
00484