17#ifndef __math_gradient_descent_bb_h__
18#define __math_gradient_descent_bb_h__
38 template <
typename ValueType>
39 inline bool operator() (Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& newx,
const Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& x,
40 const Eigen::Matrix<ValueType, Eigen::Dynamic, 1>& g, ValueType step_size) {
41 assert (newx.size() == x.size());
42 assert (g.size() == x.size());
43 newx = x - step_size * g;
44 return !newx.isApprox(x);
49 template <
class Function,
class UpdateFunctor=LinearUpdateBB>
70 const Eigen::Matrix<value_type, Eigen::Dynamic, 1>& state ()
const {
return x2; }
71 const Eigen::Matrix<value_type, Eigen::Dynamic, 1>& gradient ()
const {
return g2; }
74 int function_evaluations ()
const {
return nfeval; }
76 void be_verbose (
bool v) {
verbose = v; }
77 void precondition (
const Eigen::Matrix<value_type, Eigen::Dynamic, 1>& weights) {
81 void run (
const size_t max_iterations = 1000,
83 std::streambuf* log_stream =
nullptr)
85 std::ostream log_os(log_stream? log_stream :
nullptr);
87 log_os <<
"#iteration" <<
delim <<
"feval" <<
delim <<
"cost" <<
delim <<
"stepsize";
88 for ( ssize_t a = 0 ; a <
x1.size() ; a++ )
90 for ( ssize_t a = 0 ; a <
x1.size() ; a++ )
92 log_os <<
"\n" << std::flush;
98 DEBUG (
"Gradient descent iteration: init; cost: " +
str(
f));
100 while (
niter < max_iterations) {
101 bool retval = iterate (log_os);
108 if (
normg < gradient_tolerance) {
110 CONSOLE (
"normg (" +
str(
normg) +
") < gradient tolerance (" +
str(gradient_tolerance) +
")");
116 CONSOLE (
"unchanged parameters");
123 std::ostream dummy (
nullptr);
127 void init (std::ostream& log_os) {
136 assert(std::isfinite(
normg)); assert(!std::isnan(
normg));
144 for (ssize_t i=0; i<
x2.size(); ++i){ log_os <<
delim <<
str(
x1(i)); }
145 for (ssize_t i=0; i<
x2.size(); ++i){ log_os <<
delim <<
str(
g1(i)); }
149 assert (std::isfinite(
f)); assert (!std::isnan(
f));
150 assert (std::isfinite (
normg)); assert (!std::isnan(
normg));
159 assert (std::isfinite (
f)); assert (!std::isnan(
f));
160 assert (std::isfinite(
normg)); assert (!std::isnan(
normg));
163 for (ssize_t i=0; i<
x2.size(); ++i){ log_os <<
delim <<
str(
x2(i)); }
164 for (ssize_t i=0; i<
x2.size(); ++i){ log_os <<
delim <<
str(
g2(i)); }
174 std::ostream dummy (
nullptr);
175 return iterate (dummy);
178 bool iterate (std::ostream& log_os) {
179 assert (std::isfinite (
normg));
191 for (ssize_t i=0; i<
x2.size(); ++i){ log_os <<
delim <<
str(
x2(i)); }
192 for (ssize_t i=0; i<
x2.size(); ++i){ log_os <<
delim <<
str(
g2(i)); }
212 if (!std::isfinite (cost))
213 throw Exception (
"cost function is NaN or Inf!");
216 CONSOLE (
" << newx = [ " +
str(newx.transpose()) +
"]");
217 CONSOLE (
" << newg = [ " +
str(newg.transpose()) +
"]");
227 assert((
g2-
g1).norm()>0.0);
Computes the minimum of a function using a Barzilai Borwein gradient descent approach....
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > x2
value_type evaluate_func(const Eigen::Matrix< value_type, Eigen::Dynamic, 1 > &newx, Eigen::Matrix< value_type, Eigen::Dynamic, 1 > &newg, bool verbose=false)
UpdateFunctor update_func
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > preconditioner_weights
void compute_normg_and_step()
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > g1
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > g3
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > g2
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > x3
Eigen::Matrix< value_type, Eigen::Dynamic, 1 > x1
bool operator()(Eigen::Matrix< ValueType, Eigen::Dynamic, 1 > &newx, const Eigen::Matrix< ValueType, Eigen::Dynamic, 1 > &x, const Eigen::Matrix< ValueType, Eigen::Dynamic, 1 > &g, ValueType step_size)
MR::default_type value_type
std::string str(const T &value, int precision=0)