37 #include "gsl/gsl_multiroots.h"
38 #include "gsl/gsl_errno.h"
52 int gDefaultMaxIter = 100;
53 double gDefaultAbsTolerance = 1.E-6;
54 double gDefaultRelTolerance = 1.E-10;
57 void GSLMultiRootFinder::SetDefaultTolerance(
double abstol,
double reltol ) {
59 gDefaultAbsTolerance = abstol;
60 if (reltol > 0) gDefaultRelTolerance = reltol;
62 void GSLMultiRootFinder::SetDefaultMaxIterations(
int maxiter) {
64 gDefaultMaxIter = maxiter;
67 GSLMultiRootFinder::GSLMultiRootFinder(EType type) :
68 fIter(0), fStatus(-1), fPrintLevel(0),
69 fType(type), fUseDerivAlgo(false),
73 fFunctions.reserve(2);
76 GSLMultiRootFinder::GSLMultiRootFinder(EDerivType type) :
77 fIter(0), fStatus(-1), fPrintLevel(0),
78 fType(type), fUseDerivAlgo(true),
82 fFunctions.reserve(2);
85 GSLMultiRootFinder::GSLMultiRootFinder(
const char * name) :
86 fIter(0), fStatus(-1), fPrintLevel(0),
87 fType(0), fUseDerivAlgo(false),
91 fFunctions.reserve(2);
95 GSLMultiRootFinder::~GSLMultiRootFinder()
99 if (fSolver)
delete fSolver;
102 GSLMultiRootFinder::GSLMultiRootFinder(
const GSLMultiRootFinder &)
106 GSLMultiRootFinder & GSLMultiRootFinder::operator = (
const GSLMultiRootFinder &rhs)
109 if (
this == &rhs)
return *
this;
114 void GSLMultiRootFinder::SetType(
const char * name) {
116 std::pair<bool,int> type = GetType(name);
117 fUseDerivAlgo = type.first;
122 int GSLMultiRootFinder::AddFunction(
const ROOT::Math::IMultiGenFunction & func) {
124 ROOT::Math::IMultiGenFunction * f = func.Clone();
126 fFunctions.push_back(f);
127 return fFunctions.size();
130 void GSLMultiRootFinder::ClearFunctions() {
132 for (
unsigned int i = 0; i < fFunctions.size(); ++i) {
133 if (fFunctions[i] != 0 )
delete fFunctions[i];
139 void GSLMultiRootFinder::Clear() {
142 if (fSolver) Clear();
147 const double * GSLMultiRootFinder::X()
const {
149 return (fSolver != 0) ? fSolver->X() : 0;
151 const double * GSLMultiRootFinder::Dx()
const {
153 return (fSolver != 0) ? fSolver->Dx() : 0;
155 const double * GSLMultiRootFinder::FVal()
const {
157 return (fSolver != 0) ? fSolver->FVal() : 0;
159 const char * GSLMultiRootFinder::Name()
const {
161 return (fSolver != 0) ? fSolver->Name().c_str() :
"";
183 const gsl_multiroot_fsolver_type * GetGSLType(GSLMultiRootFinder::EType type) {
187 case ROOT::Math::GSLMultiRootFinder::kHybridS:
188 return gsl_multiroot_fsolver_hybrids;
189 case ROOT::Math::GSLMultiRootFinder::kHybrid:
190 return gsl_multiroot_fsolver_hybrid;
191 case ROOT::Math::GSLMultiRootFinder::kDNewton:
192 return gsl_multiroot_fsolver_dnewton;
193 case ROOT::Math::GSLMultiRootFinder::kBroyden:
194 return gsl_multiroot_fsolver_broyden;
196 return gsl_multiroot_fsolver_hybrids;
201 const gsl_multiroot_fdfsolver_type * GetGSLDerivType(GSLMultiRootFinder::EDerivType type) {
205 case ROOT::Math::GSLMultiRootFinder::kHybridSJ :
206 return gsl_multiroot_fdfsolver_hybridsj;
207 case ROOT::Math::GSLMultiRootFinder::kHybridJ :
208 return gsl_multiroot_fdfsolver_hybridj;
209 case ROOT::Math::GSLMultiRootFinder::kNewton :
210 return gsl_multiroot_fdfsolver_newton;
211 case ROOT::Math::GSLMultiRootFinder::kGNewton :
212 return gsl_multiroot_fdfsolver_gnewton;
214 return gsl_multiroot_fdfsolver_hybridsj;
219 std::pair<bool,int> GSLMultiRootFinder::GetType(
const char * name) {
220 if (name == 0)
return std::make_pair<bool,int>(
false, -1);
221 std::string aname = name;
222 std::transform(aname.begin(), aname.end(), aname.begin(), (int(*)(int)) tolower );
224 if (aname.find(
"hybridsj") != std::string::npos)
return std::make_pair(
true, kHybridSJ);
225 if (aname.find(
"hybridj") != std::string::npos)
return std::make_pair(
true, kHybridJ);
226 if (aname.find(
"hybrids") != std::string::npos)
return std::make_pair(
false, kHybridS);
227 if (aname.find(
"hybrid") != std::string::npos)
return std::make_pair(
false, kHybrid);
228 if (aname.find(
"gnewton") != std::string::npos)
return std::make_pair(
true, kGNewton);
229 if (aname.find(
"dnewton") != std::string::npos)
return std::make_pair(
false, kDNewton);
230 if (aname.find(
"newton") != std::string::npos)
return std::make_pair(
true, kNewton);
231 if (aname.find(
"broyden") != std::string::npos)
return std::make_pair(
false, kBroyden);
232 MATH_INFO_MSG(
"GSLMultiRootFinder::GetType",
"Unknow algorithm - use default one");
233 return std::make_pair(
false, -1);
236 bool GSLMultiRootFinder::Solve (
const double * x,
int maxIter,
double absTol,
double relTol)
240 if (fSolver)
delete fSolver;
243 if (fFunctions.size() == 0) {
244 MATH_ERROR_MSG(
"GSLMultiRootFinder::Solve",
"Function list is empty");
250 EDerivType type = (EDerivType) fType;
251 if (!fSolver) fSolver =
new GSLMultiRootDerivSolver( GetGSLDerivType(type), Dim() );
254 EType type = (EType) fType;
255 if (!fSolver) fSolver =
new GSLMultiRootSolver( GetGSLType(type), Dim() );
260 assert(fSolver != 0);
261 bool ret = fSolver->InitSolver( fFunctions, x);
263 MATH_ERROR_MSG(
"GSLMultiRootFinder::Solve",
"Error initializing the solver");
268 if (maxIter == 0) maxIter = gDefaultMaxIter;
269 if (absTol <= 0) absTol = gDefaultAbsTolerance;
270 if (relTol <= 0) relTol = gDefaultRelTolerance;
272 if (fPrintLevel >= 1)
273 std::cout <<
"GSLMultiRootFinder::Solve:" << Name() <<
" max iterations " << maxIter <<
" and tolerance " << absTol << std::endl;
281 status = fSolver->Iterate();
283 if (fPrintLevel >= 2) {
284 std::cout <<
"GSLMultiRootFinder::Solve - iteration # " << iter <<
" status = " << status << std::endl;
288 if (status == GSL_EBADFUNC) {
289 MATH_ERROR_MSG(
"GSLMultiRootFinder::Solve",
"The iteration encountered a singolar point due to a bad function value");
293 if (status == GSL_ENOPROG) {
294 MATH_ERROR_MSG(
"GSLMultiRootFinder::Solve",
"The iteration is not making any progress");
298 if (status != GSL_SUCCESS) {
299 MATH_ERROR_MSG(
"GSLMultiRootFinder::Solve",
"Uknown iteration error - exit");
305 status = fSolver->TestResidual(absTol);
309 int status2 = fSolver->TestDelta(absTol, relTol);
310 if (status2 == GSL_SUCCESS) {
311 MATH_INFO_MSG(
"GSLMultiRootFinder::Solve",
"The iteration converged");
314 while (status == GSL_CONTINUE && iter < maxIter);
315 if (status == GSL_CONTINUE) {
316 MATH_INFO_MSGVAL(
"GSLMultiRootFinder::Solve",
"exceeded max iterations, reached tolerance is not sufficient",absTol);
318 if (status == GSL_SUCCESS) {
319 if (fPrintLevel>=1) {
320 MATH_INFO_MSG(
"GSLMultiRootFinder::Solve",
"The iteration converged");
321 std::cout <<
"GSL Algorithm used is : " << fSolver->Name() << std::endl;
322 std::cout <<
"Number of iterations = " << iter<< std::endl;
329 return (fStatus == GSL_SUCCESS);
333 void GSLMultiRootFinder::PrintState(std::ostream & os) {
335 if (!fSolver)
return;
336 double ndigits = std::log10(
double( Dim() ) );
337 int wi = int(ndigits)+1;
338 const double * xtmp = fSolver->X();
339 const double * ftmp = fSolver->FVal();
340 os <<
"Root values = ";
341 for (
unsigned int i = 0; i< Dim(); ++i)
342 os <<
"x[" << std::setw(wi) << i <<
"] = " << std::setw(12) << xtmp[i] <<
" ";
344 os <<
"Function values = ";
345 for (
unsigned int i = 0; i< Dim(); ++i)
346 os <<
"f[" << std::setw(wi) << i <<
"] = " << std::setw(12) << ftmp[i] <<
" ";