Program Listing for File gradient_descent.hpp#
↰ Return to documentation for file (source/pele/gradient_descent.hpp)
#ifndef _PELE_GD_H__
#define _PELE_GD_H__
#include <memory>
#include <pele/vecn.hpp>
#include <vector>
#include "array.hpp"
#include "base_potential.hpp"
#include "optimizer.hpp"
// line search methods
#include "backtracking.hpp"
#include "bracketing.hpp"
#include "linesearch.hpp"
#include "more_thuente.hpp"
#include "nwpele.hpp"
#include "optimizer.hpp"
namespace pele {
class GradientDescent : public ODEBasedOptimizer {
private:
Array<double> xold;
Array<double> step;
double
inv_sqrt_size;
BacktrackingLineSearch line_search_method; // Line search method
double step_size_;
public:
GradientDescent(std::shared_ptr<pele::BasePotential> potential,
const pele::Array<double> x0, double tol = 1e-4,
double step_size = 1e-4, bool save_trajectory = true,
int iterations_before_save = 1,
bool use_hessian_step_size = false,
bool use_cosine_backtrack = false,
double cosine_backtrack_eps = 1e-2,
double cosine_backtrack_n = 5)
: ODEBasedOptimizer(potential, x0, tol, save_trajectory,
iterations_before_save),
xold(x_.size()),
step(x_.size()),
line_search_method(this),
step_size_(step_size) {
// set precision of printing
std::cout << std::setprecision(std::numeric_limits<double>::max_digits10);
inv_sqrt_size = 1 / sqrt(x_.size());
}
virtual ~GradientDescent() {}
void one_iteration() {
if (!func_initialized_) {
initialize_func_gradient();
}
// make a copy of the position and gradient
xold.assign(x_);
// really need to refactor and clean this up
Array<double> gold = g_.copy();
// Gradient defines step direction
step = -g_.copy() * step_size_;
// reduce the stepsize if necessary
line_search_method.set_xold_gold_(xold, gold);
line_search_method.set_g_f_ptr(g_);
step_norm_ = line_search_method.line_search(x_, step);
Array<double> gdiff = gold - g_;
Array<double> xdiff = xold - x_;
// Forward Euler time
// dx = -dt * g => dt = |dx| / |g|
time_ += step_norm_ / norm(gold);
// print some status information
if ((iprint_ > 0) && (iter_number_ % iprint_ == 0)) {
std::cout << "steepest descent: " << iter_number_ << " E " << f_
<< " rms " << gradient_norm_ << " nfev " << nfev_
<< " step norm " << step_norm_ << std::endl;
}
iter_number_ += 1;
}
virtual void reset(pele::Array<double> &x0) {
if (x0.size() != x_.size()) {
throw std::invalid_argument(
"The number of degrees of freedom (x0.size()) cannot change when "
"calling reset()");
}
iter_number_ = 0;
nfev_ = 0;
x_.assign(x0);
initialize_func_gradient();
}
};
} // namespace pele
#endif