Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_OPTIMIZATION_PROJECTED_BFGS_H
00002 #define OPENTISSUE_CORE_MATH_OPTIMIZATION_PROJECTED_BFGS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/big/big_types.h>
00013 #include <OpenTissue/core/math/optimization/optimization_bfgs.h>
00014 #include <OpenTissue/core/math/optimization/optimization_constants.h>
00015 #include <OpenTissue/core/math/optimization/optimization_armijo_projected_backtracking.h>
00016 #include <OpenTissue/core/math/optimization/optimization_stationary_point.h>
00017 #include <OpenTissue/core/math/optimization/optimization_absolute_convergence.h>
00018
00019 #include <OpenTissue/core/math/math_value_traits.h>
00020 #include <OpenTissue/core/math/math_is_number.h>
00021
00022 #include <cmath>
00023 #include <stdexcept>
00024 #include <cassert>
00025
00026 namespace OpenTissue
00027 {
00028 namespace math
00029 {
00030 namespace optimization
00031 {
00032
00054 template <
00055 typename T
00056 , typename function_functor
00057 , typename gradient_functor
00058 , typename projection_operator
00059 >
00060 inline void projected_bfgs(
00061 function_functor & f
00062 , gradient_functor & nabla_f
00063 , ublas::compressed_matrix<T> & H
00064 , boost::numeric::ublas::vector<T> & x
00065 , projection_operator const & P
00066 , size_t const & max_iterations
00067 , T const & absolute_tolerance
00068 , T const & relative_tolerance
00069 , T const & stagnation_tolerance
00070 , size_t & status
00071 , size_t & iteration
00072 , T & error
00073 , T const & alpha
00074 , T const & beta
00075 , ublas::vector<T> * profiling = 0
00076 )
00077 {
00078 using std::fabs;
00079 using std::min;
00080 using std::max;
00081
00082 typedef ublas::compressed_matrix<T> matrix_type;
00083 typedef ublas::vector<T> vector_type;
00084 typedef T real_type;
00085 typedef OpenTissue::math::ValueTraits<T> value_traits;
00086
00087 if(max_iterations <= 0)
00088 throw std::invalid_argument("max_iterations must be larger than zero");
00089 if(absolute_tolerance < value_traits::zero() )
00090 throw std::invalid_argument("absolute_tolerance must be non-negative");
00091 if(relative_tolerance < value_traits::zero() )
00092 throw std::invalid_argument("relative_tolerance must be non-negative");
00093 if(stagnation_tolerance < value_traits::zero() )
00094 throw std::invalid_argument("stagnation_tolerance must be non-negative");
00095 if (beta >= value_traits::one() )
00096 throw std::invalid_argument("Illegal beta value");
00097 if (alpha <= value_traits::zero() )
00098 throw std::invalid_argument("Illegal alpha value");
00099 if(beta<=alpha)
00100 throw std::invalid_argument("beta must be larger than alpha");
00101 if(profiling == &x)
00102 throw std::logic_error("profiling must not point to x-vector");
00103
00104 error = value_traits::infinity();
00105 iteration = 0;
00106
00107 status = OK;
00108
00109 size_t const m = x.size();
00110 if(m==0)
00111 return;
00112
00113 status = ITERATING;
00114
00115 if(profiling)
00116 {
00117 (*profiling).resize( max_iterations );
00118 (*profiling).clear();
00119 }
00120
00121
00122 vector_type y_k;
00123 vector_type s_k;
00124 vector_type dx;
00125 vector_type x_old;
00126 vector_type nabla_f_k;
00127 vector_type nabla_f_k1;
00128
00129
00130 y_k.resize(m);
00131 s_k.resize(m);
00132 dx.resize(m);
00133 x_old.resize(m);
00134 nabla_f_k.resize(m);
00135 nabla_f_k1.resize(m);
00136
00137
00138
00139 x = P(x);
00140 real_type f_0 = f(x);
00141 ublas::noalias( nabla_f_k ) = nabla_f(x);
00142
00143
00144 for (; iteration < max_iterations; ++iteration)
00145 {
00146 if(profiling)
00147 (*profiling)(iteration) = f_0;
00148
00149
00150 if(stationary_point( nabla_f_k, absolute_tolerance, error ) )
00151 {
00152 status = ABSOLUTE_CONVERGENCE;
00153 return;
00154 }
00155
00156
00157
00158 ublas::axpy_prod(H, -nabla_f_k, dx, true);
00159
00160 x_old.assign( x );
00161 real_type f_tau = f_0;
00162 armijo_projected_backtracking(
00163 f
00164 , nabla_f_k
00165 , x_old
00166 , x
00167 , dx
00168 , relative_tolerance
00169 , stagnation_tolerance
00170 , alpha
00171 , beta
00172 , f_tau
00173 , status
00174 , P
00175 );
00176
00177 if(status != OK )
00178 return;
00179
00180
00181 ublas::noalias( nabla_f_k1 ) = nabla_f(x);
00182 ublas::noalias( s_k ) = x - x_old;
00183 ublas::noalias( y_k ) = nabla_f_k1 - nabla_f_k;
00184
00185 detail::bfgs_update_inverse_hessian(y_k,s_k,H);
00186
00187
00188 f_0 = f_tau;
00189 nabla_f_k.assign( nabla_f_k1 );
00190
00191 }
00192 }
00193
00194 }
00195 }
00196 }
00197
00198
00199 #endif