00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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
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
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