Commit bd312e5a authored by Laurent Belcour's avatar Laurent Belcour

Compiling Levenberg fitter for non-linear functions

parent 70dcdcdf
......@@ -31,8 +31,8 @@ class data
virtual vec min() const = 0 ;
virtual vec max() const = 0 ;
virtual int dimX() const { return _nX ; } ;
virtual int dimY() const { return _nY ; } ;
virtual int dimX() const { return _nX ; }
virtual int dimY() const { return _nY ; }
protected:
// Dimension of the function
......
......@@ -82,6 +82,9 @@ class nonlinear_function: public function
{
public: // methods
//! Number of parameters to this non-linear function
virtual int nbParameters() const = 0;
//! Get the vector of parameters for the function
virtual vec parameters() const = 0;
......@@ -94,6 +97,9 @@ class nonlinear_function: public function
// The x input of this function is the position in the input space and
// has size dimX(), the resulting vector has the size of the parameters
// times the size of the output domain.
//
// The result vector should be orderer as res[i + dimY()*j], output
// dimension first, then parameters.
virtual vec parametersJacobian(const vec& x) const = 0;
};
......
#include "fitter.h"
#include <Eigen/Dense>
#include <Eigen/SVD>
#include <unsupported/Eigen/NonLinearOptimization>
#include <string>
#include <iostream>
#include <fstream>
#include <limits>
#include <algorithm>
#include <cmath>
#include <QTime>
struct EigenFunctor
{
EigenFunctor(nonlinear_function* f) : _f(f)
{
}
inline int inputs() const { return _f->dimX(); }
inline int values() const { return _f->dimY(); }
int operator()(const Eigen::VectorXd& x, Eigen::VectorXd& y) const
{
vec _x(inputs());
for(int i=0; i<inputs(); ++i) _x[i] = x(i);
vec _y = (*_f)(_x);
for(int i=0; i<values(); ++i) y(i) = _y[i];
return 0;
}
int df(const Eigen::VectorXd &x, Eigen::MatrixXd &fjac) const
{
vec _x(inputs());
for(int i=0; i<inputs(); ++i) _x[i] = x(i);
vec _jac = _f->parametersJacobian(_x);
for(int j=0; j<_f->nbParameters(); ++j)
for(int i=0; i<values(); ++i)
{
fjac(i,j) = _jac[values()*j + i];
}
return 0;
}
nonlinear_function* _f;
};
nonlinear_fitter_eigen::nonlinear_fitter_eigen() : QObject()
{
}
nonlinear_fitter_eigen::~nonlinear_fitter_eigen()
{
}
bool nonlinear_fitter_eigen::fit_data(const data* d, function* fit)
{
// I need to set the dimension of the resulting function to be equal
// to the dimension of my fitting problem
fit->setDimX(d->dimX()) ;
fit->setDimY(d->dimY()) ;
fit->setMin(d->min()) ;
fit->setMax(d->max()) ;
if(dynamic_cast<nonlinear_function*>(fit) == NULL)
{
std::cerr << "<<ERROR>> the function is non a non-linear function" << std::endl;
return false;
}
nonlinear_function* nf = dynamic_cast<nonlinear_function*>(fit);
/* the following starting values provide a rough fit. */
int info;
Eigen::VectorXd x;
x.setConstant(nf->parameters().size(), 1.);
EigenFunctor functor(nf);
Eigen::LevenbergMarquardt<EigenFunctor> lm(functor);
info = lm.minimize(x);
vec p(nf->parameters().size());
for(int i=0; i<p.size(); ++i)
{
p[i] = x(i);
}
nf->setParameters(p);
return info == 1 ;
}
void nonlinear_fitter_eigen::set_parameters(const arguments& args)
{
}
data* nonlinear_fitter_eigen::provide_data() const { return NULL; }
function* nonlinear_fitter_eigen::provide_function() const { return NULL; }
Q_EXPORT_PLUGIN2(nonlinear_fitter_eigen, nonlinear_fitter_eigen)
#pragma once
// Include STL
#include <vector>
#include <string>
// Interface
#include <QObject>
#include <core/function.h>
#include <core/data.h>
#include <core/fitter.h>
#include <core/args.h>
#include <core/vertical_segment.h>
class nonlinear_fitter_eigen: public QObject, public fitter
{
Q_OBJECT
Q_INTERFACES(fitter)
public: // methods
nonlinear_fitter_eigen() ;
virtual ~nonlinear_fitter_eigen() ;
// Fitting a data object
//
virtual bool fit_data(const data* d, function* fit) ;
// Provide user parameters to the fitter
//
virtual void set_parameters(const arguments& args) ;
// Unsable stuff
virtual data* provide_data() const ;
virtual function* provide_function() const ;
protected: // function
protected: // data
} ;
TARGET = nonlinear_levenberf_eigen
TEMPLATE = lib
CONFIG *= qt \
plugin \
eigen
DESTDIR = ../../build
INCLUDEPATH += ../..
HEADERS = _fitter.h
SOURCES = fitter.cpp
LIBS += -L../../build \
-lcore
......@@ -9,5 +9,6 @@ SUBDIRS = \
rational_fitter_leastsquare \
rational_function_chebychev \
rational_fitter_matlab \
nonlinear_levenberg_eigen \
data_merl
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment