00001 #ifndef OPENTISSUE_CORE_MATH_OPTIMIZATION_NON_SMOOTH_NEWTON_H
00002 #define OPENTISSUE_CORE_MATH_OPTIMIZATION_NON_SMOOTH_NEWTON_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/big/big_prod_add_rhs.h>
00014 #include <OpenTissue/core/math/big/big_shur_system.h>
00015 #include <OpenTissue/core/math/big/big_prod_trans.h>
00016
00017 #include <OpenTissue/core/math/optimization/non_smooth_newton/optimization_compute_inverse_D.h>
00018 #include <OpenTissue/core/math/optimization/non_smooth_newton/optimization_compute_jacobian.h>
00019 #include <OpenTissue/core/math/optimization/non_smooth_newton/optimization_compute_partitioned_jacobian.h>
00020 #include <OpenTissue/core/math/optimization/optimization_compute_generalized_minimal_map.h>
00021
00022 #include <OpenTissue/core/math/optimization/optimization_armijo_backtracking.h>
00023 #include <OpenTissue/core/math/optimization/optimization_compute_natural_merit.h>
00024 #include <OpenTissue/core/math/optimization/optimization_compute_index_reordering.h>
00025 #include <OpenTissue/core/math/optimization/optimization_compute_index_sets.h>
00026 #include <OpenTissue/core/math/optimization/optimization_agglomerate_vector.h>
00027 #include <OpenTissue/core/math/optimization/optimization_partition_vector.h>
00028 #include <OpenTissue/core/math/optimization/optimization_absolute_convergence.h>
00029
00030 #include <OpenTissue/core/math/math_value_traits.h>
00031 #include <OpenTissue/core/math/math_is_number.h>
00032 #include <cmath>
00033 #include <stdexcept>
00034 #include <cassert>
00035
00036 namespace OpenTissue
00037 {
00038 namespace math
00039 {
00040 namespace optimization
00041 {
00042
00043 namespace detail
00044 {
00045
00046 template<typename T, typename bound_function_type>
00047 class ThetaFunctor
00048 {
00049 protected:
00050
00051 ublas::compressed_matrix<T> const & m_A;
00052 ublas::vector<T> const & m_b;
00053 bound_function_type const & m_l;
00054 bound_function_type const & m_u;
00055 ublas::vector<T> & m_H;
00056 ublas::vector<T> & m_y;
00057
00058 public:
00059
00060 ThetaFunctor(
00061 ublas::compressed_matrix<T> const & A
00062 , ublas::vector<T> const & b
00063 , bound_function_type const & l
00064 , bound_function_type const & u
00065 , ublas::vector<T> & H
00066 , ublas::vector<T> & y
00067 )
00068 : m_A(A)
00069 , m_b(b)
00070 , m_l(l)
00071 , m_u(u)
00072 , m_H(H)
00073 , m_y(y)
00074 {}
00075
00076 T operator()( ublas::vector<T> const & x ) const
00077 {
00078 OpenTissue::math::big::prod_add_rhs(m_A,x,m_b,m_y);
00079 compute_generalized_minimal_map(m_y,m_l,m_u,x,m_H);
00080 return compute_natural_merit(m_H);
00081 }
00082
00083 };
00084
00085 template<typename T, typename bound_function_type>
00086 class NablaThetaFunctor
00087 {
00088 protected:
00089
00090 ublas::compressed_matrix<T> const & m_A;
00091 ublas::vector<T> const & m_b;
00092 bound_function_type const & m_l;
00093 bound_function_type const & m_u;
00094 ublas::vector<T> & m_H;
00095 ublas::vector<T> & m_y;
00096
00097 public:
00098
00099 NablaThetaFunctor(
00100 ublas::compressed_matrix<T> const & A
00101 , ublas::vector<T> const & b
00102 , bound_function_type const & l
00103 , bound_function_type const & u
00104 , ublas::vector<T> & H
00105 , ublas::vector<T> & y
00106 )
00107 : m_A(A)
00108 , m_b(b)
00109 , m_l(l)
00110 , m_u(u)
00111 , m_H(H)
00112 , m_y(y)
00113 {}
00114
00115 ublas::vector<T> operator()( ublas::vector<T> const & x )
00116 {
00117 OpenTissue::math::big::prod_add_rhs(m_A,x,m_b,m_y);
00118 compute_generalized_minimal_map(m_y,m_l,m_u,x,m_H);
00119
00120 ublas::vector<size_t> bitmask;
00121 size_t cnt_active = 0;
00122 size_t cnt_inactive = 0;
00123
00124 compute_index_sets( m_y, x, m_l, m_u, bitmask, cnt_active, cnt_inactive );
00125
00126 ublas::compressed_matrix<T> J;
00127 detail::compute_jacobian( m_A, m_l, m_u, bitmask, J );
00128
00129 ublas::vector<T> nabla_theta;
00130 nabla_theta.resize(x.size(), false);
00131
00132 OpenTissue::math::big::prod_trans(J, m_H, nabla_theta);
00133
00134 return nabla_theta;
00135 }
00136
00137 };
00138
00139
00140 }
00141
00210 template < typename T, typename bound_function_type, typename solver_function_type>
00211 inline void non_smooth_newton(
00212 ublas::compressed_matrix<T> const & A
00213 , ublas::vector<T> const & b
00214 , bound_function_type const & l
00215 , bound_function_type const & u
00216 , boost::numeric::ublas::vector<T> & x
00217 , size_t const & max_iterations
00218 , T const & absolute_tolerance
00219 , T const & relative_tolerance
00220 , T const & stagnation_tolerance
00221 , size_t & status
00222 , size_t & iteration
00223 , T & accuracy
00224 , T const & alpha
00225 , T const & beta
00226 , solver_function_type const & sub_system_solver
00227 , bool const & use_shur = true
00228 , ublas::vector<T> * profiling = 0
00229 )
00230 {
00231 using std::fabs;
00232 using std::min;
00233 using std::max;
00234
00235 typedef ublas::compressed_matrix<T> matrix_type;
00236 typedef ublas::vector<T> vector_type;
00237 typedef T real_type;
00238 typedef OpenTissue::math::ValueTraits<T> value_traits;
00239
00240 if(max_iterations <= 0)
00241 throw std::invalid_argument("max_iterations must be larger than zero");
00242 if(absolute_tolerance < value_traits::zero() )
00243 throw std::invalid_argument("absolute_tolerance must be non-negative");
00244 if(relative_tolerance < value_traits::zero() )
00245 throw std::invalid_argument("relative_tolerance must be non-negative");
00246 if(stagnation_tolerance < value_traits::zero() )
00247 throw std::invalid_argument("stagnation_tolerance must be non-negative");
00248 if (beta >= value_traits::one() )
00249 throw std::invalid_argument("Illegal beta value");
00250 if (alpha <= value_traits::zero() )
00251 throw std::invalid_argument("Illegal alpha value");
00252 if(beta<=alpha)
00253 throw std::invalid_argument("beta must be larger than alpha");
00254 if(profiling == &x)
00255 throw std::logic_error("profiling must not point to x-vector");
00256 if(profiling == &b)
00257 throw std::logic_error("profiling must not point to b-vector");
00258
00259 status = OK;
00260
00261 size_t const m = b.size();
00262 if(m==0)
00263 return;
00264
00265 if(x.size()<=0)
00266 throw std::invalid_argument("size of x-vector were zero");
00267
00268
00269 vector_type rhs(m);
00270 vector_type H(m);
00271 vector_type dx(m);
00272 vector_type x_old(m);
00273 vector_type y(m);
00274 ublas::vector<size_t> bitmask;
00275 ublas::vector<size_t> old2new;
00276 ublas::vector<size_t> new2old;
00277 matrix_type A_aa;
00278 matrix_type A_ab;
00279 matrix_type C;
00280 matrix_type D;
00281 vector_type rhs_a;
00282 vector_type rhs_b;
00283 vector_type dx_a;
00284 vector_type dx_b;
00285 matrix_type J;
00286
00287 detail::ThetaFunctor<real_type,bound_function_type> theta(A, b, l, u, H, y);
00288 detail::NablaThetaFunctor<real_type,bound_function_type> nabla_theta(A, b, l, u, H, y);
00289
00290
00291 accuracy = theta(x);
00292 iteration = 0;
00293 status = ITERATING;
00294
00295 if(profiling)
00296 {
00297 (*profiling).resize( max_iterations );
00298 (*profiling).clear();
00299 }
00300 for (; iteration < max_iterations; )
00301 {
00302 if(profiling)
00303 (*profiling)(iteration) = accuracy;
00304 ++iteration;
00305
00306 if( absolute_convergence( accuracy, absolute_tolerance) )
00307 {
00308 status = ABSOLUTE_CONVERGENCE;
00309 return;
00310 }
00311
00312 ublas::noalias(rhs) = -H;
00313 size_t cnt_active = 0;
00314 size_t cnt_inactive = 0;
00315 compute_index_sets( y, x, l, u, bitmask, cnt_active, cnt_inactive );
00316 if(use_shur)
00317 {
00318 compute_index_reordering( bitmask, old2new, new2old );
00319 detail::compute_partitioned_jacobian( A, l, u,bitmask, old2new, cnt_active, cnt_inactive, A_aa, A_ab, C, D);
00320 partition_vector( rhs, bitmask, old2new, cnt_active, cnt_inactive, rhs_a, rhs_b );
00321
00322
00323
00324
00325
00326
00327
00328 detail::compute_inverse_D( D );
00329
00330
00331
00332
00333 OpenTissue::math::big::shur_system( A_aa, A_ab, C, D, rhs_a, rhs_b, dx_a, dx_b, sub_system_solver);
00334 agglomerate_vector(dx_a, dx_b, new2old, dx);
00335 }
00336 else
00337 {
00338 detail::compute_jacobian( A, l, u, bitmask, J );
00339 sub_system_solver( J, dx, rhs );
00340 }
00341
00342 vector_type grad = nabla_theta(x);
00343 x_old = x;
00344
00345 armijo_backtracking(
00346 theta
00347 , grad
00348 , x_old
00349 , x
00350 , dx
00351 , relative_tolerance
00352 , stagnation_tolerance
00353 , alpha
00354 , beta
00355 , accuracy
00356 , status
00357 );
00358
00359 if( status != OK )
00360 return;
00361 status = ITERATING;
00362
00363 }
00364 }
00365
00366 }
00367 }
00368 }
00369
00370
00371 #endif