Commit a784f96c authored by Laurent Belcour's avatar Laurent Belcour
Browse files

Refactoring the plugin manager and rational function calls.

parent f1cd2122
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
/*! \brief A useful class for storing the high-level arguments of a program /*! \brief A useful class for storing the high-level arguments of a program
* or a function. * or a function.
* \ingroup core
* \internal
* *
* The set of parameters are parsed from the command line using the * The set of parameters are parsed from the command line using the
* constructor. They are stored as std::string in a std::map. * constructor. They are stored as std::string in a std::map.
...@@ -75,7 +77,7 @@ class arguments ...@@ -75,7 +77,7 @@ class arguments
} }
else else
{ {
std::cerr << "Underfined request to key : \"" << key << "\"" << std::endl ; //std::cerr << "Underfined request to key : \"" << key << "\"" << std::endl ;
return std::string() ; return std::string() ;
} }
} ; } ;
......
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
/*! \brief A core implementation of a vector of double. /*! \brief A core implementation of a vector of double.
* \ingroup core
* \internal
* *
* \details * \details
* This type is used for any transmission of vector data with unfixed * This type is used for any transmission of vector data with unfixed
* dimension. It allows to have a generic fitter working for * dimension. It allows to have a generic fitter working for
* n-Dimensional data. * n-Dimensional data.
*/ */
class vec : public std::vector<double> class vec : public std::vector<double>
{ {
...@@ -23,13 +25,21 @@ class vec : public std::vector<double> ...@@ -23,13 +25,21 @@ class vec : public std::vector<double>
vec(int dim) : std::vector<double>(dim) vec(int dim) : std::vector<double>(dim)
{ {
assign(dim, 0.0) ; assign(dim, 0.0) ;
} ; }
virtual ~vec() virtual ~vec()
{ {
} ; }
// Mathematical operators // Mathematical operators
// //
vec operator=(const vec& a)
{
for(unsigned int i=0; i<this->size(); ++i)
{
this->at(i) = a[i];
}
return *this ;
}
friend vec operator-(const vec& a) friend vec operator-(const vec& a)
{ {
vec b(a.size()) ; vec b(a.size()) ;
......
...@@ -144,6 +144,14 @@ fitter* plugins_manager::get_fitter() const ...@@ -144,6 +144,14 @@ fitter* plugins_manager::get_fitter() const
// //
function* plugins_manager::get_function(const std::string& n) function* plugins_manager::get_function(const std::string& n)
{ {
if(n.empty())
{
#ifdef DEBUG
std::cout << "<<DEBUG>> no function plugin specified, returning a rational function" << std::endl;
#endif
return new rational_function();
}
#ifdef USING_STATIC #ifdef USING_STATIC
FunctionPrototype myFunction = (FunctionPrototype) QLibrary::resolve(QString(n.c_str()), "_Z16provide_functionv"); FunctionPrototype myFunction = (FunctionPrototype) QLibrary::resolve(QString(n.c_str()), "_Z16provide_functionv");
...@@ -171,22 +179,42 @@ function* plugins_manager::get_function(const std::string& n) ...@@ -171,22 +179,42 @@ function* plugins_manager::get_function(const std::string& n)
} }
#endif #endif
} }
data* plugins_manager::get_data(const std::string& n) const data* plugins_manager::get_data(const std::string& n)
{ {
if(_datas.count(n) == 0) if(n.empty())
{ {
#ifdef DEBUG #ifdef DEBUG
std::cout << "<<DEBUG>> using vertical segment data loader" << std::endl ; std::cout << "<<DEBUG>> no data plugin specified, returning a vertial_segment loader" << std::endl;
#endif #endif
return new vertical_segment() ; return new vertical_segment();
} }
else
{ #ifdef USING_STATIC
DataPrototype myData = (DataPrototype) QLibrary::resolve(QString(n.c_str()), "_Z16provide_datav");
if(myData != NULL)
{
#ifdef DEBUG #ifdef DEBUG
std::cout << "<<DEBUG>> using \"" << n << "\" data loader" << std::endl ; std::cout << "<<DEBUG>> using function provider in file \"" << n << "\"" << std::endl;
#endif
return myData();
}
else
{
std::cerr << "<<ERROR>> no data provider found in file \"" << n << "\"" << std::endl;
return new vertical_segment() ;
}
#else
if(_functions.count(n) == 0)
{
return new vertical_segment() ;
}
else
{
return _datas.find(n)->second ;
}
#endif #endif
return _datas.find(n)->second ;
}
} }
fitter* plugins_manager::get_fitter(const std::string& n) const fitter* plugins_manager::get_fitter(const std::string& n) const
{ {
......
...@@ -32,7 +32,7 @@ class plugins_manager ...@@ -32,7 +32,7 @@ class plugins_manager
//! \brief Get instances of the function, the data and the fitter, select one //! \brief Get instances of the function, the data and the fitter, select one
//! based on the name. Return null if no one exist. //! based on the name. Return null if no one exist.
static function* get_function(const std::string& n) ; static function* get_function(const std::string& n) ;
data* get_data(const std::string& n) const ; static data* get_data(const std::string& n) ;
fitter* get_fitter(const std::string& n) const ; fitter* get_fitter(const std::string& n) const ;
//! \brief Provide a measure of how much memory there is on the system. //! \brief Provide a measure of how much memory there is on the system.
......
...@@ -13,6 +13,10 @@ rational_function::rational_function() : a(), b() ...@@ -13,6 +13,10 @@ rational_function::rational_function() : a(), b()
{ {
} }
rational_function::rational_function(int np, int nq) : a(np), b(nq)
{
}
rational_function::rational_function(const std::vector<double>& a, rational_function::rational_function(const std::vector<double>& a,
const std::vector<double>& b) : const std::vector<double>& b) :
a(a), b(b) a(a), b(b)
......
...@@ -20,6 +20,7 @@ class rational_function : public QObject, public function ...@@ -20,6 +20,7 @@ class rational_function : public QObject, public function
public: // methods public: // methods
rational_function() ; rational_function() ;
rational_function(int np, int nq) ;
rational_function(const std::vector<double>& a, const std::vector<double>& b) ; rational_function(const std::vector<double>& a, const std::vector<double>& b) ;
virtual ~rational_function() ; virtual ~rational_function() ;
......
...@@ -72,7 +72,7 @@ public: ...@@ -72,7 +72,7 @@ public:
{ {
return CI.ncols(); return CI.ncols();
} }
//! \brief Solves the quadratic program and update the p and //! \brief Solves the quadratic program and update the p and
//! q vector if necessary. //! q vector if necessary.
inline bool solve_program(QuadProgPP::Vector<double>& x, double& delta, vec& p, vec& q) inline bool solve_program(QuadProgPP::Vector<double>& x, double& delta, vec& p, vec& q)
......
...@@ -52,6 +52,8 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar ...@@ -52,6 +52,8 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar
r->setMin(d->min()) ; r->setMin(d->min()) ;
r->setMax(d->max()) ; r->setMax(d->max()) ;
const int _min_np = args.get_int("min-np", 10);
const int _max_np = args.get_int("np", _min_np);
std::cout << "<<INFO>> N in [" << _min_np << ", " << _max_np << "]" << std::endl ; std::cout << "<<INFO>> N in [" << _min_np << ", " << _max_np << "]" << std::endl ;
for(int i=_min_np; i<=_max_np; ++i) for(int i=_min_np; i<=_max_np; ++i)
...@@ -81,6 +83,24 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar ...@@ -81,6 +83,24 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar
std::cout << "<<DEBUG>> will use " << nb_cores << " threads to compute the quadratic programs" << std::endl ; std::cout << "<<DEBUG>> will use " << nb_cores << " threads to compute the quadratic programs" << std::endl ;
#endif #endif
omp_set_num_threads(nb_cores) ; omp_set_num_threads(nb_cores) ;
std::vector<rational_function*> rs;
for(int j=0; j<nb_cores; ++j)
{
rational_function* rj = dynamic_cast<rational_function*>(plugins_manager::get_function(args["func"]));
rj->setDimX(d->dimX()) ;
rj->setDimY(d->dimY()) ;
rj->setMin(d->min()) ;
rj->setMax(d->max()) ;
if(rj == NULL)
{
std::cerr << "<<ERROR>> unable to obtain a rational function from the plugins manager" << std::endl;
return false;
}
rs.push_back(rj);
}
double min_delta = std::numeric_limits<double>::max(); double min_delta = std::numeric_limits<double>::max();
int nb_sol_found = 0; int nb_sol_found = 0;
...@@ -95,7 +115,7 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar ...@@ -95,7 +115,7 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar
vec p(temp_np*r->dimY()), q(temp_nq*r->dimY()); vec p(temp_np*r->dimY()), q(temp_nq*r->dimY());
double delta; double delta;
bool is_fitted = fit_data(d, temp_np, temp_nq, r, p, q, delta); bool is_fitted = fit_data(d, temp_np, temp_nq, rs[omp_get_thread_num()], p, q, delta);
if(is_fitted) if(is_fitted)
{ {
#pragma omp critical #pragma omp critical
...@@ -116,6 +136,12 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar ...@@ -116,6 +136,12 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar
} }
} }
// Clean memory
for(int j=0; j<nb_cores; ++j)
{
delete rs[j];
}
if(min_delta < std::numeric_limits<double>::max()) if(min_delta < std::numeric_limits<double>::max())
{ {
int msec = time.elapsed() ; int msec = time.elapsed() ;
...@@ -135,10 +161,6 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar ...@@ -135,10 +161,6 @@ bool rational_fitter_parallel::fit_data(const data* dat, function* fit, const ar
void rational_fitter_parallel::set_parameters(const arguments& args) void rational_fitter_parallel::set_parameters(const arguments& args)
{ {
_max_np = args.get_float("np", 10) ;
_max_nq = args.get_float("nq", 10) ;
_min_np = args.get_float("min-np", _max_np) ;
_min_nq = args.get_float("min-nq", _max_nq) ;
} }
...@@ -182,21 +204,20 @@ bool rational_fitter_parallel::fit_data(const vertical_segment* dat, int np, int ...@@ -182,21 +204,20 @@ bool rational_fitter_parallel::fit_data(const vertical_segment* dat, int np, int
quadratic_program qp(np, nq); quadratic_program qp(np, nq);
#ifndef TODO_PUT_IN_METHOD #ifndef TODO_PUT_IN_METHOD
for(int i=0; i<d->size()/10; ++i) for(int i=0; i<d->size(); ++i)
{ {
// Create two vector of constraints // Create two vector of constraints
vec c1(n), c2(n); vec c1(n), c2(n);
get_constraint(10*i, np, nq, ny, d, r, c1, c2); get_constraint(i, np, nq, ny, d, r, c1, c2);
qp.add_constraints(c1); qp.add_constraints(c1);
qp.add_constraints(c2); qp.add_constraints(c2);
} }
#endif #endif
do while(true)
{ {
QuadProgPP::Vector<double> x(n); QuadProgPP::Vector<double> x(n);
bool solves_qp = qp.solve_program(x, delta, p, q); bool solves_qp = qp.solve_program(x, delta, p, q);
...@@ -205,30 +226,34 @@ bool rational_fitter_parallel::fit_data(const vertical_segment* dat, int np, int ...@@ -205,30 +226,34 @@ bool rational_fitter_parallel::fit_data(const vertical_segment* dat, int np, int
#ifdef DEBUG #ifdef DEBUG
std::cout << "<<INFO>> got solution " << *r << std::endl ; std::cout << "<<INFO>> got solution " << *r << std::endl ;
#endif #endif
return true;
}
/* /*
int current = 0, i=0; int current = 0, i=0;
while(i < 100 && current < m) while(i < 100 && current < m)
{ {
int next = quadratic_program::next_unmatching_constraint(current, ny, ); int next = quadratic_program::next_unmatching_constraint(current, ny, );
// Create two vector of constraints // Create two vector of constraints
vec c1(n), c2(n); vec c1(n), c2(n);
get_constraint(next, np, nq, ny, d, r, c1, c2); get_constraint(next, np, nq, ny, d, r, c1, c2);
qp.add_constraints(c1); qp.add_constraints(c1);
qp.add_constraints(c2); qp.add_constraints(c2);
++i; ++i;
current = next; current = next;
} }
*/ */
return true;
}
else
{
return false;
}
} }
while(qp.nb_constraints() < 2*m);
return false; std::cerr << "<<ERROR>> should not atteign this part of the code" << __FILE__ << ":" << __LINE__ << std::endl;
return false;
} }
void rational_fitter_parallel::get_constraint(int i, int np, int nq, int ny, void rational_fitter_parallel::get_constraint(int i, int np, int nq, int ny,
......
...@@ -53,9 +53,5 @@ class rational_fitter_parallel : public QObject, public fitter ...@@ -53,9 +53,5 @@ class rational_fitter_parallel : public QObject, public fitter
//! \brief Create a constraint vector given its index i in the data //! \brief Create a constraint vector given its index i in the data
// object and the rational function object to fit. // object and the rational function object to fit.
virtual void get_constraint(int i, int np, int nq, int ny, const vertical_segment* data, const rational_function* func, vec& cu, vec& cl); virtual void get_constraint(int i, int np, int nq, int ny, const vertical_segment* data, const rational_function* func, vec& cu, vec& cl);
// min and Max usable np and nq values for the fitting
int _max_np, _max_nq ;
int _min_np, _min_nq ;
} ; } ;
...@@ -44,22 +44,13 @@ int main(int argc, char** argv) ...@@ -44,22 +44,13 @@ int main(int argc, char** argv)
// if(fitters.size() > 0 && datas.size() > 0 && functions.size() > 0) // if(fitters.size() > 0 && datas.size() > 0 && functions.size() > 0)
{ {
fit->set_parameters(args) ; fit->set_parameters(args) ;
function* f = NULL; function* f = plugins_manager::get_function(args["func"]);
if(args.is_defined("func")) data* d = plugins_manager::get_data(args["data"]);
{
std::cout << "<<INFO>> Using plugin function \"" << args["func"] << "\"" << std::endl ;
f = manager.get_function(args["func"]) ;
}
else
{
f = fit->provide_function() ;
}
data* d = fit->provide_data() ;
d->load(args["input"], args); d->load(args["input"], args);
QTime time ; QTime time ;
time.start() ; time.start() ;
bool is_fitted = fit->fit_data(d, f) ; bool is_fitted = fit->fit_data(d, f, args) ;
int msec = time.elapsed() ; int msec = time.elapsed() ;
int sec = (msec / 1000) % 60 ; int sec = (msec / 1000) % 60 ;
int min = (msec / 60000) % 60 ; int min = (msec / 60000) % 60 ;
......
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