Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_OPTIMIZATION_ARMIJO_PROJECTED_BACKTRACKING_H
00002 #define OPENTISSUE_CORE_MATH_OPTIMIZATION_ARMIJO_PROJECTED_BACKTRACKING_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_value_traits.h>
00013 #include <OpenTissue/core/math/math_is_number.h>
00014
00015 #include <OpenTissue/core/math/big/big_types.h>
00016 #include <OpenTissue/core/math/optimization/optimization_constants.h>
00017 #include <OpenTissue/core/math/optimization/optimization_stagnation.h>
00018 #include <OpenTissue/core/math/optimization/optimization_relative_convergence.h>
00019
00020 #include <stdexcept>
00021 #include <cassert>
00022
00023 namespace OpenTissue
00024 {
00025 namespace math
00026 {
00027 namespace optimization
00028 {
00029
00098 template < typename T, typename function_type, typename projection_operator >
00099 inline T armijo_projected_backtracking(
00100 function_type const & f
00101 , ublas::vector<T> const & nabla_f
00102 , ublas::vector<T> const & x
00103 , ublas::vector<T> & x_tau
00104 , ublas::vector<T> const & dx
00105 , T const & relative_tolerance
00106 , T const & stagnation_tolerance
00107 , T const & alpha
00108 , T const & beta
00109 , T & f_tau
00110 , size_t & status
00111 , projection_operator const & P
00112 )
00113 {
00114 using std::fabs;
00115 using std::max;
00116
00117 typedef OpenTissue::math::ValueTraits<T> value_traits;
00118
00119 T const TOO_TINY = ::boost::numeric_cast<T>(0.00001);
00120
00121 status = OK;
00122
00123 if(relative_tolerance < value_traits::zero() )
00124 throw std::invalid_argument("relative_tolerance must be non-negative");
00125
00126 if(stagnation_tolerance < value_traits::zero() )
00127 throw std::invalid_argument("stagnation_tolerance must be non-negative");
00128
00129 if (beta >= value_traits::one() )
00130 throw std::invalid_argument("Illegal beta value");
00131
00132 if (alpha <= value_traits::zero() )
00133 throw std::invalid_argument("Illegal alpha value");
00134
00135 if(beta<=alpha)
00136 throw std::invalid_argument("beta must be larger than alpha");
00137
00138 size_t const m = x.size();
00139
00140
00141 if(m==0)
00142 return value_traits::zero();
00143
00144 assert(x.size() == x_tau.size() || !"armijo_projected_backtracking(): x and x_tau have incompatible dimensions");
00145
00146
00147
00148
00149
00150
00151 T gamma = alpha*ublas::inner_prod( nabla_f, dx );
00152 assert( is_number( gamma ) || !"armijo_projected_backtracking(): internal error, NAN is encountered?");
00153
00154
00155 if( gamma >= value_traits::zero() )
00156 {
00157 status = NON_DESCENT_DIRECTION;
00158 x_tau.assign( x );
00159 return value_traits::zero();
00160 }
00161
00162
00163 T const f_0 = f_tau;
00164 T tau = value_traits::one();
00165
00166 x_tau = P(x + dx);
00167 f_tau = f(x_tau);
00168 assert( is_number( f_tau ) || !"armijo_projected_backtracking(): internal error, NAN is encountered?");
00169
00170
00171
00172
00173
00174 if(stagnation( x, x_tau, value_traits::zero() ) )
00175 {
00176 status = DESCEND_DIRECTION_IN_NORMAL_CONE;
00177 f_tau = f_0;
00178 x_tau.assign( x );
00179 return value_traits::zero();
00180 }
00181
00182 gamma = alpha*ublas::inner_prod( nabla_f, x_tau - x );
00183 assert( is_number( gamma ) || !"armijo_projected_backtracking(): internal error, NAN is encountered?");
00184
00185
00186 while( ( f_tau > (f_0 + gamma*tau ) ) && tau > TOO_TINY )
00187 {
00188 tau *= beta;
00189 assert( is_number( tau ) || !"armijo_projected_backtracking(): internal error, NAN is encountered?");
00190 x_tau = P( x + dx*tau );
00191 gamma = alpha*ublas::inner_prod( nabla_f, x_tau - x );
00192 assert( is_number( gamma ) || !"armijo_projected_backtracking(): internal error, NAN is encountered?");
00193 f_tau = f(x_tau);
00194 assert( is_number( f_tau ) || !"armijo_projected_backtracking(): internal error, NAN is encountered?");
00195 }
00196
00197
00198 if( (tau < TOO_TINY) && (f_tau > f_0))
00199 status = BACKTRACKING_FAILED;
00200
00201 if(stagnation( x, x_tau, stagnation_tolerance ) )
00202 status = STAGNATION;
00203
00204 if(relative_convergence(f_0,f_tau, relative_tolerance) )
00205 status = RELATIVE_CONVERGENCE;
00206
00207
00208 return tau;
00209 }
00210
00211 }
00212 }
00213 }
00214
00215
00216 #endif