Chemical Data Processing Library C++ API - Version 1.4.0
BFGSMinimizer.hpp
Go to the documentation of this file.
1 /*
2  * BFGSMinimizer.hpp
3  *
4  * Copyright (C) 2003 Thomas Seidel <thomas.seidel@univie.ac.at>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
27 #ifndef CDPL_MATH_BFGSMINIMIZER_HPP
28 #define CDPL_MATH_BFGSMINIMIZER_HPP
29 
30 #include <cstddef>
31 #include <limits>
32 #include <functional>
33 
35 #include "CDPL/Math/TypeTraits.hpp"
36 
37 
38 namespace CDPL
39 {
40 
41  namespace Math
42  {
43 
52  template <typename VA, typename VT = typename MinimizerVariableArrayTraits<VA>::ValueType, typename FVT = VT>
54  {
55 
56  public:
60  typedef VA VariableArrayType;
61 
65  typedef VT ValueType;
66 
70  typedef FVT FunctionValueType;
71 
75  typedef typename std::function<FVT(const VA&, VA&)> GradientFunction;
76 
80  typedef typename std::function<FVT(const VA&)> ObjectiveFunction;
81 
87  enum Status
88  {
89 
93  SUCCESS = 0,
94 
99 
104 
109 
113  DELTAF_REACHED = 8
114  };
115 
121  BFGSMinimizer(const ObjectiveFunction& func, const GradientFunction& grad_func):
122  rho(0.01), tau1(9), tau2(0.05), tau3(0.5), order(3), sigma(0.1), func(func), gradFunc(grad_func), status(SUCCESS) {}
123 
129  {
130  return g0Norm;
131  }
132 
138  {
139  return -deltaF;
140  }
141 
147  {
148  return fValue;
149  }
150 
155  std::size_t getNumIterations() const
156  {
157  return numIter;
158  }
159 
165  {
166  return status;
167  }
168 
179  Status minimize(VariableArrayType& x, VariableArrayType& g, std::size_t max_iter,
180  const ValueType& g_norm, const ValueType& delta_f, bool do_setup = true)
181  {
182  if (do_setup)
183  setup(x, g);
184 
185  fValue = ValueType(0);
186 
187  for (std::size_t i = 0; max_iter == 0 || i < max_iter; i++) {
188  status = iterate(fValue, x, g);
189 
190  if (status != SUCCESS)
191  return status;
192 
193  if (g_norm >= ValueType(0) && g0Norm <= g_norm)
194  status = GNORM_REACHED;
195 
196  if (delta_f >= ValueType(0) && deltaF <= delta_f)
197  status = Status(status | DELTAF_REACHED);
198 
199  if (status != SUCCESS)
200  return status;
201  }
202 
203  return (status = ITER_LIMIT_REACHED);
204  }
205 
215  const ValueType& step_size = 0.001, const ValueType& tol = 0.15)
216  {
217  numIter = 0;
218  step = step_size;
219  deltaF = ValueType(0);
220 
221  startF = gradFunc(x, g);
222 
223  /* Use the gradient as the initial direction */
224 
225  assign(x0, x);
226  assign(g0, g);
227  g0Norm = norm2(g0);
228 
229  assign(p, g);
230  multiply(p, -1 / g0Norm);
231 
232  pNorm = norm2(p); /* should be 1 */
233  fp0 = -g0Norm;
234 
235  /* Prepare the function evaluation cache */
236 
237  initFuncEvalCache();
238 
239  /* Prepare 1d minimisation parameters */
240 
241  sigma = tol;
242 
243  return startF;
244  }
245 
255  {
256  if (numIter == 0)
257  f = startF;
258 
259  ValueType alpha = ValueType(0), alpha1;
260  ValueType f0 = f;
261 
262  if (pNorm == ValueType(0) || g0Norm == ValueType(0) || fp0 == ValueType(0)) {
263  clear(dx);
264  return NO_PROGRESS;
265  }
266 
267  if (deltaF < ValueType(0)) {
268  ValueType del = std::max(-deltaF, 10 * std::numeric_limits<ValueType>::epsilon() * TypeTraits<ValueType>::abs(f0));
269  alpha1 = std::min(ValueType(1), 2 * del / -fp0);
270 
271  } else
272  alpha1 = TypeTraits<ValueType>::abs(step);
273 
274  /* line minimisation, with cubic interpolation (order = 3) */
275 
276  Status status = minimize(alpha1, alpha);
277 
278  if (status != SUCCESS)
279  return status;
280 
281  updatePosition(alpha, x, f, g);
282 
283  deltaF = f - f0;
284 
285  /* Choose a new direction for the next step */
286 
287  /* This is the BFGS update: */
288  /* p' = g1 - A dx - B dg */
289  /* A = - (1 + dg.dg / dx.dg) B + dg.g / dx.dg */
290  /* B = dx.g / dx.dg */
291 
292  /* dx0 = x - x0 */
293 
294  assign(dx0, x);
295  sub(dx0, x0);
296  assign(dx, dx0); /* keep a copy */
297 
298  /* dg0 = g - g0 */
299 
300  assign(dg0, g);
301  sub(dg0, g0);
302 
303  ValueType dxg = dot(dx0, g);
304  ValueType dgg = dot(dg0, g);
305  ValueType dxdg = dot(dx0, dg0);
306  ValueType dgnorm = norm2(dg0);
307 
308  ValueType A = ValueType(0);
309  ValueType B = ValueType(0);
310 
311  if (dxdg != 0) {
312  B = dxg / dxdg;
313  A = -(1 + dgnorm * dgnorm / dxdg) * B + dgg / dxdg;
314  }
315 
316  assign(p, g);
317 
318  axpy(-A, dx0, p);
319  axpy(-B, dg0, p);
320 
321  assign(g0, g);
322  assign(x0, x);
323  g0Norm = norm2(g0);
324  pNorm = norm2(p);
325 
326  /* update direction and fp0 */
327 
328  ValueType pg = dot(p, g);
329  ValueType dir(pg >= ValueType(0) ? -1 : +1);
330 
331  multiply(p, dir / pNorm);
332 
333  pNorm = norm2(p);
334 
335  fp0 = dot(p, g0);
336 
337  changeDirection();
338 
339  numIter++;
340 
341  return SUCCESS;
342  }
343 
344  private:
345  void initFuncEvalCache()
346  {
347  assign(xAlpha, x0);
348  assign(gAlpha, g0);
349 
350  xCacheKey = ValueType(0);
351  fAlpha = startF;
352  fCacheKey = ValueType(0);
353  gCacheKey = ValueType(0);
354  dfAlpha = slope();
355  dfCacheKey = ValueType(0);
356  }
357 
358  void assign(VariableArrayType& v1, const VariableArrayType& v2)
359  {
361  }
362 
363  void clear(VariableArrayType& v)
364  {
366  }
367 
368  void multiply(VariableArrayType& v, const ValueType& f)
369  {
371  }
372 
373  void sub(VariableArrayType& v1, const VariableArrayType& v2)
374  {
376  }
377 
378  ValueType norm2(const VariableArrayType& v) const
379  {
380  return MinimizerVariableArrayTraits<VA>::template norm2<ValueType>(v);
381  }
382 
383  ValueType dot(const VariableArrayType& v1, const VariableArrayType& v2) const
384  {
385  return MinimizerVariableArrayTraits<VA>::template dot<ValueType>(v1, v2);
386  }
387 
388  void axpy(const ValueType& alpha, const VariableArrayType& x, VariableArrayType& y) const
389  {
391  }
392 
393  ValueType slope() const
394  { /* compute gradient . direction */
395  return dot(gAlpha, p);
396  }
397 
398  void moveTo(const ValueType& alpha)
399  {
400  if (alpha == xCacheKey) /* using previously cached position */
401  return;
402 
403  /* set xAlpha = x + alpha * p */
404 
405  assign(xAlpha, x0);
406 
407  axpy(alpha, p, xAlpha);
408 
409  xCacheKey = alpha;
410  }
411 
412  ValueType getF(const ValueType& alpha)
413  {
414  if (alpha == fCacheKey) /* using previously cached f(alpha) */
415  return fAlpha;
416 
417  moveTo(alpha);
418 
419  fAlpha = func(xAlpha);
420  fCacheKey = alpha;
421 
422  return fAlpha;
423  }
424 
425  ValueType getDF(const ValueType& alpha)
426  {
427  if (alpha == dfCacheKey) /* using previously cached df(alpha) */
428  return dfAlpha;
429 
430  moveTo(alpha);
431 
432  if (alpha != gCacheKey) {
433  fAlpha = gradFunc(xAlpha, gAlpha);
434  gCacheKey = alpha;
435  fCacheKey = alpha;
436  }
437 
438  dfAlpha = slope();
439  dfCacheKey = alpha;
440 
441  return dfAlpha;
442  }
443 
444  void getFDF(const ValueType& alpha, ValueType& f, ValueType& df)
445  {
446  /* Check for previously cached values */
447 
448  if (alpha == fCacheKey && alpha == dfCacheKey) {
449  f = fAlpha;
450  df = dfAlpha;
451  return;
452  }
453 
454  if (alpha == fCacheKey || alpha == dfCacheKey) {
455  df = getDF(alpha);
456  f = getF(alpha);
457  return;
458  }
459 
460  moveTo(alpha);
461 
462  fAlpha = gradFunc(xAlpha, gAlpha);
463  fCacheKey = alpha;
464  gCacheKey = alpha;
465 
466  dfAlpha = slope();
467  dfCacheKey = alpha;
468 
469  f = fAlpha;
470  df = dfAlpha;
471  }
472 
473  void updatePosition(const ValueType& alpha, VariableArrayType& x, ValueType& f, VariableArrayType& g)
474  {
475  ValueType f_alpha, df_alpha;
476 
477  /* ensure that everything is fully cached */
478 
479  getFDF(alpha, f_alpha, df_alpha);
480 
481  f = f_alpha;
482  assign(x, xAlpha);
483  assign(g, gAlpha);
484  }
485 
486  void changeDirection()
487  {
488  /* Convert the cache values from the end of the current minimisation
489  to those needed for the start of the next minimisation, alpha = 0 */
490 
491  /* The new xAlpha for alpha = 0 is the current position */
492 
493  assign(xAlpha, x0);
494  xCacheKey = ValueType(0);
495 
496  /* The function value does not change */
497 
498  fCacheKey = ValueType(0);
499 
500  /* The new gAlpha for alpha = 0 is the current gradient at the endpoint */
501 
502  assign(gAlpha, g0);
503  gCacheKey = ValueType(0);
504 
505  /* Calculate the slope along the new direction vector, p */
506 
507  dfAlpha = slope();
508  dfCacheKey = ValueType(0);
509  }
510 
511  std::size_t solveQuadratic(const ValueType& a, const ValueType& b, const ValueType& c,
512  ValueType& x0, ValueType& x1) const
513  {
514 
515  ValueType disc = b * b - 4 * a * c;
516 
517  if (a == ValueType(0)) { /* Handle linear case */
518  if (b == ValueType(0))
519  return 0;
520 
521  else {
522  x0 = -c / b;
523  return 1;
524  };
525  }
526 
527  if (disc > ValueType(0)) {
528  if (b == ValueType(0)) {
530  x0 = -r;
531  x1 = r;
532 
533  } else {
534  ValueType sgnb(b > ValueType(0) ? 1 : -1);
535  ValueType temp = -(b + sgnb * TypeTraits<ValueType>::sqrt(disc)) / 2;
536  ValueType r1 = temp / a;
537  ValueType r2 = c / temp;
538 
539  if (r1 < r2) {
540  x0 = r1;
541  x1 = r2;
542 
543  } else {
544  x0 = r2;
545  x1 = r1;
546  }
547  }
548 
549  return 2;
550 
551  } else if (disc == ValueType(0)) {
552  x0 = -b / (2 * a);
553  x1 = -b / (2 * a);
554  return 2;
555 
556  } else
557  return 0;
558  }
559 
560  /*
561  * Find a minimum in x = [0, 1] of the interpolating quadratic through
562  * (0, f0) (1, f1) with derivative fp0 at x = 0. The interpolating
563  * polynomial is q(x) = f0 + fp0 * z + (f1 - f0 - fp0) * z^2
564  */
565  ValueType interpolateQuadratic(const ValueType& f0, const ValueType& fp0, const ValueType& f1,
566  const ValueType& zl, const ValueType& zh) const
567  {
568 
569  ValueType fl = f0 + zl * (fp0 + zl * (f1 - f0 - fp0));
570  ValueType fh = f0 + zh * (fp0 + zh * (f1 - f0 - fp0));
571  ValueType c = 2 * (f1 - f0 - fp0); /* curvature */
572 
573  ValueType zmin = zl, fmin = fl;
574 
575  if (fh < fmin) {
576  zmin = zh;
577  fmin = fh;
578  }
579 
580  if (c > ValueType(0)) { /* positive curvature required for a minimum */
581  ValueType z = -fp0 / c; /* location of minimum */
582 
583  if (z > zl && z < zh) {
584  ValueType f = f0 + z * (fp0 + z * (f1 - f0 - fp0));
585 
586  if (f < fmin) {
587  zmin = z;
588  fmin = f;
589  }
590  }
591  }
592 
593  return zmin;
594  }
595 
596  /*
597  * Find a minimum in x = [0, 1] of the interpolating cubic through
598  * (0, f0) (1, f1) with derivatives fp0 at x = 0 and fp1 at x = 1.
599  *
600  * The interpolating polynomial is:
601  *
602  * c(x) = f0 + fp0 * z + eta * z^2 + xi * z^3
603  *
604  * where eta = 3 * (f1 - f0) - 2 * fp0 - fp1, xi = fp0 + fp1 - 2 * (f1 - f0).
605  */
606  ValueType cubic(const ValueType& c0, const ValueType& c1, const ValueType& c2,
607  const ValueType& c3, const ValueType& z) const
608  {
609 
610  return c0 + z * (c1 + z * (c2 + z * c3));
611  }
612 
613  void checkExtremum(const ValueType& c0, const ValueType& c1, const ValueType& c2,
614  const ValueType& c3, const ValueType& z, ValueType& zmin, ValueType& fmin) const
615  {
616  /* could make an early return by testing curvature > 0 for minimum */
617 
618  ValueType y = cubic(c0, c1, c2, c3, z);
619 
620  if (y < fmin) {
621  zmin = z; /* accepted new point*/
622  fmin = y;
623  }
624  }
625 
626  ValueType interpolateCubic(const ValueType& f0, const ValueType& fp0, const ValueType& f1,
627  const ValueType& fp1, const ValueType& zl, const ValueType& zh) const
628  {
629 
630  ValueType eta = 3 * (f1 - f0) - 2 * fp0 - fp1;
631  ValueType xi = fp0 + fp1 - 2 * (f1 - f0);
632  ValueType c0 = f0, c1 = fp0, c2 = eta, c3 = xi;
633 
634  ValueType zmin = zl;
635  ValueType fmin = cubic(c0, c1, c2, c3, zl);
636 
637  checkExtremum(c0, c1, c2, c3, zh, zmin, fmin);
638 
639  ValueType z0, z1;
640  std::size_t n = solveQuadratic(3 * c3, 2 * c2, c1, z0, z1);
641 
642  if (n == 2) { /* found 2 roots */
643  if (z0 > zl && z0 < zh)
644  checkExtremum(c0, c1, c2, c3, z0, zmin, fmin);
645 
646  if (z1 > zl && z1 < zh)
647  checkExtremum(c0, c1, c2, c3, z1, zmin, fmin);
648 
649  } else if (n == 1) { /* found 1 root */
650  if (z0 > zl && z0 < zh)
651  checkExtremum(c0, c1, c2, c3, z0, zmin, fmin);
652  }
653 
654  return zmin;
655  }
656 
657  ValueType interpolate(const ValueType& a, const ValueType& fa, const ValueType& fpa,
658  const ValueType& b, const ValueType& fb, const ValueType& fpb,
659  const ValueType& xmin, const ValueType& xmax) const
660  {
661  /* Map [a, b] to [0, 1] */
662 
663  ValueType zmin = (xmin - a) / (b - a);
664  ValueType zmax = (xmax - a) / (b - a);
665 
666  if (zmin > zmax) {
667  ValueType tmp(zmin);
668  zmin = zmax;
669  zmax = tmp;
670  }
671 
672  ValueType z;
673 
674  if (order > 2 && std::isfinite(fpb))
675  z = interpolateCubic(fa, fpa * (b - a), fb, fpb * (b - a), zmin, zmax);
676  else
677  z = interpolateQuadratic(fa, fpa * (b - a), fb, zmin, zmax);
678 
679  ValueType alpha = a + z * (b - a);
680 
681  return alpha;
682  }
683 
684  Status minimize(const ValueType& alpha1, ValueType& alpha_new)
685  {
686  ValueType falpha, fpalpha, delta, alpha_next;
687  ValueType alpha = alpha1, alpha_prev = ValueType(0);
688  ValueType a = ValueType(0), fb = ValueType(0), fpb = ValueType(0);
689 
690  ValueType f0, fp0;
691 
692  getFDF(ValueType(0), f0, fp0);
693 
694  ValueType falpha_prev = f0;
695  ValueType fpalpha_prev = fp0;
696 
697  ValueType b = alpha;
698  ValueType fa = f0;
699  ValueType fpa = fp0;
700 
701  /* Begin bracketing */
702 
703  const std::size_t num_brack_iter = 100, section_iters = 100;
704  std::size_t i = 0;
705 
706  while (i++ < num_brack_iter) {
707  falpha = getF(alpha);
708 
709  /* Fletcher's rho test */
710 
711  if (falpha > f0 + alpha * rho * fp0 || falpha >= falpha_prev) {
712  a = alpha_prev;
713  fa = falpha_prev;
714  fpa = fpalpha_prev;
715  b = alpha;
716  fb = falpha;
717  fpb = std::numeric_limits<ValueType>::quiet_NaN();
718  break; /* goto sectioning */
719  }
720 
721  fpalpha = getDF(alpha);
722 
723  /* Fletcher's sigma test */
724 
725  if (TypeTraits<ValueType>::abs(fpalpha) <= -sigma * fp0) {
726  alpha_new = alpha;
727  return SUCCESS;
728  }
729 
730  if (fpalpha >= ValueType(0)) {
731  a = alpha;
732  fa = falpha;
733  fpa = fpalpha;
734  b = alpha_prev;
735  fb = falpha_prev;
736  fpb = fpalpha_prev;
737  break; /* goto sectioning */
738  }
739 
740  delta = alpha - alpha_prev;
741 
742  ValueType lower = alpha + delta;
743  ValueType upper = alpha + tau1 * delta;
744 
745  alpha_next = interpolate(alpha_prev, falpha_prev, fpalpha_prev,
746  alpha, falpha, fpalpha, lower, upper);
747 
748  alpha_prev = alpha;
749  falpha_prev = falpha;
750  fpalpha_prev = fpalpha;
751  alpha = alpha_next;
752  }
753 
754  /* Sectioning of bracket [a, b] */
755 
756  while (i++ < section_iters) {
757  delta = b - a;
758 
759  ValueType lower = a + tau2 * delta;
760  ValueType upper = b - tau3 * delta;
761 
762  alpha = interpolate(a, fa, fpa, b, fb, fpb, lower, upper);
763  falpha = getF(alpha);
764 
765  if ((a - alpha) * fpa <= std::numeric_limits<ValueType>::epsilon()) {
766  /* roundoff prevents progress */
767  return NO_PROGRESS;
768  }
769 
770  if (falpha > f0 + rho * alpha * fp0 || falpha >= fa) {
771  /* a_next = a; */
772  b = alpha;
773  fb = falpha;
774  fpb = std::numeric_limits<ValueType>::quiet_NaN();
775 
776  } else {
777  fpalpha = getDF(alpha);
778 
779  if (TypeTraits<ValueType>::abs(fpalpha) <= -sigma * fp0) {
780  alpha_new = alpha;
781  return SUCCESS; /* terminate */
782  }
783 
784  if (((b - a) >= ValueType(0) && fpalpha >= ValueType(0)) || ((b - a) <= ValueType(0) && fpalpha <= ValueType(0))) {
785  b = a;
786  fb = fa;
787  fpb = fpa;
788  a = alpha;
789  fa = falpha;
790  fpa = fpalpha;
791 
792  } else {
793  a = alpha;
794  fa = falpha;
795  fpa = fpalpha;
796  }
797  }
798  }
799 
800  return SUCCESS;
801  }
802 
803  const ValueType rho;
804  const ValueType tau1;
805  const ValueType tau2;
806  const ValueType tau3;
807  const std::size_t order;
808  std::size_t numIter;
809  ValueType step;
810  ValueType g0Norm;
811  ValueType pNorm;
812  ValueType startF;
813  ValueType deltaF;
814  ValueType fValue;
815  ValueType fp0;
820  VariableArrayType dx0;
821  VariableArrayType dg0;
822  VariableArrayType xAlpha;
823  VariableArrayType gAlpha;
824  ValueType sigma;
825  ValueType fAlpha;
826  ValueType dfAlpha;
827  ValueType fCacheKey;
828  ValueType dfCacheKey;
829  ValueType xCacheKey;
830  ValueType gCacheKey;
831  ObjectiveFunction func;
832  GradientFunction gradFunc;
833  Status status;
834  };
835  } // namespace Math
836 } // namespace CDPL
837 
838 #endif // CDPL_MATH_BFGSMINIMIZER_HPP
Provides traits to flexibly handle different types of variable arrays in function optimization algori...
Definition of type traits.
Implementation of the Broyden-Fletcher-Goldfarb-Shanno (BFGS) algorithm for solving unconstrained non...
Definition: BFGSMinimizer.hpp:54
Status iterate(ValueType &f, VariableArrayType &x, VariableArrayType &g)
Performs a single BFGS iteration: line search along the current search direction, BFGS update of the ...
Definition: BFGSMinimizer.hpp:254
std::function< FVT(const VA &)> ObjectiveFunction
Type of the objective function.
Definition: BFGSMinimizer.hpp:80
ValueType getFunctionValue() const
Returns the function value at the end of the most recent iterate() call.
Definition: BFGSMinimizer.hpp:146
Status getStatus() const
Returns the current status of the minimizer.
Definition: BFGSMinimizer.hpp:164
Status minimize(VariableArrayType &x, VariableArrayType &g, std::size_t max_iter, const ValueType &g_norm, const ValueType &delta_f, bool do_setup=true)
Runs the BFGS minimization loop on x.
Definition: BFGSMinimizer.hpp:179
Status
Status bitmask reported by minimize() and getStatus().
Definition: BFGSMinimizer.hpp:88
@ NO_PROGRESS
No more progress towards the solution can be made.
Definition: BFGSMinimizer.hpp:98
@ SUCCESS
Iteration step completed successfully (no termination condition met yet).
Definition: BFGSMinimizer.hpp:93
@ GNORM_REACHED
The configured gradient-norm threshold has been reached.
Definition: BFGSMinimizer.hpp:108
@ ITER_LIMIT_REACHED
The maximum number of minimization iterations has been reached.
Definition: BFGSMinimizer.hpp:103
@ DELTAF_REACHED
The configured function value delta between successive iterations has been reached.
Definition: BFGSMinimizer.hpp:113
BFGSMinimizer(const ObjectiveFunction &func, const GradientFunction &grad_func)
Constructs the BFGSMinimizer instance with the given objective and gradient functions.
Definition: BFGSMinimizer.hpp:121
ValueType getGradientNorm() const
Returns the L2 norm of the gradient at the end of the most recent iterate() call.
Definition: BFGSMinimizer.hpp:128
std::function< FVT(const VA &, VA &)> GradientFunction
Type of the gradient function (computes the objective value and writes the gradient into the second a...
Definition: BFGSMinimizer.hpp:75
ValueType setup(const VariableArrayType &x, VariableArrayType &g, const ValueType &step_size=0.001, const ValueType &tol=0.15)
Initializes the minimizer state for a subsequent iterate() / minimize() loop.
Definition: BFGSMinimizer.hpp:214
FVT FunctionValueType
The scalar return type of the objective and gradient functions.
Definition: BFGSMinimizer.hpp:70
ValueType getFunctionDelta() const
Returns the magnitude of the function value decrease produced by the most recent iterate() call.
Definition: BFGSMinimizer.hpp:137
std::size_t getNumIterations() const
Returns the number of iterations performed by the most recent minimize() or iterate() loop.
Definition: BFGSMinimizer.hpp:155
VT ValueType
The scalar value type of VariableArrayType.
Definition: BFGSMinimizer.hpp:65
VA VariableArrayType
The type of the variable array passed to the minimizer.
Definition: BFGSMinimizer.hpp:60
constexpr unsigned int A
Generic type that covers any element except hydrogen.
Definition: AtomType.hpp:637
constexpr unsigned int B
Specifies Boron.
Definition: AtomType.hpp:87
constexpr unsigned int r
Specifies that the stereocenter has r configuration.
Definition: CIPDescriptor.hpp:76
The namespace of the Chemical Data Processing Library.
static void axpy(const T &alpha, const ArrayType &x, ArrayType &y)
Performs the in-place BLAS-style axpy operation .
Definition: MinimizerVariableArrayTraits.hpp:131
static void multiply(ArrayType &a, const T &v)
Multiplies every element of a by the scalar v.
Definition: MinimizerVariableArrayTraits.hpp:162
static void sub(ArrayType &a1, const ArrayType &a2)
Subtracts a2 from a1 element-wise ( ).
Definition: MinimizerVariableArrayTraits.hpp:172
static void assign(ArrayType &a1, const ArrayType &a2)
Copies the contents of a2 into a1.
Definition: MinimizerVariableArrayTraits.hpp:150
static void clear(ArrayType &a)
Sets all elements of a to the default-constructed ValueType.
Definition: MinimizerVariableArrayTraits.hpp:140
static RealType abs(ConstReference t)
Returns the absolute value of t (std::abs for signed types, the identity for unsigned types).
Definition: TypeTraits.hpp:142
static ValueType sqrt(ConstReference t)
Returns the square root of t.
Definition: TypeTraits.hpp:152
Primary traits template for scalar arithmetic value types.
Definition: TypeTraits.hpp:307