// Copyright (C) 2008 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_OPTIMIZATIOn_STOP_STRATEGIES_H_ #define DLIB_OPTIMIZATIOn_STOP_STRATEGIES_H_ #include #include #include "../matrix.h" #include "../algs.h" #include "optimization_stop_strategies_abstract.h" #include namespace dlib { // ---------------------------------------------------------------------------------------- class objective_delta_stop_strategy { public: explicit objective_delta_stop_strategy ( double min_delta = 1e-7 ) : _verbose(false), _been_used(false), _min_delta(min_delta), _max_iter(0), _cur_iter(0), _prev_funct_value(0) { DLIB_ASSERT ( min_delta >= 0, "\t objective_delta_stop_strategy(min_delta)" << "\n\t min_delta can't be negative" << "\n\t min_delta: " << min_delta ); } objective_delta_stop_strategy ( double min_delta, unsigned long max_iter ) : _verbose(false), _been_used(false), _min_delta(min_delta), _max_iter(max_iter), _cur_iter(0), _prev_funct_value(0) { DLIB_ASSERT ( min_delta >= 0 && max_iter > 0, "\t objective_delta_stop_strategy(min_delta, max_iter)" << "\n\t min_delta can't be negative and max_iter can't be 0" << "\n\t min_delta: " << min_delta << "\n\t max_iter: " << max_iter ); } objective_delta_stop_strategy& be_verbose( ) { _verbose = true; return *this; } template bool should_continue_search ( const T& , const double funct_value, const T& ) { if (_verbose) { using namespace std; cout << "iteration: " << _cur_iter << " objective: " << funct_value << endl; } ++_cur_iter; if (_been_used) { // Check if we have hit the max allowable number of iterations. (but only // check if _max_iter is enabled (i.e. not 0)). if (_max_iter != 0 && _cur_iter > _max_iter) return false; // check if the function change was too small if (std::abs(funct_value - _prev_funct_value) < _min_delta) return false; } _been_used = true; _prev_funct_value = funct_value; return true; } private: bool _verbose; bool _been_used; double _min_delta; unsigned long _max_iter; unsigned long _cur_iter; double _prev_funct_value; }; // ---------------------------------------------------------------------------------------- class gradient_norm_stop_strategy { public: explicit gradient_norm_stop_strategy ( double min_norm = 1e-7 ) : _verbose(false), _min_norm(min_norm), _max_iter(0), _cur_iter(0) { DLIB_ASSERT ( min_norm >= 0, "\t gradient_norm_stop_strategy(min_norm)" << "\n\t min_norm can't be negative" << "\n\t min_norm: " << min_norm ); } gradient_norm_stop_strategy ( double min_norm, unsigned long max_iter ) : _verbose(false), _min_norm(min_norm), _max_iter(max_iter), _cur_iter(0) { DLIB_ASSERT ( min_norm >= 0 && max_iter > 0, "\t gradient_norm_stop_strategy(min_norm, max_iter)" << "\n\t min_norm can't be negative and max_iter can't be 0" << "\n\t min_norm: " << min_norm << "\n\t max_iter: " << max_iter ); } gradient_norm_stop_strategy& be_verbose( ) { _verbose = true; return *this; } template bool should_continue_search ( const T& , const double funct_value, const T& funct_derivative ) { if (_verbose) { using namespace std; cout << "iteration: " << _cur_iter << " objective: " << funct_value << " gradient norm: " << length(funct_derivative) << endl; } ++_cur_iter; // Check if we have hit the max allowable number of iterations. (but only // check if _max_iter is enabled (i.e. not 0)). if (_max_iter != 0 && _cur_iter > _max_iter) return false; // check if the gradient norm is too small if (length(funct_derivative) < _min_norm) return false; return true; } private: bool _verbose; double _min_norm; unsigned long _max_iter; unsigned long _cur_iter; }; // ---------------------------------------------------------------------------------------- } #endif // DLIB_OPTIMIZATIOn_STOP_STRATEGIES_H_