PICCANTE  0.4
The hottest HDR imaging library!
nelder_mead_opt_base.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_NELDER_MEAD_OPT_BASE_HPP
19 #define PIC_NELDER_MEAD_OPT_BASE_HPP
20 
21 #include <vector>
22 #include <utility>
23 #include <algorithm>
24 
25 namespace pic{
26 
30 template <class Scalar>
32 {
33 protected:
34  bool bStopMean;
35  Scalar delta, delta_zero;
36  Scalar alpha, gamma, lambda, sigma;
37 
38  //simlex vertices
39  std::vector< std::pair<Scalar, Scalar *> > simplex;
40 
46  void InitSimplex(Scalar *x0, unsigned int n)
47  {
48  simplex.clear();
49 
50  //first point of simplex is x0
51  Scalar *vertex_0 = new Scalar[n];
52  Scalar function_vertex_0;
53  memcpy(vertex_0, x0, sizeof(Scalar) * n);
54  function_vertex_0 = function(vertex_0, n);
55 
56  simplex.push_back(std::make_pair(function_vertex_0, vertex_0));
57 
58  //computing the other vertices of the simplex
59  for(unsigned int i = 0; i < n; i++) {
60  Scalar *vertex = new Scalar[n];
61  memcpy(vertex, x0, sizeof(Scalar) * n);
62 
63  if(vertex[i] != 0.0f) {
64  vertex[i] += x0[i] * delta;
65  } else {
66  vertex[i] = delta_zero;
67  }
68 
69  Scalar function_vertex = function(vertex, n);
70 
71  simplex.push_back(std::make_pair(function_vertex, vertex));
72  }
73 
74  std::sort(simplex.begin(), simplex.end());
75  }
76 
82  void ComputeMean(Scalar *x_mean, unsigned int n)
83  {
84  Scalar n_f = Scalar(n);
85 
86  //computing the mean point in the simplex
87  for(unsigned int i = 0; i < n; i++) {
88  x_mean[i] = Scalar(0);
89  }
90 
91  for(unsigned int j = 0; j < n; j++) {
92  Scalar *vertex = simplex[j].second;
93 
94  for(unsigned int i = 0; i < n; i++) {
95  x_mean[i] += vertex[i];
96  }
97  }
98 
99  for(unsigned int i = 0; i < n; i++) {
100  x_mean[i] /= n_f;
101  }
102  }
103 
111  Scalar ComputeReflected(Scalar *x_r, Scalar *x_mean, unsigned int n)
112  {
113  Scalar *x_n = simplex[n].second;
114 
115  for(unsigned int i = 0; i < n; i++) {
116  x_r[i] = x_mean[i] + alpha * (x_mean[i] - x_n[i]);
117  }
118 
119  return function(x_r, n);
120  }
121 
129  Scalar ComputeExpansion(Scalar *x_e, Scalar *x_mean, unsigned int n)
130  {
131  Scalar *x_n = simplex[n].second;
132 
133  for(unsigned int i = 0; i < n; i++) {
134  x_e[i] = x_mean[i] + gamma * (x_mean[i] - x_n[i]);
135  }
136 
137  return function(x_e, n);
138  }
139 
147  Scalar ComputeContractionInside(Scalar *x_c, Scalar *x_mean, unsigned int n)
148  {
149  Scalar *x_n = simplex[n].second;
150 
151  for(unsigned int i = 0; i < n; i++) {
152  x_c[i] = x_mean[i] + lambda * (x_mean[i] - x_n[i]);
153  }
154 
155  return function(x_c, n);
156  }
157 
162  void ComputeReduction(unsigned int n)
163  {
164  Scalar *x_0 = simplex[0].second;
165 
166  for(unsigned int i = 1; i < (n + 1); i++) {
167 
168  Scalar *x_i = simplex[i].second;
169 
170  for(unsigned int j = 0; j < n ; j++) {
171  x_i[j] = x_0[j] + sigma * (x_i[j] - x_0[j]);
172  }
173 
174  simplex[i].first = function(x_i, n);
175  }
176  }
177 
186  Scalar *run_aux(Scalar *x_start, unsigned int n, Scalar epsilon, int max_iterations = 1000, Scalar *x = NULL)
187  {
188  InitSimplex(x_start, n);
189 
190  Scalar *x_mean = new Scalar[n];
191  Scalar *x_r = new Scalar[n];
192  Scalar *x_e = new Scalar[n];
193  Scalar *x_c = new Scalar[n];
194 
195  int i = 0;
196 
197  size_t n_size = sizeof(Scalar) * n;
198 
199  while(i < max_iterations) {
200 
201  std::sort(simplex.begin(), simplex.end());
202 
203  ComputeMean(x_mean, n);
204 
205  //Stopping check
206  if(bStopMean) {
207 
208  Scalar function_vertex_x_mean = function(x_mean, n);
209 
210  Scalar err = Scalar(0);
211  for(unsigned int j = 0; j < n; j++) {
212  Scalar tmp = simplex[j].first - function_vertex_x_mean;
213  err += tmp * tmp;
214  }
215 
216  err = sqrt( err / Scalar(n));
217 
218  if(err <= epsilon) {
219  break;
220  }
221 
222  } else {
223 
224  Scalar err_f = Scalar(0);
225  Scalar err_v = Scalar(0);
226 
227  for(unsigned int j = 1; j < (n + 1); j++) {
228  err_f = MAX(err_f, fabs(simplex[j].first - simplex[0].first));
229 
230  for(unsigned int i = 0; i < n; i++) {
231  err_v = MAX(err_v, fabs(simplex[j].second[i] - simplex[0].second[i]));
232  }
233  }
234 
235  if((err_f <= epsilon) && (err_v <= epsilon)) {
236  break;
237  }
238  }
239 
240  //main algorithm
241  Scalar function_vertex_r = ComputeReflected(x_r, x_mean, n);
242 
243  if((simplex[0].first <= function_vertex_r) &&
244  (function_vertex_r < simplex[n - 1].first)) {//reflection
245 
246  simplex[n].first = function_vertex_r;
247  memcpy(simplex[n].second, x_r, n_size);
248  } else {
249  if(function_vertex_r < simplex[0].first) {//expansion
250  Scalar function_vertex_e = ComputeExpansion(x_e, x_mean, n);
251 
252  if(function_vertex_e < function_vertex_r) {
253  simplex[n].first = function_vertex_e;
254  memcpy(simplex[n].second, x_e, n_size);
255 
256  } else {
257  simplex[n].first = function_vertex_r;
258  memcpy(simplex[n].second, x_r, n_size);
259  }
260  } else {//contraction function_vertex_r > function_vertex_(n - 1)
261 
262  Scalar function_vertex_c = ComputeContractionInside(x_c, x_mean, n);
263 
264  if(function_vertex_c < simplex[n].first) {
265  simplex[n].first = function_vertex_c;
266  memcpy(simplex[n].second, x_c, n_size);
267 
268  } else {//reduction
269  ComputeReduction(n);
270  }
271  }
272  }
273 
274  i++;
275  }
276 
277  #ifdef PIC_DEBUG
278  printf("\nNelder-Mead iterations: %d Err: %f\n", i, simplex[0].first);
279  #endif
280 
281  output_error = simplex[0].first;
282 
283  memcpy(x, simplex[0].second, n_size);
284 
285  delete[] x_mean;
286  delete[] x_r;
287  delete[] x_e;
288  delete[] x_c;
289 
290  return x;
291  }
292 
293 public:
294 
296  Scalar output_error;
297 
302  {
303  GlobalSettings();
304  }
305 
310  {
311  //initialization
312  delta = Scalar(0.05);
313  delta_zero = Scalar(0.00025);
314 
315  bStopMean = false;
316 
317  //other parts
318  alpha = Scalar(1.0);
319  gamma = Scalar(2.0);
320  lambda = Scalar(-0.5);
321  sigma = Scalar(0.5);
322  }
323 
328  virtual Scalar function(Scalar *x, unsigned int n)
329  {
330  return FLT_MAX;
331  }
332 
333  virtual Scalar *run(Scalar *x_start, unsigned int n, Scalar epsilon = 1e-4f, int max_iterations = 1000, Scalar *x = NULL)
334  {
335  if(x == NULL) {
336  x = new Scalar[n];
337  }
338 
339  return run_aux(x_start, n, epsilon, max_iterations, x);
340  }
341 
342 };
343 
344 }
345 
346 #endif // PIC_NELDER_MEAD_OPT_BASE_HPP
Scalar output_error
Definition: nelder_mead_opt_base.hpp:296
Scalar ComputeReflected(Scalar *x_r, Scalar *x_mean, unsigned int n)
ComputeReflected.
Definition: nelder_mead_opt_base.hpp:111
Scalar gamma
Definition: nelder_mead_opt_base.hpp:36
int max_iterations
Definition: nelder_mead_opt_base.hpp:295
Scalar ComputeExpansion(Scalar *x_e, Scalar *x_mean, unsigned int n)
ComputeExpansion.
Definition: nelder_mead_opt_base.hpp:129
std::vector< std::pair< Scalar, Scalar * > > simplex
Definition: nelder_mead_opt_base.hpp:39
void GlobalSettings()
GlobalSettings.
Definition: nelder_mead_opt_base.hpp:309
void ComputeMean(Scalar *x_mean, unsigned int n)
ComputeMean.
Definition: nelder_mead_opt_base.hpp:82
Scalar ComputeContractionInside(Scalar *x_c, Scalar *x_mean, unsigned int n)
ComputeContractionInside.
Definition: nelder_mead_opt_base.hpp:147
NelderMeadOptBase()
NelderMeadOptBase.
Definition: nelder_mead_opt_base.hpp:301
Scalar sigma
Definition: nelder_mead_opt_base.hpp:36
void InitSimplex(Scalar *x0, unsigned int n)
InitSimplex.
Definition: nelder_mead_opt_base.hpp:46
Scalar lambda
Definition: nelder_mead_opt_base.hpp:36
Scalar alpha
Definition: nelder_mead_opt_base.hpp:36
virtual Scalar * run(Scalar *x_start, unsigned int n, Scalar epsilon=1e-4f, int max_iterations=1000, Scalar *x=NULL)
Definition: nelder_mead_opt_base.hpp:333
The NelderMeadOptBase class.
Definition: nelder_mead_opt_base.hpp:31
Scalar * run_aux(Scalar *x_start, unsigned int n, Scalar epsilon, int max_iterations=1000, Scalar *x=NULL)
run_aux
Definition: nelder_mead_opt_base.hpp:186
void ComputeReduction(unsigned int n)
ComputeReduction.
Definition: nelder_mead_opt_base.hpp:162
Scalar delta_zero
Definition: nelder_mead_opt_base.hpp:35
Definition: bilateral_separation.hpp:25
#define MAX(a, b)
Definition: math.hpp:73
bool bStopMean
Definition: nelder_mead_opt_base.hpp:34
Scalar delta
Definition: nelder_mead_opt_base.hpp:35