1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2024-11-10 00:45:36 +00:00

first root finder class implementation

This commit is contained in:
Antonin Portelli 2014-09-22 15:19:30 +01:00
parent 8188a5541f
commit 4d19c23400
12 changed files with 499 additions and 76 deletions

View File

@ -22,7 +22,8 @@ noinst_PROGRAMS = \
exMathInterpreter \
exMin \
exPlot \
exRand
exRand \
exRootFinder
exCompiledDoubleFunction_SOURCES = exCompiledDoubleFunction.cpp
exCompiledDoubleFunction_CFLAGS = -g -O2
@ -56,4 +57,8 @@ exRand_SOURCES = exRand.cpp
exRand_CFLAGS = -g -O2
exRand_LDFLAGS = -L../lib/.libs -lLatAnalyze
exRootFinder_SOURCES = exRootFinder.cpp
exRootFinder_CFLAGS = -g -O2
exRootFinder_LDFLAGS = -L../lib/.libs -lLatAnalyze
ACLOCAL_AMFLAGS = -I .buildutils/m4

24
examples/exRootFinder.cpp Normal file
View File

@ -0,0 +1,24 @@
#include <iostream>
#include <LatAnalyze/Function.hpp>
#include <LatAnalyze/GslHybridRootFinder.hpp>
using namespace std;
using namespace Latan;
int main(void)
{
constexpr double a = 1., b = 10.;
DoubleFunction f1(2, [a](const double *x){return a*(1.-x[0]);});
DoubleFunction f2(2, [b](const double *x){return b*(x[1]-x[0]*x[0]);});
vector<DoubleFunction *> system = {&f1, &f2};
GslHybridRootFinder solve;
DVec init(2), x;
solve.setVerbosity(Solver::Verbosity::Debug);
init(0) = -10.; init(1) = -5.;
solve.setInit(init);
x = solve(system);
cout << "solution: " << x.transpose() << endl;
return 0;
}

140
lib/GslHybridRootFinder.cpp Normal file
View File

@ -0,0 +1,140 @@
/*
* GslHybridRootFinder.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/GslHybridRootFinder.hpp>
#include <LatAnalyze/includes.hpp>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_multiroots.h>
using namespace std;
using namespace Latan;
/******************************************************************************
* GslHybridRootFinder implementation *
******************************************************************************/
// output //////////////////////////////////////////////////////////////////////
void GslHybridRootFinder::printState(void)
{
if (solver_)
{
cout << "x=";
for (size_t i = 0; i < solver_->x->size; ++i)
{
cout << " " << scientific << gsl_vector_get(solver_->x, i);
}
cout << endl;
cout << "f=";
for (size_t i = 0; i < solver_->f->size; ++i)
{
cout << " " << scientific << gsl_vector_get(solver_->f, i);
}
cout << endl;
}
}
// solver //////////////////////////////////////////////////////////////////////
const DVec &
GslHybridRootFinder::operator()(const vector<DoubleFunction *> &func)
{
DVec &res = getState();
Verbosity verbosity = getVerbosity();
int status;
unsigned int iter = 0;
const size_t nFunc = func.size();
Index nArg;
gsl_vector *x;
gsl_multiroot_function fStruct;
int (*fWrap)(const gsl_vector *, void *, gsl_vector *) =
[](const gsl_vector *var, void *vFunc, gsl_vector *f)->int
{
vector<DoubleFunction *> &fPt =
*static_cast<vector<DoubleFunction *> *>(vFunc);
for (unsigned int i = 0; i < fPt.size(); ++i)
{
gsl_vector_set(f, i, (*fPt[i])(var->data));
}
return GSL_SUCCESS;
};
nArg = func[0]->getNArg();
for (auto f: func)
{
if (f->getNArg() != nArg)
{
LATAN_ERROR(Size,
"equations do not have the same number of unknown");
}
}
if (nArg != static_cast<Index>(nFunc))
{
LATAN_ERROR(Size, "equation and unknown number mismatch");
}
if (res.size() != nArg)
{
res.conservativeResize(nArg);
}
solver_ = gsl_multiroot_fsolver_alloc(gsl_multiroot_fsolver_hybrids, nFunc);
x = gsl_vector_alloc(nFunc);
FOR_VEC(res, i)
{
gsl_vector_set(x, static_cast<size_t>(i), res(i));
}
fStruct.n = nFunc;
fStruct.params = reinterpret_cast<void *>(
const_cast<vector<DoubleFunction *> *>(&func));
fStruct.f = fWrap;
gsl_multiroot_fsolver_set(solver_, &fStruct, x);
do
{
iter++;
status = gsl_multiroot_fsolver_iterate(solver_);
if (verbosity >= Verbosity::Debug)
{
cout << "--- iteration " << iter << endl;
printState();
}
if (status)
{
break;
}
status = gsl_multiroot_test_residual(solver_->f, getPrecision());
} while ((status == GSL_CONTINUE)&&(iter < getMaxIteration()));
if (verbosity >= Verbosity::Debug)
{
cout << "--- done" << endl;
cout << "end status: " << gsl_strerror(status) << endl;
}
if (status)
{
LATAN_WARNING("GSL hybrid root finder ended with status '" +
strFrom(gsl_strerror(status)) + "'");
}
FOR_VEC(res, i)
{
res(i) = gsl_vector_get(solver_->x, static_cast<size_t>(i));
}
gsl_vector_free(x);
gsl_multiroot_fsolver_free(solver_);
solver_ = nullptr;
return res;
}

View File

@ -0,0 +1,51 @@
/*
* GslHybridRootFinder.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_GslHybridRootFinder_hpp_
#define Latan_GslHybridRootFinder_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/RootFinder.hpp>
#include <gsl/gsl_multiroots.h>
BEGIN_NAMESPACE
/******************************************************************************
* GslHybridRootFinder *
******************************************************************************/
class GslHybridRootFinder: public RootFinder
{
public:
// constructor
GslHybridRootFinder(void) = default;
// destructor
virtual ~GslHybridRootFinder(void) = default;
// solver
virtual const DVec & operator()(const std::vector<DoubleFunction *> &func);
private:
// output
void printState(void);
private:
gsl_multiroot_fsolver *solver_{nullptr};
};
END_NAMESPACE
#endif // Latan_GslHybridRootFinder_hpp_

View File

@ -45,7 +45,7 @@ GslQagsIntegrator::~GslQagsIntegrator(void)
double GslQagsIntegrator::operator()(const DoubleFunction &f, const double xMin,
const double xMax)
{
double (*fWrap)(double, void *) = [](double x, void *fPt)
double (*fWrap)(double, void *) = [](double x, void *fPt)->double
{
return (*static_cast<DoubleFunction *>(fPt))(&x);
};

View File

@ -24,62 +24,67 @@ BUILT_SOURCES = AsciiParser.hpp MathParser.hpp
lib_LTLIBRARIES = libLatAnalyze.la
libLatAnalyze_la_SOURCES =\
AsciiFile.cpp \
AsciiParser.ypp \
AsciiLexer.lpp \
Chi2Function.cpp \
CompiledFunction.cpp \
CompiledModel.cpp \
Exceptions.cpp \
File.cpp \
FitInterface.cpp \
Function.cpp \
Global.cpp \
GslQagsIntegrator.cpp \
includes.hpp \
Mat.cpp \
Math.cpp \
MathInterpreter.cpp \
MathParser.ypp \
MathLexer.lpp \
MatSample.cpp \
Minimizer.cpp \
Model.cpp \
Plot.cpp \
RandGen.cpp \
XmlReader.cpp \
XYSampleData.cpp \
XYStatData.cpp \
XML/tinyxml2.cpp \
libLatAnalyze_la_SOURCES = \
AsciiFile.cpp \
AsciiParser.ypp \
AsciiLexer.lpp \
Chi2Function.cpp \
CompiledFunction.cpp \
CompiledModel.cpp \
Exceptions.cpp \
File.cpp \
FitInterface.cpp \
Function.cpp \
Global.cpp \
GslHybridRootFinder.cpp\
GslQagsIntegrator.cpp \
includes.hpp \
Mat.cpp \
Math.cpp \
MathInterpreter.cpp \
MathParser.ypp \
MathLexer.lpp \
MatSample.cpp \
Model.cpp \
Plot.cpp \
RandGen.cpp \
Solver.cpp \
TabFunction.cpp \
XmlReader.cpp \
XYSampleData.cpp \
XYStatData.cpp \
XML/tinyxml2.cpp \
../config.h
libLatAnalyze_ladir = $(pkgincludedir)
libLatAnalyze_la_HEADERS =\
AsciiFile.hpp \
Chi2Function.hpp \
CompiledFunction.hpp \
CompiledModel.hpp \
Dataset.hpp \
Exceptions.hpp \
FitInterface.hpp \
Function.hpp \
File.hpp \
Global.hpp \
GslQagsIntegrator.hpp \
Integrator.hpp \
IoObject.hpp \
Mat.hpp \
Math.hpp \
MathInterpreter.hpp \
MatSample.hpp \
Minimizer.hpp \
Model.hpp \
ParserState.hpp \
Plot.hpp \
RandGen.hpp \
StatArray.hpp \
XmlReader.hpp \
XYSampleData.hpp \
libLatAnalyze_la_HEADERS = \
AsciiFile.hpp \
Chi2Function.hpp \
CompiledFunction.hpp \
CompiledModel.hpp \
Dataset.hpp \
Exceptions.hpp \
FitInterface.hpp \
Function.hpp \
File.hpp \
Global.hpp \
GslHybridRootFinder.hpp\
GslQagsIntegrator.hpp \
Integrator.hpp \
IoObject.hpp \
Mat.hpp \
Math.hpp \
MathInterpreter.hpp \
MatSample.hpp \
Minimizer.hpp \
Model.hpp \
ParserState.hpp \
Plot.hpp \
RandGen.hpp \
TabFunction.hpp \
Solver.hpp \
StatArray.hpp \
XmlReader.hpp \
XYSampleData.hpp \
XYStatData.hpp
if HAVE_MINUIT
libLatAnalyze_la_SOURCES += MinuitMinimizer.cpp

View File

@ -23,6 +23,7 @@
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Function.hpp>
#include <LatAnalyze/Mat.hpp>
#include <LatAnalyze/Solver.hpp>
BEGIN_NAMESPACE
@ -30,33 +31,15 @@ BEGIN_NAMESPACE
* Abstract minimizer class *
******************************************************************************/
class Minimizer
class Minimizer: public Solver
{
public:
enum class Verbosity
{
Silent = 0,
Normal = 1,
Debug = 2
};
public:
// constructor
explicit Minimizer(Verbosity verbosity = Verbosity::Silent);
Minimizer(void) = default;
// destructor
virtual ~Minimizer(void) = default;
// access
Index getDim(void) const;
Verbosity getVerbosity(void) const;
void setInit(const DVec &x0);
void setVerbosity(const Verbosity verbosity);
// minimization
virtual const DVec & operator()(const DoubleFunction &f) = 0;
protected:
// access
DVec & getState(void);
private:
DVec x_;
Verbosity verbosity_;
};
END_NAMESPACE

View File

@ -58,6 +58,21 @@ double MinuitMinimizer::MinuitFunction::Up(void) const
return 1.;
}
// access //////////////////////////////////////////////////////////////////////
double MinuitMinimizer::getPrecision(void) const
{
LATAN_ERROR(Implementation,
"Minuit minimizer precision cannot be accessed");
return 0.;
}
void MinuitMinimizer::setPrecision(const double precision __unused)
{
LATAN_ERROR(Implementation,
"Minuit minimizer precision cannot be accessed");
}
// minimization ////////////////////////////////////////////////////////////////
const DVec & MinuitMinimizer::operator()(const DoubleFunction &f)
{

View File

@ -52,6 +52,9 @@ public:
MinuitMinimizer(void) = default;
// destructor
virtual ~MinuitMinimizer(void) = default;
// access
virtual double getPrecision(void) const;
virtual void setPrecision(const double precision);
// minimization
virtual const DVec & operator()(const DoubleFunction &f);
};

47
lib/RootFinder.hpp Normal file
View File

@ -0,0 +1,47 @@
/*
* RootFinder.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_RootFinder_hpp_
#define Latan_RootFinder_hpp_
#include <LatAnalyze/Global.hpp>
#include <LatAnalyze/Function.hpp>
#include <LatAnalyze/Solver.hpp>
BEGIN_NAMESPACE
/******************************************************************************
* RootFinder *
******************************************************************************/
class RootFinder: public Solver
{
public:
// constructor
RootFinder(void) = default;
// destructor
virtual ~RootFinder(void) = default;
// solver
virtual const DVec & operator()(const std::vector<DoubleFunction *> &func)
= 0;
};
END_NAMESPACE
#endif // Latan_RootFinder_hpp_

80
lib/Solver.cpp Normal file
View File

@ -0,0 +1,80 @@
/*
* Solver.cpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#include <LatAnalyze/Solver.hpp>
#include <LatAnalyze/includes.hpp>
using namespace std;
using namespace Latan;
/******************************************************************************
* Solver implementation *
******************************************************************************/
// constructor /////////////////////////////////////////////////////////////////
Solver::Solver(const double precision, const unsigned int maxIteration)
{
setMaxIteration(maxIteration);
setPrecision(precision);
}
// access //////////////////////////////////////////////////////////////////////
Index Solver::getDim(void) const
{
return x_.size();
}
unsigned int Solver::getMaxIteration(void) const
{
return maxIteration_;
}
double Solver::getPrecision(void) const
{
return precision_;
}
DVec & Solver::getState(void)
{
return x_;
}
Solver::Verbosity Solver::getVerbosity(void) const
{
return verbosity_;
}
void Solver::setInit(const DVec &x0)
{
x_ = x0;
}
void Solver::setMaxIteration(const unsigned int maxIteration)
{
maxIteration_ = maxIteration;
}
void Solver::setPrecision(const double precision)
{
precision_ = precision;
}
void Solver::setVerbosity(const Verbosity verbosity)
{
verbosity_ = verbosity;
}

70
lib/Solver.hpp Normal file
View File

@ -0,0 +1,70 @@
/*
* Solver.hpp, part of LatAnalyze 3
*
* Copyright (C) 2013 - 2014 Antonin Portelli
*
* LatAnalyze 3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LatAnalyze 3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LatAnalyze 3. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef Latan_Solver_hpp_
#define Latan_Solver_hpp_
#include <LatAnalyze/Global.hpp>
BEGIN_NAMESPACE
/******************************************************************************
* Solver *
******************************************************************************/
class Solver
{
public:
static const unsigned int defaultMaxIteration = 1000u;
static constexpr double defaultPrec = 1.0e-7;
public:
enum class Verbosity
{
Silent = 0,
Normal = 1,
Debug = 2
};
public:
// constructor
Solver(const double precision = defaultPrec,
const unsigned int maxIteration = defaultMaxIteration);
// destructor
virtual ~Solver(void) = default;
// access
Index getDim(void) const;
virtual double getPrecision(void) const;
virtual unsigned int getMaxIteration(void) const;
Verbosity getVerbosity(void) const;
virtual void setInit(const DVec &x0);
virtual void setPrecision(const double precision);
virtual void setMaxIteration(const unsigned int maxIteration);
void setVerbosity(const Verbosity verbosity);
protected:
// access
DVec & getState(void);
private:
unsigned int maxIteration_;
double precision_;
DVec x_;
Verbosity verbosity_{Verbosity::Silent};
};
END_NAMESPACE
#endif // Latan_Solver_hpp_