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