NimbRo ROS Soccer Package
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
SimplexOptimizer.hpp
1 //SimplexOptimizer.hpp
2 // Created on: Feb 20, 2016
3 // Author: Hafez Farazi <farazi@ais.uni-bonn.de>
4 // This code is based on (Copyright (C) 2010 Botao Jia): http://www.codeguru.com/cpp/article.php/c17505/Simplex-Optimization-Algorithm-and-Implemetation-in-C-Programming.htm
5 
6 #include <vector>
7 #include <limits>
8 #include <algorithm>
9 #include <functional>
10 #include <iostream>
11 #include <vision_module/Tools/OptimizorParam.hpp>
12 
18 template<class T>
20 {
21 private:
22  vector<OptimizorParam> parameters;
23  unsigned int paramsCount;
24  T& obj;
25  float (T::*pFunc)(const vector<float>& parameters);
26 public:
27  SimplexOptimizer(T& obj,
28  float (T::*pFunc)(const vector<float>& parameters)) :
29  paramsCount(0), obj(obj), pFunc(pFunc)
30  {
31 
32  }
33 
34  bool TuneForBest(int maxIteration,
35  double tol = 1E8 * std::numeric_limits<float>::epsilon(),
36  std::vector<std::vector<float> > x = std::vector<
37  std::vector<float> >())
38  {
39  std::vector<float> init;
40  for(size_t pi=0;pi<paramsCount;pi++)
41  {
42  init.push_back(parameters[pi].data);
43  }
44  int N = paramsCount; //space dimension
45  const double a = 1.0, b = 1.0, g = 0.5, h = 0.5; //coefficients
46  //a: reflection -> xr
47  //b: expansion -> xe
48  //g: contraction -> xc
49  //h: full contraction to x1
50  std::vector<float> xcentroid_old(N, 0); //simplex center * (N+1)
51  std::vector<float> xcentroid_new(N, 0); //simplex center * (N+1)
52  std::vector<float> vf(N + 1, 0); //f evaluated at simplex vertexes
53  int x1 = 0, xn = 0, xnp1 = 0; //x1: f(x1) = min { f(x1), f(x2)...f(x_{n+1} }
54  //xnp1: f(xnp1) = max { f(x1), f(x2)...f(x_{n+1} }
55  //xn: f(xn)<f(xnp1) && f(xn)> all other f(x_i)
56  int cnt = 0; //iteration step number
57 
58  if (x.size() == 0) //if no initial simplex is specified
59  { //construct the trial simplex
60  //based upon the initial guess parameters
61  std::vector<float> del(init);
62  std::transform(del.begin(), del.end(), del.begin(),
63  std::bind2nd(std::divides<float>(), 20)); //'20' is picked
64  //assuming initial trail close to true
65 
66  for (int i = 0; i < N; ++i)
67  {
68  std::vector<float> tmp(init);
69  tmp[i] += del[i];
70  x.push_back(tmp);
71  }
72  x.push_back(init); //x.size()=N+1, x[i].size()=N
73 
74  //xcentriod
75  std::transform(init.begin(), init.end(), xcentroid_old.begin(),
76  std::bind2nd(std::multiplies<float>(), N + 1));
77  } //constructing the simplex finished
78 
79  //optimization begins
80  for (cnt = 0; cnt < maxIteration; ++cnt)
81  {
82 
83  for (int i = 0; i < N + 1; ++i)
84  {
85  vf[i] = (obj.*pFunc)(x[i]);
86  }
87 
88  x1 = 0;
89  xn = 0;
90  xnp1 = 0; //find index of max, second max, min of vf.
91 
92  for (size_t i = 0; i < vf.size(); ++i)
93  {
94  if (vf[i] < vf[x1])
95  {
96  x1 = i;
97  }
98  if (vf[i] > vf[xnp1])
99  {
100  xnp1 = i;
101  }
102  }
103 
104  xn = x1;
105 
106  for (size_t i = 0; i < vf.size(); ++i)
107  {
108  if (vf[i] < vf[xnp1] && vf[i] > vf[xn])
109  xn = i;
110  }
111  //x1, xn, xnp1 are found
112 
113  std::vector<float> xg(N, 0); //xg: centroid of the N best vertexes
114  for (size_t i = 0; i < x.size(); ++i)
115  {
116  if (i != (size_t)xnp1)
117  std::transform(xg.begin(), xg.end(), x[i].begin(),
118  xg.begin(), std::plus<float>());
119  }
120  std::transform(xg.begin(), xg.end(), x[xnp1].begin(),
121  xcentroid_new.begin(), std::plus<float>());
122  std::transform(xg.begin(), xg.end(), xg.begin(),
123  std::bind2nd(std::divides<float>(), N));
124  //xg found, xcentroid_new updated
125 
126  //termination condition
127  float diff = 0; //calculate the difference of the simplex centers
128  //see if the difference is less than the termination criteria
129  for (int i = 0; i < N; ++i)
130  diff += fabs(xcentroid_old[i] - xcentroid_new[i]);
131 
132  if (diff / N < tol)
133  break; //terminate the optimizer
134  else
135  xcentroid_old.swap(xcentroid_new); //update simplex center
136 
137  //reflection:
138  std::vector<float> xr(N, 0);
139  for (int i = 0; i < N; ++i)
140  xr[i] = xg[i] + a * (xg[i] - x[xnp1][i]);
141  //reflection, xr found
142 
143  float fxr = (obj.*pFunc)(xr); //record function at xr
144 
145  if (vf[x1] <= fxr && fxr <= vf[xn])
146  std::copy(xr.begin(), xr.end(), x[xnp1].begin());
147 
148  //expansion:
149  else if (fxr < vf[x1])
150  {
151  std::vector<float> xe(N, 0);
152  for (int i = 0; i < N; ++i)
153  xe[i] = xr[i] + b * (xr[i] - xg[i]);
154  if ((obj.*pFunc)(xe) < fxr)
155  std::copy(xe.begin(), xe.end(), x[xnp1].begin());
156  else
157  std::copy(xr.begin(), xr.end(), x[xnp1].begin());
158  } //expansion finished, xe is not used outside the scope
159 
160  //contraction:
161  else if (fxr > vf[xn])
162  {
163  std::vector<float> xc(N, 0);
164  for (int i = 0; i < N; ++i)
165  xc[i] = xg[i] + g * (x[xnp1][i] - xg[i]);
166  if ((obj.*pFunc)(xc) < vf[xnp1])
167  std::copy(xc.begin(), xc.end(), x[xnp1].begin());
168  else
169  {
170  for (size_t i = 0; i < x.size(); ++i)
171  {
172  if (i != (size_t)x1)
173  {
174  for (int j = 0; j < N; ++j)
175  x[i][j] = x[x1][j] + h * (x[i][j] - x[x1][j]);
176  }
177  }
178  }
179  } //contraction finished, xc is not used outside the scope
180 
181  } //optimization is finished
182 
183  for(size_t pi=0;pi<x[x1].size();pi++)
184  {
185  parameters[pi].data = x[x1][pi];
186  }
187  cout << " Tune counter = " << cnt << endl;
188  if (cnt == maxIteration)
189  {
190  return false;
191  }
192  return true;
193  }
194 
195  void setParameters(vector<OptimizorParam> _parameters)
196  {
197  parameters = _parameters;
198  paramsCount = _parameters.size();
199  }
200 
201  vector<OptimizorParam> getParameters() const
202  {
203  return parameters;
204  }
205 };
Nelder–Mead optimization.
Definition: SimplexOptimizer.hpp:19