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 
85  enum Status
86  {
87 
91  SUCCESS = 0,
92 
97 
102 
107 
111  DELTAF_REACHED = 8
112  };
113 
119  BFGSMinimizer(const ObjectiveFunction& func, const GradientFunction& grad_func):
120  rho(0.01), tau1(9), tau2(0.05), tau3(0.5), order(3), sigma(0.1), func(func), gradFunc(grad_func), status(SUCCESS) {}
121 
127  {
128  return g0Norm;
129  }
130 
136  {
137  return -deltaF;
138  }
139 
145  {
146  return fValue;
147  }
148 
153  std::size_t getNumIterations() const
154  {
155  return numIter;
156  }
157 
163  {
164  return status;
165  }
166 
177  Status minimize(VariableArrayType& x, VariableArrayType& g, std::size_t max_iter,
178  const ValueType& g_norm, const ValueType& delta_f, bool do_setup = true)
179  {
180  if (do_setup)
181  setup(x, g);
182 
183  fValue = ValueType(0);
184 
185  for (std::size_t i = 0; max_iter == 0 || i < max_iter; i++) {
186  status = iterate(fValue, x, g);
187 
188  if (status != SUCCESS)
189  return status;
190 
191  if (g_norm >= ValueType(0) && g0Norm <= g_norm)
192  status = GNORM_REACHED;
193 
194  if (delta_f >= ValueType(0) && deltaF <= delta_f)
195  status = Status(status | DELTAF_REACHED);
196 
197  if (status != SUCCESS)
198  return status;
199  }
200 
201  return (status = ITER_LIMIT_REACHED);
202  }
203 
213  const ValueType& step_size = 0.001, const ValueType& tol = 0.15)
214  {
215  numIter = 0;
216  step = step_size;
217  deltaF = ValueType(0);
218 
219  startF = gradFunc(x, g);
220 
221  /* Use the gradient as the initial direction */
222 
223  assign(x0, x);
224  assign(g0, g);
225  g0Norm = norm2(g0);
226 
227  assign(p, g);
228  multiply(p, -1 / g0Norm);
229 
230  pNorm = norm2(p); /* should be 1 */
231  fp0 = -g0Norm;
232 
233  /* Prepare the function evaluation cache */
234 
235  initFuncEvalCache();
236 
237  /* Prepare 1d minimisation parameters */
238 
239  sigma = tol;
240 
241  return startF;
242  }
243 
253  {
254  if (numIter == 0)
255  f = startF;
256 
257  ValueType alpha = ValueType(0), alpha1;
258  ValueType f0 = f;
259 
260  if (pNorm == ValueType(0) || g0Norm == ValueType(0) || fp0 == ValueType(0)) {
261  clear(dx);
262  return NO_PROGRESS;
263  }
264 
265  if (deltaF < ValueType(0)) {
266  ValueType del = std::max(-deltaF, 10 * std::numeric_limits<ValueType>::epsilon() * TypeTraits<ValueType>::abs(f0));
267  alpha1 = std::min(ValueType(1), 2 * del / -fp0);
268 
269  } else
270  alpha1 = TypeTraits<ValueType>::abs(step);
271 
272  /* line minimisation, with cubic interpolation (order = 3) */
273 
274  Status status = minimize(alpha1, alpha);
275 
276  if (status != SUCCESS)
277  return status;
278 
279  updatePosition(alpha, x, f, g);
280 
281  deltaF = f - f0;
282 
283  /* Choose a new direction for the next step */
284 
285  /* This is the BFGS update: */
286  /* p' = g1 - A dx - B dg */
287  /* A = - (1 + dg.dg / dx.dg) B + dg.g / dx.dg */
288  /* B = dx.g / dx.dg */
289 
290  /* dx0 = x - x0 */
291 
292  assign(dx0, x);
293  sub(dx0, x0);
294  assign(dx, dx0); /* keep a copy */
295 
296  /* dg0 = g - g0 */
297 
298  assign(dg0, g);
299  sub(dg0, g0);
300 
301  ValueType dxg = dot(dx0, g);
302  ValueType dgg = dot(dg0, g);
303  ValueType dxdg = dot(dx0, dg0);
304  ValueType dgnorm = norm2(dg0);
305 
306  ValueType A = ValueType(0);
307  ValueType B = ValueType(0);
308 
309  if (dxdg != 0) {
310  B = dxg / dxdg;
311  A = -(1 + dgnorm * dgnorm / dxdg) * B + dgg / dxdg;
312  }
313 
314  assign(p, g);
315 
316  axpy(-A, dx0, p);
317  axpy(-B, dg0, p);
318 
319  assign(g0, g);
320  assign(x0, x);
321  g0Norm = norm2(g0);
322  pNorm = norm2(p);
323 
324  /* update direction and fp0 */
325 
326  ValueType pg = dot(p, g);
327  ValueType dir(pg >= ValueType(0) ? -1 : +1);
328 
329  multiply(p, dir / pNorm);
330 
331  pNorm = norm2(p);
332 
333  fp0 = dot(p, g0);
334 
335  changeDirection();
336 
337  numIter++;
338 
339  return SUCCESS;
340  }
341 
342  private:
343  void initFuncEvalCache()
344  {
345  assign(xAlpha, x0);
346  assign(gAlpha, g0);
347 
348  xCacheKey = ValueType(0);
349  fAlpha = startF;
350  fCacheKey = ValueType(0);
351  gCacheKey = ValueType(0);
352  dfAlpha = slope();
353  dfCacheKey = ValueType(0);
354  }
355 
356  void assign(VariableArrayType& v1, const VariableArrayType& v2)
357  {
359  }
360 
361  void clear(VariableArrayType& v)
362  {
364  }
365 
366  void multiply(VariableArrayType& v, const ValueType& f)
367  {
369  }
370 
371  void sub(VariableArrayType& v1, const VariableArrayType& v2)
372  {
374  }
375 
376  ValueType norm2(const VariableArrayType& v) const
377  {
378  return MinimizerVariableArrayTraits<VA>::template norm2<ValueType>(v);
379  }
380 
381  ValueType dot(const VariableArrayType& v1, const VariableArrayType& v2) const
382  {
383  return MinimizerVariableArrayTraits<VA>::template dot<ValueType>(v1, v2);
384  }
385 
386  void axpy(const ValueType& alpha, const VariableArrayType& x, VariableArrayType& y) const
387  {
389  }
390 
391  ValueType slope() const
392  { /* compute gradient . direction */
393  return dot(gAlpha, p);
394  }
395 
396  void moveTo(const ValueType& alpha)
397  {
398  if (alpha == xCacheKey) /* using previously cached position */
399  return;
400 
401  /* set xAlpha = x + alpha * p */
402 
403  assign(xAlpha, x0);
404 
405  axpy(alpha, p, xAlpha);
406 
407  xCacheKey = alpha;
408  }
409 
410  ValueType getF(const ValueType& alpha)
411  {
412  if (alpha == fCacheKey) /* using previously cached f(alpha) */
413  return fAlpha;
414 
415  moveTo(alpha);
416 
417  fAlpha = func(xAlpha);
418  fCacheKey = alpha;
419 
420  return fAlpha;
421  }
422 
423  ValueType getDF(const ValueType& alpha)
424  {
425  if (alpha == dfCacheKey) /* using previously cached df(alpha) */
426  return dfAlpha;
427 
428  moveTo(alpha);
429 
430  if (alpha != gCacheKey) {
431  fAlpha = gradFunc(xAlpha, gAlpha);
432  gCacheKey = alpha;
433  fCacheKey = alpha;
434  }
435 
436  dfAlpha = slope();
437  dfCacheKey = alpha;
438 
439  return dfAlpha;
440  }
441 
442  void getFDF(const ValueType& alpha, ValueType& f, ValueType& df)
443  {
444  /* Check for previously cached values */
445 
446  if (alpha == fCacheKey && alpha == dfCacheKey) {
447  f = fAlpha;
448  df = dfAlpha;
449  return;
450  }
451 
452  if (alpha == fCacheKey || alpha == dfCacheKey) {
453  df = getDF(alpha);
454  f = getF(alpha);
455  return;
456  }
457 
458  moveTo(alpha);
459 
460  fAlpha = gradFunc(xAlpha, gAlpha);
461  fCacheKey = alpha;
462  gCacheKey = alpha;
463 
464  dfAlpha = slope();
465  dfCacheKey = alpha;
466 
467  f = fAlpha;
468  df = dfAlpha;
469  }
470 
471  void updatePosition(const ValueType& alpha, VariableArrayType& x, ValueType& f, VariableArrayType& g)
472  {
473  ValueType f_alpha, df_alpha;
474 
475  /* ensure that everything is fully cached */
476 
477  getFDF(alpha, f_alpha, df_alpha);
478 
479  f = f_alpha;
480  assign(x, xAlpha);
481  assign(g, gAlpha);
482  }
483 
484  void changeDirection()
485  {
486  /* Convert the cache values from the end of the current minimisation
487  to those needed for the start of the next minimisation, alpha = 0 */
488 
489  /* The new xAlpha for alpha = 0 is the current position */
490 
491  assign(xAlpha, x0);
492  xCacheKey = ValueType(0);
493 
494  /* The function value does not change */
495 
496  fCacheKey = ValueType(0);
497 
498  /* The new gAlpha for alpha = 0 is the current gradient at the endpoint */
499 
500  assign(gAlpha, g0);
501  gCacheKey = ValueType(0);
502 
503  /* Calculate the slope along the new direction vector, p */
504 
505  dfAlpha = slope();
506  dfCacheKey = ValueType(0);
507  }
508 
509  std::size_t solveQuadratic(const ValueType& a, const ValueType& b, const ValueType& c,
510  ValueType& x0, ValueType& x1) const
511  {
512 
513  ValueType disc = b * b - 4 * a * c;
514 
515  if (a == ValueType(0)) { /* Handle linear case */
516  if (b == ValueType(0))
517  return 0;
518 
519  else {
520  x0 = -c / b;
521  return 1;
522  };
523  }
524 
525  if (disc > ValueType(0)) {
526  if (b == ValueType(0)) {
528  x0 = -r;
529  x1 = r;
530 
531  } else {
532  ValueType sgnb(b > ValueType(0) ? 1 : -1);
533  ValueType temp = -(b + sgnb * TypeTraits<ValueType>::sqrt(disc)) / 2;
534  ValueType r1 = temp / a;
535  ValueType r2 = c / temp;
536 
537  if (r1 < r2) {
538  x0 = r1;
539  x1 = r2;
540 
541  } else {
542  x0 = r2;
543  x1 = r1;
544  }
545  }
546 
547  return 2;
548 
549  } else if (disc == ValueType(0)) {
550  x0 = -b / (2 * a);
551  x1 = -b / (2 * a);
552  return 2;
553 
554  } else
555  return 0;
556  }
557 
558  /*
559  * Find a minimum in x = [0, 1] of the interpolating quadratic through
560  * (0, f0) (1, f1) with derivative fp0 at x = 0. The interpolating
561  * polynomial is q(x) = f0 + fp0 * z + (f1 - f0 - fp0) * z^2
562  */
563  ValueType interpolateQuadratic(const ValueType& f0, const ValueType& fp0, const ValueType& f1,
564  const ValueType& zl, const ValueType& zh) const
565  {
566 
567  ValueType fl = f0 + zl * (fp0 + zl * (f1 - f0 - fp0));
568  ValueType fh = f0 + zh * (fp0 + zh * (f1 - f0 - fp0));
569  ValueType c = 2 * (f1 - f0 - fp0); /* curvature */
570 
571  ValueType zmin = zl, fmin = fl;
572 
573  if (fh < fmin) {
574  zmin = zh;
575  fmin = fh;
576  }
577 
578  if (c > ValueType(0)) { /* positive curvature required for a minimum */
579  ValueType z = -fp0 / c; /* location of minimum */
580 
581  if (z > zl && z < zh) {
582  ValueType f = f0 + z * (fp0 + z * (f1 - f0 - fp0));
583 
584  if (f < fmin) {
585  zmin = z;
586  fmin = f;
587  }
588  }
589  }
590 
591  return zmin;
592  }
593 
594  /*
595  * Find a minimum in x = [0, 1] of the interpolating cubic through
596  * (0, f0) (1, f1) with derivatives fp0 at x = 0 and fp1 at x = 1.
597  *
598  * The interpolating polynomial is:
599  *
600  * c(x) = f0 + fp0 * z + eta * z^2 + xi * z^3
601  *
602  * where eta = 3 * (f1 - f0) - 2 * fp0 - fp1, xi = fp0 + fp1 - 2 * (f1 - f0).
603  */
604  ValueType cubic(const ValueType& c0, const ValueType& c1, const ValueType& c2,
605  const ValueType& c3, const ValueType& z) const
606  {
607 
608  return c0 + z * (c1 + z * (c2 + z * c3));
609  }
610 
611  void checkExtremum(const ValueType& c0, const ValueType& c1, const ValueType& c2,
612  const ValueType& c3, const ValueType& z, ValueType& zmin, ValueType& fmin) const
613  {
614  /* could make an early return by testing curvature > 0 for minimum */
615 
616  ValueType y = cubic(c0, c1, c2, c3, z);
617 
618  if (y < fmin) {
619  zmin = z; /* accepted new point*/
620  fmin = y;
621  }
622  }
623 
624  ValueType interpolateCubic(const ValueType& f0, const ValueType& fp0, const ValueType& f1,
625  const ValueType& fp1, const ValueType& zl, const ValueType& zh) const
626  {
627 
628  ValueType eta = 3 * (f1 - f0) - 2 * fp0 - fp1;
629  ValueType xi = fp0 + fp1 - 2 * (f1 - f0);
630  ValueType c0 = f0, c1 = fp0, c2 = eta, c3 = xi;
631 
632  ValueType zmin = zl;
633  ValueType fmin = cubic(c0, c1, c2, c3, zl);
634 
635  checkExtremum(c0, c1, c2, c3, zh, zmin, fmin);
636 
637  ValueType z0, z1;
638  std::size_t n = solveQuadratic(3 * c3, 2 * c2, c1, z0, z1);
639 
640  if (n == 2) { /* found 2 roots */
641  if (z0 > zl && z0 < zh)
642  checkExtremum(c0, c1, c2, c3, z0, zmin, fmin);
643 
644  if (z1 > zl && z1 < zh)
645  checkExtremum(c0, c1, c2, c3, z1, zmin, fmin);
646 
647  } else if (n == 1) { /* found 1 root */
648  if (z0 > zl && z0 < zh)
649  checkExtremum(c0, c1, c2, c3, z0, zmin, fmin);
650  }
651 
652  return zmin;
653  }
654 
655  ValueType interpolate(const ValueType& a, const ValueType& fa, const ValueType& fpa,
656  const ValueType& b, const ValueType& fb, const ValueType& fpb,
657  const ValueType& xmin, const ValueType& xmax) const
658  {
659  /* Map [a, b] to [0, 1] */
660 
661  ValueType zmin = (xmin - a) / (b - a);
662  ValueType zmax = (xmax - a) / (b - a);
663 
664  if (zmin > zmax) {
665  ValueType tmp(zmin);
666  zmin = zmax;
667  zmax = tmp;
668  }
669 
670  ValueType z;
671 
672  if (order > 2 && std::isfinite(fpb))
673  z = interpolateCubic(fa, fpa * (b - a), fb, fpb * (b - a), zmin, zmax);
674  else
675  z = interpolateQuadratic(fa, fpa * (b - a), fb, zmin, zmax);
676 
677  ValueType alpha = a + z * (b - a);
678 
679  return alpha;
680  }
681 
682  Status minimize(const ValueType& alpha1, ValueType& alpha_new)
683  {
684  ValueType falpha, fpalpha, delta, alpha_next;
685  ValueType alpha = alpha1, alpha_prev = ValueType(0);
686  ValueType a = ValueType(0), fb = ValueType(0), fpb = ValueType(0);
687 
688  ValueType f0, fp0;
689 
690  getFDF(ValueType(0), f0, fp0);
691 
692  ValueType falpha_prev = f0;
693  ValueType fpalpha_prev = fp0;
694 
695  ValueType b = alpha;
696  ValueType fa = f0;
697  ValueType fpa = fp0;
698 
699  /* Begin bracketing */
700 
701  const std::size_t num_brack_iter = 100, section_iters = 100;
702  std::size_t i = 0;
703 
704  while (i++ < num_brack_iter) {
705  falpha = getF(alpha);
706 
707  /* Fletcher's rho test */
708 
709  if (falpha > f0 + alpha * rho * fp0 || falpha >= falpha_prev) {
710  a = alpha_prev;
711  fa = falpha_prev;
712  fpa = fpalpha_prev;
713  b = alpha;
714  fb = falpha;
715  fpb = std::numeric_limits<ValueType>::quiet_NaN();
716  break; /* goto sectioning */
717  }
718 
719  fpalpha = getDF(alpha);
720 
721  /* Fletcher's sigma test */
722 
723  if (TypeTraits<ValueType>::abs(fpalpha) <= -sigma * fp0) {
724  alpha_new = alpha;
725  return SUCCESS;
726  }
727 
728  if (fpalpha >= ValueType(0)) {
729  a = alpha;
730  fa = falpha;
731  fpa = fpalpha;
732  b = alpha_prev;
733  fb = falpha_prev;
734  fpb = fpalpha_prev;
735  break; /* goto sectioning */
736  }
737 
738  delta = alpha - alpha_prev;
739 
740  ValueType lower = alpha + delta;
741  ValueType upper = alpha + tau1 * delta;
742 
743  alpha_next = interpolate(alpha_prev, falpha_prev, fpalpha_prev,
744  alpha, falpha, fpalpha, lower, upper);
745 
746  alpha_prev = alpha;
747  falpha_prev = falpha;
748  fpalpha_prev = fpalpha;
749  alpha = alpha_next;
750  }
751 
752  /* Sectioning of bracket [a, b] */
753 
754  while (i++ < section_iters) {
755  delta = b - a;
756 
757  ValueType lower = a + tau2 * delta;
758  ValueType upper = b - tau3 * delta;
759 
760  alpha = interpolate(a, fa, fpa, b, fb, fpb, lower, upper);
761  falpha = getF(alpha);
762 
763  if ((a - alpha) * fpa <= std::numeric_limits<ValueType>::epsilon()) {
764  /* roundoff prevents progress */
765  return NO_PROGRESS;
766  }
767 
768  if (falpha > f0 + rho * alpha * fp0 || falpha >= fa) {
769  /* a_next = a; */
770  b = alpha;
771  fb = falpha;
772  fpb = std::numeric_limits<ValueType>::quiet_NaN();
773 
774  } else {
775  fpalpha = getDF(alpha);
776 
777  if (TypeTraits<ValueType>::abs(fpalpha) <= -sigma * fp0) {
778  alpha_new = alpha;
779  return SUCCESS; /* terminate */
780  }
781 
782  if (((b - a) >= ValueType(0) && fpalpha >= ValueType(0)) || ((b - a) <= ValueType(0) && fpalpha <= ValueType(0))) {
783  b = a;
784  fb = fa;
785  fpb = fpa;
786  a = alpha;
787  fa = falpha;
788  fpa = fpalpha;
789 
790  } else {
791  a = alpha;
792  fa = falpha;
793  fpa = fpalpha;
794  }
795  }
796  }
797 
798  return SUCCESS;
799  }
800 
801  const ValueType rho;
802  const ValueType tau1;
803  const ValueType tau2;
804  const ValueType tau3;
805  const std::size_t order;
806  std::size_t numIter;
807  ValueType step;
808  ValueType g0Norm;
809  ValueType pNorm;
810  ValueType startF;
811  ValueType deltaF;
812  ValueType fValue;
813  ValueType fp0;
818  VariableArrayType dx0;
819  VariableArrayType dg0;
820  VariableArrayType xAlpha;
821  VariableArrayType gAlpha;
822  ValueType sigma;
823  ValueType fAlpha;
824  ValueType dfAlpha;
825  ValueType fCacheKey;
826  ValueType dfCacheKey;
827  ValueType xCacheKey;
828  ValueType gCacheKey;
829  ObjectiveFunction func;
830  GradientFunction gradFunc;
831  Status status;
832  };
833  } // namespace Math
834 } // namespace CDPL
835 
836 #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:252
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:144
Status getStatus() const
Returns the current status of the minimizer.
Definition: BFGSMinimizer.hpp:162
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:177
Status
Status bitmask reported by minimize() and getStatus(). Multiple flags may be combined.
Definition: BFGSMinimizer.hpp:86
@ NO_PROGRESS
No more progress towards the solution can be made.
Definition: BFGSMinimizer.hpp:96
@ SUCCESS
Iteration step completed successfully (no termination condition met yet).
Definition: BFGSMinimizer.hpp:91
@ GNORM_REACHED
The configured gradient-norm threshold has been reached.
Definition: BFGSMinimizer.hpp:106
@ ITER_LIMIT_REACHED
The maximum number of minimization iterations has been reached.
Definition: BFGSMinimizer.hpp:101
@ DELTAF_REACHED
The configured function-value delta between successive iterations has been reached.
Definition: BFGSMinimizer.hpp:111
BFGSMinimizer(const ObjectiveFunction &func, const GradientFunction &grad_func)
Constructs the BFGSMinimizer instance with the given objective and gradient functions.
Definition: BFGSMinimizer.hpp:119
ValueType getGradientNorm() const
Returns the L2 norm of the gradient at the end of the most recent iterate() call.
Definition: BFGSMinimizer.hpp:126
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:212
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:135
std::size_t getNumIterations() const
Returns the number of iterations performed by the most recent minimize() or iterate() loop.
Definition: BFGSMinimizer.hpp:153
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