QMCPACK
MinimizeOneDim.h
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2018 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #ifndef QMCPLUSPLUS_MINIMIZE_ONED_H
13 #define QMCPLUSPLUS_MINIMIZE_ONED_H
14 
15 #include <algorithm>
16 #include <stdexcept>
17 #include <tuple>
18 
19 // Storage for bracketed minimum.
20 
21 template<typename T>
23 {
24  T a;
25  T b;
26  T c;
27  bool success;
28 
29  Bracket_min_t(T a1, T b1, T c1, bool okay = true) : a(a1), b(b1), c(c1), success(okay) {}
30 };
31 
32 
33 // Minimize a function in one dimension
34 // Bracket a minimum in preparation for minimization
35 
36 // If 'bound_max' is a positive number, the search range is bounded between zero and 'bound_max'.
37 // If the search falls outside that range, the function returns with bracket.success set to 'false',
38 // and the position in bracket.a. This means the minimum occurs at the edge of the boundary, and
39 // there is no need to call 'find_minimum' (nor should it be called).
40 
41 
42 template<class F, typename T>
43 Bracket_min_t<T> bracket_minimum(const F& f, T initial_value, T bound_max = -1.0)
44 {
45  T xa = initial_value;
46  T fa = f(xa);
47 
48  T xb = xa + 0.005;
49  T fb = f(xb);
50 
51  // swap a and b
52  if (fb > fa)
53  {
54  std::swap(xa, xb);
55  std::swap(fa, fb);
56  }
57 
58  bool check_bound = false;
59  if (bound_max > 0.0)
60  {
61  check_bound = true;
62  }
63  T best_val = xb;
64 
65  T delx = 1.61 * (xb - xa);
66  T xd = xb + delx;
67  T fd = f(xd);
68 
69  int cnt = 0;
70  while (fb > fd)
71  {
72  T xtmp = xb;
73  T ftmp = fb;
74  xb = xd;
75  fb = fd;
76  xa = xtmp;
77  fa = ftmp;
78  xd += delx;
79  if (check_bound && (xd < 0.0 || xd > bound_max))
80  {
81  // minimum occurs at the boundary of the range
82  return Bracket_min_t<T>(best_val, 0.0, 0.0, false);
83  }
84 
85 
86  fd = f(xd);
87 
88  if (cnt == 50)
89  {
90  delx *= 5;
91  }
92  if (cnt == 100)
93  {
94  delx *= 5;
95  }
96  if (cnt == 1000)
97  {
98  delx *= 5;
99  }
100  if (cnt == 10000)
101  {
102  delx *= 5;
103  }
104  cnt++;
105  if (cnt == 100000)
106  {
107  throw std::runtime_error("Failed to bracket minimum");
108  }
109  }
110  if (xa > xd)
111  std::swap(xa, xd);
112  return Bracket_min_t<T>(xa, xb, xd);
113 }
114 
115 // Use a golden-section search
116 
117 // Returns a pair with the location of the minimum and the value of the function.
118 
119 template<class F, typename T>
120 std::pair<T, T> find_minimum(const F& f, Bracket_min_t<T>& bracket)
121 {
122  // assert(bracket.success == true);
123  T xa = bracket.a;
124  T xb = bracket.b;
125  T xd = bracket.c;
126  T fb = f(xb);
127  T xc = xb + 0.4 * (xd - xb);
128  T fc = f(xc);
129 
130  T tol = 1e-5;
131  while (std::abs(xa - xd) > tol * (std::abs(xb) + std::abs(xc)))
132  {
133  if (fb > fc)
134  {
135  xa = xb;
136  xb = xa + 0.4 * (xd - xa);
137  fb = f(xb);
138  xc = xa + 0.6 * (xd - xa);
139  fc = f(xc);
140  }
141  else
142  {
143  xd = xc;
144  xb = xa + 0.4 * (xd - xa);
145  fb = f(xb);
146  xc = xa + 0.6 * (xd - xa);
147  fc = f(xc);
148  }
149  }
150  T final_value;
151  T final_x;
152  if (fb < fc)
153  {
154  final_x = xb;
155  }
156  else
157  {
158  final_x = xc;
159  }
160  final_value = f(final_x);
161  return std::pair<T, T>(final_x, final_value);
162 }
163 
164 #endif
Bracket_min_t< T > bracket_minimum(const F &f, T initial_value, T bound_max=-1.0)
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
std::pair< T, T > find_minimum(const F &f, Bracket_min_t< T > &bracket)
Bracket_min_t(T a1, T b1, T c1, bool okay=true)