Loading...
Searching...
No Matches
LBFGS Class Referencefinal

#include <LBFGS.h>

Inheritance diagram for LBFGS:

Public Member Functions

 LBFGS (std::shared_ptr< ObjectiveFunction > a_objf, const Parameters &a_params)
 ~LBFGS ()=default
int step (double a_maxMove) override
int run (size_t a_maxIterations, double a_maxMove) override
int update (const Eigen::VectorXd &a_r1, const Eigen::VectorXd &a_r0, const Eigen::VectorXd &a_f1, const Eigen::VectorXd &a_f0)
void reset (void)
Public Member Functions inherited from eonc::Optimizer
 Optimizer (std::shared_ptr< ObjectiveFunction > a_objf, const OptimizerConfig &a_config)
 Optimizer (std::shared_ptr< ObjectiveFunction > a_objf, OptType a_optype, const OptimizerConfig &a_config)
 Optimizer (std::shared_ptr< ObjectiveFunction > a_objf, const Parameters &a_params)
 Optimizer (std::shared_ptr< ObjectiveFunction > a_objf, OptType a_optype, const Parameters &a_params)
virtual ~Optimizer ()

Private Member Functions

Eigen::VectorXd getStep (double a_maxMove, const Eigen::VectorXd &a_f)

Private Attributes

int m_iteration
int m_memory
std::deque< Eigen::VectorXd > m_s
std::deque< Eigen::VectorXd > m_y
std::deque< double > m_rho
Eigen::VectorXd m_rPrev
Eigen::VectorXd m_fPrev
eonc::log::FileScoped m_log {"lbfgs", "_lbfgs.log"}

Additional Inherited Members

Protected Attributes inherited from eonc::Optimizer
const OptimizerConfig m_optConfig
std::shared_ptr< ObjectiveFunctionm_objf

Detailed Description

Definition at line 27 of file LBFGS.h.

Constructor & Destructor Documentation

◆ LBFGS()

eonc::LBFGS::LBFGS ( std::shared_ptr< ObjectiveFunction > a_objf,
const Parameters & a_params )
inline

Definition at line 30 of file LBFGS.h.

31 : Optimizer(a_objf, OptType::LBFGS, a_params),
32 m_iteration{0},
33 m_memory{std::min(
34 a_objf->degreesOfFreedom(),
35 static_cast<int>(a_params.optimizer_options.lbfgs.memory))} {}
int m_iteration
Definition LBFGS.h:48
int m_memory
Definition LBFGS.h:49
Optimizer(std::shared_ptr< ObjectiveFunction > a_objf, const OptimizerConfig &a_config)
Definition Optimizer.h:71
struct eonc::Parameters::optimizer_options_t optimizer_options
struct eonc::Parameters::optimizer_options_t::lbfgs_t lbfgs

◆ ~LBFGS()

eonc::LBFGS::~LBFGS ( )
default

Member Function Documentation

◆ getStep()

Eigen::VectorXd LBFGS::getStep ( double a_maxMove,
const Eigen::VectorXd & a_f )
private

Definition at line 19 of file LBFGS.cpp.

19 {
20 double H0 = m_optConfig.opts.lbfgs.inverse_curvature;
21 Eigen::VectorXd r = m_objf->getPositions();
22
23 if (m_iteration > 0) {
24 Eigen::VectorXd dr = m_objf->difference(r, m_rPrev);
25 // double C = dr.dot(fPrev-f)/dr.dot(dr);
26 double C = eonc::safemath::safe_div((m_fPrev - a_f).dot(m_fPrev - a_f),
27 dr.dot(m_fPrev - a_f), -1.0);
28 if (C < 0) {
29 QUILL_LOG_DEBUG(
30 m_log, "[LBFGS] Negative curvature: {:.4f} eV/A^2 take max move step",
31 C);
32 reset();
33 return eonc::helpers::maxAtomMotionAppliedV(1000 * a_f, a_maxMove);
34 }
35
36 if (m_optConfig.opts.lbfgs.auto_scale) {
37 H0 = eonc::safemath::safe_recip(C, -1.0);
38 QUILL_LOG_DEBUG(m_log, "[LBFGS] Curvature: {:.4e} eV/A^2", C);
39 }
40 }
41
42 if (m_iteration == 0 && m_optConfig.opts.lbfgs.auto_scale) {
43 m_objf->setPositions(r + m_optConfig.finiteDifference *
44 eonc::safemath::safe_normalized(a_f));
45 Eigen::VectorXd dg = m_objf->getGradient(true) + a_f;
46 double C = dg.dot(eonc::safemath::safe_normalized(a_f)) /
47 m_optConfig.finiteDifference;
48 H0 = eonc::safemath::safe_recip(C, -1.0);
49 m_objf->setPositions(r);
50 if (H0 < 0) {
51 QUILL_LOG_WARNING(m_log,
52 "[LBFGS] Negative curvature calculated via FD: {:.4e} "
53 "eV/A^2, take max move step",
54 C);
55 reset();
56 return eonc::helpers::maxAtomMotionAppliedV(1000 * a_f, a_maxMove);
57 } else {
58 QUILL_LOG_DEBUG(m_log,
59 "[LBFGS] Curvature calculated via FD: {:.4e} eV/A^2", C);
60 }
61 }
62
63 int loopmax = m_s.size();
64 std::vector<double> a(loopmax);
65
66 Eigen::VectorXd q = -a_f;
67
68 for (int i = loopmax - 1; i >= 0; i--) {
69 a[i] = m_rho[i] * m_s[i].dot(q);
70 q -= a[i] * m_y[i];
71 }
72
73 Eigen::VectorXd z = H0 * q;
74
75 for (int i = 0; i < loopmax; i++) {
76 double b = m_rho[i] * m_y[i].dot(z);
77 z += m_s[i] * (a[i] - b);
78 }
79
80 Eigen::VectorXd d = -z;
81
82 double distance = eonc::helpers::maxAtomMotionV(d);
83 if (distance >= a_maxMove && m_optConfig.opts.lbfgs.distance_reset) {
84 QUILL_LOG_DEBUG(m_log,
85 "[LBFGS] reset memory, proposed step too large: {:.4f}",
86 distance);
87 reset();
88 return eonc::helpers::maxAtomMotionAppliedV(H0 * a_f, a_maxMove);
89 }
90
91 double vd = eonc::safemath::safe_normalized(d).dot(
92 eonc::safemath::safe_normalized(a_f));
93 if (vd > 1.0)
94 vd = 1.0;
95 if (vd < -1.0)
96 vd = -1.0;
97 double angle = eonc::safemath::safe_acos(vd) * (180.0 / eonc::helpers::pi);
98 if (angle > 90.0 && m_optConfig.opts.lbfgs.angle_reset) {
99 QUILL_LOG_DEBUG(m_log,
100 "[LBFGS] reset memory, angle between LBFGS angle and "
101 "force too large: {:.4f}",
102 angle);
103 reset();
104 return eonc::helpers::maxAtomMotionAppliedV(H0 * a_f, a_maxMove);
105 }
106
107 return eonc::helpers::maxAtomMotionAppliedV(d, a_maxMove);
108}
std::deque< double > m_rho
Definition LBFGS.h:53
Eigen::VectorXd m_fPrev
Definition LBFGS.h:56
std::deque< Eigen::VectorXd > m_y
Definition LBFGS.h:52
std::deque< Eigen::VectorXd > m_s
Definition LBFGS.h:51
Eigen::VectorXd m_rPrev
Definition LBFGS.h:55
eonc::log::FileScoped m_log
Definition LBFGS.h:57
void reset(void)
Definition LBFGS.cpp:110
const OptimizerConfig m_optConfig
Definition Optimizer.h:67
std::shared_ptr< ObjectiveFunction > m_objf
Definition Optimizer.h:68
constexpr double pi
VectorXd maxAtomMotionAppliedV(const VectorXd v1, double maxMotion)
double maxAtomMotionV(const VectorXd v1)
constexpr double safe_div(double num, double denom, double fallback=0.0)
Definition SafeMath.h:21
double safe_acos(double x)
Definition SafeMath.h:34
constexpr double safe_recip(double x, double fallback=0.0)
Definition SafeMath.h:29

◆ reset()

void LBFGS::reset ( void )

Definition at line 110 of file LBFGS.cpp.

110 {
111 m_s.clear();
112 m_y.clear();
113 m_rho.clear();
114}

◆ run()

int LBFGS::run ( size_t a_maxIterations,
double a_maxMove )
overridevirtual

Implements eonc::Optimizer.

Definition at line 167 of file LBFGS.cpp.

167 {
168 int status;
169 while (!m_objf->isConverged() && m_iteration < a_maxSteps) {
170 status = step(a_maxMove);
171 if (status < 0)
172 return -1;
173 }
174 return m_objf->isConverged() ? 1 : 0;
175}
int step(double a_maxMove) override
Definition LBFGS.cpp:144

◆ step()

int LBFGS::step ( double a_maxMove)
overridevirtual

Implements eonc::Optimizer.

Definition at line 144 of file LBFGS.cpp.

144 {
145 int status = 0;
146 Eigen::VectorXd r = m_objf->getPositions();
147 Eigen::VectorXd f = -m_objf->getGradient();
148
149 if (m_iteration > 0) {
150 status = update(r, m_rPrev, f, m_fPrev);
151 }
152 if (status < 0)
153 return -1;
154
155 Eigen::VectorXd dr = getStep(a_maxMove, f);
156
157 m_objf->setPositions(r + dr);
158
159 m_rPrev = r;
160 m_fPrev = f;
161
162 m_iteration++;
163
164 return m_objf->isConverged() ? 1 : 0;
165}
Eigen::VectorXd getStep(double a_maxMove, const Eigen::VectorXd &a_f)
Definition LBFGS.cpp:19
int update(const Eigen::VectorXd &a_r1, const Eigen::VectorXd &a_r0, const Eigen::VectorXd &a_f1, const Eigen::VectorXd &a_f0)
Definition LBFGS.cpp:116

◆ update()

int LBFGS::update ( const Eigen::VectorXd & a_r1,
const Eigen::VectorXd & a_r0,
const Eigen::VectorXd & a_f1,
const Eigen::VectorXd & a_f0 )

Definition at line 116 of file LBFGS.cpp.

117 {
118 Eigen::VectorXd s0 = m_objf->difference(a_r1, a_r0);
119
120 // y0 is the change in the gradient, not the force
121 Eigen::VectorXd y0 = a_f0 - a_f1;
122
123 // Skip degenerate curvature update (reset memory instead of aborting)
124 if (std::abs(s0.dot(y0)) < LBFGS_EPS) {
125 QUILL_LOG_WARNING(m_log,
126 "[LBFGS] s0.y0 too small ({:.4e}), resetting memory",
127 s0.dot(y0));
128 reset();
129 return 0;
130 }
131
132 m_rho.push_back(eonc::safemath::safe_recip(s0.dot(y0), 0.0));
133 m_s.push_back(std::move(s0));
134 m_y.push_back(std::move(y0));
135
136 if (static_cast<int>(m_s.size()) > m_memory) {
137 m_s.pop_front();
138 m_y.pop_front();
139 m_rho.pop_front();
140 }
141 return 0;
142}
#define LBFGS_EPS
Definition LBFGS.h:25

Member Data Documentation

◆ m_fPrev

Eigen::VectorXd eonc::LBFGS::m_fPrev
private

Definition at line 56 of file LBFGS.h.

◆ m_iteration

Definition at line 48 of file LBFGS.h.

◆ m_log

eonc::log::FileScoped eonc::LBFGS::m_log {"lbfgs", "_lbfgs.log"}
private

Definition at line 57 of file LBFGS.h.

57{"lbfgs", "_lbfgs.log"};

◆ m_memory

int eonc::LBFGS::m_memory
private

Definition at line 49 of file LBFGS.h.

◆ m_rho

std::deque<double> eonc::LBFGS::m_rho
private

Definition at line 53 of file LBFGS.h.

◆ m_rPrev

Eigen::VectorXd eonc::LBFGS::m_rPrev
private

Definition at line 55 of file LBFGS.h.

◆ m_s

std::deque<Eigen::VectorXd> eonc::LBFGS::m_s
private

Definition at line 51 of file LBFGS.h.

◆ m_y

std::deque<Eigen::VectorXd> eonc::LBFGS::m_y
private

Definition at line 52 of file LBFGS.h.


The documentation for this class was generated from the following files:
  • /home/runner/work/eOn/eOn/include/eon/LBFGS.h
  • /home/runner/work/eOn/eOn/client/LBFGS.cpp