Commit 61e69c12 authored by Laurent Belcour's avatar Laurent Belcour

Correction of the bug. Now the parametrized dependancy works.

parent 3ca4a521
TEMPLATE = lib
CONFIG *= static \
qt
CONFIG *= static \
qt \
console
DESTDIR = ../build
......
......@@ -16,9 +16,12 @@
/*! \brief A data object. Allows to load data from files.
* \ingroup core
*/
class data
class data : public parametrized
{
public: // methods
/*
data() : _in_param(params::UNKNOWN_INPUT), _out_param(params::UNKNOWN_OUTPUT) { }
*/
// Load data from a file
virtual void load(const std::string& filename) = 0 ;
......@@ -69,7 +72,7 @@ class data
// Get the size of the input X domain and output Y domain
virtual int dimX() const { return _nX ; }
virtual int dimY() const { return _nY ; }
/*
//! \brief provide the parametrization of the function.
//! \note some function type can modify the parametrization to adapt
//! to the data.
......@@ -88,15 +91,16 @@ class data
_in_param = new_param;
}
*/
protected: // data
// Dimensions of the data
int _nX, _nY ;
/*
// Input and output parametrization
params::input _in_param ;
params::output _out_param ;
*/
} ;
Q_DECLARE_INTERFACE(data, "Fitter.Data")
......
......@@ -22,14 +22,14 @@
* Any function used by the fitting algorithm should overload publicly this
* interface.
*/
class function
class function : public parametrized
{
public: // methods
// Constructor
function() : _in_param(params::UNKNOWN_INPUT),
/* function() : _in_param(params::UNKNOWN_INPUT),
_out_param(params::UNKNOWN_OUTPUT) { }
*/
// Overload the function operator
virtual vec operator()(const vec& x) const = 0 ;
virtual vec value(const vec& x) const = 0 ;
......@@ -106,7 +106,7 @@ class function
}
virtual vec getMin() const { return _min ; }
virtual vec getMax() const { return _max ; }
/*
//! \brief provide the parametrization of the function.
//! \note some function type can modify the parametrization to adapt
//! to the data.
......@@ -154,9 +154,10 @@ class function
_out_param = new_param;
else
{
std::cout << "<<ERROR>> A parametrization is already defined: " << params::get_name(_in_param) << std::endl;
std::cout << "<<ERROR>> A parametrization is already defined" << std::endl;
}
}
*/
protected: // function
......@@ -226,10 +227,10 @@ class function
// Dimension of the function & domain of definition.
int _nX, _nY ;
vec _min, _max ;
/*
// Input and output parametrization
params::input _in_param ;
params::output _out_param ;
params::output _out_param ;*/
};
/*! \brief Non-linear function interface
......
......@@ -223,3 +223,78 @@ class params
static void print_input_params();
};
/*! \brief A parametrized object. Allow to define function object (either data
* or functions that are defined over an input space and output space. This
* Object allowas to change the parametrization of the input or output space.
*/
class parametrized
{
public:
parametrized() : _in_param(params::UNKNOWN_INPUT),
_out_param(params::UNKNOWN_OUTPUT) { }
//! \brief provide the input parametrization of the object.
virtual params::input parametrization() const
{
return _in_param;
}
//! \brief provide the input parametrization of the object.
virtual params::input input_parametrization() const
{
return _in_param;
}
//! \brief provide the outout parametrization of the object.
virtual params::output output_parametrization() const
{
return _out_param;
}
//! \brief can set the input parametrization of a non-parametrized
//! object. Print an error if it is already defined.
virtual void setParametrization(params::input new_param)
{
//! \todo Here is something strange happening. The equality between
//! those enums is not correct for UNKNOWN_INPUT
if(_in_param == new_param)
{
return;
}
else if(_in_param == params::UNKNOWN_INPUT)
{
_in_param = new_param;
}
else
{
std::cout << "<<ERROR>> an input parametrization is already defined: " << params::get_name(_in_param) << std::endl;
std::cout << "<<ERROR>> trying to change to: " << params::get_name(new_param) << std::endl;
}
}
//! \brief can set the output parametrization of a non-parametrized
//! function. Throw an exception if it tries to erase a previously
//! defined one.
virtual void setParametrization(params::output new_param)
{
if(_out_param == new_param)
{
return;
}
else if(_out_param == params::UNKNOWN_INPUT)
{
_out_param = new_param;
}
else
{
std::cout << "<<ERROR>> an output parametrization is already defined: " << std::endl;
}
}
protected:
// Input and output parametrization
params::input _in_param ;
params::output _out_param ;
};
......@@ -65,13 +65,13 @@ bool rational_fitter_dca::fit_data(const data* dat, function* fit, const argumen
QTime time ;
time.start() ;
if(fit_data(d, _max_np, _max_nq, r, args))
if(fit_data(d, r, args))
{
int msec = time.elapsed() ;
int sec = (msec / 1000) % 60 ;
int min = (msec / 60000) % 60 ;
int hour = (msec / 3600000) ;
std::cout << "<<INFO>> got a fit using np = " << _max_np << " & nq = " << _max_nq << " " << std::endl ;
std::cout << "<<INFO>> got a fit using np = " << r->getP().size() << " & nq = " << r->getQ().size() << " " << std::endl ;
std::cout << "<<INFO>> it took " << hour << "h " << min << "m " << sec << "s" << std::endl ;
return true ;
......@@ -83,8 +83,6 @@ bool rational_fitter_dca::fit_data(const data* dat, function* fit, const argumen
void rational_fitter_dca::set_parameters(const arguments& args)
{
_max_np = args.get_float("np", 10) ;
_max_nq = args.get_float("nq", 10) ;
}
double distance(const rational_function* f, const data* d)
......@@ -98,33 +96,40 @@ double distance(const rational_function* f, const data* d)
for(int j=0; j<d->dimY(); ++j)
{
double diff = y[j] - xi[d->dimX()+j];
double diff = std::abs(y[j] - xi[d->dimX()+j]);
current_d += diff;
}
current_d = std::abs(current_d);
if(current_d > distance)
distance = current_d;
distance = std::max(current_d, distance);
}
return distance;
}
// Bootstrap the DCA algorithm with an already done fit
void rational_fitter_dca::bootstrap(const data* d, int np, int nq, rational_function* fit, double& delta, const arguments& args)
void rational_fitter_dca::bootstrap(const data* d, int& np, int& nq, rational_function* fit, double& delta, const arguments& args)
{
vec p(np*d->dimY());
vec q(nq*d->dimY());
if(args.is_defined("bootstrap"))
{
fit->load(args["bootstrap"]);
np = fit->getP().size();
nq = fit->getQ().size();
}
else
{
#ifdef DEBUG
std::cout << "<<DEBUG>> Using the constant function equals to 0 as input: not optimal" << std::endl;
#endif
np = args.get_int("np", 10);
nq = args.get_int("nq", 10);
vec p(np*d->dimY());
vec q(nq*d->dimY());
q[0] = 1.0;
p[1] = 0.0;
fit->update(p, q);
}
......@@ -135,17 +140,20 @@ void rational_fitter_dca::bootstrap(const data* d, int np, int nq, rational_func
// np and nq are the degree of the RP to fit to the data
// y is the dimension to fit on the y-data (e.g. R, G or B for RGB signals)
// the function return a ration BRDF function and a boolean
bool rational_fitter_dca::fit_data(const data* d, int np, int nq, rational_function* r, const arguments& args)
bool rational_fitter_dca::fit_data(const data* d, rational_function* r, const arguments& args)
{
int np, nq;
// Bootstrap the delta and rational function using the Papamarkos
// algorithm.
double delta = 0.0;
bootstrap(d, np, nq, r, delta, args);
// Size of the problem
int N = np+nq+1 ;
int M = d->size() ;
int N = np+nq+1;
int M = d->size();
int nY = d->dimY();
// Bootstrap the delta and rational function using the Papamarkos
// algorithm.
double delta = 0.0;
bootstrap(d, np, nq, r, delta, args);
#ifdef DEBUG
std::cout << "<<DEBUG>> delta value after boostrap: " << delta << std::endl;
std::cout << "<<DEBUG>> r: " << *r << std::endl;
......@@ -202,6 +210,7 @@ bool rational_fitter_dca::fit_data(const data* d, int np, int nq, rational_funct
// delta_{k+1} = delta_{k}
//delta_k = distance(r, d);
delta_k = delta;
std::cout << "<<DEBUG>> input delta = " << delta << std::endl;
// The function to minimize is \delta which is the last element of
// the result vector
......@@ -302,7 +311,7 @@ bool rational_fitter_dca::fit_data(const data* d, int np, int nq, rational_funct
engOutputBuffer(ep, output, BUFFER_SIZE) ;
engEvalString(ep, "[x, fval, flag] = linprog(f,A,b,[],[], l, u);");
#ifdef DEBUG
#ifndef DEBUG
std::cout << output << std::endl ;
#endif
......@@ -335,13 +344,13 @@ bool rational_fitter_dca::fit_data(const data* d, int np, int nq, rational_funct
// Compute the new delta_k, the distance to the data points
delta = distance(r, d);
//delta = val[(np+nq)*nY];
std::cout << "<<DEBUG>> pass n°" << nb_passes << "delta = " << delta << " / " << val[(np+nq)*nY] << std::endl;
// Stopping condition if the optimization did not manage to improve the
// L_inf norm quit !
if(delta > delta_k)
{
r->update(tempP, tempQ);
break;
}
......@@ -357,12 +366,13 @@ bool rational_fitter_dca::fit_data(const data* d, int np, int nq, rational_funct
if(nb_passes == 1)
{
std::cout << "<<ERROR>> Could no optimize with respect to Linf" << std::endl;
std::cout << "<<ERROR>> could no optimize with respect to Linf" << std::endl;
return false;
}
else
{
std::cout << "<<INFO>> Used " << nb_passes << " passes to optimize the solution" << std::endl;
std::cout << "<<INFO>> used " << nb_passes << " passes to optimize the solution" << std::endl;
std::cout << "<<INFO>> got solution " << *r << std::endl ;
return true;
}
}
......
......@@ -47,19 +47,17 @@ class rational_fitter_dca : public QObject, public fitter
// Fitting a data object using np elements in the numerator and nq
// elements in the denominator
virtual bool fit_data(const data* d, int np, int nq, rational_function* fit, const arguments& args) ;
virtual bool fit_data(const data* d, rational_function* fit, const arguments& args) ;
//! \brief Bootstrap the DCA algorithm with an already fitted function. It will
//! load the the rational function object from a text file defined in the argument
//! --bootstrap %filename%.
void bootstrap(const data* d, int np, int nq, rational_function* fit, double& delta,
void bootstrap(const data* d, int& np, int& nq, rational_function* fit, double& delta,
const arguments& args) ;
protected: // data
// min and Max usable np and nq values for the fitting
//
int _max_np, _max_nq ;
// Matlab Engine
Engine *ep;
} ;
......@@ -23,7 +23,7 @@ test_merl=0
fitter="eigen"
#fitter_args="--min-np 1 --np 100 --min-nq 1 --nq 100"
fitter_args="--np 10 --nq 10"
fitter_args="--np 3 --nq 3"
mkdir tests
......
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