mirror of
https://github.com/aportelli/LatAnalyze.git
synced 2025-06-17 06:47:06 +01:00
reintegration of LatCore & folder restructuration
This commit is contained in:
234
lib/Numerical/Derivative.cpp
Normal file
234
lib/Numerical/Derivative.cpp
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Derivative.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/Derivative.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
#include <LatAnalyze/Core/Math.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
using namespace Math;
|
||||
|
||||
/******************************************************************************
|
||||
* Derivative implementation *
|
||||
******************************************************************************/
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
Derivative::Derivative(const DoubleFunction &f, const Index dir,
|
||||
const double step)
|
||||
: buffer_(new DVec(f.getNArg()))
|
||||
{
|
||||
setFunction(f);
|
||||
setDir(dir);
|
||||
setStep(step);
|
||||
}
|
||||
|
||||
Derivative::Derivative(const DoubleFunction &f, const Index dir,
|
||||
const Index order, const DVec &point, const double step)
|
||||
: Derivative(f, dir, step)
|
||||
{
|
||||
setOrderAndPoint(order, point);
|
||||
}
|
||||
|
||||
// access //////////////////////////////////////////////////////////////////////
|
||||
Index Derivative::getDir(void) const
|
||||
{
|
||||
return dir_;
|
||||
}
|
||||
|
||||
Index Derivative::getOrder(void) const
|
||||
{
|
||||
return order_;
|
||||
}
|
||||
|
||||
Index Derivative::getNPoint(void) const
|
||||
{
|
||||
return point_.size();
|
||||
}
|
||||
|
||||
double Derivative::getStep(void) const
|
||||
{
|
||||
return step_;
|
||||
}
|
||||
|
||||
void Derivative::setDir(const Index dir)
|
||||
{
|
||||
dir_ = dir;
|
||||
}
|
||||
|
||||
void Derivative::setFunction(const DoubleFunction &f)
|
||||
{
|
||||
f_ = f;
|
||||
}
|
||||
|
||||
void Derivative::setOrderAndPoint(const Index order, const DVec &point)
|
||||
{
|
||||
if (order >= point.size())
|
||||
{
|
||||
LATAN_ERROR(Size, "derivative order is superior or equal to the number of point");
|
||||
}
|
||||
order_ = order;
|
||||
point_ = point;
|
||||
coefficient_.resize(point.size());
|
||||
makeCoefficients();
|
||||
}
|
||||
|
||||
void Derivative::setStep(const double step)
|
||||
{
|
||||
step_ = step;
|
||||
}
|
||||
// coefficient generation //////////////////////////////////////////////////////
|
||||
// from B. Fornberg, “Generation of finite difference formulas on arbitrarily
|
||||
// spaced grids,” Math. Comp., vol. 51, no. 184, pp. 699–706, 1988.
|
||||
// http://dx.doi.org/10.1090/S0025-5718-1988-0935077-0
|
||||
void Derivative::makeCoefficients(void)
|
||||
{
|
||||
double c[3];
|
||||
const Index N = point_.size() - 1, M = order_;
|
||||
DMat curr(M + 1, N + 1), prev(M + 1, N + 1);
|
||||
|
||||
curr.fill(0.);
|
||||
prev.fill(0.);
|
||||
prev(0, 0) = 1.;
|
||||
c[0] = 1.;
|
||||
for (Index n = 1; n <= N; ++n)
|
||||
{
|
||||
c[1] = 1.;
|
||||
for (Index nu = 0; nu <= n - 1; ++nu)
|
||||
{
|
||||
c[2] = point_(n) - point_(nu);
|
||||
c[1] *= c[2];
|
||||
for (Index m = 0; m <= min(n, M); ++m)
|
||||
{
|
||||
curr(m, nu) = point_(n)*prev(m, nu);
|
||||
if (m)
|
||||
{
|
||||
curr(m, nu) -= m*prev(m-1, nu);
|
||||
}
|
||||
curr(m, nu) /= c[2];
|
||||
}
|
||||
}
|
||||
for (Index m = 0; m <= min(n, M); ++m)
|
||||
{
|
||||
curr(m, n) = -point_(n-1)*prev(m, n-1);
|
||||
if (m)
|
||||
{
|
||||
curr(m, n) += m*prev(m-1, n-1);
|
||||
}
|
||||
curr(m, n) *= c[0]/c[1];
|
||||
}
|
||||
c[0] = c[1];
|
||||
prev = curr;
|
||||
}
|
||||
coefficient_ = curr.row(M);
|
||||
}
|
||||
|
||||
// function call ///////////////////////////////////////////////////////////////
|
||||
double Derivative::operator()(const double *x) const
|
||||
{
|
||||
ConstMap<DVec> xMap(x, f_.getNArg());
|
||||
double res = 0.;
|
||||
|
||||
*buffer_ = xMap;
|
||||
FOR_VEC(point_, i)
|
||||
{
|
||||
(*buffer_)(dir_) = x[dir_] + point_(i)*step_;
|
||||
res += coefficient_[i]*f_(*buffer_);
|
||||
}
|
||||
res /= pow(step_, order_);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// function factory ////////////////////////////////////////////////////////////
|
||||
DoubleFunction Derivative::makeFunction(const bool makeHardCopy) const
|
||||
{
|
||||
DoubleFunction res;
|
||||
|
||||
if (makeHardCopy)
|
||||
{
|
||||
Derivative copy(*this);
|
||||
|
||||
res.setFunction([copy](const double *x){return copy(x);}, f_.getNArg());
|
||||
}
|
||||
else
|
||||
{
|
||||
res.setFunction([this](const double *x){return (*this)(x);},
|
||||
f_.getNArg());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
DoubleFunction Latan::derivative(const DoubleFunction &f, const Index dir,
|
||||
const Index order, const DVec point,
|
||||
const double step)
|
||||
{
|
||||
return Derivative(f, dir, order, point, step).makeFunction();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CentralDerivative implementation *
|
||||
******************************************************************************/
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
CentralDerivative::CentralDerivative(const DoubleFunction &f, const Index dir,
|
||||
const Index order, const Index precOrder)
|
||||
: Derivative(f, dir)
|
||||
{
|
||||
setOrder(order, precOrder);
|
||||
}
|
||||
|
||||
// access //////////////////////////////////////////////////////////////////////
|
||||
Index CentralDerivative::getPrecOrder(void) const
|
||||
{
|
||||
return precOrder_;
|
||||
}
|
||||
|
||||
void CentralDerivative::setOrder(const Index order, const Index precOrder)
|
||||
{
|
||||
const Index nPoint = 2*(precOrder + (order - 1)/2) + 1;
|
||||
DVec point(nPoint);
|
||||
|
||||
precOrder_ = precOrder;
|
||||
FOR_VEC(point, i)
|
||||
{
|
||||
point(i) = static_cast<double>(i - (nPoint - 1)/2);
|
||||
}
|
||||
setOrderAndPoint(order, point);
|
||||
tuneStep();
|
||||
}
|
||||
|
||||
// step tuning /////////////////////////////////////////////////////////////////
|
||||
// the rounding error should be O(N*epsilon/h^order)
|
||||
//
|
||||
void CentralDerivative::tuneStep(void)
|
||||
{
|
||||
const Index nPoint = getNPoint();
|
||||
const double epsilon = numeric_limits<double>::epsilon();
|
||||
const double step = pow(epsilon*nPoint, 1./(2.*precOrder_+getOrder()));
|
||||
|
||||
setStep(step);
|
||||
}
|
||||
|
||||
// function factory ////////////////////////////////////////////////////////////
|
||||
DoubleFunction Latan::centralDerivative(const DoubleFunction &f,
|
||||
const Index dir, const Index order,
|
||||
const Index precOrder)
|
||||
{
|
||||
return CentralDerivative(f, dir, order, precOrder).makeFunction();
|
||||
}
|
103
lib/Numerical/Derivative.hpp
Normal file
103
lib/Numerical/Derivative.hpp
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Derivative.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_Derivative_hpp_
|
||||
#define Latan_Derivative_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* Derivative *
|
||||
******************************************************************************/
|
||||
class Derivative: public DoubleFunctionFactory
|
||||
{
|
||||
public:
|
||||
static constexpr double defaultStep = 1.0e-2;
|
||||
public:
|
||||
// constructor
|
||||
Derivative(const DoubleFunction &f, const Index dir, const Index order,
|
||||
const DVec &point, const double step = defaultStep);
|
||||
// destructor
|
||||
virtual ~Derivative(void) = default;
|
||||
// access
|
||||
Index getDir(void) const;
|
||||
Index getNPoint(void) const;
|
||||
Index getOrder(void) const;
|
||||
double getStep(void) const;
|
||||
void setDir(const Index dir);
|
||||
void setFunction(const DoubleFunction &f);
|
||||
void setOrderAndPoint(const Index order, const DVec &point);
|
||||
void setStep(const double step);
|
||||
// function call
|
||||
double operator()(const double *x) const;
|
||||
// function factory
|
||||
virtual DoubleFunction makeFunction(const bool makeHardCopy = true) const;
|
||||
protected:
|
||||
// constructor
|
||||
Derivative(const DoubleFunction &f, const Index dir,
|
||||
const double step = defaultStep);
|
||||
private:
|
||||
void makeCoefficients(void);
|
||||
private:
|
||||
DoubleFunction f_;
|
||||
Index dir_, order_;
|
||||
double step_;
|
||||
DVec point_, coefficient_;
|
||||
std::shared_ptr<DVec> buffer_;
|
||||
};
|
||||
|
||||
DoubleFunction derivative(const DoubleFunction &f, const Index dir,
|
||||
const Index order, const DVec point,
|
||||
const double step = Derivative::defaultStep);
|
||||
|
||||
class CentralDerivative: public Derivative
|
||||
{
|
||||
public:
|
||||
static const Index defaultPrecOrder = 2;
|
||||
public:
|
||||
// constructor
|
||||
CentralDerivative(const DoubleFunction &f = DoubleFunction(),
|
||||
const Index dir = 0,
|
||||
const Index order = 1,
|
||||
const Index precOrder = defaultPrecOrder);
|
||||
// destructor
|
||||
virtual ~CentralDerivative(void) = default;
|
||||
// access
|
||||
Index getPrecOrder(void) const;
|
||||
void setOrder(const Index order, const Index precOrder = defaultPrecOrder);
|
||||
// function call
|
||||
using Derivative::operator();
|
||||
private:
|
||||
// step tuning
|
||||
void tuneStep(void);
|
||||
private:
|
||||
Index precOrder_;
|
||||
};
|
||||
|
||||
DoubleFunction centralDerivative(const DoubleFunction &f, const Index dir = 0,
|
||||
const Index order = 1,
|
||||
const Index precOrder =
|
||||
CentralDerivative::defaultPrecOrder);
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_Derivative_hpp_
|
53
lib/Numerical/FFT.hpp
Normal file
53
lib/Numerical/FFT.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* FFT.hpp, part of LatAnalyze
|
||||
*
|
||||
* Copyright (C) 2013 - 2017 Antonin Portelli
|
||||
*
|
||||
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Latan_FFT_hpp_
|
||||
#define Latan_FFT_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* FFT abstract class *
|
||||
******************************************************************************/
|
||||
|
||||
class FFT
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
Forward = 0,
|
||||
Backward = 1
|
||||
};
|
||||
public:
|
||||
// constructor
|
||||
FFT(void) = default;
|
||||
FFT(const Index size);
|
||||
// destructor
|
||||
virtual ~FFT(void) = default;
|
||||
// size
|
||||
virtual void resize(const Index size) = 0;
|
||||
// FFT
|
||||
virtual void operator()(CMat &x, const unsigned int dir = FFT::Forward) = 0;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_FFT_hpp_
|
89
lib/Numerical/GslFFT.cpp
Normal file
89
lib/Numerical/GslFFT.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* GslFFT.cpp, part of LatAnalyze
|
||||
*
|
||||
* Copyright (C) 2013 - 2017 Antonin Portelli
|
||||
*
|
||||
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <LatAnalyze/Numerical/GslFFT.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
/******************************************************************************
|
||||
* GslFFT implementation *
|
||||
******************************************************************************/
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
GslFFT::GslFFT(const Index size)
|
||||
{
|
||||
resize(size);
|
||||
}
|
||||
|
||||
// destructor //////////////////////////////////////////////////////////////////
|
||||
GslFFT::~GslFFT(void)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// size ////////////////////////////////////////////////////////////////////////
|
||||
void GslFFT::resize(const Index size)
|
||||
{
|
||||
if (size_ != size)
|
||||
{
|
||||
size_ = size;
|
||||
wavetable_ = gsl_fft_complex_wavetable_alloc(size_);
|
||||
workspace_ = gsl_fft_complex_workspace_alloc(size_);
|
||||
}
|
||||
}
|
||||
|
||||
// fft /////////////////////////////////////////////////////////////////////////
|
||||
void GslFFT::operator()(CMat &x, const unsigned int dir)
|
||||
{
|
||||
if (x.size() != size_)
|
||||
{
|
||||
LATAN_ERROR(Size, "wrong input vector size");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dir)
|
||||
{
|
||||
case FFT::Forward:
|
||||
gsl_fft_complex_forward((double *)x.data(), 1, size_,
|
||||
wavetable_, workspace_);
|
||||
break;
|
||||
case FFT::Backward:
|
||||
gsl_fft_complex_backward((double *)x.data(), 1, size_,
|
||||
wavetable_, workspace_);
|
||||
break;
|
||||
default:
|
||||
LATAN_ERROR(Argument, "invalid FT direction");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// destroy GSL objects /////////////////////////////////////////////////////////
|
||||
void GslFFT::clear(void)
|
||||
{
|
||||
if (!wavetable_)
|
||||
{
|
||||
gsl_fft_complex_wavetable_free(wavetable_);
|
||||
}
|
||||
if (!workspace_)
|
||||
{
|
||||
gsl_fft_complex_workspace_free(workspace_);
|
||||
}
|
||||
}
|
57
lib/Numerical/GslFFT.hpp
Normal file
57
lib/Numerical/GslFFT.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* GslFFT.hpp, part of LatAnalyze
|
||||
*
|
||||
* Copyright (C) 2013 - 2017 Antonin Portelli
|
||||
*
|
||||
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Latan_GslFFT_hpp_
|
||||
#define Latan_GslFFT_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Core/Mat.hpp>
|
||||
#include <LatAnalyze/Numerical/FFT.hpp>
|
||||
#include <gsl/gsl_fft_complex.h>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* GSL FFT *
|
||||
******************************************************************************/
|
||||
|
||||
class GslFFT: public FFT
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
GslFFT(void) = default;
|
||||
GslFFT(const Index size);
|
||||
// destructor
|
||||
virtual ~GslFFT(void);
|
||||
// size
|
||||
void resize(const Index size);
|
||||
// fft
|
||||
virtual void operator()(CMat &x, const unsigned int dir = FFT::Forward);
|
||||
private:
|
||||
// destroy GSL objects
|
||||
void clear(void);
|
||||
private:
|
||||
Index size_{0};
|
||||
gsl_fft_complex_wavetable *wavetable_{nullptr};
|
||||
gsl_fft_complex_workspace *workspace_{nullptr};
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_GslFFT_hpp_
|
145
lib/Numerical/GslHybridRootFinder.cpp
Normal file
145
lib/Numerical/GslHybridRootFinder.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* GslHybridRootFinder.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/GslHybridRootFinder.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
#include <gsl/gsl_vector.h>
|
||||
#include <gsl/gsl_multiroots.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
/******************************************************************************
|
||||
* GslHybridRootFinder implementation *
|
||||
******************************************************************************/
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
GslHybridRootFinder::GslHybridRootFinder(const Index dim)
|
||||
: RootFinder(dim)
|
||||
{}
|
||||
|
||||
// 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)
|
||||
{
|
||||
resize(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) and (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;
|
||||
}
|
52
lib/Numerical/GslHybridRootFinder.hpp
Normal file
52
lib/Numerical/GslHybridRootFinder.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* GslHybridRootFinder.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/RootFinder.hpp>
|
||||
#include <gsl/gsl_multiroots.h>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* GslHybridRootFinder *
|
||||
******************************************************************************/
|
||||
|
||||
class GslHybridRootFinder: public RootFinder
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
GslHybridRootFinder(void) = default;
|
||||
explicit GslHybridRootFinder(const Index dim);
|
||||
// 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_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_GslHybridRootFinder_hpp_
|
361
lib/Numerical/GslMinimizer.cpp
Normal file
361
lib/Numerical/GslMinimizer.cpp
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* GslMinimizer.cpp, part of LatAnalyze
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 Antonin Portelli
|
||||
*
|
||||
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <LatAnalyze/Numerical/GslMinimizer.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
#include <LatAnalyze/Core/Math.hpp>
|
||||
#include <gsl/gsl_multimin.h>
|
||||
#include <gsl/gsl_blas.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
/******************************************************************************
|
||||
* GslMinimizer implementation *
|
||||
******************************************************************************/
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
GslMinimizer::GslMinimizer(const Algorithm algorithm)
|
||||
{
|
||||
setAlgorithm(algorithm);
|
||||
der_.setOrder(1, 1);
|
||||
}
|
||||
|
||||
// access //////////////////////////////////////////////////////////////////////
|
||||
GslMinimizer::Algorithm GslMinimizer::getAlgorithm(void) const
|
||||
{
|
||||
return algorithm_;
|
||||
}
|
||||
|
||||
void GslMinimizer::setAlgorithm(const Algorithm algorithm)
|
||||
{
|
||||
algorithm_ = algorithm;
|
||||
}
|
||||
|
||||
bool GslMinimizer::supportLimits(void) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// test ////////////////////////////////////////////////////////////////////////
|
||||
bool GslMinimizer::isDerAlgorithm(const Algorithm algorithm)
|
||||
{
|
||||
return (algorithm <= Algorithm::lastDerAlg);
|
||||
}
|
||||
|
||||
// minimization ////////////////////////////////////////////////////////////////
|
||||
const DVec & GslMinimizer::operator()(const DoubleFunction &f)
|
||||
{
|
||||
DVec &x = getState();
|
||||
|
||||
// resize minimizer state to match function number of arguments
|
||||
if (f.getNArg() != x.size())
|
||||
{
|
||||
resize(f.getNArg());
|
||||
}
|
||||
|
||||
// set function data
|
||||
GslFuncData data;
|
||||
|
||||
der_.setFunction(f);
|
||||
data.f = &f;
|
||||
data.d = &der_;
|
||||
|
||||
// set initial position
|
||||
gsl_vector *gslX = gsl_vector_alloc(getDim());
|
||||
|
||||
for (Index i = 0; i < getDim(); ++i)
|
||||
{
|
||||
gsl_vector_set(gslX, i, x(i));
|
||||
}
|
||||
|
||||
// minimization
|
||||
int status;
|
||||
|
||||
if (isDerAlgorithm(getAlgorithm()))
|
||||
{
|
||||
// set function
|
||||
gsl_multimin_function_fdf gslFunc;
|
||||
|
||||
gslFunc.n = getDim();
|
||||
gslFunc.f = &fWrapper;
|
||||
gslFunc.df = &dfWrapper;
|
||||
gslFunc.fdf = &fdfWrapper;
|
||||
gslFunc.params = &data;
|
||||
|
||||
// create and set minimizer
|
||||
const gsl_multimin_fdfminimizer_type *gslAlg;
|
||||
gsl_multimin_fdfminimizer *gslMin;
|
||||
|
||||
switch (getAlgorithm())
|
||||
{
|
||||
case Algorithm::cgFR:
|
||||
gslAlg = gsl_multimin_fdfminimizer_conjugate_fr;
|
||||
break;
|
||||
case Algorithm::cgPR:
|
||||
gslAlg = gsl_multimin_fdfminimizer_conjugate_pr;
|
||||
break;
|
||||
case Algorithm::bfgs:
|
||||
gslAlg = gsl_multimin_fdfminimizer_vector_bfgs;
|
||||
break;
|
||||
case Algorithm::bfgs2:
|
||||
gslAlg = gsl_multimin_fdfminimizer_vector_bfgs2;
|
||||
break;
|
||||
case Algorithm::steepDesc:
|
||||
gslAlg = gsl_multimin_fdfminimizer_vector_bfgs2;
|
||||
break;
|
||||
default:
|
||||
LATAN_ERROR(Argument, "unknow GSL minization algorithm "
|
||||
+ strFrom(static_cast<int>(getAlgorithm())));
|
||||
break;
|
||||
}
|
||||
gslMin = gsl_multimin_fdfminimizer_alloc(gslAlg, getDim());
|
||||
|
||||
// minimize
|
||||
unsigned int pass = 0, it;
|
||||
double dxRel;
|
||||
|
||||
do
|
||||
{
|
||||
pass++;
|
||||
gsl_multimin_fdfminimizer_set(gslMin, &gslFunc, gslX, 0.01, 0.001);
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
cout << "========== GSL minimization, pass #" << pass;
|
||||
cout << " ==========" << endl;
|
||||
cout << "Algorithm: " << getAlgorithmName(getAlgorithm());
|
||||
cout << endl;
|
||||
cout << "Max eval.= " << getMaxIteration();
|
||||
cout << " -- Precision= " << getPrecision() << endl;
|
||||
printf("Starting f(x)= %.10e\n", f(x));
|
||||
}
|
||||
it = 0;
|
||||
do
|
||||
{
|
||||
it++;
|
||||
gsl_multimin_fdfminimizer_iterate(gslMin);
|
||||
dxRel = gsl_blas_dnrm2(gslMin->dx)/gsl_blas_dnrm2(gslMin->x);
|
||||
status = (dxRel < getPrecision()) ? GSL_SUCCESS : GSL_CONTINUE;
|
||||
if (getVerbosity() >= Verbosity::Debug)
|
||||
{
|
||||
printf("iteration %4d: f= %.10e dxrel= %.10e eval= %d\n",
|
||||
it, gslMin->f, dxRel, data.evalCount);
|
||||
}
|
||||
|
||||
} while (status == GSL_CONTINUE and
|
||||
(data.evalCount < getMaxIteration()));
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
printf("Found minimum %.10e at:\n", gslMin->f);
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
printf("%8s= %.10e\n", f.varName().getName(i).c_str(),
|
||||
gsl_vector_get(gslMin->x, i));
|
||||
}
|
||||
cout << "after " << data.evalCount << " evaluations" << endl;
|
||||
cout << "Minimization ended with code " << status;
|
||||
cout << endl;
|
||||
}
|
||||
data.evalCount = 0;
|
||||
for (Index i = 0; i < getDim(); ++i)
|
||||
{
|
||||
gsl_vector_set(gslX, i, gsl_vector_get(gslMin->x, i));
|
||||
}
|
||||
} while (status != GSL_SUCCESS and (pass < getMaxPass()));
|
||||
|
||||
// deallocate GSL minimizer
|
||||
gsl_multimin_fdfminimizer_free(gslMin);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set function
|
||||
gsl_multimin_function gslFunc;
|
||||
|
||||
gslFunc.n = getDim();
|
||||
gslFunc.f = &fWrapper;
|
||||
gslFunc.params = &data;
|
||||
|
||||
// create and set minimizer
|
||||
const gsl_multimin_fminimizer_type *gslAlg;
|
||||
gsl_multimin_fminimizer *gslMin;
|
||||
|
||||
switch (getAlgorithm())
|
||||
{
|
||||
case Algorithm::simplex:
|
||||
gslAlg = gsl_multimin_fminimizer_nmsimplex;
|
||||
break;
|
||||
case Algorithm::simplex2:
|
||||
gslAlg = gsl_multimin_fminimizer_nmsimplex2;
|
||||
break;
|
||||
case Algorithm::simplex2R:
|
||||
gslAlg = gsl_multimin_fminimizer_nmsimplex2rand;
|
||||
break;
|
||||
default:
|
||||
LATAN_ERROR(Argument, "unknow GSL minization algorithm "
|
||||
+ strFrom(static_cast<int>(getAlgorithm())));
|
||||
break;
|
||||
}
|
||||
gslMin = gsl_multimin_fminimizer_alloc(gslAlg, getDim());
|
||||
|
||||
// minimize
|
||||
unsigned int pass = 0, it;
|
||||
gsl_vector *step = gsl_vector_alloc(getDim());
|
||||
double relSize;
|
||||
|
||||
gsl_vector_set_all(step, 0.01);
|
||||
do
|
||||
{
|
||||
pass++;
|
||||
gsl_multimin_fminimizer_set(gslMin, &gslFunc, gslX, step);
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
cout << "========== GSL minimization, pass #" << pass;
|
||||
cout << " ==========" << endl;
|
||||
cout << "Algorithm: " << getAlgorithmName(getAlgorithm());
|
||||
cout << endl;
|
||||
cout << "Max eval.= " << getMaxIteration();
|
||||
cout << " -- Precision= " << getPrecision() << endl;
|
||||
printf("Starting f(x)= %.10e\n", f(x));
|
||||
}
|
||||
it = 0;
|
||||
do
|
||||
{
|
||||
it++;
|
||||
gsl_multimin_fminimizer_iterate(gslMin);
|
||||
relSize = Math::pow<2>(gslMin->size)/gsl_blas_dnrm2(gslMin->x);
|
||||
status = (relSize < getPrecision()) ? GSL_SUCCESS
|
||||
: GSL_CONTINUE;
|
||||
if (getVerbosity() >= Verbosity::Debug)
|
||||
{
|
||||
printf("iteration %4d: f= %.10e relSize= %.10e eval= %d\n",
|
||||
it, gslMin->fval, relSize, data.evalCount);
|
||||
}
|
||||
|
||||
} while (status == GSL_CONTINUE and
|
||||
(data.evalCount < getMaxIteration()));
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
printf("Found minimum %.10e at:\n", gslMin->fval);
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
printf("%8s= %.10e\n", f.varName().getName(i).c_str(),
|
||||
gsl_vector_get(gslMin->x, i));
|
||||
}
|
||||
cout << "after " << data.evalCount << " evaluations" << endl;
|
||||
cout << "Minimization ended with code " << status;
|
||||
cout << endl;
|
||||
}
|
||||
data.evalCount = 0;
|
||||
for (Index i = 0; i < getDim(); ++i)
|
||||
{
|
||||
gsl_vector_set(gslX, i, gsl_vector_get(gslMin->x, i));
|
||||
}
|
||||
} while (status != GSL_SUCCESS and (pass < getMaxPass()));
|
||||
|
||||
// deallocate GSL minimizer
|
||||
gsl_multimin_fminimizer_free(gslMin);
|
||||
gsl_vector_free(step);
|
||||
}
|
||||
if (status != GSL_SUCCESS)
|
||||
{
|
||||
LATAN_WARNING("invalid minimum: maximum number of call reached");
|
||||
}
|
||||
|
||||
// save final result
|
||||
for (Index i = 0; i < getDim(); ++i)
|
||||
{
|
||||
x(i) = gsl_vector_get(gslX, i);
|
||||
}
|
||||
|
||||
// deallocate GSL state and return
|
||||
gsl_vector_free(gslX);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// function wrappers ///////////////////////////////////////////////////////////
|
||||
double GslMinimizer::fWrapper(const gsl_vector *x, void *vdata)
|
||||
{
|
||||
GslFuncData &data = *static_cast<GslFuncData *>(vdata);
|
||||
|
||||
data.evalCount++;
|
||||
|
||||
return (*data.f)(x->data);
|
||||
}
|
||||
|
||||
void GslMinimizer::dfWrapper(const gsl_vector *x, void *vdata, gsl_vector * df)
|
||||
{
|
||||
GslFuncData &data = *static_cast<GslFuncData *>(vdata);
|
||||
const unsigned int n = data.f->getNArg();
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
{
|
||||
data.d->setDir(i);
|
||||
gsl_vector_set(df, i, (*(data.d))(x->data));
|
||||
}
|
||||
data.evalCount += data.d->getNPoint()*n;
|
||||
}
|
||||
|
||||
void GslMinimizer::fdfWrapper(const gsl_vector *x, void *vdata, double *f,
|
||||
gsl_vector * df)
|
||||
{
|
||||
GslFuncData &data = *static_cast<GslFuncData *>(vdata);
|
||||
const unsigned int n = data.f->getNArg();
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
{
|
||||
data.d->setDir(i);
|
||||
gsl_vector_set(df, i, (*(data.d))(x->data));
|
||||
}
|
||||
*f = (*data.f)(x->data);
|
||||
data.evalCount += data.d->getNPoint()*n + 1;
|
||||
}
|
||||
|
||||
// algorithm names /////////////////////////////////////////////////////////////
|
||||
string GslMinimizer::getAlgorithmName(const Algorithm algorithm)
|
||||
{
|
||||
switch (algorithm)
|
||||
{
|
||||
case Algorithm::cgFR:
|
||||
return "Fletcher-Reeves conjugate gradient";
|
||||
break;
|
||||
case Algorithm::cgPR:
|
||||
return "Polak-Ribiere conjugate gradient";
|
||||
break;
|
||||
case Algorithm::bfgs:
|
||||
return "Broyden-Fletcher-Goldfarb-Shanno";
|
||||
break;
|
||||
case Algorithm::bfgs2:
|
||||
return "improved Broyden-Fletcher-Goldfarb-Shanno";
|
||||
break;
|
||||
case Algorithm::steepDesc:
|
||||
return "steepest descent";
|
||||
break;
|
||||
case Algorithm::simplex:
|
||||
return "Nelder-Mead simplex";
|
||||
break;
|
||||
case Algorithm::simplex2:
|
||||
return "improved Nelder-Mead simplex";
|
||||
break;
|
||||
case Algorithm::simplex2R:
|
||||
return "improved Nelder-Mead simplex with random start";
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
86
lib/Numerical/GslMinimizer.hpp
Normal file
86
lib/Numerical/GslMinimizer.hpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* GslMinimizer.hpp, part of LatAnalyze
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 Antonin Portelli
|
||||
*
|
||||
* LatAnalyze 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 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. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef Latan_GslMinimizer_hpp_
|
||||
#define Latan_GslMinimizer_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Numerical/Derivative.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
#include <LatAnalyze/Numerical/Minimizer.hpp>
|
||||
#include <gsl/gsl_vector.h>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* interface to the GSL minimizers *
|
||||
******************************************************************************/
|
||||
class GslMinimizer: public Minimizer
|
||||
{
|
||||
public:
|
||||
enum class Algorithm
|
||||
{
|
||||
cgFR = 1,
|
||||
cgPR = 2,
|
||||
bfgs = 3,
|
||||
bfgs2 = 4,
|
||||
steepDesc = 5,
|
||||
lastDerAlg = 5,
|
||||
simplex = 6,
|
||||
simplex2 = 7,
|
||||
simplex2R = 8
|
||||
};
|
||||
private:
|
||||
struct GslFuncData
|
||||
{
|
||||
const DoubleFunction *f{nullptr};
|
||||
Derivative *d{nullptr};
|
||||
unsigned int evalCount{0};
|
||||
};
|
||||
public:
|
||||
// constructor
|
||||
explicit GslMinimizer(const Algorithm algorithm = defaultAlg_);
|
||||
// destructor
|
||||
virtual ~GslMinimizer(void) = default;
|
||||
// access
|
||||
Algorithm getAlgorithm(void) const;
|
||||
void setAlgorithm(const Algorithm algorithm);
|
||||
virtual bool supportLimits(void) const;
|
||||
// minimization
|
||||
virtual const DVec & operator()(const DoubleFunction &f);
|
||||
private:
|
||||
// test
|
||||
static bool isDerAlgorithm(const Algorithm algorithm);
|
||||
// function wrappers
|
||||
static double fWrapper(const gsl_vector *x, void * params);
|
||||
static void dfWrapper(const gsl_vector *x, void * params,
|
||||
gsl_vector * df);
|
||||
static void fdfWrapper(const gsl_vector *x, void *params, double *f,
|
||||
gsl_vector * df);
|
||||
// algorithm names
|
||||
std::string getAlgorithmName(const Algorithm algorithm);
|
||||
private:
|
||||
Algorithm algorithm_;
|
||||
static constexpr Algorithm defaultAlg_ = Algorithm::simplex2;
|
||||
CentralDerivative der_;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_GslMinimizer_hpp_
|
87
lib/Numerical/GslQagsIntegrator.cpp
Normal file
87
lib/Numerical/GslQagsIntegrator.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* GslQagsIntegrator.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/GslQagsIntegrator.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
#include <LatAnalyze/Core/Math.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
/******************************************************************************
|
||||
* GslQagIntegrator implementation *
|
||||
******************************************************************************/
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
GslQagsIntegrator::GslQagsIntegrator(const unsigned int limit,
|
||||
const double precision)
|
||||
: limit_(limit)
|
||||
, precision_(precision)
|
||||
{
|
||||
workspace_ = gsl_integration_workspace_alloc(limit);
|
||||
}
|
||||
|
||||
// destructor //////////////////////////////////////////////////////////////////
|
||||
GslQagsIntegrator::~GslQagsIntegrator(void)
|
||||
{
|
||||
gsl_integration_workspace_free(workspace_);
|
||||
}
|
||||
|
||||
// integral calculation ////////////////////////////////////////////////////////
|
||||
double GslQagsIntegrator::operator()(const DoubleFunction &f, const double xMin,
|
||||
const double xMax)
|
||||
{
|
||||
double (*fWrap)(double, void *) = [](double x, void *fPt)->double
|
||||
{
|
||||
return (*static_cast<DoubleFunction *>(fPt))(&x);
|
||||
};
|
||||
|
||||
gsl_function gslF;
|
||||
double result;
|
||||
|
||||
gslF.function = fWrap;
|
||||
gslF.params = reinterpret_cast<void *>(&const_cast<DoubleFunction &>(f));
|
||||
if ((xMin > -Math::inf) and (xMax < Math::inf))
|
||||
{
|
||||
gsl_integration_qags(&gslF, xMin, xMax, 0.0, precision_, limit_,
|
||||
workspace_, &result, &error_);
|
||||
}
|
||||
else if (xMax < Math::inf)
|
||||
{
|
||||
gsl_integration_qagil(&gslF, xMax, 0.0, precision_, limit_,
|
||||
workspace_, &result, &error_);
|
||||
}
|
||||
else if (xMin > -Math::inf)
|
||||
{
|
||||
gsl_integration_qagiu(&gslF, xMin, 0.0, precision_, limit_,
|
||||
workspace_, &result, &error_);
|
||||
}
|
||||
else
|
||||
{
|
||||
gsl_integration_qagi(&gslF, 0.0, precision_, limit_,
|
||||
workspace_, &result, &error_);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// get last error //////////////////////////////////////////////////////////////
|
||||
double GslQagsIntegrator::getLastError(void) const
|
||||
{
|
||||
return error_;
|
||||
}
|
58
lib/Numerical/GslQagsIntegrator.hpp
Normal file
58
lib/Numerical/GslQagsIntegrator.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* GslQagsIntegrator.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_GslQagsIntegrator_hpp_
|
||||
#define Latan_GslQagsIntegrator_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
#include <LatAnalyze/Numerical/Integrator.hpp>
|
||||
#include <gsl/gsl_integration.h>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* GSL general quadrature adaptive integration with singularities *
|
||||
******************************************************************************/
|
||||
|
||||
class GslQagsIntegrator: public Integrator
|
||||
{
|
||||
public:
|
||||
static const unsigned int defaultLimit = 1000;
|
||||
static constexpr double defaultPrec = 1.0e-7;
|
||||
public:
|
||||
// constructor
|
||||
GslQagsIntegrator(const unsigned int limit = defaultLimit,
|
||||
const double precision = defaultPrec);
|
||||
// destructor
|
||||
virtual ~GslQagsIntegrator(void);
|
||||
// integral calculation
|
||||
virtual double operator()(const DoubleFunction &f, const double xMin,
|
||||
const double xMax);
|
||||
// get last error
|
||||
double getLastError(void) const;
|
||||
private:
|
||||
unsigned int limit_;
|
||||
double precision_, error_;
|
||||
gsl_integration_workspace *workspace_;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_GslQagsIntegrator_hpp_
|
46
lib/Numerical/Integrator.hpp
Normal file
46
lib/Numerical/Integrator.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Integrator.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_Integrator_hpp_
|
||||
#define Latan_Integrator_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* abstract integrator class *
|
||||
******************************************************************************/
|
||||
|
||||
class Integrator
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
Integrator(void) = default;
|
||||
// destructor
|
||||
virtual ~Integrator(void) = default;
|
||||
// integral calculation
|
||||
virtual double operator()(const DoubleFunction &f, const double xMin,
|
||||
const double xMax) = 0;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_Integrator_hpp_
|
194
lib/Numerical/Minimizer.cpp
Normal file
194
lib/Numerical/Minimizer.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Minimizer.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/Minimizer.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
// access //////////////////////////////////////////////////////////////////////
|
||||
void Minimizer::resize(const Index dim)
|
||||
{
|
||||
const Index oldDim = getDim();
|
||||
|
||||
Solver::resize(dim);
|
||||
highLimit_.conservativeResize(dim);
|
||||
lowLimit_.conservativeResize(dim);
|
||||
hasHighLimit_.conservativeResize(dim);
|
||||
hasLowLimit_.conservativeResize(dim);
|
||||
if (dim > oldDim)
|
||||
{
|
||||
highLimit_.segment(oldDim, dim - oldDim).fill(0.);
|
||||
highLimit_.segment(oldDim, dim - oldDim).fill(0.);
|
||||
lowLimit_.segment(oldDim, dim - oldDim).fill(0.);
|
||||
hasHighLimit_.segment(oldDim, dim - oldDim).fill(false);
|
||||
hasLowLimit_.segment(oldDim, dim - oldDim).fill(false);
|
||||
}
|
||||
}
|
||||
|
||||
#define checkSupport \
|
||||
if (!supportLimits())\
|
||||
{\
|
||||
LATAN_ERROR(Implementation, "minimizer does not support limits");\
|
||||
}
|
||||
|
||||
double Minimizer::getHighLimit(const Index i) const
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
LATAN_ERROR(Size, "invalid variable index");
|
||||
}
|
||||
|
||||
return highLimit_(i);
|
||||
}
|
||||
|
||||
const DVec & Minimizer::getHighLimit(const PlaceHolder ph __dumb) const
|
||||
{
|
||||
checkSupport;
|
||||
|
||||
return highLimit_;
|
||||
}
|
||||
|
||||
double Minimizer::getLowLimit(const Index i) const
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
LATAN_ERROR(Size, "invalid variable index");
|
||||
}
|
||||
|
||||
return lowLimit_(i);
|
||||
}
|
||||
|
||||
const DVec & Minimizer::getLowLimit(const PlaceHolder ph __dumb) const
|
||||
{
|
||||
checkSupport;
|
||||
|
||||
return lowLimit_;
|
||||
}
|
||||
|
||||
bool Minimizer::hasHighLimit(const Index i) const
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
LATAN_ERROR(Size, "invalid variable index");
|
||||
}
|
||||
|
||||
return hasHighLimit_(i);
|
||||
}
|
||||
|
||||
bool Minimizer::hasLowLimit(const Index i) const
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
LATAN_ERROR(Size, "invalid variable index");
|
||||
}
|
||||
|
||||
return hasLowLimit_(i);
|
||||
}
|
||||
|
||||
void Minimizer::setHighLimit(const Index i, const double l)
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
resize(i + 1);
|
||||
}
|
||||
highLimit_(i) = l;
|
||||
useHighLimit(i);
|
||||
}
|
||||
|
||||
void Minimizer::setHighLimit(const PlaceHolder ph __dumb, const DVec &l)
|
||||
{
|
||||
checkSupport;
|
||||
if (l.size() != getDim())
|
||||
{
|
||||
resize(l.size());
|
||||
}
|
||||
highLimit_ = l;
|
||||
useHighLimit(_);
|
||||
}
|
||||
|
||||
void Minimizer::setLowLimit(const Index i, const double l)
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
resize(i + 1);
|
||||
}
|
||||
lowLimit_(i) = l;
|
||||
useLowLimit(i);
|
||||
}
|
||||
|
||||
void Minimizer::setLowLimit(const PlaceHolder ph __dumb, const DVec &l)
|
||||
{
|
||||
checkSupport;
|
||||
if (l.size() != getDim())
|
||||
{
|
||||
resize(l.size());
|
||||
}
|
||||
lowLimit_ = l;
|
||||
useLowLimit(_);
|
||||
}
|
||||
|
||||
void Minimizer::useHighLimit(const Index i, const bool use)
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
resize(i + 1);
|
||||
}
|
||||
hasHighLimit_(i) = use;
|
||||
}
|
||||
|
||||
void Minimizer::useHighLimit(const PlaceHolder ph __dumb, const bool use)
|
||||
{
|
||||
checkSupport;
|
||||
hasHighLimit_.fill(use);
|
||||
}
|
||||
|
||||
void Minimizer::useLowLimit(const Index i, const bool use)
|
||||
{
|
||||
checkSupport;
|
||||
if (i >= getDim())
|
||||
{
|
||||
resize(i + 1);
|
||||
}
|
||||
hasLowLimit_(i) = use;
|
||||
}
|
||||
|
||||
void Minimizer::useLowLimit(const PlaceHolder ph __dumb, const bool use)
|
||||
{
|
||||
checkSupport;
|
||||
hasLowLimit_.fill(use);
|
||||
}
|
||||
|
||||
unsigned int Minimizer::getMaxPass(void) const
|
||||
{
|
||||
return maxPass_;
|
||||
}
|
||||
|
||||
void Minimizer::setMaxPass(const unsigned int maxPass)
|
||||
{
|
||||
maxPass_ = maxPass;
|
||||
}
|
72
lib/Numerical/Minimizer.hpp
Normal file
72
lib/Numerical/Minimizer.hpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Minimizer.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_Minimizer_hpp_
|
||||
#define Latan_Minimizer_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
#include <LatAnalyze/Core/Mat.hpp>
|
||||
#include <LatAnalyze/Numerical/Solver.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* Abstract minimizer class *
|
||||
******************************************************************************/
|
||||
|
||||
class Minimizer: public Solver
|
||||
{
|
||||
public:
|
||||
// constructor
|
||||
Minimizer(void) = default;
|
||||
// destructor
|
||||
virtual ~Minimizer(void) = default;
|
||||
// access
|
||||
virtual void resize(const Index dim);
|
||||
virtual double getHighLimit(const Index i) const ;
|
||||
virtual const DVec & getHighLimit(const PlaceHolder ph = _) const;
|
||||
virtual double getLowLimit(const Index i) const;
|
||||
virtual const DVec & getLowLimit(const PlaceHolder ph = _) const;
|
||||
virtual bool hasHighLimit(const Index i) const;
|
||||
virtual bool hasLowLimit(const Index i) const;
|
||||
virtual void setHighLimit(const Index i, const double l);
|
||||
virtual void setHighLimit(const PlaceHolder ph, const DVec &l);
|
||||
virtual void setLowLimit(const Index i, const double l);
|
||||
virtual void setLowLimit(const PlaceHolder ph, const DVec &l);
|
||||
virtual void useHighLimit(const Index i, const bool use = true);
|
||||
virtual void useHighLimit(const PlaceHolder ph = _,
|
||||
const bool use = true);
|
||||
virtual void useLowLimit(const Index i, const bool use = true);
|
||||
virtual void useLowLimit(const PlaceHolder ph = _,
|
||||
const bool use = true);
|
||||
virtual bool supportLimits(void) const = 0;
|
||||
virtual unsigned int getMaxPass(void) const;
|
||||
virtual void setMaxPass(const unsigned int maxPass);
|
||||
// minimization
|
||||
virtual const DVec & operator()(const DoubleFunction &f) = 0;
|
||||
private:
|
||||
DVec highLimit_, lowLimit_;
|
||||
Vec<bool> hasHighLimit_, hasLowLimit_;
|
||||
unsigned int maxPass_{5u};
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_Minimizer_hpp_
|
184
lib/Numerical/MinuitMinimizer.cpp
Normal file
184
lib/Numerical/MinuitMinimizer.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* MinuitMinimizer.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/MinuitMinimizer.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
#include <Minuit2/Minuit2Minimizer.h>
|
||||
#include <Math/Functor.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
static constexpr double initErr = 0.1;
|
||||
|
||||
/******************************************************************************
|
||||
* MinuitMinimizer implementation *
|
||||
******************************************************************************/
|
||||
// constructors ////////////////////////////////////////////////////////////////
|
||||
MinuitMinimizer::MinuitMinimizer(const Algorithm algorithm)
|
||||
{
|
||||
setAlgorithm(algorithm);
|
||||
}
|
||||
|
||||
// access //////////////////////////////////////////////////////////////////////
|
||||
MinuitMinimizer::Algorithm MinuitMinimizer::getAlgorithm(void) const
|
||||
{
|
||||
return algorithm_;
|
||||
}
|
||||
|
||||
void MinuitMinimizer::setAlgorithm(const Algorithm algorithm)
|
||||
{
|
||||
algorithm_ = algorithm;
|
||||
}
|
||||
|
||||
bool MinuitMinimizer::supportLimits(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// minimization ////////////////////////////////////////////////////////////////
|
||||
const DVec & MinuitMinimizer::operator()(const DoubleFunction &f)
|
||||
{
|
||||
using namespace ROOT;
|
||||
using namespace Minuit2;
|
||||
|
||||
DVec &x = getState();
|
||||
int printLevel = 0;
|
||||
EMinimizerType minuitAlg = kCombined;
|
||||
double prec = getPrecision();
|
||||
|
||||
// convert Latan parameters to Minuit parameters
|
||||
switch (getVerbosity())
|
||||
{
|
||||
case Verbosity::Silent:
|
||||
printLevel = 0;
|
||||
break;
|
||||
case Verbosity::Normal:
|
||||
printLevel = 2;
|
||||
break;
|
||||
case Verbosity::Debug:
|
||||
printLevel = 3;
|
||||
break;
|
||||
}
|
||||
// The factor of 0.002 here is to compensate the dirty hack in Minuit
|
||||
// source used to match the C++ and F77 versions
|
||||
// (cf. VariableMetricBuilder.cxx)
|
||||
switch (getAlgorithm())
|
||||
{
|
||||
case Algorithm::migrad:
|
||||
minuitAlg = kMigrad;
|
||||
prec /= 0.002;
|
||||
break;
|
||||
case Algorithm::simplex:
|
||||
minuitAlg = kSimplex;
|
||||
break;
|
||||
case Algorithm::combined:
|
||||
minuitAlg = kCombined;
|
||||
prec /= 0.002;
|
||||
break;
|
||||
}
|
||||
|
||||
// resize minimizer state to match function number of arguments
|
||||
if (f.getNArg() != x.size())
|
||||
{
|
||||
resize(f.getNArg());
|
||||
}
|
||||
|
||||
// create and set minimizer
|
||||
Minuit2Minimizer min(minuitAlg);
|
||||
|
||||
min.SetStrategy(2);
|
||||
min.SetMaxFunctionCalls(getMaxIteration());
|
||||
min.SetTolerance(prec);
|
||||
min.SetPrintLevel(printLevel);
|
||||
|
||||
// set function and variables
|
||||
Math::Functor minuitF(f, x.size());
|
||||
string name;
|
||||
double val, step;
|
||||
|
||||
min.SetFunction(minuitF);
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
name = f.varName().getName(i);
|
||||
val = x(i);
|
||||
step = (fabs(x(i)) != 0.) ? initErr*fabs(x(i)) : 1.;
|
||||
if (hasHighLimit(i) and !hasLowLimit(i))
|
||||
{
|
||||
min.SetUpperLimitedVariable(i, name, val, step, getHighLimit(i));
|
||||
}
|
||||
else if (!hasHighLimit(i) and hasLowLimit(i))
|
||||
{
|
||||
min.SetLowerLimitedVariable(i, name, val, step, getLowLimit(i));
|
||||
}
|
||||
else if (hasHighLimit(i) and hasLowLimit(i))
|
||||
{
|
||||
min.SetLimitedVariable(i, name, val, step, getLowLimit(i),
|
||||
getHighLimit(i));
|
||||
}
|
||||
else
|
||||
{
|
||||
min.SetVariable(i, name, val, step);
|
||||
}
|
||||
}
|
||||
|
||||
// minimize
|
||||
int status;
|
||||
unsigned int n = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
cout << "========== Minuit minimization, pass #" << n + 1;
|
||||
cout << " =========" << endl;
|
||||
}
|
||||
min.Minimize();
|
||||
status = min.Status();
|
||||
n++;
|
||||
} while ((status >= 2) and (n < getMaxPass()));
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
cout << "=================================================" << endl;
|
||||
}
|
||||
switch (status)
|
||||
{
|
||||
case 1:
|
||||
// covariance matrix was made positive, the minimum is still good
|
||||
// it just means that Minuit error analysis is inaccurate
|
||||
break;
|
||||
case 2:
|
||||
LATAN_WARNING("invalid minimum: Hesse analysis is not valid");
|
||||
break;
|
||||
case 3:
|
||||
LATAN_WARNING("invalid minimum: requested precision not reached");
|
||||
break;
|
||||
case 4:
|
||||
LATAN_WARNING("invalid minimum: iteration limit reached");
|
||||
break;
|
||||
}
|
||||
|
||||
// save and return result
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
x(i) = min.X()[i];
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
60
lib/Numerical/MinuitMinimizer.hpp
Normal file
60
lib/Numerical/MinuitMinimizer.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* MinuitMinimizer.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_MinuitMinimizer_hpp_
|
||||
#define Latan_MinuitMinimizer_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
#include <LatAnalyze/Numerical/Minimizer.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* interface to CERN Minuit minimizer *
|
||||
* ( http://www.cern.ch/minuit ) *
|
||||
******************************************************************************/
|
||||
class MinuitMinimizer: public Minimizer
|
||||
{
|
||||
public:
|
||||
enum class Algorithm
|
||||
{
|
||||
migrad = 1,
|
||||
simplex = 2,
|
||||
combined = 3
|
||||
};
|
||||
public:
|
||||
// constructor
|
||||
explicit MinuitMinimizer(const Algorithm algorithm = defaultAlg_);
|
||||
// destructor
|
||||
virtual ~MinuitMinimizer(void) = default;
|
||||
// access
|
||||
Algorithm getAlgorithm(void) const;
|
||||
void setAlgorithm(const Algorithm algorithm);
|
||||
virtual bool supportLimits(void) const;
|
||||
// minimization
|
||||
virtual const DVec & operator()(const DoubleFunction &f);
|
||||
private:
|
||||
Algorithm algorithm_;
|
||||
static constexpr Algorithm defaultAlg_ = Algorithm::combined;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_MinuitMinimizer_hpp_
|
201
lib/Numerical/NloptMinimizer.cpp
Normal file
201
lib/Numerical/NloptMinimizer.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* NloptMinimizer.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/NloptMinimizer.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
/******************************************************************************
|
||||
* NloptMinimizer implementation *
|
||||
******************************************************************************/
|
||||
// constructors ////////////////////////////////////////////////////////////////
|
||||
NloptMinimizer::NloptMinimizer(const Algorithm algorithm)
|
||||
{
|
||||
setAlgorithm(algorithm);
|
||||
der_.setOrder(1, 1);
|
||||
}
|
||||
|
||||
// access //////////////////////////////////////////////////////////////////////
|
||||
NloptMinimizer::Algorithm NloptMinimizer::getAlgorithm(void) const
|
||||
{
|
||||
return algorithm_;
|
||||
}
|
||||
|
||||
void NloptMinimizer::setAlgorithm(const Algorithm algorithm)
|
||||
{
|
||||
algorithm_ = algorithm;
|
||||
}
|
||||
|
||||
bool NloptMinimizer::supportLimits(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// minimization ////////////////////////////////////////////////////////////////
|
||||
const DVec & NloptMinimizer::operator()(const DoubleFunction &f)
|
||||
{
|
||||
DVec &x = getState();
|
||||
|
||||
// resize minimizer state to match function number of arguments
|
||||
if (f.getNArg() != x.size())
|
||||
{
|
||||
resize(f.getNArg());
|
||||
}
|
||||
|
||||
// create and set minimizer
|
||||
nlopt::opt min(getAlgorithm(), x.size());
|
||||
NloptFuncData data;
|
||||
vector<double> lb(x.size()), hb(x.size());
|
||||
|
||||
min.set_maxeval(getMaxIteration());
|
||||
min.set_xtol_rel(getPrecision());
|
||||
min.set_ftol_rel(-1.);
|
||||
der_.setFunction(f);
|
||||
data.f = &f;
|
||||
data.d = &der_;
|
||||
min.set_min_objective(&funcWrapper, &data);
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
lb[i] = hasLowLimit(i) ? getLowLimit(i) : -HUGE_VAL;
|
||||
hb[i] = hasHighLimit(i) ? getHighLimit(i) : HUGE_VAL;
|
||||
}
|
||||
min.set_lower_bounds(lb);
|
||||
min.set_upper_bounds(hb);
|
||||
|
||||
// minimize
|
||||
double res;
|
||||
vector<double> vx(x.size());
|
||||
nlopt::result status;
|
||||
unsigned int n = 0;
|
||||
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
vx[i] = x(i);
|
||||
}
|
||||
do
|
||||
{
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
cout << "========== NLopt minimization, pass #" << n + 1;
|
||||
cout << " ==========" << endl;
|
||||
cout << "Algorithm: " << min.get_algorithm_name() << endl;
|
||||
cout << "Max eval.= " << min.get_maxeval();
|
||||
cout << " -- Precision= " << min.get_xtol_rel() << endl;
|
||||
printf("Starting f(x)= %.10e\n", f(x));
|
||||
}
|
||||
try
|
||||
{
|
||||
status = min.optimize(vx, res);
|
||||
}
|
||||
catch (invalid_argument &e)
|
||||
{
|
||||
LATAN_ERROR(Runtime, "NLopt has reported receving invalid "
|
||||
"arguments (if you are using a global minimizer, did "
|
||||
"you specify limits for all variables?)");
|
||||
}
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
printf("Found minimum %.10e at:\n", res);
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
printf("%8s= %.10e\n", f.varName().getName(i).c_str(), vx[i]);
|
||||
}
|
||||
cout << "after " << data.evalCount << " evaluations" << endl;
|
||||
cout << "Minimization ended with code " << status;
|
||||
cout << " (" << returnMessage(status) << ")";
|
||||
cout << endl;
|
||||
}
|
||||
data.evalCount = 0;
|
||||
for (Index i = 0; i < x.size(); ++i)
|
||||
{
|
||||
x(i) = vx[i];
|
||||
}
|
||||
n++;
|
||||
} while (!minSuccess(status) and (n < getMaxPass()));
|
||||
if (getVerbosity() >= Verbosity::Normal)
|
||||
{
|
||||
cout << "=================================================" << endl;
|
||||
}
|
||||
if (!minSuccess(status))
|
||||
{
|
||||
LATAN_WARNING("invalid minimum: " + returnMessage(status));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// NLopt return code parser ////////////////////////////////////////////////////
|
||||
string NloptMinimizer::returnMessage(const nlopt::result status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case nlopt::SUCCESS:
|
||||
return "success";
|
||||
case nlopt::STOPVAL_REACHED:
|
||||
return "stopping value reached";
|
||||
case nlopt::FTOL_REACHED:
|
||||
return "tolerance on function reached";
|
||||
case nlopt::XTOL_REACHED:
|
||||
return "tolerance on variable reached";
|
||||
case nlopt::MAXEVAL_REACHED:
|
||||
return "maximum function evaluation reached";
|
||||
case nlopt::MAXTIME_REACHED:
|
||||
return "maximum time reached";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// NLopt function wrapper //////////////////////////////////////////////////////
|
||||
double NloptMinimizer::funcWrapper(unsigned int n, const double *arg,
|
||||
double *grad , void *vdata)
|
||||
{
|
||||
NloptFuncData &data = *static_cast<NloptFuncData *>(vdata);
|
||||
|
||||
if (grad)
|
||||
{
|
||||
for (unsigned int i = 0; i < n; ++i)
|
||||
{
|
||||
data.d->setDir(i);
|
||||
grad[i] = (*(data.d))(arg);
|
||||
}
|
||||
data.evalCount += data.d->getNPoint()*n;
|
||||
}
|
||||
data.evalCount++;
|
||||
|
||||
return (*data.f)(arg);
|
||||
}
|
||||
|
||||
// NLopt return status parser //////////////////////////////////////////////////
|
||||
bool NloptMinimizer::minSuccess(const nlopt::result status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case nlopt::SUCCESS:
|
||||
case nlopt::FTOL_REACHED:
|
||||
case nlopt::XTOL_REACHED:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
76
lib/Numerical/NloptMinimizer.hpp
Normal file
76
lib/Numerical/NloptMinimizer.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* NloptMinimizer.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_NloptMinimizer_hpp_
|
||||
#define Latan_NloptMinimizer_hpp_
|
||||
|
||||
#include <LatAnalyze/Global.hpp>
|
||||
#include <LatAnalyze/Numerical/Derivative.hpp>
|
||||
#include <LatAnalyze/Functional/Function.hpp>
|
||||
#include <LatAnalyze/Numerical/Minimizer.hpp>
|
||||
#include <nlopt.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* interface to NLOpt minimizers *
|
||||
* ( http://ab-initio.mit.edu/wiki/index.php/NLopt ) *
|
||||
* -------------------------------------------------------------------------- *
|
||||
* cf. http://ab-initio.mit.edu/wiki/index.php/NLopt_Algorithms for algorithm *
|
||||
* references and naming conventions *
|
||||
******************************************************************************/
|
||||
class NloptMinimizer: public Minimizer
|
||||
{
|
||||
public:
|
||||
typedef nlopt::algorithm Algorithm;
|
||||
private:
|
||||
struct NloptFuncData
|
||||
{
|
||||
const DoubleFunction *f{nullptr};
|
||||
Derivative *d{nullptr};
|
||||
unsigned int evalCount{0};
|
||||
};
|
||||
public:
|
||||
// constructor
|
||||
explicit NloptMinimizer(const Algorithm algorithm = defaultAlg_);
|
||||
// destructor
|
||||
virtual ~NloptMinimizer(void) = default;
|
||||
// access
|
||||
Algorithm getAlgorithm(void) const;
|
||||
void setAlgorithm(const Algorithm algorithm);
|
||||
virtual bool supportLimits(void) const;
|
||||
// minimization
|
||||
virtual const DVec & operator()(const DoubleFunction &f);
|
||||
private:
|
||||
// NLopt return code parser
|
||||
static std::string returnMessage(const nlopt::result status);
|
||||
// NLopt function wrapper
|
||||
static double funcWrapper(unsigned int n, const double *arg,
|
||||
double *grad , void *vdata);
|
||||
// NLopt return status parser
|
||||
static bool minSuccess(const nlopt::result status);
|
||||
private:
|
||||
Algorithm algorithm_;
|
||||
static constexpr Algorithm defaultAlg_ = Algorithm::LN_NELDERMEAD;
|
||||
CentralDerivative der_;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_NloptMinimizer_hpp_
|
29
lib/Numerical/RootFinder.cpp
Normal file
29
lib/Numerical/RootFinder.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* RootFinder.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/RootFinder.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
// constructor /////////////////////////////////////////////////////////////////
|
||||
RootFinder::RootFinder(const Index dim)
|
||||
: Solver(dim)
|
||||
{}
|
48
lib/Numerical/RootFinder.hpp
Normal file
48
lib/Numerical/RootFinder.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* RootFinder.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Functional/Function.hpp>
|
||||
#include <LatAnalyze/Numerical/Solver.hpp>
|
||||
|
||||
BEGIN_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* RootFinder *
|
||||
******************************************************************************/
|
||||
|
||||
class RootFinder: public Solver
|
||||
{
|
||||
public:
|
||||
// constructors
|
||||
RootFinder(void) = default;
|
||||
explicit RootFinder(const Index dim);
|
||||
// destructor
|
||||
virtual ~RootFinder(void) = default;
|
||||
// solver
|
||||
virtual const DVec & operator()(const std::vector<DoubleFunction *> &func)
|
||||
= 0;
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_RootFinder_hpp_
|
96
lib/Numerical/Solver.cpp
Normal file
96
lib/Numerical/Solver.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Solver.cpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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/Numerical/Solver.hpp>
|
||||
#include <LatAnalyze/includes.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace Latan;
|
||||
|
||||
/******************************************************************************
|
||||
* Solver implementation *
|
||||
******************************************************************************/
|
||||
// constructors ////////////////////////////////////////////////////////////////
|
||||
Solver::Solver(const double precision, const unsigned int maxIteration)
|
||||
{
|
||||
setMaxIteration(maxIteration);
|
||||
setPrecision(precision);
|
||||
}
|
||||
|
||||
Solver::Solver(const Index dim, const double precision,
|
||||
const unsigned int maxIteration)
|
||||
: Solver(precision, maxIteration)
|
||||
{
|
||||
resize(dim);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (x0.size() != x_.size())
|
||||
{
|
||||
resize(x0.size());
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
void Solver::resize(const Index dim)
|
||||
{
|
||||
x_.resize(dim);
|
||||
}
|
73
lib/Numerical/Solver.hpp
Normal file
73
lib/Numerical/Solver.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Solver.hpp, part of LatAnalyze 3
|
||||
*
|
||||
* Copyright (C) 2013 - 2016 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_LATAN_NAMESPACE
|
||||
|
||||
/******************************************************************************
|
||||
* Solver *
|
||||
******************************************************************************/
|
||||
|
||||
class Solver
|
||||
{
|
||||
public:
|
||||
static const unsigned int defaultMaxIteration = 10000u;
|
||||
static constexpr double defaultPrec = 1.0e-7;
|
||||
public:
|
||||
enum class Verbosity
|
||||
{
|
||||
Silent = 0,
|
||||
Normal = 1,
|
||||
Debug = 2
|
||||
};
|
||||
public:
|
||||
// constructors
|
||||
Solver(const double precision = defaultPrec,
|
||||
const unsigned int maxIteration = defaultMaxIteration);
|
||||
explicit Solver(const Index dim, 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);
|
||||
virtual void resize(const Index dim);
|
||||
protected:
|
||||
// access
|
||||
DVec & getState(void);
|
||||
private:
|
||||
unsigned int maxIteration_;
|
||||
double precision_;
|
||||
DVec x_;
|
||||
Verbosity verbosity_{Verbosity::Silent};
|
||||
};
|
||||
|
||||
END_LATAN_NAMESPACE
|
||||
|
||||
#endif // Latan_Solver_hpp_
|
Reference in New Issue
Block a user