Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_MATH_OPTIMIZATION_ARMIJO_BACKTRACKING_H
00002 #define OPENTISSUE_CORE_MATH_OPTIMIZATION_ARMIJO_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 {
00077 template < typename T, typename function_type >
00078 inline T armijo_backtracking(
00079 function_type const & f
00080 , ublas::vector<T> const & nabla_f
00081 , ublas::vector<T> const & x
00082 , ublas::vector<T> & x_tau
00083 , ublas::vector<T> const & dx
00084 , T const & relative_tolerance
00085 , T const & stagnation_tolerance
00086 , T const & alpha
00087 , T const & beta
00088 , T & f_tau
00089 , size_t & status
00090 )
00091 {
00092 using std::fabs;
00093 using std::max;
00094
00095 typedef OpenTissue::math::ValueTraits<T> value_traits;
00096
00097 T const TOO_TINY = ::boost::numeric_cast<T>(0.00001);
00098
00099 status = OK;
00100
00101 if(relative_tolerance < value_traits::zero() )
00102 throw std::invalid_argument("relative_tolerance must be non-negative");
00103 if(stagnation_tolerance < value_traits::zero() )
00104 throw std::invalid_argument("stagnation_tolerance must be non-negative");
00105 if (beta >= value_traits::one() )
00106 throw std::invalid_argument("Illegal beta value");
00107 if (alpha <= value_traits::zero() )
00108 throw std::invalid_argument("Illegal alpha value");
00109 if(beta<=alpha)
00110 throw std::invalid_argument("beta must be larger than alpha");
00111
00112 size_t const m = x.size();
00113
00114
00115 if(m==0)
00116 return value_traits::zero();
00117
00118 assert(x.size() == x_tau.size() || !"armijo_backtracking(): x and x_tau have incompatible dimensions");
00119
00120
00121 T const f_0 = f_tau;
00122 T tau = value_traits::one();
00123 x_tau = x + dx;
00124 f_tau = f(x_tau);
00125
00126 assert( is_number( f_tau ) || !"armijo_backtracking(): internal error, NAN is encountered?");
00127
00128 T gamma = alpha*ublas::inner_prod( nabla_f, dx );
00129
00130 assert( is_number( gamma ) || !"armijo_backtracking(): internal error, NAN is encountered?");
00131
00132
00133 if( gamma >= value_traits::zero() )
00134 {
00135 status = NON_DESCENT_DIRECTION;
00136 f_tau = f_0;
00137 x_tau.assign( x );
00138 return value_traits::zero();
00139 }
00140
00141
00142 while( ( f_tau > (f_0 + gamma*tau ) ) && tau > TOO_TINY )
00143 {
00144 tau *= beta;
00145 assert( is_number( tau ) || !"armijo_backtracking(): internal error, NAN is encountered?");
00146 x_tau = x + dx*tau;
00147 f_tau = f(x_tau);
00148 assert( is_number( f_tau ) || !"armijo_backtracking(): internal error, NAN is encountered?");
00149 }
00150
00151
00152 if( (tau < TOO_TINY) && (f_tau > f_0))
00153 status = BACKTRACKING_FAILED;
00154
00155 if(stagnation( x, x_tau, stagnation_tolerance ) )
00156 status = STAGNATION;
00157
00158 if(relative_convergence(f_0,f_tau, relative_tolerance) )
00159 status = RELATIVE_CONVERGENCE;
00160
00161
00162 return tau;
00163 }
00164
00165 }
00166 }
00167 }
00168
00169
00170 #endif