Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
joptimization.hpp
Go to the documentation of this file.
00001 /* $Id$ */
00010 #ifndef JMATH_JOPTIMIZATION_HPP
00011 #define JMATH_JOPTIMIZATION_HPP
00012 
00013 #ifdef USE_JMATH_SERIALIZATION
00014 #include "jmath/serialize_vector.hpp"
00015 #include "jmath/serialize_matrix.hpp"
00016 #include "jmath/serialize_symmetric.hpp"
00017 #include "jmath/serialize_banded.hpp"
00018 #else
00019 #include "boost/numeric/ublas/vector.hpp"
00020 #include "boost/numeric/ublas/matrix.hpp"
00021 #include "boost/numeric/ublas/symmetric.hpp"
00022 #include "boost/numeric/ublas/banded.hpp"
00023 #endif
00024 
00025 #include "boost/numeric/ublas/io.hpp"
00026 
00027 #include "boost/numeric/ublas/matrix_proxy.hpp"
00028 #include "boost/numeric/ublas/vector_proxy.hpp"
00029 
00030 #include "jmath/ublasCompatibility.hpp"
00031 
00032 #include "boost/numeric/bindings/lapack/gesv.hpp"
00033 #include "boost/numeric/bindings/traits/ublas_matrix.hpp"
00034 #include "boost/numeric/bindings/traits/ublas_vector.hpp"
00035 
00038 
00039 namespace ublas = boost::numeric::ublas;
00041 namespace lapack = boost::numeric::bindings::lapack;
00042 
00043 // Declaration
00044 namespace joptimization {
00045   namespace methods {
00050     template< class _TFunction_, typename _TType_ >
00051     struct GaussNewton {
00052       typedef _TType_ Type;
00053       typedef _TFunction_ Function;
00054       static void computeM(const ublas::matrix<_TType_>& jacobian, 
00055                            const _TFunction_* f, 
00056                            ublas::vector<_TType_>& parameters, 
00057                            ublas::vector<_TType_>& values, 
00058                            ublas::matrix<_TType_>& M);
00059     };
00060 
00066     template< class _TFunction_, typename _TType_ >
00067     struct Newton {
00068       typedef _TType_ Type;
00069       typedef _TFunction_ Function;
00070       static void computeM(const ublas::matrix<_TType_>& jacobian, 
00071                            const _TFunction_* f, 
00072                            ublas::vector<_TType_>& parameters, 
00073                            ublas::vector<_TType_>& values, 
00074                            ublas::matrix<_TType_>& M);
00075     };
00076   }
00077 
00167   namespace algorithms {
00177     template< class _TFunction_, typename _TType_  >
00178     _TType_ gradientDescent(_TFunction_* f, 
00179                             ublas::vector<_TType_>& parameters, 
00180                             int iter, 
00181                             _TType_ epsilon, 
00182                             _TType_ gamma);
00191     template< class _TMethod_ >
00192     typename _TMethod_::Type gaussNewton(typename _TMethod_::Function* f, 
00193                                          ublas::vector<typename _TMethod_::Type>& parameters, 
00194                                          int iter, 
00195                                          typename _TMethod_::Type epsilon);
00206     template< class _TFunction_, typename _TType_  >
00207     _TType_ levenbergMarquardt(_TFunction_* f, 
00208                                ublas::vector<_TType_>& parameters, 
00209                                int iter, 
00210                                _TType_ epsilon, 
00211                                _TType_ lambda0, 
00212                                _TType_ nu);
00213   }
00214 }
00215 // Implementation
00216 namespace optimization {
00217   namespace details { // Private functions used by the algorithms
00218     // Compute the remain
00219     template<typename _TType_>
00220     double computeRemain(const ublas::vector<_TType_>& values) {
00221       _TType_ remain = 0.0;
00222       for(unsigned-int j = 0; j < values.size(); j++)
00223       {
00224         _TType_ v = values[j];
00225         remain += v * v;
00226       }
00227       return sqrt(remain / values.size() );
00228     }
00229     // Solve (common to levenbergMarquardt and gaussNewton
00230     template<typename _TType_>
00231     ublas::vector<double> solve(const ublas::matrix<_TType_>& M, 
00232                                 const ublas::matrix<_TType_>& jacobian, 
00233                                 const ublas::vector<_TType_>& values, 
00234                                 int p_count) {
00235       ublas::matrix<_TType_> MD(M.size1(),M.size2());
00236       MD = M;
00237       // Solve the linear system
00238 //       jblas::ilut_precond< ublas::matrix<_TType_> > P(M, 10, 1e-4);
00239 //       jblas::iteration iter(1E-8);  // defines an iteration object, with a max residu of 1E-8
00240       ublas::vector<_TType_> B(p_count); // Unknown and left hand side.
00241       B = ublas::prec_prod(ublas::trans(jacobian), values);
00242       B = B * -1.0;
00243       //jblas::lu_solve(MD, X, B);
00244       int ierr = lapack::gesv(MD, B); 
00245       if (ierr!=0) {
00246         throw(jmath::LapackException(ierr, 
00247                                      "joptimization::dtails::solve: error in lapack::gesv() routine",
00248                                      __FILE__,
00249                                      __LINE__));
00250       }
00251        
00252 //       std::cout << " M = " << M << endl;
00253 //       std::cout << " Values= " << values << endl;
00254 //       std::cout << " B = " << B << endl;
00255 //       iter.set_maxiter(250);
00256 //       jblas::gmres(M, X, B, P, 50, iter);  // execute the GMRES algorithm
00257 //       jblas::qmr(M, X, B, P, iter);  // execute the GMRES algorithm
00258 /*      std::cout << " B = " << B << endl;
00259       std::cout << " X = " << X << endl;*/
00260 //       ublas::vector<_TType_> tmp(p_count);
00261 //       tmp = ublas::prec_prod(M, X);
00262 //       tmp = -1.0 * tmp;
00263 //       //add(tmp,B);
00264 //       B = tmp + B;
00265 //       std::cout << " M * X - B = " << X << endl;
00266       // Update
00267       return B;
00268     }
00269   }
00270   namespace methods {
00271     template< class _TFunction_, typename _TType_ >
00272     void GaussNewton< _TFunction_, _TType_ >::computeM(const ublas::matrix<_TType_>& jacobian, 
00273                                                        const _TFunction_* f, 
00274                                                        ublas::vector<_TType_>& parameters, 
00275                                                        ublas::vector<_TType_>& values, 
00276                                                        ublas::matrix<_TType_> &M) {
00277       M = ublas::prec_prod( ublas::trans(jacobian), jacobian);
00278     }
00279     template< class _TFunction_, typename _TType_ >
00280     void Newton< _TFunction_, _TType_ >::computeM(const ublas::matrix<_TType_>& jacobian, 
00281                                                   const _TFunction_* f, 
00282                                                   ublas::vector<_TType_>& parameters, 
00283                                                   ublas::vector<_TType_>& values, 
00284                                                   ublas::matrix<_TType_> &M) {
00285       M = ublas::prec_prod( ublas::trans(jacobian), jacobian);
00286       // Compute the sum hessian
00287       for(int i = 0; i < f->count(); i++) {
00288         ublas::matrix< _TType_ > hessian = f->hessian( parameters,i);
00289         hessian = values[0] * hessian;
00290         //add( hessian, M);
00291         M = hessian + M;
00292       }
00293     }
00294   }
00295   namespace algorithms {
00296     // Gradient descent
00297     template< class _TFunction_, typename _TType_  >
00298     _TType_ gradientDescent(_TFunction_* f, 
00299                             ublas::vector<_TType_>& parameters, 
00300                             int iter, 
00301                             _TType_ epsilon, 
00302                             _TType_ gamma) {
00303       int p_count = parameters.size();
00304       int f_count = f->count();
00305       for(int i = 0; i < iter; i++) {
00306         // Compute the values
00307         ublas::vector<_TType_> values = f->values(parameters);
00308         // Compute the remaining
00309         _TType_ remain = details::computeRemain(values);
00310         JFR_DEBUG("Iteration " << i << ", error : " << remain << std::endl);
00311         if(remain < epsilon) {
00312           return remain;
00313         }
00314         // Compute the jacobian
00315         ublas::matrix<_TType_> jacobian = f->jacobian(parameters);
00316   //       std::cout << "jacobian = " << jacobian << " values " << values << std::endl;
00317   //       std::cout << "parameters = " << parameters << std::endl;
00318         // update
00319         for(int j = 0; j < p_count; j++) {
00320           double update = 0.0;
00321           for(int i = 0; i < f_count; i++) {
00322             update += values[i] * jacobian(i,j);
00323           }
00324   //         std::cout << " update = " << update << " j = " << j << endl;
00325           parameters[j] -=  update * gamma;
00326         }
00327         JFR_DEBUG("parameters = " << parameters << std::endl);
00328       }
00329       return details::computeRemain(f->values(parameters));
00330     }
00331     // Gauss-Newton
00332     template< class _TMethod_ >
00333     typename _TMethod_::Type gaussNewton(typename _TMethod_::Function* f, 
00334                                          ublas::vector<typename _TMethod_::Type>& parameters, 
00335                                          int iter, 
00336                                          typename _TMethod_::Type epsilon) {
00337       int p_count = parameters.size();
00338       int f_count = f->count();
00339       for(int i = 0; i < iter; i++) {
00340         // Compute the values
00341         ublas::vector<typename _TMethod_::Type> values = f->values(parameters);
00342         // Compute the remaining
00343         typename _TMethod_::Type remain = details::computeRemain(values);
00344         JFR_DEBUG("Iteration " << i << ", error : " << remain << std::endl);
00345         if(remain < epsilon) {
00346           return remain;
00347         }
00348         // Compute the jacobian
00349         ublas::matrix<typename _TMethod_::Type> jacobian = f->jacobian(parameters);
00350   //       std::cout << "Jacobian = " << jacobian << endl;
00351   //       std::cout << "Transposed Jacobian = " << ublas::trans(jacobian) << endl;
00352         ublas::matrix<typename _TMethod_::Type> M(jacobian.size2(), jacobian.size2());
00353         _TMethod_::computeM(jacobian, f, parameters, values, M);
00354         ublas::vector<typename _TMethod_::Type> X = details::solve(M, jacobian, values, p_count);
00355         //add(X, parameters);
00356         X = X + parameters;
00357         JFR_DEBUG(" Parameters " << parameters << endl);
00358       }
00359       return details::computeRemain(f->values(parameters));
00360     }
00361     template< class _TFunction_, typename _TType_  >
00362     _TType_ levenbergMarquardt(_TFunction_* f, 
00363                                ublas::vector<_TType_>& parameters, 
00364                                int iter, 
00365                                _TType_ epsilon, 
00366                                _TType_ lambda0, 
00367                                _TType_ nu) {
00368       int p_count = parameters.size();
00369 //       int f_count = f->count();
00370       _TType_ lambda = lambda0 / nu;
00371       _TType_ invnu = 1.0 / nu;
00372       if(nu < invnu) {
00373         double t = nu;
00374         nu = invnu;
00375         invnu = t;
00376       }
00377         // Compute the values
00378       ublas::vector<_TType_> values = f->values(parameters);
00379         // Compute the remaining
00380       _TType_ previousremain = details::computeRemain(f->values(parameters));
00381       // optimization
00382       for(int i = 0; i < iter; i++) {
00383         if(previousremain < epsilon) {
00384           return previousremain;
00385         }
00386         // Compute the jacobian
00387         ublas::matrix<_TType_> jacobian = f->jacobian(parameters);
00388   //       std::cout << "Jacobian = " << jacobian << endl;
00389   //       std::cout << "Transposed Jacobian = " << ublas::trans(jacobian) << endl;
00390         ublas::matrix<_TType_> M(jacobian.size2(), jacobian.size2());
00391         M = ublas::prec_prod( ublas::trans(jacobian), jacobian);
00392         
00393         // Compute lambda * identity
00394         ublas::identity_matrix<_TType_> M2(jacobian.size2());
00395         M2 = M2 * -lambda;
00396         // substract it to M
00397         //add(M, M2);
00398         M = M + M2; 
00399 //         std::cout << M2 << std::endl;
00400 /*        std::cout << std::endl << "[[";
00401         for(unsigned-int m = 0; m < M2.size1(); m++)
00402         {
00403           for(unsigned-int n = 0; n < M2.size2(); n++)
00404           {
00405             std::cout << M2(n,m) << " ";
00406           }
00407           std::cout << "];[";
00408         }
00409         std::cout << std::endl;
00410         std::cout << std::endl;*/
00411         ublas::vector<_TType_> X = details::solve(M2, jacobian, values, p_count);
00412         // Compute the update
00413         ublas::vector<double> newparameters = parameters;
00414         //add(X, newparameters);        
00415         X = X + newparameters;
00416         ublas::vector<_TType_> newvalues = f->values(newparameters);
00417         double newremain = details::computeRemain(newvalues);
00418         // Check if the update is an improvement
00419         JFR_DEBUG( "Iteration " << i << ", error : " << previousremain << ", new error " << newremain << ", lambda : "<< lambda << std::endl );
00420         if(newremain < previousremain) {
00421           parameters = newparameters;
00422           values = newvalues;
00423           previousremain = newremain;
00424           lambda *= invnu;
00425 //           lambda = lambda0;
00426         } else {
00427           lambda *= nu;
00428         }
00429         if(lambda == 0.0 or lambda >= 1.0e200) {
00430           lambda = lambda0;
00431 //           return previousremain;
00432         }
00433         JFR_DEBUG(" Parameters " << parameters << endl);
00434       }
00435       return details::computeRemain(f->values(parameters));
00436     }
00437   }
00438 }
00439 
00440 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:21 for Jafar by doxygen 1.7.6.1
LAAS-CNRS