/* * FunctionApproximation.hpp * * Created on: 02.10.2012 * Author: heber */ #ifndef FUNCTIONAPPROXIMATION_HPP_ #define FUNCTIONAPPROXIMATION_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include "FunctionApproximation/FunctionModel.hpp" /** This class encapsulates the solution to approximating a high-dimensional * function represented by two vectors of tuples, being input variables and * output of the function via a model function, manipulated by a set of * parameters. * * \note For this reason the input and output dimension has to be given in * the constructor since these are fixed parameters to the problem as a * whole and usually: a different input dimension means we have a completely * different problem (and hence we may as well construct and new instance of * this class). * * The "training data", i.e. the two sets of input and output values, is * given extra. * * The problem is then that a given high-dimensional function is supplied, * the "model", and we have to fit this function via its set of variable * parameters. This fitting procedure is executed via a Levenberg-Marquardt * algorithm as implemented in the * LevMar * package. * */ class FunctionApproximation { public: //!> typedef for a vector of input arguments typedef std::vector inputs_t; //!> typedef for a vector of output values typedef std::vector outputs_t; public: /** Constructor of the class FunctionApproximation. * * \param _input_dimension input dimension for this function approximation * \param _output_dimension output dimension for this function approximation */ FunctionApproximation( const size_t &_input_dimension, const size_t &_output_dimension, FunctionModel &_model) : input_dimension(_input_dimension), output_dimension(_output_dimension), model(_model) {} /** Destructor for class FunctionApproximation. * */ ~FunctionApproximation() {} /** Setter for the training data to be used. * * \param input vector of input tuples, needs to be of * FunctionApproximation::input_dimension size * \param output vector of output tuples, needs to be of * FunctionApproximation::output_dimension size */ void setTrainingData(const inputs_t &input, const outputs_t &output); /** Setter for the model function to be used in the approximation. * */ void setModelFunction(FunctionModel &_model); /** This enum steers whether we use finite differences or * FunctionModel::parameter_derivative to calculate the jacobian. * */ enum JacobianMode { FiniteDifferences, ParameterDerivative, MAXMODE }; /** This starts the fitting process, resulting in the parameters to * the model function being optimized with respect to the given training * data. * * \param mode whether to use finite differences or the parameter derivative * in calculating the jacobian */ void operator()(const enum JacobianMode mode = FiniteDifferences); /** Evaluates the model function for each pair of training tuple and returns * the output of the function as a vector. * * This function as a signature compatible to the one required by the * LevMar package (with double precision). * * \param *p array of parameters for the model function of dimension \a m * \param *x array of result values of dimension \a n * \param m parameter dimension * \param n output dimension * \param *data additional data, unused here */ void evaluate(double *p, double *x, int m, int n, void *data); /** Evaluates the parameter derivative of the model function for each pair of * training tuple and returns the output of the function as vector. * * This function as a signature compatible to the one required by the * LevMar package (with double precision). * * \param *p array of parameters for the model function of dimension \a m * \param *jac on output jacobian matrix of result values of dimension \a n times \a m * \param m parameter dimension * \param n output dimension times parameter dimension * \param *data additional data, unused here */ void evaluateDerivative(double *p, double *jac, int m, int n, void *data); /** This functions checks whether the parameter derivative of the FunctionModel * has been correctly implemented by validating against finite differences. * * We use LevMar's dlevmar_chkjac() function. * * \return true - gradients are ok (>0.5), false - else */ bool checkParameterDerivatives(); private: static void LevMarCallback(double *p, double *x, int m, int n, void *data); static void LevMarDerivativeCallback(double *p, double *x, int m, int n, void *data); void prepareModel(double *p, int m); void prepareParameters(double *&p, int &m) const; void prepareOutput(double *&x, int &n) const; private: //!> input dimension (is fixed from construction) const size_t input_dimension; //!> output dimension (is fixed from construction) const size_t output_dimension; //!> current input set of training data inputs_t input_data; //!> current output set of training data outputs_t output_data; //!> the model function to be used in the high-dimensional approximation FunctionModel &model; }; #endif /* FUNCTIONAPPROXIMATION_HPP_ */