Loading...
Searching...
No Matches
eonc::ConjugateGradients Class Referencefinal

Decleration of the Conjugate Gradients optimizer. More...

#include <ConjugateGradients.h>

Inheritance diagram for eonc::ConjugateGradients:

Public Member Functions

 ConjugateGradients (std::shared_ptr< ObjectiveFunction > a_objf, const Parameters &a_params)
 Conjugate Gradients optimizer constructor.
 ~ConjugateGradients ()=default
 Conjugant Gradient deconstructor.
int step (double a_maxMove) override
 Calls the next step in the algorithm.
int run (size_t a_maxIterations, double a_maxMove) override
 Runs the conjugate gradient.
Eigen::VectorXd getStep ()
 Gets the direction of the next step.
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 ()=default

Private Member Functions

int single_step (double a_maxMove)
 Steps the conjugate gradient.
int line_search (double a_maxMove)
 Steps the conjugate gradient.

Private Attributes

Eigen::VectorXd m_direction
 Current step direction of the conjugate gradient.
Eigen::VectorXd m_directionOld
 Algorithms previous step direction.
Eigen::VectorXd m_directionNorm
 Normalised version of the current direction vector.
Eigen::VectorXd m_force
 Current force vector.
Eigen::VectorXd m_forceOld
 Previous force vector.
eonc::log::FileScoped m_log {"cg", "_cg.log"}
size_t m_cg_i {0}
 Counts the number of discrete steps until algorithm convergence.

Additional Inherited Members

Protected Attributes inherited from eonc::Optimizer
const OptimizerConfig m_optConfig
std::shared_ptr< ObjectiveFunction > m_objf

Detailed Description

Decleration of the Conjugate Gradients optimizer.

Definition at line 38 of file ConjugateGradients.h.

Constructor & Destructor Documentation

◆ ConjugateGradients()

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

Conjugate Gradients optimizer constructor.

Parameters
std::shared_ptr<ObjectiveFunction>m_objf that tells the optimizer how to run
constParameters& m_params defined by the config.init file

Definition at line 46 of file ConjugateGradients.h.

49 m_direction{Eigen::VectorXd::Zero(a_objf->degreesOfFreedom())},
50 m_directionOld{Eigen::VectorXd::Zero(a_objf->degreesOfFreedom())},
51 m_directionNorm{Eigen::VectorXd::Zero(a_objf->degreesOfFreedom())},
52 m_force{Eigen::VectorXd::Zero(a_objf->degreesOfFreedom())},
53 m_forceOld{Eigen::VectorXd::Zero(a_objf->degreesOfFreedom())} {}
Eigen::VectorXd m_force
Current force vector.
Eigen::VectorXd m_directionNorm
Normalised version of the current direction vector.
Eigen::VectorXd m_directionOld
Algorithms previous step direction.
Eigen::VectorXd m_direction
Current step direction of the conjugate gradient.
Eigen::VectorXd m_forceOld
Previous force vector.
Optimizer(std::shared_ptr< ObjectiveFunction > a_objf, const OptimizerConfig &a_config)
Definition Optimizer.h:73
static OptimizerConfig fromParams(const Parameters &p)
Definition Optimizer.h:57

◆ ~ConjugateGradients()

eonc::ConjugateGradients::~ConjugateGradients ( )
default

Conjugant Gradient deconstructor.

Member Function Documentation

◆ getStep()

Eigen::VectorXd eonc::ConjugateGradients::getStep ( )

Gets the direction of the next step.

Definition at line 19 of file ConjugateGradients.cpp.

19 {
20 double a = std::abs(m_force.dot(m_forceOld));
21 double b = m_forceOld.squaredNorm();
22 double gamma = 0.0;
23 if (a < 0.5 * b) {
24 // Polak-Ribiere way to determine how much to mix in of old direction
25 gamma = eonc::safemath::safe_div(m_force.dot(m_force - m_forceOld), b, 0.0);
26 } else {
27 gamma = 0;
28 }
31 eonc::safemath::safe_normalize_inplace(m_directionNorm);
34
35 // Only if value for max nr of iteration before reset
36 if (m_optConfig.opts.cg.max_iter_before_reset > 0 &&
37 m_optConfig.opts.cg.max_iter_before_reset <= m_cg_i) {
38 m_cg_i = 0;
39 m_forceOld.setZero();
40 m_directionOld.setZero();
41 }
42 m_cg_i += 1;
43
44 return m_direction;
45}
size_t m_cg_i
Counts the number of discrete steps until algorithm convergence.
const OptimizerConfig m_optConfig
Definition Optimizer.h:69
constexpr double safe_div(double num, double denom, double fallback=0.0)
Definition SafeMath.h:21

◆ line_search()

int eonc::ConjugateGradients::line_search ( double a_maxMove)
private

Steps the conjugate gradient.

Checks for convergence based on the ratio of the projected force along a line to the norm of the total force

Definition at line 59 of file ConjugateGradients.cpp.

59 {
60 Eigen::VectorXd pos;
61 Eigen::VectorXd posStep;
62 Eigen::VectorXd forceBeforeStep;
63 double stepSize;
64 double projectedForce;
65 double projectedForceBeforeStep;
66 double curvature;
67
68 forceBeforeStep = -m_objf->getGradient();
69 m_force = forceBeforeStep;
70 getStep();
71 pos = m_objf->getPositions();
72 projectedForceBeforeStep = m_force.dot(m_directionNorm);
73
74 // move system an infinitesimal step to determine the optimal step size along
75 // the search line
76 posStep = pos + m_directionNorm * m_optConfig.finiteDifference;
77 m_objf->setPositions(posStep);
78 m_force = -m_objf->getGradient(true);
79 projectedForce = m_force.dot(m_directionNorm);
80 stepSize = m_optConfig.finiteDifference;
81
82 int line_i = 0;
83 do {
84 // Determine curvature from last step (Secant method)
85 curvature = std::abs(eonc::safemath::safe_div(
86 projectedForceBeforeStep - projectedForce, stepSize, 0.0));
87 // A negative max move is a length (bowl breakout), not a backward step.
88 const double maxMove = std::fabs(a_maxMove);
89 stepSize = eonc::safemath::safe_div(projectedForce, curvature, maxMove);
90
91 if (maxMove < std::fabs(stepSize)) {
92 // first part get the sign of stepSize
93 stepSize = ((stepSize > 0) - (stepSize < 0)) * maxMove;
94 }
95
96 forceBeforeStep = m_force;
97 projectedForceBeforeStep = projectedForce;
98
99 pos += stepSize * m_directionNorm;
100 m_objf->setPositions(pos);
101 m_force = -m_objf->getGradient();
102 projectedForce = m_force.dot(m_directionNorm);
103
104 line_i += 1;
105
106 // Line search considered converged based in the ratio between the projected
107 // force and the norm of the true force
108 } while (m_optConfig.opts.cg.line_converged <
109 std::abs(projectedForce) /
110 (std::sqrt(m_force.dot(m_force) +
111 m_optConfig.opts.cg.line_converged)) &&
112 line_i < m_optConfig.opts.cg.line_search_max_iter);
113 if (m_objf->isConverged())
114 return 1;
115 return 0;
116}
Eigen::VectorXd getStep()
Gets the direction of the next step.
std::shared_ptr< ObjectiveFunction > m_objf
Definition Optimizer.h:70

◆ run()

int eonc::ConjugateGradients::run ( size_t a_maxIterations,
double a_maxMove )
overridevirtual

Runs the conjugate gradient.

Todo
method should also return an error code and message if the algorithm errors out
Returns
algorithm convergence

Implements eonc::Optimizer.

Definition at line 196 of file ConjugateGradients.cpp.

196 {
197 size_t iterations = 0;
198 while (!m_objf->isConverged() && iterations < a_maxIterations) {
199 step(a_maxMove);
200 iterations++;
201 }
202 return m_objf->isConverged() ? 1 : 0;
203}
int step(double a_maxMove) override
Calls the next step in the algorithm.

◆ single_step()

int eonc::ConjugateGradients::single_step ( double a_maxMove)
private

Steps the conjugate gradient.

Checks for convergence based on the change in displacement or direction

Definition at line 118 of file ConjugateGradients.cpp.

118 {
119 Eigen::VectorXd pos;
120 Eigen::VectorXd posStep;
121 Eigen::VectorXd forceAfterStep;
122
123 m_force = -m_objf->getGradient();
124 pos = m_objf->getPositions();
125 getStep();
126
127 // move system an infinitesimal step to determine the optimal step size along
128 // the search line
129 posStep = pos + m_directionNorm * m_optConfig.finiteDifference;
130 m_objf->setPositions(posStep);
131 forceAfterStep = -m_objf->getGradient(true);
132
133 // Determine curvature
134 double projectedForce1 = m_force.dot(m_directionNorm);
135 double projectedForce2 = forceAfterStep.dot(m_directionNorm);
136 double curvature = eonc::safemath::safe_div(
137 projectedForce1 - projectedForce2, m_optConfig.finiteDifference, 0.0);
138
139 double stepSize = a_maxMove;
140
141 if (curvature > 0.0) {
142 stepSize = eonc::safemath::safe_div(projectedForce1, curvature, a_maxMove);
143 }
144
145 if (m_optConfig.bowlBreakout && a_maxMove < 0.0) {
146 stepSize = -a_maxMove;
147 a_maxMove = -a_maxMove;
148 }
149
150 if (!m_optConfig.opts.cg.no_overshooting) {
151 if (m_optConfig.bowlBreakout) {
152 // max displacement is based on system not single atom
154 a_maxMove);
155 } else {
157 a_maxMove);
158 }
159 m_objf->setPositions(pos);
160 } else {
161 // negative if product of the projected forces before and after the step are
162 // in opposite directions
163 double passedMinimum = -1.;
164 double forceChange = 0.;
165 while (passedMinimum < 0.0 &&
166 0.1 * std::abs(projectedForce1) < std::abs(projectedForce2)) {
168 stepSize * m_directionNorm, a_maxMove);
169 m_objf->setPositions(posStep);
170 forceAfterStep = -m_objf->getGradient(true);
171 projectedForce2 = forceAfterStep.dot(m_directionNorm);
172
173 passedMinimum = projectedForce1 * projectedForce2;
174 if (passedMinimum < 0.0 &&
175 0.1 * std::abs(projectedForce1) < std::abs(projectedForce2)) {
176 forceChange = (projectedForce1 - projectedForce2);
177 stepSize = eonc::safemath::safe_div(projectedForce1, forceChange, 0.0) *
178 stepSize;
179 QUILL_LOG_DEBUG(m_log, "Force changed {}, step size adjusted to {}",
180 forceChange, stepSize);
181 }
182 }
183 }
184 if (m_optConfig.opts.cg.knock_out_max_move) {
185 if (stepSize >= a_maxMove) {
186 // knockout old search direction
187 m_directionOld.setZero();
188 m_forceOld.setZero();
189 QUILL_LOG_DEBUG(m_log, "Resetting the old search direction");
190 }
191 }
192
193 return m_objf->isConverged() ? 1 : 0;
194}
eonc::log::FileScoped m_log
VectorXd maxMotionAppliedV(const VectorXd v1, double maxMotion)
VectorXd maxAtomMotionAppliedV(const VectorXd v1, double maxMotion)

◆ step()

int eonc::ConjugateGradients::step ( double a_maxMove)
overridevirtual

Calls the next step in the algorithm.

Either calls the single_step or line_search method depending on the parameters

Returns
whether or not the algorithm has converged

Implements eonc::Optimizer.

Definition at line 47 of file ConjugateGradients.cpp.

47 {
48 bool converged;
49 if (m_optConfig.opts.cg.line_search) {
50 converged = line_search(a_maxMove);
51 } else {
52 converged = single_step(a_maxMove);
53 }
54 if (converged)
55 return 1;
56 return 0;
57}
int single_step(double a_maxMove)
Steps the conjugate gradient.
int line_search(double a_maxMove)
Steps the conjugate gradient.

Member Data Documentation

◆ m_cg_i

size_t eonc::ConjugateGradients::m_cg_i {0}
private

Counts the number of discrete steps until algorithm convergence.

Definition at line 86 of file ConjugateGradients.h.

86{0};

◆ m_direction

Eigen::VectorXd eonc::ConjugateGradients::m_direction
private

Current step direction of the conjugate gradient.

Definition at line 74 of file ConjugateGradients.h.

◆ m_directionNorm

Eigen::VectorXd eonc::ConjugateGradients::m_directionNorm
private

Normalised version of the current direction vector.

Definition at line 78 of file ConjugateGradients.h.

◆ m_directionOld

Eigen::VectorXd eonc::ConjugateGradients::m_directionOld
private

Algorithms previous step direction.

Definition at line 76 of file ConjugateGradients.h.

◆ m_force

Eigen::VectorXd eonc::ConjugateGradients::m_force
private

Current force vector.

Definition at line 80 of file ConjugateGradients.h.

◆ m_forceOld

Eigen::VectorXd eonc::ConjugateGradients::m_forceOld
private

Previous force vector.

Definition at line 82 of file ConjugateGradients.h.

◆ m_log

eonc::log::FileScoped eonc::ConjugateGradients::m_log {"cg", "_cg.log"}
private

Definition at line 83 of file ConjugateGradients.h.

83{"cg", "_cg.log"};

The documentation for this class was generated from the following files: