PARP Research Group University of Murcia, Spain


src/qvmath/qvnumericalanalysis.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008, 2009. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00021 
00025 
00026 #include <qvmath/qvnumericalanalysis.h>
00027 
00028 const QVVector qvEstimateGradient(const QVFunction<QVVector, double> &multivariateFunction, const QVVector &location, const double h)
00029         {
00030         const int dim = location.size();
00031         QVVector gradient(dim);
00032         const double actual = multivariateFunction(location);
00033         for (int i = 0; i < dim; i++)
00034                 {
00035                 QVVector stepLocation = location;
00036                 stepLocation[i] += h;
00037                 gradient[i] = (multivariateFunction(stepLocation) - actual)/h;
00038                 }
00039         return gradient;
00040         }
00041 
00042 const QVMatrix qvEstimateHessian(       const QVFunction<QVVector, double> &multivariateFunction,
00043                                         const QVVector &location, const double h)
00044         {
00045         const int dim = location.size();
00046         const QVVector g = qvEstimateGradient(multivariateFunction, location, h);
00047 
00048         QVMatrix hessian(dim, dim);
00049 
00050         const double actual = multivariateFunction(location);
00051         for (int i = 0; i < dim; i++)
00052                 for (int j = 0; j < dim; j++)
00053                 {
00054                 QVVector stepLocationIJ = location;
00055                 stepLocationIJ[i] += h;
00056                 stepLocationIJ[j] += h;
00057                 hessian(i,j) = (multivariateFunction(stepLocationIJ) - actual)/(h*h) - (g[i] + g[j])/h;
00058                 }
00059         return hessian;
00060         }
00061 
00063 // GSL minimization
00064 #include <gsl/gsl_multimin.h>
00065 
00066 double my_f (const gsl_vector *v, void *params)
00067         {
00068         return ((QVFunction<QVVector, double> *) params)->operator()(QVVector(v));
00069         }
00070         
00071 /* The gradient of f, df = (df/dx, df/dy). */
00072 void my_df (const gsl_vector *v, void *params, gsl_vector *df)
00073         {
00074         gsl_vector_memcpy(df, qvEstimateGradient( * (QVFunction<QVVector, double> *) params,QVVector(v)));
00075         }
00076 
00077 /* Compute both f and df together. */
00078 void my_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *df) 
00079         {
00080         *f = my_f(x, params); 
00081         my_df(x, params, df);
00082         }
00083 
00084 const bool qvGSLMinimizeFDF (   QVFunction<QVVector, double> & function, QVVector &point,
00085                                 const GSLMultiminFDFMinimizerType gslMinimizerAlgorithm,
00086                                 const int maxIterations, const double maxGradientNorm,
00087                                 const double step, const double tol)
00088         {
00089         const int dims = point.size();
00090         const gsl_multimin_fdfminimizer_type *minimizer_type = NULL;
00091         switch(gslMinimizerAlgorithm)
00092                 {
00093                 case ConjugateFR:       minimizer_type = gsl_multimin_fdfminimizer_conjugate_fr;        break;
00094                 case ConjugatePR:       minimizer_type = gsl_multimin_fdfminimizer_conjugate_pr;        break;
00095                 case VectorBFGS:        minimizer_type = gsl_multimin_fdfminimizer_vector_bfgs;         break;
00096                 case SteepestDescent:   minimizer_type = gsl_multimin_fdfminimizer_steepest_descent;    break;
00097                 }
00098 
00099         gsl_multimin_fdfminimizer *minimizer = gsl_multimin_fdfminimizer_alloc (minimizer_type, dims);
00100 
00101         gsl_multimin_function_fdf my_func;
00102         my_func.n = dims;
00103         my_func.f = &my_f;
00104         my_func.df = &my_df;
00105         my_func.fdf = &my_fdf;
00106         my_func.params = &function;
00107         
00108         gsl_vector *x = point;
00109 
00110         gsl_multimin_fdfminimizer_set (minimizer, &my_func, x, step, tol);
00111         
00112         int status = GSL_CONTINUE;
00113         for (int i = 0; status == GSL_CONTINUE && i < maxIterations; i++)
00114                 {
00115                 if ((status = gsl_multimin_fdfminimizer_iterate (minimizer)))
00116                         break;
00117         
00118                 status = gsl_multimin_test_gradient (gsl_multimin_fdfminimizer_gradient(minimizer), maxGradientNorm);
00119                 }
00120 
00121         // Store resulting value.
00122         point = QVVector(gsl_multimin_fdfminimizer_x(minimizer));
00123 
00124         gsl_multimin_fdfminimizer_free (minimizer);
00125 
00126         gsl_vector_free (x);
00127 
00128         return (status == GSL_SUCCESS);
00129         }
00130 
00132 #include <QPair>
00133 double my_f_gradient (const gsl_vector *v, void *params)
00134         {
00135         return ((QPair< QVFunction<QVVector, double> *, QVFunction<QVVector, QVVector> *> *) params)->first->operator()(QVVector(v));
00136         }
00137         
00138 /* The gradient of f, df = (df/dx, df/dy). */
00139 void my_df_gradient (const gsl_vector *v, void *params, gsl_vector *df)
00140         {
00141         gsl_vector_memcpy(df, ((QPair< QVFunction<QVVector, double> *, QVFunction<QVVector, QVVector> *> *) params)->second->operator()(QVVector(v)));
00142         }
00143 
00144 /* Compute both f and df together. */
00145 void my_fdf_gradient (const gsl_vector *x, void *params, double *f, gsl_vector *df) 
00146         {
00147         *f = my_f_gradient(x, params); 
00148         my_df_gradient(x, params, df);
00149         }
00150 
00151 const bool qvGSLMinimizeFDF (   QVFunction<QVVector, double> & function, QVFunction<QVVector, QVVector> & gradientFunction,
00152                                 QVVector &point, const GSLMultiminFDFMinimizerType gslMinimizerAlgorithm,
00153                                 const int maxIterations, const double maxGradientNorm,
00154                                 const double step, const double tol)
00155         {
00156         const int dims = point.size();
00157         const gsl_multimin_fdfminimizer_type *minimizer_type = NULL;
00158         switch(gslMinimizerAlgorithm)
00159                 {
00160                 case ConjugateFR:       minimizer_type = gsl_multimin_fdfminimizer_conjugate_fr;        break;
00161                 case ConjugatePR:       minimizer_type = gsl_multimin_fdfminimizer_conjugate_pr;        break;
00162                 case VectorBFGS:        minimizer_type = gsl_multimin_fdfminimizer_vector_bfgs;         break;
00163                 case SteepestDescent:   minimizer_type = gsl_multimin_fdfminimizer_steepest_descent;    break;
00164                 }
00165 
00166         gsl_multimin_fdfminimizer *minimizer = gsl_multimin_fdfminimizer_alloc (minimizer_type, dims);
00167         QPair< QVFunction<QVVector, double> *, QVFunction<QVVector, QVVector> *> functions(&function, &gradientFunction);
00168 
00169         gsl_multimin_function_fdf my_func;
00170         my_func.n = dims;
00171         my_func.f = &my_f_gradient;
00172         my_func.df = &my_df_gradient;
00173         my_func.fdf = &my_fdf_gradient;
00174         my_func.params = &functions;
00175         
00176         gsl_vector *x = point;
00177 
00178         gsl_multimin_fdfminimizer_set (minimizer, &my_func, x, step, tol);
00179         
00180         int status = GSL_CONTINUE;
00181         for (int i = 0; status == GSL_CONTINUE && i < maxIterations; i++)
00182                 {
00183                 if ((status = gsl_multimin_fdfminimizer_iterate (minimizer)))
00184                         break;
00185         
00186                 status = gsl_multimin_test_gradient (gsl_multimin_fdfminimizer_gradient(minimizer), maxGradientNorm);
00187                 }
00188 
00189         // Store resulting value.
00190         point = QVVector(gsl_multimin_fdfminimizer_x(minimizer));
00191 
00192         gsl_multimin_fdfminimizer_free (minimizer);
00193 
00194         gsl_vector_free (x);
00195 
00196         return (status == GSL_SUCCESS);
00197         }
00198 
00199 



QVision framework. PARP research group, copyright 2007, 2008.